cnss2: Check for BT Enable GPIO in QCA6490

QCA6490 requires synchronization between BT and WLAN enable gpio
to avoid power up issue. Update platform driver to get BT enable
GPIO config and perform delayed WLAN enable if BT is off.

Change-Id: I77e5aa87b09128dbac41b59927f88f53fa4ddebd
Signed-off-by: Manikandan Mohan <manikand@codeaurora.org>
This commit is contained in:
Manikandan Mohan 2020-09-25 22:20:04 -07:00
commit 14c829cd8c
2 changed files with 54 additions and 1 deletions

View file

@ -89,6 +89,7 @@ struct cnss_pinctrl_info {
struct pinctrl_state *bootstrap_active;
struct pinctrl_state *wlan_en_active;
struct pinctrl_state *wlan_en_sleep;
int bt_en_gpio;
};
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)

View file

@ -7,6 +7,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include <soc/qcom/cmd-db.h>
#include <linux/of_gpio.h>
#include "main.h"
#include "debug.h"
@ -41,6 +42,7 @@ static struct cnss_clk_cfg cnss_clk_list[] = {
#define BOOTSTRAP_GPIO "qcom,enable-bootstrap-gpio"
#define BOOTSTRAP_ACTIVE "bootstrap_active"
#define WLAN_EN_GPIO "wlan-en-gpio"
#define BT_EN_GPIO "qcom,bt-en-gpio"
#define WLAN_EN_ACTIVE "wlan_en_active"
#define WLAN_EN_SLEEP "wlan_en_sleep"
@ -700,6 +702,15 @@ int cnss_get_pinctrl(struct cnss_plat_data *plat_priv)
}
}
/* Added for QCA6490 PMU delayed WLAN_EN_GPIO */
if (of_find_property(dev->of_node, BT_EN_GPIO, NULL)) {
pinctrl_info->bt_en_gpio = of_get_named_gpio(dev->of_node,
BT_EN_GPIO, 0);
cnss_pr_dbg("BT GPIO: %d\n", pinctrl_info->bt_en_gpio);
} else {
pinctrl_info->bt_en_gpio = -EINVAL;
}
return 0;
out:
return ret;
@ -763,6 +774,47 @@ out:
return ret;
}
/**
* cnss_select_pinctrl_enable - select WLAN_GPIO for Active pinctrl status
* @plat_priv: Platform private data structure pointer
*
* For QCA6490, PMU requires minimum 100ms delay between BT_EN_GPIO off and
* WLAN_EN_GPIO on. This is done to avoid power up issues.
*
* Return: Status of pinctrl select operation. 0 - Success.
*/
static int cnss_select_pinctrl_enable(struct cnss_plat_data *plat_priv)
{
int ret = 0, bt_en_gpio = plat_priv->pinctrl_info.bt_en_gpio;
u8 wlan_en_state = 0;
if (bt_en_gpio < 0 || plat_priv->device_id != QCA6490_DEVICE_ID)
goto set_wlan_en;
if (gpio_get_value(bt_en_gpio)) {
cnss_pr_dbg("BT_EN_GPIO State: On\n");
ret = cnss_select_pinctrl_state(plat_priv, true);
if (!ret)
return ret;
wlan_en_state = 1;
}
if (!gpio_get_value(bt_en_gpio)) {
cnss_pr_dbg("BT_EN_GPIO State: Off. Delay WLAN_GPIO enable\n");
/* check for BT_EN_GPIO down race during above operation */
if (wlan_en_state) {
cnss_pr_dbg("Reset WLAN_EN as BT got turned off during enable\n");
cnss_select_pinctrl_state(plat_priv, false);
wlan_en_state = 0;
}
/* 100 ms delay for BT_EN and WLAN_EN QCA6490 PMU sequencing */
msleep(100);
}
set_wlan_en:
if (!wlan_en_state)
ret = cnss_select_pinctrl_state(plat_priv, true);
return ret;
}
int cnss_power_on_device(struct cnss_plat_data *plat_priv)
{
int ret = 0;
@ -784,7 +836,7 @@ int cnss_power_on_device(struct cnss_plat_data *plat_priv)
goto vreg_off;
}
ret = cnss_select_pinctrl_state(plat_priv, true);
ret = cnss_select_pinctrl_enable(plat_priv);
if (ret) {
cnss_pr_err("Failed to select pinctrl state, err = %d\n", ret);
goto clk_off;