summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-23 19:44:16 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-20 08:13:37 -0500
commit5927467d0ca274bc3b8eed9fd5db964bbde56e1c (patch)
treefd531f890b936663a77440eaf80203ed0ac97c28
parentd781009ca6bb5b9711c74700242855e0a70ee7a3 (diff)
mfd: arizona: Support use of external DCVDD
When the device is used with an external DCVDD supply instead of the internal LDO1 then an extra step is required when suspending and resuming the device. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/mfd/arizona-core.c43
-rw-r--r--include/linux/mfd/arizona/core.h2
2 files changed, 45 insertions, 0 deletions
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index d8d30c0a488..437f199fe5f 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 cc281368dc5..f797bb9b8b5 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;