aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-15 12:54:53 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-20 08:02:09 -0400
commit523d9cfbb2094e095ff08a01c4eac10cc7d287c3 (patch)
treed1cd9bc2434332e2e79170d6c21d443f2ce5c3ff
parent92afb286d744511f51a05f8acb6c111d05737617 (diff)
mfd: Support software initiated shutdown of WM831x PMICs
In systems where there is no hardware signal from the processor to the PMIC to initiate the final power off sequence we must initiate the shutdown with a register write to the PMIC. Support such systems in the driver. Since this may prevent a full shutdown of the system platform data is used to enable the feature. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/wm831x-core.c11
-rw-r--r--drivers/mfd/wm831x-i2c.c8
-rw-r--r--drivers/mfd/wm831x-spi.c8
-rw-r--r--include/linux/mfd/wm831x/core.h3
-rw-r--r--include/linux/mfd/wm831x/pdata.h3
5 files changed, 33 insertions, 0 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 9338f8dcbb83..e758c89ac5bb 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -25,6 +25,7 @@
25#include <linux/mfd/wm831x/irq.h> 25#include <linux/mfd/wm831x/irq.h>
26#include <linux/mfd/wm831x/auxadc.h> 26#include <linux/mfd/wm831x/auxadc.h>
27#include <linux/mfd/wm831x/otp.h> 27#include <linux/mfd/wm831x/otp.h>
28#include <linux/mfd/wm831x/pmu.h>
28#include <linux/mfd/wm831x/regulator.h> 29#include <linux/mfd/wm831x/regulator.h>
29 30
30/* Current settings - values are 2*2^(reg_val/4) microamps. These are 31/* Current settings - values are 2*2^(reg_val/4) microamps. These are
@@ -1621,6 +1622,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1621 mutex_init(&wm831x->io_lock); 1622 mutex_init(&wm831x->io_lock);
1622 mutex_init(&wm831x->key_lock); 1623 mutex_init(&wm831x->key_lock);
1623 dev_set_drvdata(wm831x->dev, wm831x); 1624 dev_set_drvdata(wm831x->dev, wm831x);
1625 wm831x->soft_shutdown = pdata->soft_shutdown;
1624 1626
1625 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); 1627 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
1626 if (ret < 0) { 1628 if (ret < 0) {
@@ -1922,6 +1924,15 @@ int wm831x_device_suspend(struct wm831x *wm831x)
1922 return 0; 1924 return 0;
1923} 1925}
1924 1926
1927void wm831x_device_shutdown(struct wm831x *wm831x)
1928{
1929 if (wm831x->soft_shutdown) {
1930 dev_info(wm831x->dev, "Initiating shutdown...\n");
1931 wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON, 0);
1932 }
1933}
1934EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
1935
1925MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC"); 1936MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
1926MODULE_LICENSE("GPL"); 1937MODULE_LICENSE("GPL");
1927MODULE_AUTHOR("Mark Brown"); 1938MODULE_AUTHOR("Mark Brown");
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index 3ec6085d5fc0..ac8da1d439da 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -65,6 +65,13 @@ static int wm831x_i2c_suspend(struct device *dev)
65 return wm831x_device_suspend(wm831x); 65 return wm831x_device_suspend(wm831x);
66} 66}
67 67
68static void wm831x_i2c_shutdown(struct i2c_client *i2c)
69{
70 struct wm831x *wm831x = i2c_get_clientdata(i2c);
71
72 wm831x_device_shutdown(wm831x);
73}
74
68static const struct i2c_device_id wm831x_i2c_id[] = { 75static const struct i2c_device_id wm831x_i2c_id[] = {
69 { "wm8310", WM8310 }, 76 { "wm8310", WM8310 },
70 { "wm8311", WM8311 }, 77 { "wm8311", WM8311 },
@@ -89,6 +96,7 @@ static struct i2c_driver wm831x_i2c_driver = {
89 }, 96 },
90 .probe = wm831x_i2c_probe, 97 .probe = wm831x_i2c_probe,
91 .remove = wm831x_i2c_remove, 98 .remove = wm831x_i2c_remove,
99 .shutdown = wm831x_i2c_shutdown,
92 .id_table = wm831x_i2c_id, 100 .id_table = wm831x_i2c_id,
93}; 101};
94 102
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 5ea60cd860fc..8d6a9a969dbc 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -68,6 +68,13 @@ static int wm831x_spi_suspend(struct device *dev)
68 return wm831x_device_suspend(wm831x); 68 return wm831x_device_suspend(wm831x);
69} 69}
70 70
71static void wm831x_spi_shutdown(struct spi_device *spi)
72{
73 struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
74
75 wm831x_device_shutdown(wm831x);
76}
77
71static const struct dev_pm_ops wm831x_spi_pm = { 78static const struct dev_pm_ops wm831x_spi_pm = {
72 .freeze = wm831x_spi_suspend, 79 .freeze = wm831x_spi_suspend,
73 .suspend = wm831x_spi_suspend, 80 .suspend = wm831x_spi_suspend,
@@ -95,6 +102,7 @@ static struct spi_driver wm831x_spi_driver = {
95 .id_table = wm831x_spi_ids, 102 .id_table = wm831x_spi_ids,
96 .probe = wm831x_spi_probe, 103 .probe = wm831x_spi_probe,
97 .remove = __devexit_p(wm831x_spi_remove), 104 .remove = __devexit_p(wm831x_spi_remove),
105 .shutdown = wm831x_spi_shutdown,
98}; 106};
99 107
100static int __init wm831x_spi_init(void) 108static int __init wm831x_spi_init(void)
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 44acdb25681b..ed8fe0d04097 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -371,6 +371,8 @@ struct wm831x {
371 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ 371 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
372 int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ 372 int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
373 373
374 bool soft_shutdown;
375
374 /* Chip revision based flags */ 376 /* Chip revision based flags */
375 unsigned has_gpio_ena:1; /* Has GPIO enable bit */ 377 unsigned has_gpio_ena:1; /* Has GPIO enable bit */
376 unsigned has_cs_sts:1; /* Has current sink status bit */ 378 unsigned has_cs_sts:1; /* Has current sink status bit */
@@ -409,6 +411,7 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
409int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq); 411int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
410void wm831x_device_exit(struct wm831x *wm831x); 412void wm831x_device_exit(struct wm831x *wm831x);
411int wm831x_device_suspend(struct wm831x *wm831x); 413int wm831x_device_suspend(struct wm831x *wm831x);
414void wm831x_device_shutdown(struct wm831x *wm831x);
412int wm831x_irq_init(struct wm831x *wm831x, int irq); 415int wm831x_irq_init(struct wm831x *wm831x, int irq);
413void wm831x_irq_exit(struct wm831x *wm831x); 416void wm831x_irq_exit(struct wm831x *wm831x);
414void wm831x_auxadc_init(struct wm831x *wm831x); 417void wm831x_auxadc_init(struct wm831x *wm831x);
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index 0ba24599fe51..1d7a3f7b3b5d 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -123,6 +123,9 @@ struct wm831x_pdata {
123 /** Disable the touchscreen */ 123 /** Disable the touchscreen */
124 bool disable_touch; 124 bool disable_touch;
125 125
126 /** The driver should initiate a power off sequence during shutdown */
127 bool soft_shutdown;
128
126 int irq_base; 129 int irq_base;
127 int gpio_base; 130 int gpio_base;
128 int gpio_defaults[WM831X_GPIO_NUM]; 131 int gpio_defaults[WM831X_GPIO_NUM];