diff --git a/drivers/mfd/msm-cdc-pinctrl.c b/drivers/mfd/msm-cdc-pinctrl.c index a19e3a536950..3ffd20245877 100644 --- a/drivers/mfd/msm-cdc-pinctrl.c +++ b/drivers/mfd/msm-cdc-pinctrl.c @@ -25,6 +25,7 @@ struct msm_cdc_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *pinctrl_active; struct pinctrl_state *pinctrl_sleep; + int gpio; bool state; }; @@ -53,6 +54,28 @@ static struct msm_cdc_pinctrl_info *msm_cdc_pinctrl_get_gpiodata( return gpio_data; } +/* + * msm_cdc_get_gpio_state: select pinctrl sleep state + * @np: pointer to struct device_node + * + * Returns error code for failure and GPIO value on success + */ +int msm_cdc_get_gpio_state(struct device_node *np) +{ + struct msm_cdc_pinctrl_info *gpio_data; + int value = -EINVAL; + + gpio_data = msm_cdc_pinctrl_get_gpiodata(np); + if (!gpio_data) + return value; + + if (gpio_is_valid(gpio_data->gpio)) + value = gpio_get_value_cansleep(gpio_data->gpio); + + return value; +} +EXPORT_SYMBOL(msm_cdc_get_gpio_state); + /* * msm_cdc_pinctrl_select_sleep_state: select pinctrl sleep state * @np: pointer to struct device_node @@ -165,6 +188,17 @@ static int msm_cdc_pinctrl_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: set cdc gpio sleep state fail: %d\n", __func__, ret); + gpio_data->gpio = of_get_named_gpio(pdev->dev.of_node, + "qcom,cdc-rst-n-gpio", 0); + if (gpio_is_valid(gpio_data->gpio)) { + ret = gpio_request(gpio_data->gpio, "MSM_CDC_RESET"); + if (ret) { + dev_err(&pdev->dev, "%s: Failed to request gpio %d\n", + __func__, gpio_data->gpio); + goto err_lookup_state; + } + } + dev_set_drvdata(&pdev->dev, gpio_data); return 0; diff --git a/drivers/mfd/msm-cdc-supply.c b/drivers/mfd/msm-cdc-supply.c index d553f7b3f492..bfb19de8ce89 100644 --- a/drivers/mfd/msm-cdc-supply.c +++ b/drivers/mfd/msm-cdc-supply.c @@ -202,7 +202,6 @@ int msm_cdc_release_supplies(struct device *dev, msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg, num_supplies); - for (i = 0; i < num_supplies; i++) { if (regulator_count_voltages(supplies[i].consumer) < 0) continue; @@ -210,9 +209,9 @@ int msm_cdc_release_supplies(struct device *dev, regulator_set_voltage(supplies[i].consumer, 0, cdc_vreg[i].max_uV); regulator_set_load(supplies[i].consumer, 0); + devm_regulator_put(supplies[i].consumer); + supplies[i].consumer = NULL; } - - regulator_bulk_free(num_supplies, supplies); devm_kfree(dev, supplies); return rc; diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c index 555fac10377f..a32a20e19567 100644 --- a/drivers/mfd/wcd9xxx-core.c +++ b/drivers/mfd/wcd9xxx-core.c @@ -1507,6 +1507,7 @@ static int wcd9xxx_slim_device_down(struct slim_device *sldev) wcd9xxx_irq_exit(&wcd9xxx->core_res); if (wcd9xxx->dev_down) wcd9xxx->dev_down(wcd9xxx); + wcd9xxx_reset_low(wcd9xxx->dev); return 0; } diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c index 6bfe3d5a1788..52346b551481 100644 --- a/drivers/mfd/wcd9xxx-utils.c +++ b/drivers/mfd/wcd9xxx-utils.c @@ -618,6 +618,7 @@ int wcd9xxx_reset(struct device *dev) { struct wcd9xxx *wcd9xxx; int rc; + int value; if (!dev) return -ENODEV; @@ -632,6 +633,12 @@ int wcd9xxx_reset(struct device *dev) return -EINVAL; } + value = msm_cdc_get_gpio_state(wcd9xxx->wcd_rst_np); + if (value > 0) { + wcd9xxx->avoid_cdc_rstlow = 1; + return 0; + } + rc = msm_cdc_pinctrl_select_sleep_state(wcd9xxx->wcd_rst_np); if (rc) { dev_err(dev, "%s: wcd sleep state request fail!\n", @@ -679,6 +686,11 @@ int wcd9xxx_reset_low(struct device *dev) __func__); return -EINVAL; } + if (wcd9xxx->avoid_cdc_rstlow) { + wcd9xxx->avoid_cdc_rstlow = 0; + dev_dbg(dev, "%s: avoid pull down of reset GPIO\n", __func__); + return 0; + } rc = msm_cdc_pinctrl_select_sleep_state(wcd9xxx->wcd_rst_np); if (rc) diff --git a/include/linux/mfd/msm-cdc-pinctrl.h b/include/linux/mfd/msm-cdc-pinctrl.h index 395b935b6aec..951b8d4d1ed9 100644 --- a/include/linux/mfd/msm-cdc-pinctrl.h +++ b/include/linux/mfd/msm-cdc-pinctrl.h @@ -20,6 +20,7 @@ extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *); extern int msm_cdc_pinctrl_select_active_state(struct device_node *); extern bool msm_cdc_pinctrl_get_state(struct device_node *); +extern int msm_cdc_get_gpio_state(struct device_node *); #else int msm_cdc_pinctrl_select_sleep_state(struct device_node *np) @@ -30,6 +31,11 @@ int msm_cdc_pinctrl_select_active_state(struct device_node *np) { return 0; } +int msm_cdc_get_gpio_state(struct device_node *np) +{ + return 0; +} +# #endif #endif diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h index 96937a4338a8..c56ad3afcd46 100644 --- a/include/linux/mfd/wcd9xxx/core.h +++ b/include/linux/mfd/wcd9xxx/core.h @@ -328,6 +328,7 @@ struct wcd9xxx { struct wcd9xxx_codec_type *codec_type; bool prev_pg_valid; u8 prev_pg; + u8 avoid_cdc_rstlow; struct wcd9xxx_power_region *wcd9xxx_pwr[WCD9XXX_MAX_PWR_REGIONS]; };