Commit 133df0f8 authored by Raja Mani's avatar Raja Mani Committed by Kalle Valo

ath10k: add chip and bus halt logic in ahb

Add function to perform chip halt sequence and function to halt axi
bus in ahb module. Mainly used in the scenario like driver unload.
Signed-off-by: default avatarRaja Mani <rmani@qti.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 14854bfd
...@@ -345,6 +345,119 @@ static int ath10k_ahb_release_reset(struct ath10k *ar) ...@@ -345,6 +345,119 @@ static int ath10k_ahb_release_reset(struct ath10k *ar)
return 0; return 0;
} }
static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg,
u32 haltack_reg)
{
unsigned long timeout;
u32 val;
/* Issue halt axi bus request */
val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
val |= AHB_AXI_BUS_HALT_REQ;
ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
/* Wait for axi bus halted ack */
timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT);
do {
val = ath10k_ahb_tcsr_read32(ar, haltack_reg);
if (val & AHB_AXI_BUS_HALT_ACK)
break;
mdelay(1);
} while (time_before(jiffies, timeout));
if (!(val & AHB_AXI_BUS_HALT_ACK)) {
ath10k_err(ar, "failed to halt axi bus: %d\n", val);
return;
}
ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n");
}
static void ath10k_ahb_halt_chip(struct ath10k *ar)
{
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg;
u32 val;
int ret;
if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) ||
IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||
IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||
IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||
IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");
return;
}
core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG);
switch (core_id) {
case 0:
glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG;
haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ;
haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK;
break;
case 1:
glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG;
haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ;
haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK;
break;
default:
ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n",
core_id);
return;
}
ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg);
val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
ret = reset_control_assert(ar_ahb->core_cold_rst);
if (ret)
ath10k_err(ar, "failed to assert core cold rst: %d\n", ret);
msleep(1);
ret = reset_control_assert(ar_ahb->radio_cold_rst);
if (ret)
ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret);
msleep(1);
ret = reset_control_assert(ar_ahb->radio_warm_rst);
if (ret)
ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret);
msleep(1);
ret = reset_control_assert(ar_ahb->radio_srif_rst);
if (ret)
ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret);
msleep(1);
ret = reset_control_assert(ar_ahb->cpu_init_rst);
if (ret)
ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret);
msleep(10);
/* Clear halt req and core clock disable req before
* deasserting wifi core reset.
*/
val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
val &= ~AHB_AXI_BUS_HALT_REQ;
ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
ret = reset_control_deassert(ar_ahb->core_cold_rst);
if (ret)
ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret);
ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id);
}
static int ath10k_ahb_probe(struct platform_device *pdev) static int ath10k_ahb_probe(struct platform_device *pdev)
{ {
return 0; return 0;
......
...@@ -39,6 +39,21 @@ struct ath10k_ahb { ...@@ -39,6 +39,21 @@ struct ath10k_ahb {
#ifdef CONFIG_ATH10K_AHB #ifdef CONFIG_ATH10K_AHB
#define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030
#define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000
#define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004
#define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25)
#define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000
#define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010
#define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004
#define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014
#define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */
#define AHB_AXI_BUS_HALT_REQ 1
#define AHB_AXI_BUS_HALT_ACK 1
int ath10k_ahb_init(void); int ath10k_ahb_init(void);
void ath10k_ahb_exit(void); void ath10k_ahb_exit(void);
......
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