Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1d374ea authored by Yana Esina's avatar Yana Esina Committed by Greg Kroah-Hartman
Browse files

net: aquantia: fix hw_atl_utils_fw_upload_dwords



[ Upstream commit 3ee5c8873fd369e2005dc93bf6d4b299b4976e68 ]

This patch fixes the upload function, which worked incorrectly with
some chips.

Signed-off-by: default avatarYana Esina <yana.esina@aquantia.com>
Signed-off-by: default avatarNikita Danilov <nikita.danilov@aquantia.com>
Tested-by: default avatarNikita Danilov <nikita.danilov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent a9cab0fe
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1468,3 +1468,11 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw,
	aq_hw_write_reg(aq_hw, HW_ATL_GLB_CPU_SCRATCH_SCP_ADR(scratch_scp),
			glb_cpu_scratch_scp);
}

void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr)
{
	aq_hw_write_reg_bit(aq_hw, HW_ATL_MCP_UP_FORCE_INTERRUPT_ADR,
			    HW_ATL_MCP_UP_FORCE_INTERRUPT_MSK,
			    HW_ATL_MCP_UP_FORCE_INTERRUPT_SHIFT,
			    up_force_intr);
}
+3 −0
Original line number Diff line number Diff line
@@ -701,4 +701,7 @@ void hw_atl_msm_reg_wr_strobe_set(struct aq_hw_s *aq_hw, u32 reg_wr_strobe);
/* set pci register reset disable */
void hw_atl_pci_pci_reg_res_dis_set(struct aq_hw_s *aq_hw, u32 pci_reg_res_dis);

/* set uP Force Interrupt */
void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr);

#endif /* HW_ATL_LLH_H */
+13 −0
Original line number Diff line number Diff line
@@ -2405,4 +2405,17 @@
#define HW_ATL_GLB_CPU_SCRATCH_SCP_ADR(scratch_scp) \
	(0x00000300u + (scratch_scp) * 0x4)

/* register address for bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_ADR 0x00000404
/* bitmask for bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_MSK 0x00000002
/* inverted bitmask for bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_MSKN 0xFFFFFFFD
/* lower bit position of bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_SHIFT 1
/* width of bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_WIDTH 1
/* default value of bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0

#endif /* HW_ATL_LLH_INTERNAL_H */
+25 −11
Original line number Diff line number Diff line
@@ -327,17 +327,31 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
		err = -ETIME;
		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 */
			AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
						       0x32C) & 0xF0000000) !=
				       0x80000000,
				       10, 1000);
		}
	} else {
		u32 offset = 0;

	aq_hw_write_reg(self, 0x00000208U, a);

	for (++cnt; --cnt;) {
		u32 i = 0U;
		aq_hw_write_reg(self, 0x208, a);

		aq_hw_write_reg(self, 0x0000020CU, *(p++));
		aq_hw_write_reg(self, 0x00000200U, 0xC000U);
		for (; offset < cnt; ++offset) {
			aq_hw_write_reg(self, 0x20C, p[offset]);
			aq_hw_write_reg(self, 0x200, 0xC000);

		for (i = 1024U;
			(0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
			AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U) &
					0x100) == 0, 10, 1000);
		}
	}

@@ -401,7 +415,7 @@ struct aq_hw_atl_utils_fw_rpc_tid_s {

#define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)

static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
{
	int err = 0;
	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
@@ -425,7 +439,7 @@ static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
	return err;
}

static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
			     struct hw_aq_atl_utils_fw_rpc **rpc)
{
	int err = 0;
+5 −0
Original line number Diff line number Diff line
@@ -319,6 +319,11 @@ 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_rpc_call(struct aq_hw_s *self, unsigned int rpc_size);

int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
			     struct hw_aq_atl_utils_fw_rpc **rpc);

extern const struct aq_fw_ops aq_fw_1x_ops;
extern const struct aq_fw_ops aq_fw_2x_ops;

Loading