Loading Documentation/devicetree/bindings/cnss/cnss-wlan.txt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ Required properties: Optional properties: - qcom,notify-modem-status: Boolean property to decide whether modem notification should be enabled or not in this platform - wlan-soc-swreg-supply: phandle to the external 1.15V regulator for QCA6174 Example: Loading @@ -30,4 +31,5 @@ Example: wlan-en-gpio = <&msmgpio 82 0>; vdd-wlan-supply = <&wlan_vreg>; qcom,notify-modem-status; wlan-soc-swreg-supply = <&pma8084_l27>; }; drivers/net/wireless/cnss/cnss.c +111 −11 Original line number Diff line number Diff line Loading @@ -52,9 +52,13 @@ #define QCA6174_FW_3_0 (0x30) #define WLAN_VREG_NAME "vdd-wlan" #define WLAN_SWREG_NAME "wlan-soc-swreg" #define WLAN_EN_GPIO_NAME "wlan-en-gpio" #define PM_OPTIONS 0 #define SOC_SWREG_VOLT_MAX 1150000 #define SOC_SWREG_VOLT_MIN 1150000 #define POWER_ON_DELAY 2000 #define WLAN_ENABLE_DELAY 10000 Loading @@ -68,6 +72,7 @@ struct cnss_wlan_gpio_info { struct cnss_wlan_vreg_info { struct regulator *wlan_reg; struct regulator *soc_swreg; bool state; }; Loading Loading @@ -101,27 +106,87 @@ static struct cnss_data { bool notify_modem_status; } *penv; static int cnss_wlan_vreg_set(struct cnss_wlan_vreg_info *vreg_info, bool state) static int cnss_wlan_vreg_on(struct cnss_wlan_vreg_info *vreg_info) { int ret; ret = regulator_enable(vreg_info->wlan_reg); if (ret) { pr_err("%s: regulator enable failed for WLAN power\n", __func__); goto error_enable; } if (vreg_info->soc_swreg) { ret = regulator_enable(vreg_info->soc_swreg); if (ret) { pr_err("%s: regulator enable failed for external soc-swreg\n", __func__); goto error_enable2; } } return ret; error_enable2: regulator_disable(vreg_info->wlan_reg); error_enable: return ret; } static int cnss_wlan_vreg_off(struct cnss_wlan_vreg_info *vreg_info) { int ret, ret2; if (vreg_info->soc_swreg) { ret = regulator_disable(vreg_info->soc_swreg); if (ret) { pr_err("%s: regulator disable failed for external soc-swreg\n", __func__); goto error_disable; } } ret = regulator_disable(vreg_info->wlan_reg); if (ret) { pr_err("%s: regulator disable failed for WLAN power\n", __func__); goto error_disable2; } return ret; error_disable2: if (vreg_info->soc_swreg) { ret2 = regulator_enable(vreg_info->soc_swreg); if (ret2) ret = ret2; } error_disable: return ret; } static int cnss_wlan_vreg_set(struct cnss_wlan_vreg_info *vreg_info, bool state) { int ret = 0; if (vreg_info->state == state) { pr_debug("Already wlan vreg state is %s\n", state ? "enabled" : "disabled"); return 0; goto out; } if (state) ret = regulator_enable(vreg_info->wlan_reg); ret = cnss_wlan_vreg_on(vreg_info); else ret = regulator_disable(vreg_info->wlan_reg); ret = cnss_wlan_vreg_off(vreg_info); if (ret) goto out; if (!ret) { vreg_info->state = state; pr_debug("%s: wlan vreg is now %s\n", __func__, state ? "enabled" : "disabled"); } vreg_info->state = state; out: return ret; } Loading Loading @@ -195,6 +260,31 @@ static int cnss_wlan_get_resources(struct platform_device *pdev) pr_err("%s: vreg initial vote failed\n", __func__); goto err_reg_enable; } if (of_get_property(pdev->dev.of_node, WLAN_SWREG_NAME"-supply", NULL)) { vreg_info->soc_swreg = regulator_get(&pdev->dev, WLAN_SWREG_NAME); if (IS_ERR(vreg_info->soc_swreg)) { pr_err("%s: soc-swreg node not found\n", __func__); goto err_reg_get2; } ret = regulator_set_voltage(vreg_info->soc_swreg, SOC_SWREG_VOLT_MIN, SOC_SWREG_VOLT_MAX); if (ret) { pr_err("%s: vreg initial voltage set failed on soc-swreg\n", __func__); goto err_reg_set; } ret = regulator_enable(vreg_info->soc_swreg); if (ret) { pr_err("%s: vreg initial vote failed\n", __func__); goto err_reg_enable2; } } vreg_info->state = VREG_ON; if (!of_find_property((&pdev->dev)->of_node, gpio_info->name, NULL)) { Loading Loading @@ -230,14 +320,21 @@ end: err_gpio_init: err_get_gpio: regulator_disable(vreg_info->wlan_reg); if (vreg_info->soc_swreg) regulator_disable(vreg_info->soc_swreg); vreg_info->state = VREG_OFF; err_reg_enable2: err_reg_set: if (vreg_info->soc_swreg) regulator_put(vreg_info->soc_swreg); err_reg_get2: regulator_disable(vreg_info->wlan_reg); err_reg_enable: regulator_put(vreg_info->wlan_reg); err_reg_get: return ret; } Loading @@ -247,7 +344,10 @@ static void cnss_wlan_release_resources(void) struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info; gpio_free(gpio_info->num); cnss_wlan_vreg_set(vreg_info, VREG_OFF); regulator_put(vreg_info->wlan_reg); if (vreg_info->soc_swreg) regulator_put(vreg_info->soc_swreg); gpio_info->state = WLAN_EN_LOW; gpio_info->prop = false; vreg_info->state = VREG_OFF; Loading Loading
Documentation/devicetree/bindings/cnss/cnss-wlan.txt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ Required properties: Optional properties: - qcom,notify-modem-status: Boolean property to decide whether modem notification should be enabled or not in this platform - wlan-soc-swreg-supply: phandle to the external 1.15V regulator for QCA6174 Example: Loading @@ -30,4 +31,5 @@ Example: wlan-en-gpio = <&msmgpio 82 0>; vdd-wlan-supply = <&wlan_vreg>; qcom,notify-modem-status; wlan-soc-swreg-supply = <&pma8084_l27>; };
drivers/net/wireless/cnss/cnss.c +111 −11 Original line number Diff line number Diff line Loading @@ -52,9 +52,13 @@ #define QCA6174_FW_3_0 (0x30) #define WLAN_VREG_NAME "vdd-wlan" #define WLAN_SWREG_NAME "wlan-soc-swreg" #define WLAN_EN_GPIO_NAME "wlan-en-gpio" #define PM_OPTIONS 0 #define SOC_SWREG_VOLT_MAX 1150000 #define SOC_SWREG_VOLT_MIN 1150000 #define POWER_ON_DELAY 2000 #define WLAN_ENABLE_DELAY 10000 Loading @@ -68,6 +72,7 @@ struct cnss_wlan_gpio_info { struct cnss_wlan_vreg_info { struct regulator *wlan_reg; struct regulator *soc_swreg; bool state; }; Loading Loading @@ -101,27 +106,87 @@ static struct cnss_data { bool notify_modem_status; } *penv; static int cnss_wlan_vreg_set(struct cnss_wlan_vreg_info *vreg_info, bool state) static int cnss_wlan_vreg_on(struct cnss_wlan_vreg_info *vreg_info) { int ret; ret = regulator_enable(vreg_info->wlan_reg); if (ret) { pr_err("%s: regulator enable failed for WLAN power\n", __func__); goto error_enable; } if (vreg_info->soc_swreg) { ret = regulator_enable(vreg_info->soc_swreg); if (ret) { pr_err("%s: regulator enable failed for external soc-swreg\n", __func__); goto error_enable2; } } return ret; error_enable2: regulator_disable(vreg_info->wlan_reg); error_enable: return ret; } static int cnss_wlan_vreg_off(struct cnss_wlan_vreg_info *vreg_info) { int ret, ret2; if (vreg_info->soc_swreg) { ret = regulator_disable(vreg_info->soc_swreg); if (ret) { pr_err("%s: regulator disable failed for external soc-swreg\n", __func__); goto error_disable; } } ret = regulator_disable(vreg_info->wlan_reg); if (ret) { pr_err("%s: regulator disable failed for WLAN power\n", __func__); goto error_disable2; } return ret; error_disable2: if (vreg_info->soc_swreg) { ret2 = regulator_enable(vreg_info->soc_swreg); if (ret2) ret = ret2; } error_disable: return ret; } static int cnss_wlan_vreg_set(struct cnss_wlan_vreg_info *vreg_info, bool state) { int ret = 0; if (vreg_info->state == state) { pr_debug("Already wlan vreg state is %s\n", state ? "enabled" : "disabled"); return 0; goto out; } if (state) ret = regulator_enable(vreg_info->wlan_reg); ret = cnss_wlan_vreg_on(vreg_info); else ret = regulator_disable(vreg_info->wlan_reg); ret = cnss_wlan_vreg_off(vreg_info); if (ret) goto out; if (!ret) { vreg_info->state = state; pr_debug("%s: wlan vreg is now %s\n", __func__, state ? "enabled" : "disabled"); } vreg_info->state = state; out: return ret; } Loading Loading @@ -195,6 +260,31 @@ static int cnss_wlan_get_resources(struct platform_device *pdev) pr_err("%s: vreg initial vote failed\n", __func__); goto err_reg_enable; } if (of_get_property(pdev->dev.of_node, WLAN_SWREG_NAME"-supply", NULL)) { vreg_info->soc_swreg = regulator_get(&pdev->dev, WLAN_SWREG_NAME); if (IS_ERR(vreg_info->soc_swreg)) { pr_err("%s: soc-swreg node not found\n", __func__); goto err_reg_get2; } ret = regulator_set_voltage(vreg_info->soc_swreg, SOC_SWREG_VOLT_MIN, SOC_SWREG_VOLT_MAX); if (ret) { pr_err("%s: vreg initial voltage set failed on soc-swreg\n", __func__); goto err_reg_set; } ret = regulator_enable(vreg_info->soc_swreg); if (ret) { pr_err("%s: vreg initial vote failed\n", __func__); goto err_reg_enable2; } } vreg_info->state = VREG_ON; if (!of_find_property((&pdev->dev)->of_node, gpio_info->name, NULL)) { Loading Loading @@ -230,14 +320,21 @@ end: err_gpio_init: err_get_gpio: regulator_disable(vreg_info->wlan_reg); if (vreg_info->soc_swreg) regulator_disable(vreg_info->soc_swreg); vreg_info->state = VREG_OFF; err_reg_enable2: err_reg_set: if (vreg_info->soc_swreg) regulator_put(vreg_info->soc_swreg); err_reg_get2: regulator_disable(vreg_info->wlan_reg); err_reg_enable: regulator_put(vreg_info->wlan_reg); err_reg_get: return ret; } Loading @@ -247,7 +344,10 @@ static void cnss_wlan_release_resources(void) struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info; gpio_free(gpio_info->num); cnss_wlan_vreg_set(vreg_info, VREG_OFF); regulator_put(vreg_info->wlan_reg); if (vreg_info->soc_swreg) regulator_put(vreg_info->soc_swreg); gpio_info->state = WLAN_EN_LOW; gpio_info->prop = false; vreg_info->state = VREG_OFF; Loading