icnss: Add hardware reset logic
Add hardware reset logic which is going to be executed before bringing down hardware. CRs-fixed: 1027110 Change-Id: Ied1229da9e9f72c25343533b933fdcfcb7f80975 Signed-off-by: Prashanth Bhatta <bhattap@codeaurora.org>
This commit is contained in:
parent
4fcefc6691
commit
60ce7a7d8d
1 changed files with 556 additions and 34 deletions
|
@ -45,9 +45,106 @@
|
|||
#define WLFW_TIMEOUT_MS 3000
|
||||
#define WLFW_SERVICE_INS_ID_V01 0
|
||||
#define MAX_PROP_SIZE 32
|
||||
#define MPM2_MPM_WCSSAON_CONFIG_OFFSET 0x18
|
||||
#define NUM_LOG_PAGES 4
|
||||
|
||||
/*
|
||||
* Registers: MPM2_PSHOLD
|
||||
* Base Address: 0x10AC000
|
||||
*/
|
||||
#define MPM_WCSSAON_CONFIG_OFFSET 0x18
|
||||
#define MPM_WCSSAON_CONFIG_ARES_N BIT(0)
|
||||
#define MPM_WCSSAON_CONFIG_WLAN_DISABLE BIT(1)
|
||||
#define MPM_WCSSAON_CONFIG_FORCE_ACTIVE BIT(14)
|
||||
#define MPM_WCSSAON_CONFIG_FORCE_XO_ENABLE BIT(19)
|
||||
#define MPM_WCSSAON_CONFIG_DISCONNECT_CLR BIT(21)
|
||||
|
||||
/*
|
||||
* Registers: WCSS_SR_SHADOW_REGISTERS
|
||||
* Base Address: 0x18820000
|
||||
*/
|
||||
#define SR_WCSSAON_SR_LSB_OFFSET 0x22070
|
||||
#define SR_WCSSAON_SR_LSB_RETENTION_STATUS BIT(20)
|
||||
|
||||
#define SR_PMM_SR_MSB 0x2206C
|
||||
#define SR_PMM_SR_MSB_AHB_CLOCK_MASK GENMASK(26, 22)
|
||||
#define SR_PMM_SR_MSB_XO_CLOCK_MASK GENMASK(31, 27)
|
||||
|
||||
/*
|
||||
* Registers: WCSS_HM_A_WCSS_CLK_CTL_WCSS_CC_REG
|
||||
* Base Address: 0x189D0000
|
||||
*/
|
||||
#define WCSS_WLAN1_GDSCR_OFFSET 0x1D3004
|
||||
#define WCSS_WLAN1_GDSCR_SW_COLLAPSE BIT(0)
|
||||
#define WCSS_WLAN1_GDSCR_HW_CONTROL BIT(1)
|
||||
#define WCSS_WLAN1_GDSCR_PWR_ON BIT(31)
|
||||
|
||||
#define WCSS_RFACTRL_GDSCR_OFFSET 0x1D60C8
|
||||
#define WCSS_RFACTRL_GDSCR_SW_COLLAPSE BIT(0)
|
||||
#define WCSS_RFACTRL_GDSCR_HW_CONTROL BIT(1)
|
||||
#define WCSS_RFACTRL_GDSCR_PWR_ON BIT(31)
|
||||
|
||||
#define WCSS_CLK_CTL_WCSS_CSS_GDSCR_OFFSET 0x1D1004
|
||||
#define WCSS_CLK_CTL_WCSS_CSS_GDSCR_SW_COLLAPSE BIT(0)
|
||||
#define WCSS_CLK_CTL_WCSS_CSS_GDSCR_HW_CONTROL BIT(1)
|
||||
#define WCSS_CLK_CTL_WCSS_CSS_GDSCR_PWR_ON BIT(31)
|
||||
|
||||
/*
|
||||
* Registers: WCSS_HM_A_WIFI_APB_3_A_WCMN_MAC_WCMN_REG
|
||||
* Base Address: 0x18AF0000
|
||||
*/
|
||||
#define WCMN_PMM_WLAN1_CFG_REG1_OFFSET 0x2F0804
|
||||
#define WCMN_PMM_WLAN1_CFG_REG1_RFIF_ADC_PORDN_N BIT(9)
|
||||
#define WCMN_PMM_WLAN1_CFG_REG1_ADC_DIGITAL_CLAMP BIT(10)
|
||||
|
||||
/*
|
||||
* Registers: WCSS_HM_A_PMM_PMM
|
||||
* Base Address: 0x18880000
|
||||
*/
|
||||
#define PMM_COMMON_IDLEREQ_CSR_OFFSET 0x80120
|
||||
#define PMM_COMMON_IDLEREQ_CSR_SW_WNOC_IDLEREQ_SET BIT(16)
|
||||
#define PMM_COMMON_IDLEREQ_CSR_WNOC_IDLEACK BIT(26)
|
||||
#define PMM_COMMON_IDLEREQ_CSR_WNOC_IDLE BIT(27)
|
||||
|
||||
#define PMM_RFACTRL_IDLEREQ_CSR_OFFSET 0x80164
|
||||
#define PMM_RFACTRL_IDLEREQ_CSR_SW_RFACTRL_IDLEREQ_SET BIT(16)
|
||||
#define PMM_RFACTRL_IDLEREQ_CSR_RFACTRL_IDLETACK BIT(26)
|
||||
|
||||
#define PMM_WSI_CMD_OFFSET 0x800E0
|
||||
#define PMM_WSI_CMD_USE_WLAN1_WSI BIT(0)
|
||||
#define PMM_WSI_CMD_SW_USE_PMM_WSI BIT(2)
|
||||
#define PMM_WSI_CMD_SW_BUS_SYNC BIT(3)
|
||||
#define PMM_WSI_CMD_SW_RF_RESET BIT(4)
|
||||
#define PMM_WSI_CMD_SW_REG_READ BIT(5)
|
||||
#define PMM_WSI_CMD_SW_XO_DIS BIT(8)
|
||||
#define PMM_WSI_CMD_SW_FORCE_IDLE BIT(9)
|
||||
#define PMM_WSI_CMD_PMM_WSI_SM GENMASK(24, 16)
|
||||
#define PMM_WSI_CMD_RF_CMD_IP BIT(31)
|
||||
|
||||
#define PMM_REG_RW_ADDR_OFFSET 0x800F0
|
||||
#define PMM_REG_RW_ADDR_SW_REG_RW_ADDR GENMASK(15, 0)
|
||||
|
||||
#define PMM_REG_READ_DATA_OFFSET 0x800F8
|
||||
|
||||
#define PMM_RF_VAULT_REG_ADDR_OFFSET 0x800FC
|
||||
#define PMM_RF_VAULT_REG_ADDR_RF_VAULT_REG_ADDR GENMASK(15, 0)
|
||||
|
||||
#define PMM_RF_VAULT_REG_DATA_OFFSET 0x80100
|
||||
#define PMM_RF_VAULT_REG_DATA_RF_VAULT_REG_DATA GENMASK(31, 0)
|
||||
|
||||
#define PMM_XO_DIS_ADDR_OFFSET 0x800E8
|
||||
#define PMM_XO_DIS_ADDR_XO_DIS_ADDR GENMASK(15, 0)
|
||||
|
||||
#define PMM_XO_DIS_DATA_OFFSET 0x800EC
|
||||
#define PMM_XO_DIS_DATA_XO_DIS_DATA GENMASK(31, 0)
|
||||
|
||||
#define PMM_RF_RESET_ADDR_OFFSET 0x80104
|
||||
#define PMM_RF_RESET_ADDR_RF_RESET_ADDR GENMASK(15, 0)
|
||||
|
||||
#define PMM_RF_RESET_DATA_OFFSET 0x80108
|
||||
#define PMM_RF_RESET_DATA_RF_RESET_DATA GENMASK(31, 0)
|
||||
|
||||
#define ICNSS_HW_REG_RETRY 10
|
||||
|
||||
#define icnss_ipc_log_string(_x...) do { \
|
||||
if (icnss_ipc_log_context) \
|
||||
ipc_log_string(icnss_ipc_log_context, _x); \
|
||||
|
@ -96,9 +193,10 @@
|
|||
#endif
|
||||
|
||||
enum icnss_debug_quirks {
|
||||
HW_ALWAY_ON,
|
||||
HW_ALWAYS_ON,
|
||||
HW_DEBUG_ENABLE,
|
||||
SKIP_QMI,
|
||||
HW_ONLY_TOP_LEVEL_RESET,
|
||||
};
|
||||
|
||||
#define ICNSS_QUIRKS_DEFAULT 0
|
||||
|
@ -252,6 +350,71 @@ static struct icnss_priv {
|
|||
struct icnss_stats stats;
|
||||
} *penv;
|
||||
|
||||
static void icnss_hw_write_reg(void *base, u32 offset, u32 val)
|
||||
{
|
||||
writel_relaxed(val, base + offset);
|
||||
wmb(); /* Ensure data is written to hardware register */
|
||||
}
|
||||
|
||||
static u32 icnss_hw_read_reg(void *base, u32 offset)
|
||||
{
|
||||
u32 rdata = readl_relaxed(base + offset);
|
||||
|
||||
icnss_pr_dbg(" READ: offset: 0x%06x 0x%08x\n", offset, rdata);
|
||||
|
||||
return rdata;
|
||||
}
|
||||
|
||||
static void icnss_hw_write_reg_field(void *base, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
u32 shift = find_first_bit((void *)&mask, 32);
|
||||
u32 rdata = readl_relaxed(base + offset);
|
||||
|
||||
val = (rdata & ~mask) | (val << shift);
|
||||
|
||||
icnss_pr_dbg("WRITE: offset: 0x%06x 0x%08x -> 0x%08x\n",
|
||||
offset, rdata, val);
|
||||
|
||||
icnss_hw_write_reg(base, offset, val);
|
||||
}
|
||||
|
||||
static int icnss_hw_poll_reg_field(void *base, u32 offset, u32 mask, u32 val,
|
||||
unsigned long usecs, int retry)
|
||||
{
|
||||
u32 shift;
|
||||
u32 rdata;
|
||||
int r = 0;
|
||||
|
||||
shift = find_first_bit((void *)&mask, 32);
|
||||
|
||||
val = val << shift;
|
||||
|
||||
rdata = readl_relaxed(base + offset);
|
||||
|
||||
icnss_pr_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
|
||||
offset, val, rdata, mask);
|
||||
|
||||
while ((rdata & mask) != val) {
|
||||
if (retry != 0 && r >= retry) {
|
||||
icnss_pr_err(" POLL FAILED: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
|
||||
offset, val, rdata, mask);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
r++;
|
||||
udelay(usecs);
|
||||
rdata = readl_relaxed(base + offset);
|
||||
|
||||
if (retry)
|
||||
icnss_pr_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
|
||||
offset, val, rdata, mask);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *icnss_driver_event_to_str(enum icnss_driver_event_type type)
|
||||
{
|
||||
switch (type) {
|
||||
|
@ -525,36 +688,394 @@ static int icnss_clk_deinit(struct icnss_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void icnss_hw_release_reset(struct icnss_priv *priv)
|
||||
static void icnss_hw_top_level_release_reset(struct icnss_priv *priv)
|
||||
{
|
||||
uint32_t rdata = 0;
|
||||
icnss_pr_dbg("RESET: HW Release reset: state: 0x%lx\n", priv->state);
|
||||
|
||||
icnss_pr_dbg("HW Release reset: state: 0x%lx\n", priv->state);
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_ARES_N, 1);
|
||||
|
||||
if (priv->mpm_config_va) {
|
||||
writel_relaxed(0x1,
|
||||
priv->mpm_config_va +
|
||||
MPM2_MPM_WCSSAON_CONFIG_OFFSET);
|
||||
while (rdata != 0x1)
|
||||
rdata = readl_relaxed(priv->mpm_config_va +
|
||||
MPM2_MPM_WCSSAON_CONFIG_OFFSET);
|
||||
}
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_WLAN_DISABLE, 0x0);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mpm_config_va,
|
||||
MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_ARES_N, 1, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
}
|
||||
|
||||
static void icnss_hw_reset(struct icnss_priv *priv)
|
||||
static void icnss_hw_top_level_reset(struct icnss_priv *priv)
|
||||
{
|
||||
uint32_t rdata = 0;
|
||||
icnss_pr_dbg("RESET: HW top level reset: state: 0x%lx\n", priv->state);
|
||||
|
||||
icnss_pr_dbg("HW reset: state: 0x%lx\n", priv->state);
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va,
|
||||
MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_ARES_N, 0);
|
||||
|
||||
if (priv->mpm_config_va) {
|
||||
writel_relaxed(0x0,
|
||||
priv->mpm_config_va +
|
||||
MPM2_MPM_WCSSAON_CONFIG_OFFSET);
|
||||
while (rdata != 0x0)
|
||||
rdata = readl_relaxed(priv->mpm_config_va +
|
||||
MPM2_MPM_WCSSAON_CONFIG_OFFSET);
|
||||
icnss_hw_poll_reg_field(priv->mpm_config_va,
|
||||
MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_ARES_N, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
}
|
||||
|
||||
int icnss_hw_reset_wlan_ss_power_down(struct icnss_priv *priv)
|
||||
{
|
||||
u32 rdata;
|
||||
|
||||
icnss_pr_dbg("RESET: WLAN SS power down, state: 0x%lx\n", priv->state);
|
||||
|
||||
rdata = icnss_hw_read_reg(priv->mem_base_va, WCSS_WLAN1_GDSCR_OFFSET);
|
||||
|
||||
if ((rdata & WCSS_WLAN1_GDSCR_PWR_ON) == 0)
|
||||
return 0;
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, WCSS_WLAN1_GDSCR_OFFSET,
|
||||
WCSS_WLAN1_GDSCR_HW_CONTROL, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, WCSS_WLAN1_GDSCR_OFFSET,
|
||||
WCSS_WLAN1_GDSCR_SW_COLLAPSE, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va, WCSS_WLAN1_GDSCR_OFFSET,
|
||||
WCSS_WLAN1_GDSCR_PWR_ON, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
WCMN_PMM_WLAN1_CFG_REG1_OFFSET,
|
||||
WCMN_PMM_WLAN1_CFG_REG1_ADC_DIGITAL_CLAMP, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
WCMN_PMM_WLAN1_CFG_REG1_OFFSET,
|
||||
WCMN_PMM_WLAN1_CFG_REG1_RFIF_ADC_PORDN_N, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icnss_hw_reset_common_ss_power_down(struct icnss_priv *priv)
|
||||
{
|
||||
u32 rdata;
|
||||
|
||||
icnss_pr_dbg("RESET: Common SS power down, state: 0x%lx\n",
|
||||
priv->state);
|
||||
|
||||
rdata = icnss_hw_read_reg(priv->mem_base_va,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_OFFSET);
|
||||
|
||||
if ((rdata & WCSS_CLK_CTL_WCSS_CSS_GDSCR_PWR_ON) == 0)
|
||||
return 0;
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_COMMON_IDLEREQ_CSR_OFFSET,
|
||||
PMM_COMMON_IDLEREQ_CSR_SW_WNOC_IDLEREQ_SET,
|
||||
1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va,
|
||||
PMM_COMMON_IDLEREQ_CSR_OFFSET,
|
||||
PMM_COMMON_IDLEREQ_CSR_WNOC_IDLEACK,
|
||||
1, 20, ICNSS_HW_REG_RETRY);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va,
|
||||
PMM_COMMON_IDLEREQ_CSR_OFFSET,
|
||||
PMM_COMMON_IDLEREQ_CSR_WNOC_IDLE,
|
||||
1, 10, ICNSS_HW_REG_RETRY);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_OFFSET,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_HW_CONTROL, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_OFFSET,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_SW_COLLAPSE, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_OFFSET,
|
||||
WCSS_CLK_CTL_WCSS_CSS_GDSCR_PWR_ON, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int icnss_hw_reset_wlan_rfactrl_power_down(struct icnss_priv *priv)
|
||||
{
|
||||
u32 rdata;
|
||||
|
||||
icnss_pr_dbg("RESET: RFACTRL power down, state: 0x%lx\n", priv->state);
|
||||
|
||||
rdata = icnss_hw_read_reg(priv->mem_base_va, WCSS_RFACTRL_GDSCR_OFFSET);
|
||||
|
||||
if ((rdata & WCSS_RFACTRL_GDSCR_PWR_ON) == 0)
|
||||
return 0;
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_RFACTRL_IDLEREQ_CSR_OFFSET,
|
||||
PMM_RFACTRL_IDLEREQ_CSR_SW_RFACTRL_IDLEREQ_SET,
|
||||
1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va,
|
||||
PMM_RFACTRL_IDLEREQ_CSR_OFFSET,
|
||||
PMM_RFACTRL_IDLEREQ_CSR_RFACTRL_IDLETACK,
|
||||
1, 10, ICNSS_HW_REG_RETRY);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, WCSS_RFACTRL_GDSCR_OFFSET,
|
||||
WCSS_RFACTRL_GDSCR_HW_CONTROL, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, WCSS_RFACTRL_GDSCR_OFFSET,
|
||||
WCSS_RFACTRL_GDSCR_SW_COLLAPSE, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void icnss_hw_wsi_cmd_error_recovery(struct icnss_priv *priv)
|
||||
{
|
||||
icnss_pr_dbg("RESET: WSI CMD Error recovery, state: 0x%lx\n",
|
||||
priv->state);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_FORCE_IDLE, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_PMM_WSI_SM, 1, 100, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_FORCE_IDLE, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_BUS_SYNC, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_RF_CMD_IP, 0, 100, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_BUS_SYNC, 0);
|
||||
}
|
||||
|
||||
u32 icnss_hw_rf_register_read_command(struct icnss_priv *priv, u32 addr)
|
||||
{
|
||||
u32 rdata = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
icnss_pr_dbg("RF register read command, addr: 0x%04x, state: 0x%lx\n",
|
||||
addr, priv->state);
|
||||
|
||||
for (i = 0; i < ICNSS_HW_REG_RETRY; i++) {
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_USE_WLAN1_WSI, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_REG_RW_ADDR_OFFSET,
|
||||
PMM_REG_RW_ADDR_SW_REG_RW_ADDR,
|
||||
addr & 0xFFFF);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_REG_READ, 1);
|
||||
|
||||
ret = icnss_hw_poll_reg_field(priv->mem_base_va,
|
||||
PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_RF_CMD_IP, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
icnss_hw_wsi_cmd_error_recovery(priv);
|
||||
}
|
||||
|
||||
|
||||
rdata = icnss_hw_read_reg(priv->mem_base_va, PMM_REG_READ_DATA_OFFSET);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_REG_READ, 0);
|
||||
|
||||
icnss_pr_dbg("RF register read command, data: 0x%08x, state: 0x%lx\n",
|
||||
rdata, priv->state);
|
||||
|
||||
return rdata;
|
||||
}
|
||||
|
||||
int icnss_hw_reset_rf_reset_cmd(struct icnss_priv *priv)
|
||||
{
|
||||
u32 rdata;
|
||||
int ret;
|
||||
|
||||
icnss_pr_dbg("RESET: RF reset command, state: 0x%lx\n", priv->state);
|
||||
|
||||
rdata = icnss_hw_rf_register_read_command(priv, 0x5080);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_USE_WLAN1_WSI, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_RF_VAULT_REG_ADDR_OFFSET,
|
||||
PMM_RF_VAULT_REG_ADDR_RF_VAULT_REG_ADDR,
|
||||
0x5082);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_RF_VAULT_REG_DATA_OFFSET,
|
||||
PMM_RF_VAULT_REG_DATA_RF_VAULT_REG_DATA,
|
||||
0x12AB8FAD);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_RF_RESET_ADDR_OFFSET,
|
||||
PMM_RF_RESET_ADDR_RF_RESET_ADDR, 0x5080);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_RF_RESET_DATA_OFFSET,
|
||||
PMM_RF_RESET_DATA_RF_RESET_DATA,
|
||||
rdata & 0xBFFF);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_RF_RESET, 1);
|
||||
|
||||
ret = icnss_hw_poll_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_RF_CMD_IP, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
|
||||
if (ret) {
|
||||
icnss_pr_err("RESET: RF reset command failed, state: 0x%lx\n",
|
||||
priv->state);
|
||||
icnss_hw_wsi_cmd_error_recovery(priv);
|
||||
}
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_RF_RESET, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icnss_hw_reset_xo_disable_cmd(struct icnss_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
icnss_pr_dbg("RESET: XO disable command, state: 0x%lx\n", priv->state);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_USE_WLAN1_WSI, 1);
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_RF_VAULT_REG_ADDR_OFFSET,
|
||||
PMM_RF_VAULT_REG_ADDR_RF_VAULT_REG_ADDR,
|
||||
0x5082);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va,
|
||||
PMM_RF_VAULT_REG_DATA_OFFSET,
|
||||
PMM_RF_VAULT_REG_DATA_RF_VAULT_REG_DATA,
|
||||
0x12AB8FAD);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_XO_DIS_ADDR_OFFSET,
|
||||
PMM_XO_DIS_ADDR_XO_DIS_ADDR, 0x5081);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_XO_DIS_DATA_OFFSET,
|
||||
PMM_XO_DIS_DATA_XO_DIS_DATA, 1);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_XO_DIS, 1);
|
||||
|
||||
ret = icnss_hw_poll_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_RF_CMD_IP, 0, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
if (ret) {
|
||||
icnss_pr_err("RESET: XO disable command failed, state: 0x%lx\n",
|
||||
priv->state);
|
||||
icnss_hw_wsi_cmd_error_recovery(priv);
|
||||
}
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_USE_PMM_WSI, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mem_base_va, PMM_WSI_CMD_OFFSET,
|
||||
PMM_WSI_CMD_SW_XO_DIS, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icnss_hw_reset(struct icnss_priv *priv)
|
||||
{
|
||||
u32 rdata;
|
||||
u32 rdata1;
|
||||
int i;
|
||||
|
||||
if (test_bit(HW_ONLY_TOP_LEVEL_RESET, &quirks))
|
||||
goto top_level_reset;
|
||||
|
||||
icnss_pr_dbg("RESET: START, state: 0x%lx\n", priv->state);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_FORCE_ACTIVE, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va, SR_WCSSAON_SR_LSB_OFFSET,
|
||||
SR_WCSSAON_SR_LSB_RETENTION_STATUS, 1, 10,
|
||||
ICNSS_HW_REG_RETRY);
|
||||
|
||||
for (i = 0; i < ICNSS_HW_REG_RETRY; i++) {
|
||||
rdata = icnss_hw_read_reg(priv->mem_base_va, SR_PMM_SR_MSB);
|
||||
udelay(10);
|
||||
rdata1 = icnss_hw_read_reg(priv->mem_base_va, SR_PMM_SR_MSB);
|
||||
|
||||
icnss_pr_dbg("RESET: XO: 0x%05lx/0x%05lx, AHB: 0x%05lx/0x%05lx\n",
|
||||
rdata & SR_PMM_SR_MSB_XO_CLOCK_MASK,
|
||||
rdata1 & SR_PMM_SR_MSB_XO_CLOCK_MASK,
|
||||
rdata & SR_PMM_SR_MSB_AHB_CLOCK_MASK,
|
||||
rdata1 & SR_PMM_SR_MSB_AHB_CLOCK_MASK);
|
||||
|
||||
if ((rdata & SR_PMM_SR_MSB_AHB_CLOCK_MASK) !=
|
||||
(rdata1 & SR_PMM_SR_MSB_AHB_CLOCK_MASK) &&
|
||||
(rdata & SR_PMM_SR_MSB_XO_CLOCK_MASK) !=
|
||||
(rdata1 & SR_PMM_SR_MSB_XO_CLOCK_MASK))
|
||||
break;
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va,
|
||||
MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_FORCE_XO_ENABLE,
|
||||
0x1);
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
if (i >= ICNSS_HW_REG_RETRY)
|
||||
ICNSS_ASSERT(false);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_DISCONNECT_CLR, 0x1);
|
||||
|
||||
icnss_hw_reset_wlan_ss_power_down(priv);
|
||||
|
||||
icnss_hw_reset_common_ss_power_down(priv);
|
||||
|
||||
icnss_hw_reset_wlan_rfactrl_power_down(priv);
|
||||
|
||||
icnss_hw_reset_rf_reset_cmd(priv);
|
||||
|
||||
icnss_hw_reset_xo_disable_cmd(priv);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_FORCE_ACTIVE, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_DISCONNECT_CLR, 0);
|
||||
|
||||
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
|
||||
MPM_WCSSAON_CONFIG_WLAN_DISABLE, 1);
|
||||
|
||||
icnss_hw_poll_reg_field(priv->mem_base_va, SR_WCSSAON_SR_LSB_OFFSET,
|
||||
BIT(26), 1, 200, ICNSS_HW_REG_RETRY);
|
||||
|
||||
top_level_reset:
|
||||
icnss_hw_top_level_reset(priv);
|
||||
|
||||
icnss_pr_dbg("RESET: DONE, state: 0x%lx\n", priv->state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icnss_hw_power_on(struct icnss_priv *priv)
|
||||
|
@ -580,7 +1101,7 @@ static int icnss_hw_power_on(struct icnss_priv *priv)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
icnss_hw_release_reset(priv);
|
||||
icnss_hw_top_level_release_reset(priv);
|
||||
|
||||
return ret;
|
||||
out:
|
||||
|
@ -593,6 +1114,9 @@ static int icnss_hw_power_off(struct icnss_priv *priv)
|
|||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (test_bit(HW_ALWAYS_ON, &quirks))
|
||||
return 0;
|
||||
|
||||
icnss_pr_dbg("Power off: 0x%lx\n", priv->state);
|
||||
|
||||
spin_lock_irqsave(&priv->on_off_lock, flags);
|
||||
|
@ -1317,34 +1841,32 @@ static int icnss_driver_event_fw_ready_ind(void *data)
|
|||
|
||||
icnss_pr_info("WLAN FW is ready: 0x%lx\n", penv->state);
|
||||
|
||||
icnss_hw_power_off(penv);
|
||||
|
||||
if (!penv->pdev) {
|
||||
icnss_pr_err("Device is not ready\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* WAR required after FW ready without which CCPM init fails in firmware
|
||||
* when WLAN enable is sent to firmware
|
||||
*/
|
||||
icnss_hw_reset(penv);
|
||||
usleep_range(100, 102);
|
||||
icnss_hw_release_reset(penv);
|
||||
|
||||
if (!penv->ops || !penv->ops->probe)
|
||||
goto out;
|
||||
|
||||
icnss_hw_power_on(penv);
|
||||
|
||||
ret = penv->ops->probe(&penv->pdev->dev);
|
||||
if (ret < 0) {
|
||||
icnss_pr_err("Driver probe failed: %d\n", ret);
|
||||
goto out;
|
||||
goto out_power_off;
|
||||
}
|
||||
|
||||
set_bit(ICNSS_DRIVER_PROBED, &penv->state);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
||||
out_power_off:
|
||||
icnss_hw_power_off(penv);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue