diff options
-rw-r--r-- | drivers/mfd/arizona-core.c | 43 | ||||
-rw-r--r-- | include/linux/mfd/arizona/core.h | 2 |
2 files changed, 45 insertions, 0 deletions
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index d8d30c0a488d..437f199fe5f2 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -22,6 +22,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/regulator/machine.h> #include <linux/slab.h> #include <linux/mfd/arizona/core.h> @@ -347,6 +348,17 @@ static int arizona_runtime_resume(struct device *dev) switch (arizona->type) { case WM5102: + if (arizona->external_dcvdd) { + ret = regmap_update_bits(arizona->regmap, + ARIZONA_ISOLATION_CONTROL, + ARIZONA_ISOLATE_DCVDD1, 0); + if (ret != 0) { + dev_err(arizona->dev, + "Failed to connect DCVDD: %d\n", ret); + goto err; + } + } + ret = wm5102_patch(arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to apply patch: %d\n", @@ -368,6 +380,16 @@ static int arizona_runtime_resume(struct device *dev) goto err; } + if (arizona->external_dcvdd) { + ret = regmap_update_bits(arizona->regmap, + ARIZONA_ISOLATION_CONTROL, + ARIZONA_ISOLATE_DCVDD1, 0); + if (ret != 0) { + dev_err(arizona->dev, + "Failed to connect DCVDD: %d\n", ret); + goto err; + } + } break; } @@ -400,9 +422,22 @@ err: static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); + int ret; dev_dbg(arizona->dev, "Entering AoD mode\n"); + if (arizona->external_dcvdd) { + ret = regmap_update_bits(arizona->regmap, + ARIZONA_ISOLATION_CONTROL, + ARIZONA_ISOLATE_DCVDD1, + ARIZONA_ISOLATE_DCVDD1); + if (ret != 0) { + dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", + ret); + return ret; + } + } + regulator_disable(arizona->dcvdd); regcache_cache_only(arizona->regmap, true); regcache_mark_dirty(arizona->regmap); @@ -771,6 +806,14 @@ int arizona_dev_init(struct arizona *arizona) arizona->pdata.gpio_defaults[i]); } + /* + * LDO1 can only be used to supply DCVDD so if it has no + * consumers then DCVDD is supplied externally. + */ + if (arizona->pdata.ldo1 && + arizona->pdata.ldo1->num_consumer_supplies == 0) + arizona->external_dcvdd = true; + pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_use_autosuspend(arizona->dev); pm_runtime_enable(arizona->dev); diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index cc281368dc55..f797bb9b8b56 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h @@ -95,6 +95,8 @@ struct arizona { struct arizona_pdata pdata; + unsigned int external_dcvdd:1; + int irq; struct irq_domain *virq; struct regmap_irq_chip_data *aod_irq_chip; |