aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2015-06-24 08:14:21 -0400
committerMark Brown <broonie@kernel.org>2015-07-13 06:19:28 -0400
commit4245746037e379dc9f1388e422d52001cd431921 (patch)
tree97530e94d05c03494dfbe0a8aec1f270187c1ad2
parentd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff)
regulator: da9210: Add optional interrupt support
Add optional interrupt support to the da9210 regulator driver, to handle over-current, under- and over-voltage, and over-temperature events. Only the interrupt sources for which we handle events are unmasked, to avoid interrupts we cannot handle. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/regulator/da9210.txt4
-rw-r--r--drivers/regulator/da9210-regulator.c75
2 files changed, 79 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt
index 3297c53cb915..7aa9b1fa6b21 100644
--- a/Documentation/devicetree/bindings/regulator/da9210.txt
+++ b/Documentation/devicetree/bindings/regulator/da9210.txt
@@ -5,6 +5,10 @@ Required properties:
5- compatible: must be "dlg,da9210" 5- compatible: must be "dlg,da9210"
6- reg: the i2c slave address of the regulator. It should be 0x68. 6- reg: the i2c slave address of the regulator. It should be 0x68.
7 7
8Optional properties:
9
10- interrupts: a reference to the DA9210 interrupt, if available.
11
8Any standard regulator properties can be used to configure the single da9210 12Any standard regulator properties can be used to configure the single da9210
9DCDC. 13DCDC.
10 14
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index f0489cb9018b..8e39f7457bc3 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -22,6 +22,8 @@
22#include <linux/i2c.h> 22#include <linux/i2c.h>
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
25#include <linux/slab.h> 27#include <linux/slab.h>
26#include <linux/regulator/driver.h> 28#include <linux/regulator/driver.h>
27#include <linux/regulator/machine.h> 29#include <linux/regulator/machine.h>
@@ -120,6 +122,55 @@ static int da9210_get_current_limit(struct regulator_dev *rdev)
120 return da9210_buck_limits[sel]; 122 return da9210_buck_limits[sel];
121} 123}
122 124
125static irqreturn_t da9210_irq_handler(int irq, void *data)
126{
127 struct da9210 *chip = data;
128 unsigned int val, handled = 0;
129 int error, ret = IRQ_NONE;
130
131 error = regmap_read(chip->regmap, DA9210_REG_EVENT_B, &val);
132 if (error < 0)
133 goto error_i2c;
134
135 if (val & DA9210_E_OVCURR) {
136 regulator_notifier_call_chain(chip->rdev,
137 REGULATOR_EVENT_OVER_CURRENT,
138 NULL);
139 handled |= DA9210_E_OVCURR;
140 }
141 if (val & DA9210_E_NPWRGOOD) {
142 regulator_notifier_call_chain(chip->rdev,
143 REGULATOR_EVENT_UNDER_VOLTAGE,
144 NULL);
145 handled |= DA9210_E_NPWRGOOD;
146 }
147 if (val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT)) {
148 regulator_notifier_call_chain(chip->rdev,
149 REGULATOR_EVENT_OVER_TEMP, NULL);
150 handled |= val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT);
151 }
152 if (val & DA9210_E_VMAX) {
153 regulator_notifier_call_chain(chip->rdev,
154 REGULATOR_EVENT_REGULATION_OUT,
155 NULL);
156 handled |= DA9210_E_VMAX;
157 }
158 if (handled) {
159 /* Clear handled events */
160 error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
161 if (error < 0)
162 goto error_i2c;
163
164 ret = IRQ_HANDLED;
165 }
166
167 return ret;
168
169error_i2c:
170 dev_err(regmap_get_device(chip->regmap), "I2C error : %d\n", error);
171 return ret;
172}
173
123/* 174/*
124 * I2C driver interface functions 175 * I2C driver interface functions
125 */ 176 */
@@ -168,6 +219,30 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
168 } 219 }
169 220
170 chip->rdev = rdev; 221 chip->rdev = rdev;
222 if (i2c->irq) {
223 error = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
224 da9210_irq_handler,
225 IRQF_TRIGGER_LOW |
226 IRQF_ONESHOT | IRQF_SHARED,
227 "da9210", chip);
228 if (error) {
229 dev_err(&i2c->dev, "Failed to request IRQ%u: %d\n",
230 i2c->irq, error);
231 return error;
232 }
233
234 error = regmap_update_bits(chip->regmap, DA9210_REG_MASK_B,
235 DA9210_M_OVCURR | DA9210_M_NPWRGOOD |
236 DA9210_M_TEMP_WARN |
237 DA9210_M_TEMP_CRIT | DA9210_M_VMAX, 0);
238 if (error < 0) {
239 dev_err(&i2c->dev, "Failed to update mask reg: %d\n",
240 error);
241 return error;
242 }
243 } else {
244 dev_warn(&i2c->dev, "No IRQ configured\n");
245 }
171 246
172 i2c_set_clientdata(i2c, chip); 247 i2c_set_clientdata(i2c, chip);
173 248