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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+95 −34
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@

#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,36 +332,53 @@ 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 val;
	u32 data_offset = 0;
	u32 offset = addr;
	int err = 0;
	u32 val;

	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
					val, val == 1U,
					10U, 100000U);
	if (err < 0)
		goto err_exit;
	switch (area) {
	case MCP_AREA_CONFIG:
		offset -= self->rpc_addr;
		break;

	if (IS_CHIP_FEATURE(REVISION_B1)) {
		u32 offset = 0;
	case MCP_AREA_SETTINGS:
		offset -= self->settings_addr;
		break;
	}

		for (; offset < cnt; ++offset) {
			aq_hw_write_reg(self, 0x328, p[offset]);
	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,
					(0x80000000 | (0xFFFF & (offset * 4))));
				(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) !=
							0x80000000,
						area,
						10U, 10000U);

		if (err < 0)
			break;
	}
	} else {

	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, a);
	aq_hw_write_reg(self, 0x208, addr);

	for (; offset < cnt; ++offset) {
		aq_hw_write_reg(self, 0x20C, p[offset]);
@@ -364,17 +386,57 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt)

		err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
						self, val,
							(val & 0x100) == 0,
							1000U, 10000U);
						(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,
					10U, 100000U);
	if (err < 0)
		goto err_exit;

	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);

	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);

	if (err < 0)
		goto err_exit;

	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,8 +499,7 @@ 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,
	err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
					(rpc_size + sizeof(u32) -
					 sizeof(u8)) / sizeof(u32));
	if (err < 0)
+46 −1
Original line number Diff line number Diff line
@@ -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);

+17 −2
Original line number Diff line number Diff line
@@ -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);