Commit dc12f75a authored by Nikita Danilov's avatar Nikita Danilov Committed by David S. Miller

net: atlantic: add fw configuration memory area

Device FW has a separate memory area where various
config fields are stored and could be used by the
driver.

Here we modify download/upload infrastructure to
allow accessing this area.

Lateron this will be used to configure various behaviours
Signed-off-by: default avatarNikita Danilov <ndanilov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d1287ce4
...@@ -140,6 +140,7 @@ struct aq_hw_s { ...@@ -140,6 +140,7 @@ struct aq_hw_s {
atomic_t dpc; atomic_t dpc;
u32 mbox_addr; u32 mbox_addr;
u32 rpc_addr; u32 rpc_addr;
u32 settings_addr;
u32 rpc_tid; u32 rpc_tid;
struct hw_atl_utils_fw_rpc rpc; struct hw_atl_utils_fw_rpc rpc;
s64 ptp_clk_offset; s64 ptp_clk_offset;
......
...@@ -47,6 +47,11 @@ ...@@ -47,6 +47,11 @@
#define FORCE_FLASHLESS 0 #define FORCE_FLASHLESS 0
enum mcp_area {
MCP_AREA_CONFIG = 0x80000000,
MCP_AREA_SETTINGS = 0x20000000,
};
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
...@@ -327,10 +332,75 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, ...@@ -327,10 +332,75 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
return err; return err;
} }
int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr,
u32 *p, u32 cnt, enum mcp_area area)
{
u32 data_offset = 0;
u32 offset = addr;
int err = 0;
u32 val;
switch (area) {
case MCP_AREA_CONFIG:
offset -= self->rpc_addr;
break;
case MCP_AREA_SETTINGS:
offset -= self->settings_addr;
break;
}
offset = offset / sizeof(u32);
for (; data_offset < cnt; ++data_offset, ++offset) {
aq_hw_write_reg(self, 0x328, p[data_offset]);
aq_hw_write_reg(self, 0x32C,
(area | (0xFFFF & (offset * 4))));
hw_atl_mcp_up_force_intr_set(self, 1);
/* 1000 times by 10us = 10ms */
err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
self, val,
(val & 0xF0000000) !=
area,
10U, 10000U);
if (err < 0)
break;
}
return err;
}
static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr,
u32 *p, u32 cnt)
{ {
u32 offset = 0;
int err = 0;
u32 val; u32 val;
aq_hw_write_reg(self, 0x208, addr);
for (; offset < cnt; ++offset) {
aq_hw_write_reg(self, 0x20C, p[offset]);
aq_hw_write_reg(self, 0x200, 0xC000);
err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
self, val,
(val & 0x100) == 0U,
10U, 10000U);
if (err < 0)
break;
}
return err;
}
static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p,
u32 cnt, enum mcp_area area)
{
int err = 0; int err = 0;
u32 val;
err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self, err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
val, val == 1U, val, val == 1U,
...@@ -338,43 +408,35 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) ...@@ -338,43 +408,35 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt)
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
if (IS_CHIP_FEATURE(REVISION_B1)) { if (IS_CHIP_FEATURE(REVISION_B1))
u32 offset = 0; err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
else
for (; offset < cnt; ++offset) { err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
aq_hw_write_reg(self, 0x328, p[offset]);
aq_hw_write_reg(self, 0x32C,
(0x80000000 | (0xFFFF & (offset * 4))));
hw_atl_mcp_up_force_intr_set(self, 1);
/* 1000 times by 10us = 10ms */
err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
self, val,
(val & 0xF0000000) !=
0x80000000,
10U, 10000U);
}
} else {
u32 offset = 0;
aq_hw_write_reg(self, 0x208, a);
for (; offset < cnt; ++offset) { hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
aq_hw_write_reg(self, 0x20C, p[offset]);
aq_hw_write_reg(self, 0x200, 0xC000);
err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, if (err < 0)
self, val, goto err_exit;
(val & 0x100) == 0,
1000U, 10000U);
}
}
hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); err = aq_hw_err_from_flags(self);
err_exit: err_exit:
return err; return err;
} }
int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt)
{
return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p,
cnt, MCP_AREA_CONFIG);
}
int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
u32 cnt)
{
return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset,
p, cnt, MCP_AREA_SETTINGS);
}
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
{ {
int err = 0; int err = 0;
...@@ -437,10 +499,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) ...@@ -437,10 +499,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
err = -1; err = -1;
goto err_exit; goto err_exit;
} }
err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
(u32 *)(void *)&self->rpc, (rpc_size + sizeof(u32) -
(rpc_size + sizeof(u32) - sizeof(u8)) / sizeof(u32));
sizeof(u8)) / sizeof(u32));
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
......
...@@ -277,6 +277,48 @@ struct __packed hw_fw_request_iface { ...@@ -277,6 +277,48 @@ struct __packed hw_fw_request_iface {
}; };
}; };
struct __packed hw_atl_utils_settings {
u32 mtu;
u32 downshift_retry_count;
u32 link_pause_frame_quanta_100m;
u32 link_pause_frame_threshold_100m;
u32 link_pause_frame_quanta_1g;
u32 link_pause_frame_threshold_1g;
u32 link_pause_frame_quanta_2p5g;
u32 link_pause_frame_threshold_2p5g;
u32 link_pause_frame_quanta_5g;
u32 link_pause_frame_threshold_5g;
u32 link_pause_frame_quanta_10g;
u32 link_pause_frame_threshold_10g;
u32 pfc_quanta_class_0;
u32 pfc_threshold_class_0;
u32 pfc_quanta_class_1;
u32 pfc_threshold_class_1;
u32 pfc_quanta_class_2;
u32 pfc_threshold_class_2;
u32 pfc_quanta_class_3;
u32 pfc_threshold_class_3;
u32 pfc_quanta_class_4;
u32 pfc_threshold_class_4;
u32 pfc_quanta_class_5;
u32 pfc_threshold_class_5;
u32 pfc_quanta_class_6;
u32 pfc_threshold_class_6;
u32 pfc_quanta_class_7;
u32 pfc_threshold_class_7;
u32 eee_link_down_timeout;
u32 eee_link_up_timeout;
u32 eee_max_link_drops;
u32 eee_rates_mask;
u32 wake_timer;
u32 thermal_shutdown_off_temp;
u32 thermal_shutdown_warning_temp;
u32 thermal_shutdown_cold_temp;
u32 msm_options;
u32 dac_cable_serdes_modes;
u32 media_detect;
};
enum hw_atl_rx_action_with_traffic { enum hw_atl_rx_action_with_traffic {
HW_ATL_RX_DISCARD, HW_ATL_RX_DISCARD,
HW_ATL_RX_HOST, HW_ATL_RX_HOST,
...@@ -554,7 +596,10 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); ...@@ -554,7 +596,10 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self);
int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt); u32 *p, u32 cnt);
int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt); int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt);
int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
u32 cnt);
int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac); int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac);
......
...@@ -78,6 +78,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, ...@@ -78,6 +78,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self,
static u32 aq_fw2x_mbox_get(struct aq_hw_s *self); static u32 aq_fw2x_mbox_get(struct aq_hw_s *self);
static u32 aq_fw2x_rpc_get(struct aq_hw_s *self); static u32 aq_fw2x_rpc_get(struct aq_hw_s *self);
static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr);
static u32 aq_fw2x_state2_get(struct aq_hw_s *self); static u32 aq_fw2x_state2_get(struct aq_hw_s *self);
static int aq_fw2x_init(struct aq_hw_s *self) static int aq_fw2x_init(struct aq_hw_s *self)
...@@ -95,6 +96,8 @@ static int aq_fw2x_init(struct aq_hw_s *self) ...@@ -95,6 +96,8 @@ static int aq_fw2x_init(struct aq_hw_s *self)
self->rpc_addr != 0U, self->rpc_addr != 0U,
1000U, 100000U); 1000U, 100000U);
err = aq_fw2x_settings_get(self, &self->settings_addr);
return err; return err;
} }
...@@ -418,8 +421,7 @@ static int aq_fw2x_send_fw_request(struct aq_hw_s *self, ...@@ -418,8 +421,7 @@ static int aq_fw2x_send_fw_request(struct aq_hw_s *self,
dword_cnt = size / sizeof(u32); dword_cnt = size / sizeof(u32);
if (size % sizeof(u32)) if (size % sizeof(u32))
dword_cnt++; dword_cnt++;
err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self), err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt);
(void *)fw_req, dword_cnt);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -547,6 +549,19 @@ static u32 aq_fw2x_rpc_get(struct aq_hw_s *self) ...@@ -547,6 +549,19 @@ static u32 aq_fw2x_rpc_get(struct aq_hw_s *self)
return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR); return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR);
} }
static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr)
{
int err = 0;
u32 offset;
offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
info.setting_address);
err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1);
return err;
}
static u32 aq_fw2x_state2_get(struct aq_hw_s *self) static u32 aq_fw2x_state2_get(struct aq_hw_s *self)
{ {
return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment