cnss2: Add support XO Clock selection leakage prevention

QCA6490 needs XO clock selection assert for 2ms to latch the clock
configuration before WLAN enable gpio assert. Update cnss platform
driver code to support this gpio toggling.

Change-Id: I31c48365e6b5cfbbeae849f1a9a9ee1dc44050cd
Signed-off-by: Manikandan Mohan <manikand@codeaurora.org>
This commit is contained in:
Manikandan Mohan 2020-12-03 11:14:43 -08:00
commit b3dd9f66e1
2 changed files with 50 additions and 1 deletions

View file

@ -90,6 +90,7 @@ struct cnss_pinctrl_info {
struct pinctrl_state *wlan_en_active;
struct pinctrl_state *wlan_en_sleep;
int bt_en_gpio;
int xo_clk_gpio; /*qca6490 only */
};
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)

View file

@ -43,6 +43,7 @@ static struct cnss_clk_cfg cnss_clk_list[] = {
#define BOOTSTRAP_ACTIVE "bootstrap_active"
#define WLAN_EN_GPIO "wlan-en-gpio"
#define BT_EN_GPIO "qcom,bt-en-gpio"
#define XO_CLK_GPIO "qcom,xo-clk-gpio"
#define WLAN_EN_ACTIVE "wlan_en_active"
#define WLAN_EN_SLEEP "wlan_en_sleep"
@ -711,11 +712,57 @@ int cnss_get_pinctrl(struct cnss_plat_data *plat_priv)
pinctrl_info->bt_en_gpio = -EINVAL;
}
/* Added for QCA6490 to minimize XO CLK selection leakage prevention */
if (of_find_property(dev->of_node, XO_CLK_GPIO, NULL)) {
pinctrl_info->xo_clk_gpio = of_get_named_gpio(dev->of_node,
XO_CLK_GPIO, 0);
cnss_pr_dbg("QCA6490 XO_CLK GPIO: %d\n",
pinctrl_info->xo_clk_gpio);
} else {
pinctrl_info->xo_clk_gpio = -EINVAL;
}
return 0;
out:
return ret;
}
#define CNSS_XO_CLK_RETRY_COUNT_MAX 5
static void cnss_set_xo_clk_gpio_state(struct cnss_plat_data *plat_priv,
bool enable)
{
int xo_clk_gpio = plat_priv->pinctrl_info.xo_clk_gpio, retry = 0, ret;
if (xo_clk_gpio < 0 || plat_priv->device_id != QCA6490_DEVICE_ID)
return;
retry_gpio_req:
ret = gpio_request(xo_clk_gpio, "XO_CLK_GPIO");
if (ret) {
if (retry++ < CNSS_XO_CLK_RETRY_COUNT_MAX) {
/* wait for ~(10 - 20) ms */
usleep_range(10000, 20000);
goto retry_gpio_req;
}
}
if (ret) {
cnss_pr_err("QCA6490 XO CLK Gpio request failed\n");
return;
}
if (enable) {
gpio_direction_output(xo_clk_gpio, 1);
/*XO CLK must be asserted for some time before WLAN_EN */
usleep_range(100, 200);
} else {
/* Assert XO CLK ~(2-5)ms before off for valid latch in HW */
usleep_range(2000, 5000);
gpio_direction_output(xo_clk_gpio, 0);
}
gpio_free(xo_clk_gpio);
}
static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv,
bool state)
{
@ -742,7 +789,7 @@ static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv,
}
udelay(BOOTSTRAP_DELAY);
}
cnss_set_xo_clk_gpio_state(plat_priv, true);
if (!IS_ERR_OR_NULL(pinctrl_info->wlan_en_active)) {
ret = pinctrl_select_state
(pinctrl_info->pinctrl,
@ -754,6 +801,7 @@ static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv,
}
udelay(WLAN_ENABLE_DELAY);
}
cnss_set_xo_clk_gpio_state(plat_priv, false);
} else {
if (!IS_ERR_OR_NULL(pinctrl_info->wlan_en_sleep)) {
ret = pinctrl_select_state(pinctrl_info->pinctrl,