From b3dd9f66e183658aeca7b801337af53d0c2cc3ec Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Thu, 3 Dec 2020 11:14:43 -0800 Subject: [PATCH] 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 --- drivers/net/wireless/cnss2/main.h | 1 + drivers/net/wireless/cnss2/power.c | 50 +++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index a4127bb7b564..134ce317621a 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -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) diff --git a/drivers/net/wireless/cnss2/power.c b/drivers/net/wireless/cnss2/power.c index add15f9eead9..f57925d45588 100644 --- a/drivers/net/wireless/cnss2/power.c +++ b/drivers/net/wireless/cnss2/power.c @@ -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,