aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2014-11-24 09:10:52 -0500
committerMark Brown <broonie@kernel.org>2014-11-24 10:26:02 -0500
commita1c8a5512b7cddc81767172f0de37b155cea039f (patch)
tree23404a6a919910d9909d5261e0119748ade7e725
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
regulator: core: Add PRE_DISABLE notification
Add a PRE_DISABLE notification so that consumers can use a notifier to run any steps required to prepare for the regulator being switched off. Since the regulator disable can fail an abort notification is also added. Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/core.c16
-rw-r--r--include/linux/regulator/consumer.h4
2 files changed, 20 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index cd87c0c37034..53de911a0954 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1976,9 +1976,18 @@ static int _regulator_disable(struct regulator_dev *rdev)
1976 1976
1977 /* we are last user */ 1977 /* we are last user */
1978 if (_regulator_can_change_status(rdev)) { 1978 if (_regulator_can_change_status(rdev)) {
1979 ret = _notifier_call_chain(rdev,
1980 REGULATOR_EVENT_PRE_DISABLE,
1981 NULL);
1982 if (ret & NOTIFY_STOP_MASK)
1983 return -EINVAL;
1984
1979 ret = _regulator_do_disable(rdev); 1985 ret = _regulator_do_disable(rdev);
1980 if (ret < 0) { 1986 if (ret < 0) {
1981 rdev_err(rdev, "failed to disable\n"); 1987 rdev_err(rdev, "failed to disable\n");
1988 _notifier_call_chain(rdev,
1989 REGULATOR_EVENT_ABORT_DISABLE,
1990 NULL);
1982 return ret; 1991 return ret;
1983 } 1992 }
1984 _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 1993 _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
@@ -2035,9 +2044,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
2035{ 2044{
2036 int ret = 0; 2045 int ret = 0;
2037 2046
2047 ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
2048 REGULATOR_EVENT_PRE_DISABLE, NULL);
2049 if (ret & NOTIFY_STOP_MASK)
2050 return -EINVAL;
2051
2038 ret = _regulator_do_disable(rdev); 2052 ret = _regulator_do_disable(rdev);
2039 if (ret < 0) { 2053 if (ret < 0) {
2040 rdev_err(rdev, "failed to force disable\n"); 2054 rdev_err(rdev, "failed to force disable\n");
2055 _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
2056 REGULATOR_EVENT_ABORT_DISABLE, NULL);
2041 return ret; 2057 return ret;
2042 } 2058 }
2043 2059
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index d347c805f923..9efddd2a63ee 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -99,6 +99,8 @@ struct regmap;
99 * Data passed is "struct pre_voltage_change_data" 99 * Data passed is "struct pre_voltage_change_data"
100 * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason. 100 * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason.
101 * Data passed is old voltage cast to (void *). 101 * Data passed is old voltage cast to (void *).
102 * PRE_DISABLE Regulator is about to be disabled
103 * ABORT_DISABLE Regulator disable failed for some reason
102 * 104 *
103 * NOTE: These events can be OR'ed together when passed into handler. 105 * NOTE: These events can be OR'ed together when passed into handler.
104 */ 106 */
@@ -113,6 +115,8 @@ struct regmap;
113#define REGULATOR_EVENT_DISABLE 0x80 115#define REGULATOR_EVENT_DISABLE 0x80
114#define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 116#define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100
115#define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 117#define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200
118#define REGULATOR_EVENT_PRE_DISABLE 0x400
119#define REGULATOR_EVENT_ABORT_DISABLE 0x800
116 120
117/** 121/**
118 * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event 122 * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event