diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-09-15 12:54:53 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-09-20 08:02:09 -0400 |
commit | 523d9cfbb2094e095ff08a01c4eac10cc7d287c3 (patch) | |
tree | d1cd9bc2434332e2e79170d6c21d443f2ce5c3ff /drivers | |
parent | 92afb286d744511f51a05f8acb6c111d05737617 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/wm831x-core.c | 11 | ||||
-rw-r--r-- | drivers/mfd/wm831x-i2c.c | 8 | ||||
-rw-r--r-- | drivers/mfd/wm831x-spi.c | 8 |
3 files changed, 27 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 | ||
1927 | void 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 | } | ||
1934 | EXPORT_SYMBOL_GPL(wm831x_device_shutdown); | ||
1935 | |||
1925 | MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC"); | 1936 | MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC"); |
1926 | MODULE_LICENSE("GPL"); | 1937 | MODULE_LICENSE("GPL"); |
1927 | MODULE_AUTHOR("Mark Brown"); | 1938 | MODULE_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 | ||
68 | static 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 | |||
68 | static const struct i2c_device_id wm831x_i2c_id[] = { | 75 | static 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 | ||
71 | static 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 | |||
71 | static const struct dev_pm_ops wm831x_spi_pm = { | 78 | static 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 | ||
100 | static int __init wm831x_spi_init(void) | 108 | static int __init wm831x_spi_init(void) |