diff --git a/cnss2/debug.c b/cnss2/debug.c index beeadbe3a9..5833ccf2d9 100644 --- a/cnss2/debug.c +++ b/cnss2/debug.c @@ -145,6 +145,9 @@ static int cnss_stats_show_state(struct seq_file *s, case CNSS_FS_READY: seq_puts(s, "FS READY"); continue; + case CNSS_DRIVER_REGISTERED: + seq_puts(s, "DRIVER REGISTERED"); + continue; } seq_printf(s, "UNKNOWN-%d", i); diff --git a/cnss2/main.c b/cnss2/main.c index 29fef131eb..d28f5b3d55 100644 --- a/cnss2/main.c +++ b/cnss2/main.c @@ -4038,11 +4038,11 @@ int cnss_wlan_hw_enable(void) struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); int ret = 0; - if (test_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state)) - return 0; - clear_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state); + if (test_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state)) + goto register_driver; + ret = cnss_wlan_device_init(plat_priv); if (ret) { CNSS_ASSERT(0); @@ -4054,6 +4054,7 @@ int cnss_wlan_hw_enable(void) CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START, 0, NULL); +register_driver: if (plat_priv->driver_ops) ret = cnss_wlan_register_driver(plat_priv->driver_ops); diff --git a/cnss2/main.h b/cnss2/main.h index c4710eba6e..e8d4bdfa11 100644 --- a/cnss2/main.h +++ b/cnss2/main.h @@ -111,6 +111,7 @@ struct cnss_pinctrl_info { struct pinctrl_state *wlan_en_active; struct pinctrl_state *wlan_en_sleep; int bt_en_gpio; + int wlan_en_gpio; int xo_clk_gpio; /*qca6490 only */ int sw_ctrl_gpio; int wlan_sw_ctrl_gpio; @@ -320,6 +321,7 @@ enum cnss_driver_state { CNSS_DRIVER_REGISTER, CNSS_WLAN_HW_DISABLED, CNSS_FS_READY = 25, + CNSS_DRIVER_REGISTERED, }; struct cnss_recovery_data { diff --git a/cnss2/pci.c b/cnss2/pci.c index c791ff8ac6..91f49acf93 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -2945,6 +2945,9 @@ static void cnss_wlan_reg_driver_work(struct work_struct *work) struct cnss_cal_info *cal_info; unsigned int timeout; + if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) + return; + if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) { goto reg_driver; } else { @@ -2993,7 +2996,7 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) { int ret = 0; struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); - struct cnss_pci_data *pci_priv; + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; const struct pci_device_id *id_table = driver_ops->id_table; unsigned int timeout; @@ -3030,8 +3033,7 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) return -EAGAIN; } - pci_priv = plat_priv->bus_priv; - if (pci_priv->driver_ops) { + if (test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state)) { cnss_pr_err("Driver has already registered\n"); return -EEXIST; } @@ -3162,6 +3164,8 @@ int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, if (ret) { clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state); pci_priv->driver_ops = NULL; + } else { + set_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state); } return ret; @@ -3174,6 +3178,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv) set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); cnss_pci_dev_shutdown(pci_priv); pci_priv->driver_ops = NULL; + clear_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state); return 0; } diff --git a/cnss2/power.c b/cnss2/power.c index 9c8e4e899c..0d7fe691dc 100644 --- a/cnss2/power.c +++ b/cnss2/power.c @@ -761,6 +761,9 @@ int cnss_get_pinctrl(struct cnss_plat_data *plat_priv) } if (of_find_property(dev->of_node, WLAN_EN_GPIO, NULL)) { + pinctrl_info->wlan_en_gpio = of_get_named_gpio(dev->of_node, + WLAN_EN_GPIO, 0); + cnss_pr_dbg("WLAN_EN GPIO: %d\n", pinctrl_info->wlan_en_gpio); pinctrl_info->wlan_en_active = pinctrl_lookup_state(pinctrl_info->pinctrl, WLAN_EN_ACTIVE); @@ -780,6 +783,8 @@ int cnss_get_pinctrl(struct cnss_plat_data *plat_priv) ret); goto out; } + } else { + pinctrl_info->wlan_en_gpio = -EINVAL; } /* Added for QCA6490 PMU delayed WLAN_EN_GPIO */ @@ -923,10 +928,18 @@ static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv, goto out; } udelay(WLAN_ENABLE_DELAY); + cnss_set_xo_clk_gpio_state(plat_priv, false); + } else { + cnss_set_xo_clk_gpio_state(plat_priv, false); + goto out; } - cnss_set_xo_clk_gpio_state(plat_priv, false); } else { if (!IS_ERR_OR_NULL(pinctrl_info->wlan_en_sleep)) { + cnss_wlan_hw_disable_check(plat_priv); + if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) { + cnss_pr_dbg("Avoid WLAN_EN low. WLAN HW Disbaled"); + goto out; + } ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->wlan_en_sleep); if (ret) { @@ -934,9 +947,12 @@ static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv, ret); goto out; } + } else { + goto out; } } + cnss_pr_dbg("WLAN_EN Value: %d\n", gpio_get_value(pinctrl_info->wlan_en_gpio)); cnss_pr_dbg("%s WLAN_EN GPIO successfully\n", state ? "Assert" : "De-assert"); @@ -1012,6 +1028,12 @@ int cnss_power_on_device(struct cnss_plat_data *plat_priv) return 0; } + cnss_wlan_hw_disable_check(plat_priv); + if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) { + cnss_pr_dbg("Avoid WLAN Power On. WLAN HW Disbaled"); + return -EINVAL; + } + ret = cnss_vreg_on_type(plat_priv, CNSS_VREG_PRIM); if (ret) { cnss_pr_err("Failed to turn on vreg, err = %d\n", ret);