mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
cnss2: Control the power on/off wlan device for PCIe switch platform
CNSS driver controls the power on/off wlan device. because on CPE platform the link/power status of RC<->USP may be still on when wlan device is turning on/off, this may cause uncorrectable AER error on DSP side, to avoid this issue DSPs downstream link should be disabled before power on/off wlan device, and re-enabled after wlan power on, and also wait for link training of DSP<->WLAN to complete. Change-Id: Iaca103850d5ffc717a2a8bc40d16358e03c0c9db Signed-off-by: Harrison Meng <quic_hmeng@quicinc.com>
This commit is contained in:
parent
757fbe8895
commit
8b2ff5a1ed
5 changed files with 64 additions and 0 deletions
|
|
@ -621,3 +621,20 @@ bool cnss_bus_is_smmu_s1_enabled(struct cnss_plat_data *plat_priv)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dsp_link_control(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dsp_link_control(plat_priv->bus_priv,
|
||||
link_enable);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,4 +72,6 @@ int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
|
|||
u32 *user_base_data,
|
||||
u32 *base_vector);
|
||||
bool cnss_bus_is_smmu_s1_enabled(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dsp_link_control(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable);
|
||||
#endif /* _CNSS_BUS_H */
|
||||
|
|
|
|||
|
|
@ -612,6 +612,12 @@ static int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv,
|
|||
{
|
||||
return msm_pcie_reg_dump(pci_priv->pci_dev, buf, len);
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
return msm_pcie_dsp_link_control(pci_priv->pci_dev, link_enable);
|
||||
}
|
||||
#else
|
||||
static int _cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -262,4 +262,6 @@ int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
|
|||
u32 *user_base_data,
|
||||
u32 *base_vector);
|
||||
bool cnss_pci_is_smmu_s1_enabled(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable);
|
||||
#endif /* _CNSS_PCI_H */
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ static struct cnss_clk_cfg cnss_clk_list[] = {
|
|||
#define MAX_TCS_CMD_NUM 5
|
||||
#define BT_CXMX_VOLTAGE_MV 950
|
||||
|
||||
#define DSP_LINK_ENABLE_DELAY_TIME_US_MIN (25000)
|
||||
#define DSP_LINK_ENABLE_DELAY_TIME_US_MAX (25100)
|
||||
#define DSP_LINK_ENABLE_RETRY_COUNT_MAX (3)
|
||||
|
||||
static int cnss_get_vreg_single(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_vreg_info *vreg)
|
||||
{
|
||||
|
|
@ -975,12 +979,20 @@ int cnss_gpio_get_value(struct cnss_plat_data *plat_priv, int gpio_num)
|
|||
int cnss_power_on_device(struct cnss_plat_data *plat_priv, bool reset)
|
||||
{
|
||||
int ret = 0;
|
||||
bool dsp_link_disabled = false;
|
||||
int retry_count = 0;
|
||||
|
||||
if (plat_priv->powered_on) {
|
||||
cnss_pr_dbg("Already powered up");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (plat_priv->bus_priv &&
|
||||
(plat_priv->bus_type == CNSS_BUS_PCI)) {
|
||||
cnss_bus_dsp_link_control(plat_priv, false);
|
||||
dsp_link_disabled = true;
|
||||
}
|
||||
|
||||
ret = cnss_vreg_on_type(plat_priv, CNSS_VREG_PRIM);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to turn on vreg, err = %d\n", ret);
|
||||
|
|
@ -1016,6 +1028,26 @@ int cnss_power_on_device(struct cnss_plat_data *plat_priv, bool reset)
|
|||
goto clk_off;
|
||||
}
|
||||
|
||||
while (dsp_link_disabled &&
|
||||
(retry_count++ < DSP_LINK_ENABLE_RETRY_COUNT_MAX)) {
|
||||
ret = cnss_bus_dsp_link_control(plat_priv, true);
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
cnss_bus_dsp_link_control(plat_priv, false);
|
||||
cnss_pr_err("DSP<->WLAN link train failed, retry...\n");
|
||||
cnss_select_pinctrl_state(plat_priv, false);
|
||||
usleep_range(DSP_LINK_ENABLE_DELAY_TIME_US_MIN,
|
||||
DSP_LINK_ENABLE_DELAY_TIME_US_MAX);
|
||||
ret = cnss_select_pinctrl_enable(plat_priv);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to select pinctrl state, err = %d\n", ret);
|
||||
goto clk_off;
|
||||
}
|
||||
usleep_range(DSP_LINK_ENABLE_DELAY_TIME_US_MIN,
|
||||
DSP_LINK_ENABLE_DELAY_TIME_US_MAX);
|
||||
}
|
||||
|
||||
plat_priv->powered_on = true;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1035,6 +1067,11 @@ void cnss_power_off_device(struct cnss_plat_data *plat_priv)
|
|||
return;
|
||||
}
|
||||
|
||||
if (plat_priv->bus_priv &&
|
||||
(plat_priv->bus_type == CNSS_BUS_PCI)) {
|
||||
cnss_bus_dsp_link_control(plat_priv, false);
|
||||
}
|
||||
|
||||
cnss_select_pinctrl_state(plat_priv, false);
|
||||
cnss_clk_off(plat_priv, &plat_priv->clk_list);
|
||||
cnss_vreg_off_type(plat_priv, CNSS_VREG_PRIM);
|
||||
|
|
|
|||
Loading…
Reference in a new issue