net: atlantic: add fw configuration memory area
authorNikita Danilov <ndanilov@marvell.com>
Thu, 7 Nov 2019 22:41:57 +0000 (22:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Nov 2019 03:54:43 +0000 (19:54 -0800)
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: Nikita Danilov <ndanilov@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/aquantia/atlantic/aq_hw.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c

index c2725a5..57396e5 100644 (file)
@@ -140,6 +140,7 @@ struct aq_hw_s {
        atomic_t dpc;
        u32 mbox_addr;
        u32 rpc_addr;
+       u32 settings_addr;
        u32 rpc_tid;
        struct hw_atl_utils_fw_rpc rpc;
        s64 ptp_clk_offset;
index fc82ede..db8c09c 100644 (file)
 
 #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_mpi_set_state(struct aq_hw_s *self,
@@ -327,10 +332,75 @@ err_exit:
        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;
+
+       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;
+       u32 val;
 
        err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
                                        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)
        if (err < 0)
                goto err_exit;
 
-       if (IS_CHIP_FEATURE(REVISION_B1)) {
-               u32 offset = 0;
-
-               for (; offset < cnt; ++offset) {
-                       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);
+       if (IS_CHIP_FEATURE(REVISION_B1))
+               err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
+       else
+               err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
 
-               for (; offset < cnt; ++offset) {
-                       aq_hw_write_reg(self, 0x20C, p[offset]);
-                       aq_hw_write_reg(self, 0x200, 0xC000);
+       hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
 
-                       err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
-                                                       self, val,
-                                                       (val & 0x100) == 0,
-                                                       1000U, 10000U);
-               }
-       }
+       if (err < 0)
+               goto err_exit;
 
-       hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
+       err = aq_hw_err_from_flags(self);
 
 err_exit:
        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)
 {
        int err = 0;
@@ -437,10 +499,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
                err = -1;
                goto err_exit;
        }
-       err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
-                                           (u32 *)(void *)&self->rpc,
-                                           (rpc_size + sizeof(u32) -
-                                            sizeof(u8)) / sizeof(u32));
+       err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
+                                       (rpc_size + sizeof(u32) -
+                                        sizeof(u8)) / sizeof(u32));
        if (err < 0)
                goto err_exit;
 
index c6708f0..68fe17e 100644 (file)
@@ -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 {
        HW_ATL_RX_DISCARD,
        HW_ATL_RX_HOST,
@@ -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,
                                  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);
 
index 4eab51b..3dbce03 100644 (file)
@@ -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_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 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,
                                        1000U, 100000U);
 
+       err = aq_fw2x_settings_get(self, &self->settings_addr);
+
        return err;
 }
 
@@ -418,8 +421,7 @@ static int aq_fw2x_send_fw_request(struct aq_hw_s *self,
        dword_cnt = size / sizeof(u32);
        if (size % sizeof(u32))
                dword_cnt++;
-       err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self),
-                                           (void *)fw_req, dword_cnt);
+       err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt);
        if (err < 0)
                goto err_exit;
 
@@ -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);
 }
 
+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)
 {
        return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);