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

Commit 8b2ff5a1 authored by Harrison Meng's avatar Harrison Meng Committed by Gerrit - the friendly Code Review server
Browse files

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 DSP’s 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: default avatarHarrison Meng <quic_hmeng@quicinc.com>
parent 757fbe88
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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;
	}
}
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+6 −0
Original line number Diff line number Diff line
@@ -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)
{
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+37 −0
Original line number Diff line number Diff line
@@ -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);