diff options
-rw-r--r-- | Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wcnss/wcnss_vreg.c | 177 | ||||
-rw-r--r-- | drivers/net/wireless/wcnss/wcnss_wlan.c | 149 | ||||
-rw-r--r-- | include/linux/wcnss_wlan.h | 3 |
4 files changed, 176 insertions, 156 deletions
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt index 77d6bf06ee26..d0855115b6d1 100644 --- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt +++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt @@ -64,8 +64,6 @@ support for pronto hardware. to use for VBATT feature. - qcom,has-a2xb-split-reg: boolean flag to determine A2xb split timeout limit register is available or not. -- qcom,wcn-external-gpio-support: boolean flag to determine 3.3v gpio support -for pronto hardware for a target. Example: @@ -87,7 +85,6 @@ Example: gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>, <&msmgpio 39 0>, <&msmgpio 40 0>; - qcom,wcn-external-gpio-support; qcom,has-48mhz-xo; qcom,is-pronto-vt; qcom,wlan-rx-buff-count = <512>; diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c index d0a74744f70a..d94bd90f64da 100644 --- a/drivers/net/wireless/wcnss/wcnss_vreg.c +++ b/drivers/net/wireless/wcnss/wcnss_vreg.c @@ -71,23 +71,33 @@ static int is_power_on; struct vregs_info { const char * const name; + const char * const curr; + const char * const volt; int state; + bool required; struct regulator *regulator; }; /* IRIS regulators for Pronto hardware */ -static struct vregs_info iris_vregs_pronto[] = { - {"qcom,iris-vddxo", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vddrfa", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vddpa", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vdddig", VREG_NULL_CONFIG, NULL}, +static struct vregs_info iris_vregs[] = { + {"qcom,iris-vddxo", "qcom,iris-vddxo-current", + "qcom,iris-vddxo-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,iris-vddrfa", "qcom,iris-vddrfa-current", + "qcom,iris-vddrfa-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,iris-vddpa", "qcom,iris-vddpa-current", + "qcom,iris-vddpa-voltage-level", VREG_NULL_CONFIG, false, NULL}, + {"qcom,iris-vdddig", "qcom,iris-vdddig-current", + "qcom,iris-vdddig-voltage-level", VREG_NULL_CONFIG, true, NULL}, }; /* WCNSS regulators for Pronto hardware */ static struct vregs_info pronto_vregs[] = { - {"qcom,pronto-vddmx", VREG_NULL_CONFIG, NULL}, - {"qcom,pronto-vddcx", VREG_NULL_CONFIG, NULL}, - {"qcom,pronto-vddpx", VREG_NULL_CONFIG, NULL}, + {"qcom,pronto-vddmx", "qcom,pronto-vddmx-current", + "qcom,vddmx-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,pronto-vddcx", "qcom,pronto-vddcx-current", + "qcom,vddcx-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,pronto-vddpx", "qcom,pronto-vddpx-current", + "qcom,vddpx-voltage-level", VREG_NULL_CONFIG, true, NULL}, }; struct host_driver { @@ -184,6 +194,129 @@ int validate_iris_chip_id(u32 reg) } } +static void wcnss_free_regulator(void) +{ + int vreg_i; + + /* Free pronto voltage regulators from device node */ + for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) { + if (pronto_vregs[vreg_i].state) { + regulator_put(pronto_vregs[vreg_i].regulator); + pronto_vregs[vreg_i].state = VREG_NULL_CONFIG; + } + } + + /* Free IRIS voltage regulators from device node */ + for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) { + if (iris_vregs[vreg_i].state) { + regulator_put(iris_vregs[vreg_i].regulator); + iris_vregs[vreg_i].state = VREG_NULL_CONFIG; + } + } +} + +static int +wcnss_dt_parse_vreg_level(struct device *dev, int index, + const char *current_vreg_name, const char *vreg_name, + struct vregs_level *vlevel) +{ + int ret = 0; + /* array used to store nominal, low and high voltage values */ + u32 voltage_levels[3], current_vreg; + + ret = of_property_read_u32_array(dev->of_node, vreg_name, + voltage_levels, + ARRAY_SIZE(voltage_levels)); + if (ret) { + dev_err(dev, "error reading %s property\n", vreg_name); + return ret; + } + + vlevel[index].nominal_min = voltage_levels[0]; + vlevel[index].low_power_min = voltage_levels[1]; + vlevel[index].max_voltage = voltage_levels[2]; + + ret = of_property_read_u32(dev->of_node, current_vreg_name, + ¤t_vreg); + if (ret) { + dev_err(dev, "error reading %s property\n", current_vreg_name); + return ret; + } + + vlevel[index].uA_load = current_vreg; + + return ret; +} + +int +wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config, + struct device *dev) +{ + int rc, vreg_i; + + /* Parse pronto voltage regulators from device node */ + for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) { + pronto_vregs[vreg_i].regulator = + regulator_get(dev, pronto_vregs[vreg_i].name); + if (IS_ERR(pronto_vregs[vreg_i].regulator)) { + if (pronto_vregs[vreg_i].required) { + rc = PTR_ERR(pronto_vregs[vreg_i].regulator); + dev_err(dev, "regulator get of %s failed (%d)\n", + pronto_vregs[vreg_i].name, rc); + goto wcnss_vreg_get_err; + } else { + dev_dbg(dev, "Skip optional regulator configuration: %s\n", + pronto_vregs[vreg_i].name); + continue; + } + } + + pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK; + rc = wcnss_dt_parse_vreg_level(dev, vreg_i, + pronto_vregs[vreg_i].curr, + pronto_vregs[vreg_i].volt, + wlan_config->pronto_vlevel); + if (rc) { + dev_err(dev, "error reading voltage-level property\n"); + goto wcnss_vreg_get_err; + } + } + + /* Parse iris voltage regulators from device node */ + for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) { + iris_vregs[vreg_i].regulator = + regulator_get(dev, iris_vregs[vreg_i].name); + if (IS_ERR(iris_vregs[vreg_i].regulator)) { + if (iris_vregs[vreg_i].required) { + rc = PTR_ERR(iris_vregs[vreg_i].regulator); + dev_err(dev, "regulator get of %s failed (%d)\n", + iris_vregs[vreg_i].name, rc); + goto wcnss_vreg_get_err; + } else { + dev_dbg(dev, "Skip optional regulator configuration: %s\n", + iris_vregs[vreg_i].name); + continue; + } + } + + iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK; + rc = wcnss_dt_parse_vreg_level(dev, vreg_i, + iris_vregs[vreg_i].curr, + iris_vregs[vreg_i].volt, + wlan_config->iris_vlevel); + if (rc) { + dev_err(dev, "error reading voltage-level property\n"); + goto wcnss_vreg_get_err; + } + } + + return 0; + +wcnss_vreg_get_err: + wcnss_free_regulator(); + return rc; +} + void wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg) { /* Reset IRIS */ @@ -417,11 +550,6 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size, if (regulators[i].state == VREG_NULL_CONFIG) continue; - if (cfg->wcn_external_gpio_support) { - if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) - continue; - } - /* Remove PWM mode */ if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) { rc = regulator_set_load(regulators[i].regulator, 0); @@ -483,23 +611,10 @@ static int wcnss_vregs_on(struct device *dev, } for (i = 0; i < size; i++) { - if (cfg->wcn_external_gpio_support) { - if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) - continue; - } + if (regulators[i].state == VREG_NULL_CONFIG) + continue; - /* Get regulator source */ - regulators[i].regulator = - regulator_get(dev, regulators[i].name); - if (IS_ERR(regulators[i].regulator)) { - rc = PTR_ERR(regulators[i].regulator); - pr_err("regulator get of %s failed (%d)\n", - regulators[i].name, rc); - goto fail; - } - regulators[i].state |= VREG_GET_REGULATOR_MASK; reg_cnt = regulator_count_voltages(regulators[i].regulator); - /* Set voltage to nominal. Exclude swtiches e.g. LVS */ if ((voltage_level[i].nominal_min || voltage_level[i].max_voltage) && (reg_cnt > 0)) { @@ -561,8 +676,7 @@ static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type, { switch (hw_type) { case WCNSS_PRONTO_HW: - wcnss_vregs_off(iris_vregs_pronto, - ARRAY_SIZE(iris_vregs_pronto), + wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs), cfg->iris_vlevel); break; default: @@ -579,8 +693,7 @@ static int wcnss_iris_vregs_on(struct device *dev, switch (hw_type) { case WCNSS_PRONTO_HW: - ret = wcnss_vregs_on(dev, iris_vregs_pronto, - ARRAY_SIZE(iris_vregs_pronto), + ret = wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs), cfg->iris_vlevel); break; default: diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index ed56943733de..b604f61e1a05 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -64,6 +64,21 @@ #define WCNSS_CONFIG_UNSPECIFIED (-1) #define UINT32_MAX (0xFFFFFFFFU) +#define SUBSYS_NOTIF_MIN_INDEX 0 +#define SUBSYS_NOTIF_MAX_INDEX 9 +char *wcnss_subsys_notif_type[] = { + "SUBSYS_BEFORE_SHUTDOWN", + "SUBSYS_AFTER_SHUTDOWN", + "SUBSYS_BEFORE_POWERUP", + "SUBSYS_AFTER_POWERUP", + "SUBSYS_RAMDUMP_NOTIFICATION", + "SUBSYS_POWERUP_FAILURE", + "SUBSYS_PROXY_VOTE", + "SUBSYS_PROXY_UNVOTE", + "SUBSYS_SOC_RESET", + "SUBSYS_NOTIF_TYPE_COUNT" +}; + static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED; module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present"); @@ -2674,50 +2689,15 @@ static struct miscdevice wcnss_usr_ctrl = { }; static int -wcnss_dt_parse_vreg_level(struct device *dev, int index, - const char *current_vreg_name, const char *vreg_name, - struct vregs_level *vlevel) -{ - int ret = 0; - /* array used to store nominal, low and high voltage values - */ - u32 voltage_levels[3], current_vreg; - - ret = of_property_read_u32_array(dev->of_node, vreg_name, - voltage_levels, - ARRAY_SIZE(voltage_levels)); - if (ret) { - dev_err(dev, "error reading %s property\n", vreg_name); - return ret; - } - - vlevel[index].nominal_min = voltage_levels[0]; - vlevel[index].low_power_min = voltage_levels[1]; - vlevel[index].max_voltage = voltage_levels[2]; - - ret = of_property_read_u32(dev->of_node, current_vreg_name, - ¤t_vreg); - if (ret) { - dev_err(dev, "error reading %s property\n", current_vreg_name); - return ret; - } - - vlevel[index].uA_load = current_vreg; - - return ret; -} - -static int wcnss_trigger_config(struct platform_device *pdev) { int ret; - int rc, index = 0; + int rc; struct qcom_wcnss_opts *pdata; struct resource *res; int is_pronto_vadc; int is_pronto_v3; int pil_retry = 0; - struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config; struct device_node *node = (&pdev->dev)->of_node; int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw"); @@ -2729,93 +2709,14 @@ wcnss_trigger_config(struct platform_device *pdev) penv->is_a2xb_split_reg = of_property_read_bool(node, "qcom,has-a2xb-split-reg"); - wlan_cfg->wcn_external_gpio_support = - of_property_read_bool(node, "qcom,wcn-external-gpio-support"); - if (of_property_read_u32(node, "qcom,wlan-rx-buff-count", &penv->wlan_rx_buff_count)) { penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT; } - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddmx-current", - "qcom,vddmx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddcx-current", - "qcom,vddcx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddpx-current", - "qcom,vddpx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - /* assign 0 to index now onwards, index variable re used to - * represent iris regulator index - */ - index = 0; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vddxo-current", - "qcom,iris-vddxo-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vddrfa-current", - "qcom,iris-vddrfa-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - if (!wlan_cfg->wcn_external_gpio_support) { - index++; - ret = wcnss_dt_parse_vreg_level( - &pdev->dev, index, - "qcom,iris-vddpa-current", - "qcom,iris-vddpa-voltage-level", - penv->wlan_config.iris_vlevel); - if (ret) { - dev_err(&pdev->dev, - "error reading voltage-level property\n"); - goto fail; - } - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vdddig-current", - "qcom,iris-vdddig-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); + rc = wcnss_parse_voltage_regulator(&penv->wlan_config, &pdev->dev); + if (rc) { + dev_err(&pdev->dev, "Failed to parse voltage regulators\n"); goto fail; } @@ -3161,7 +3062,7 @@ wcnss_trigger_config(struct platform_device *pdev) penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss"); if (IS_ERR(penv->vadc_dev)) { - pr_err("%s: vadc get failed\n", __func__); + pr_debug("%s: vadc get failed\n", __func__); penv->vadc_dev = NULL; } else { rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt); @@ -3437,7 +3338,15 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, struct notif_data *data = (struct notif_data *)ss_handle; int ret, xo_mode; - pr_info("%s: wcnss notification event: %lu\n", __func__, code); + if (!(code >= SUBSYS_NOTIF_MIN_INDEX) && + (code <= SUBSYS_NOTIF_MAX_INDEX)) { + pr_debug("%s: Invaild subsystem notification code: %lu\n", + __func__, code); + return NOTIFY_DONE; + } + + pr_debug("%s: wcnss notification event: %lu : %s\n", + __func__, code, wcnss_subsys_notif_type[code]); if (code == SUBSYS_PROXY_VOTE) { if (pdev && pwlanconfig) { diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h index e0c47f8b06bf..bc838936d2c9 100644 --- a/include/linux/wcnss_wlan.h +++ b/include/linux/wcnss_wlan.h @@ -38,7 +38,6 @@ struct vregs_level { }; struct wcnss_wlan_config { - bool wcn_external_gpio_support; int use_48mhz_xo; int is_pronto_vadc; int is_pronto_v3; @@ -143,6 +142,8 @@ void wcnss_init_delayed_work(struct delayed_work *dwork , void *callbackptr); int wcnss_get_iris_name(char *iris_version); void wcnss_dump_stack(struct task_struct *task); void wcnss_snoc_vote(bool clk_chk_en); +int wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config, + struct device *dev); #ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE void wcnss_log_debug_regs_on_bite(void); |