blob: 344beb8413a3eca5346bd393d33e01de812a9eed [file] [log] [blame]
Mark Brownd1c6b4f2009-07-28 15:22:02 +01001/*
2 * wm831x-ldo.c -- LDO driver for the WM831x series
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/bitops.h>
18#include <linux/err.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <linux/regulator/driver.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Mark Brownd1c6b4f2009-07-28 15:22:02 +010023
24#include <linux/mfd/wm831x/core.h>
25#include <linux/mfd/wm831x/regulator.h>
26#include <linux/mfd/wm831x/pdata.h>
27
Mark Brownf1aba132012-03-28 21:40:20 +010028#define WM831X_LDO_MAX_NAME 9
Mark Brownd1c6b4f2009-07-28 15:22:02 +010029
30#define WM831X_LDO_CONTROL 0
31#define WM831X_LDO_ON_CONTROL 1
32#define WM831X_LDO_SLEEP_CONTROL 2
33
34#define WM831X_ALIVE_LDO_ON_CONTROL 0
35#define WM831X_ALIVE_LDO_SLEEP_CONTROL 1
36
37struct wm831x_ldo {
38 char name[WM831X_LDO_MAX_NAME];
Mark Brownf1aba132012-03-28 21:40:20 +010039 char supply_name[WM831X_LDO_MAX_NAME];
Mark Brownd1c6b4f2009-07-28 15:22:02 +010040 struct regulator_desc desc;
41 int base;
42 struct wm831x *wm831x;
43 struct regulator_dev *regulator;
44};
45
46/*
47 * Shared
48 */
49
50static int wm831x_ldo_is_enabled(struct regulator_dev *rdev)
51{
52 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
53 struct wm831x *wm831x = ldo->wm831x;
54 int mask = 1 << rdev_get_id(rdev);
55 int reg;
56
57 reg = wm831x_reg_read(wm831x, WM831X_LDO_ENABLE);
58 if (reg < 0)
59 return reg;
60
61 if (reg & mask)
62 return 1;
63 else
64 return 0;
65}
66
67static int wm831x_ldo_enable(struct regulator_dev *rdev)
68{
69 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
70 struct wm831x *wm831x = ldo->wm831x;
71 int mask = 1 << rdev_get_id(rdev);
72
73 return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, mask);
74}
75
76static int wm831x_ldo_disable(struct regulator_dev *rdev)
77{
78 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
79 struct wm831x *wm831x = ldo->wm831x;
80 int mask = 1 << rdev_get_id(rdev);
81
82 return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, 0);
83}
84
85static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
86{
87 struct wm831x_ldo *ldo = data;
88
89 regulator_notifier_call_chain(ldo->regulator,
90 REGULATOR_EVENT_UNDER_VOLTAGE,
91 NULL);
92
93 return IRQ_HANDLED;
94}
95
96/*
97 * General purpose LDOs
98 */
99
100#define WM831X_GP_LDO_SELECTOR_LOW 0xe
101#define WM831X_GP_LDO_MAX_SELECTOR 0x1f
102
103static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
104 unsigned int selector)
105{
106 /* 0.9-1.6V in 50mV steps */
107 if (selector <= WM831X_GP_LDO_SELECTOR_LOW)
108 return 900000 + (selector * 50000);
Axel Lin6085d4d2012-03-29 15:04:22 +0800109 /* 1.7-3.3V in 100mV steps */
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100110 if (selector <= WM831X_GP_LDO_MAX_SELECTOR)
111 return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW)
112 * 100000);
113 return -EINVAL;
114}
115
116static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000117 int min_uV, int max_uV,
118 unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100119{
120 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
121 struct wm831x *wm831x = ldo->wm831x;
122 int vsel, ret;
123
124 if (min_uV < 900000)
125 vsel = 0;
126 else if (min_uV < 1700000)
127 vsel = ((min_uV - 900000) / 50000);
128 else
129 vsel = ((min_uV - 1700000) / 100000)
130 + WM831X_GP_LDO_SELECTOR_LOW + 1;
131
132 ret = wm831x_gp_ldo_list_voltage(rdev, vsel);
133 if (ret < 0)
134 return ret;
135 if (ret < min_uV || ret > max_uV)
136 return -EINVAL;
137
Mark Brown3a93f2a2010-11-10 14:38:29 +0000138 *selector = vsel;
139
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100140 return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
141}
142
143static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000144 int min_uV, int max_uV,
145 unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100146{
147 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
148 int reg = ldo->base + WM831X_LDO_ON_CONTROL;
149
Mark Brown3a93f2a2010-11-10 14:38:29 +0000150 return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
151 selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100152}
153
154static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
155 int uV)
156{
157 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
158 int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000159 unsigned int selector;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100160
Mark Brown3a93f2a2010-11-10 14:38:29 +0000161 return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100162}
163
Mark Brownafb8bb82010-12-10 17:28:08 +0000164static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100165{
166 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
167 struct wm831x *wm831x = ldo->wm831x;
168 int reg = ldo->base + WM831X_LDO_ON_CONTROL;
169 int ret;
170
171 ret = wm831x_reg_read(wm831x, reg);
172 if (ret < 0)
173 return ret;
174
175 ret &= WM831X_LDO1_ON_VSEL_MASK;
176
Mark Brownafb8bb82010-12-10 17:28:08 +0000177 return ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100178}
179
180static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
181{
182 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
183 struct wm831x *wm831x = ldo->wm831x;
184 int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;
185 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
Roel Kluin9a767d42009-10-16 14:16:15 +0200186 int ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100187
188 ret = wm831x_reg_read(wm831x, on_reg);
189 if (ret < 0)
Roel Kluin9a767d42009-10-16 14:16:15 +0200190 return ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100191
192 if (!(ret & WM831X_LDO1_ON_MODE))
193 return REGULATOR_MODE_NORMAL;
194
195 ret = wm831x_reg_read(wm831x, ctrl_reg);
196 if (ret < 0)
Roel Kluin9a767d42009-10-16 14:16:15 +0200197 return ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100198
199 if (ret & WM831X_LDO1_LP_MODE)
200 return REGULATOR_MODE_STANDBY;
201 else
202 return REGULATOR_MODE_IDLE;
203}
204
205static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,
206 unsigned int mode)
207{
208 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
209 struct wm831x *wm831x = ldo->wm831x;
210 int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;
211 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
212 int ret;
213
214
215 switch (mode) {
216 case REGULATOR_MODE_NORMAL:
217 ret = wm831x_set_bits(wm831x, on_reg,
218 WM831X_LDO1_ON_MODE, 0);
219 if (ret < 0)
220 return ret;
221 break;
222
223 case REGULATOR_MODE_IDLE:
224 ret = wm831x_set_bits(wm831x, ctrl_reg,
Axel Line2609992010-09-06 16:48:13 +0800225 WM831X_LDO1_LP_MODE, 0);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100226 if (ret < 0)
227 return ret;
228
229 ret = wm831x_set_bits(wm831x, on_reg,
230 WM831X_LDO1_ON_MODE,
231 WM831X_LDO1_ON_MODE);
232 if (ret < 0)
233 return ret;
Axel Line2609992010-09-06 16:48:13 +0800234 break;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100235
236 case REGULATOR_MODE_STANDBY:
237 ret = wm831x_set_bits(wm831x, ctrl_reg,
Axel Line2609992010-09-06 16:48:13 +0800238 WM831X_LDO1_LP_MODE,
239 WM831X_LDO1_LP_MODE);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100240 if (ret < 0)
241 return ret;
242
243 ret = wm831x_set_bits(wm831x, on_reg,
244 WM831X_LDO1_ON_MODE,
245 WM831X_LDO1_ON_MODE);
246 if (ret < 0)
247 return ret;
248 break;
249
250 default:
251 return -EINVAL;
252 }
253
254 return 0;
255}
256
257static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev)
258{
259 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
260 struct wm831x *wm831x = ldo->wm831x;
261 int mask = 1 << rdev_get_id(rdev);
262 int ret;
263
264 /* Is the regulator on? */
265 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);
266 if (ret < 0)
267 return ret;
268 if (!(ret & mask))
269 return REGULATOR_STATUS_OFF;
270
271 /* Is it reporting under voltage? */
272 ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);
273 if (ret & mask)
274 return REGULATOR_STATUS_ERROR;
275
276 ret = wm831x_gp_ldo_get_mode(rdev);
277 if (ret < 0)
278 return ret;
279 else
280 return regulator_mode_to_status(ret);
281}
282
283static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
284 int input_uV,
285 int output_uV, int load_uA)
286{
287 if (load_uA < 20000)
288 return REGULATOR_MODE_STANDBY;
289 if (load_uA < 50000)
290 return REGULATOR_MODE_IDLE;
291 return REGULATOR_MODE_NORMAL;
292}
293
294
295static struct regulator_ops wm831x_gp_ldo_ops = {
296 .list_voltage = wm831x_gp_ldo_list_voltage,
Mark Brownafb8bb82010-12-10 17:28:08 +0000297 .get_voltage_sel = wm831x_gp_ldo_get_voltage_sel,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100298 .set_voltage = wm831x_gp_ldo_set_voltage,
299 .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
300 .get_mode = wm831x_gp_ldo_get_mode,
301 .set_mode = wm831x_gp_ldo_set_mode,
302 .get_status = wm831x_gp_ldo_get_status,
303 .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,
304
305 .is_enabled = wm831x_ldo_is_enabled,
306 .enable = wm831x_ldo_enable,
307 .disable = wm831x_ldo_disable,
308};
309
310static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
311{
312 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
313 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
Mark Brownc1727082012-04-04 00:50:22 +0100314 struct regulator_config config = { };
Mark Brown137a6352011-07-25 22:20:29 +0100315 int id;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100316 struct wm831x_ldo *ldo;
317 struct resource *res;
318 int ret, irq;
319
Mark Brown137a6352011-07-25 22:20:29 +0100320 if (pdata && pdata->wm831x_num)
321 id = (pdata->wm831x_num * 10) + 1;
322 else
323 id = 0;
324 id = pdev->id - id;
325
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100326 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
327
328 if (pdata == NULL || pdata->ldo[id] == NULL)
329 return -ENODEV;
330
Mark Brownfded2f42011-12-15 02:11:14 +0800331 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100332 if (ldo == NULL) {
333 dev_err(&pdev->dev, "Unable to allocate private data\n");
334 return -ENOMEM;
335 }
336
337 ldo->wm831x = wm831x;
338
339 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
340 if (res == NULL) {
341 dev_err(&pdev->dev, "No I/O resource\n");
342 ret = -EINVAL;
343 goto err;
344 }
345 ldo->base = res->start;
346
347 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
348 ldo->desc.name = ldo->name;
Mark Brownf1aba132012-03-28 21:40:20 +0100349
350 snprintf(ldo->supply_name, sizeof(ldo->supply_name),
351 "LDO%dVDD", id + 1);
352 ldo->desc.supply_name = ldo->supply_name;
353
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100354 ldo->desc.id = id;
355 ldo->desc.type = REGULATOR_VOLTAGE;
356 ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1;
357 ldo->desc.ops = &wm831x_gp_ldo_ops;
358 ldo->desc.owner = THIS_MODULE;
359
Mark Brownc1727082012-04-04 00:50:22 +0100360 config.dev = pdev->dev.parent;
361 config.init_data = pdata->ldo[id];
362 config.driver_data = ldo;
363
364 ldo->regulator = regulator_register(&ldo->desc, &config);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100365 if (IS_ERR(ldo->regulator)) {
366 ret = PTR_ERR(ldo->regulator);
367 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
368 id + 1, ret);
369 goto err;
370 }
371
372 irq = platform_get_irq_byname(pdev, "UV");
Mark Browndfda9c22011-03-01 16:50:43 +0000373 ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
374 IRQF_TRIGGER_RISING, ldo->name,
375 ldo);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100376 if (ret != 0) {
377 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
378 irq, ret);
379 goto err_regulator;
380 }
381
382 platform_set_drvdata(pdev, ldo);
383
384 return 0;
385
386err_regulator:
387 regulator_unregister(ldo->regulator);
388err:
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100389 return ret;
390}
391
392static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
393{
394 struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100395
Dmitry Torokhoveb66d562010-02-23 23:38:39 -0800396 platform_set_drvdata(pdev, NULL);
397
Mark Browndfda9c22011-03-01 16:50:43 +0000398 free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100399 regulator_unregister(ldo->regulator);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100400
401 return 0;
402}
403
404static struct platform_driver wm831x_gp_ldo_driver = {
405 .probe = wm831x_gp_ldo_probe,
406 .remove = __devexit_p(wm831x_gp_ldo_remove),
407 .driver = {
408 .name = "wm831x-ldo",
Dmitry Torokhoveb66d562010-02-23 23:38:39 -0800409 .owner = THIS_MODULE,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100410 },
411};
412
413/*
414 * Analogue LDOs
415 */
416
417
418#define WM831X_ALDO_SELECTOR_LOW 0xc
419#define WM831X_ALDO_MAX_SELECTOR 0x1f
420
421static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
422 unsigned int selector)
423{
424 /* 1-1.6V in 50mV steps */
425 if (selector <= WM831X_ALDO_SELECTOR_LOW)
426 return 1000000 + (selector * 50000);
Axel Lin6085d4d2012-03-29 15:04:22 +0800427 /* 1.7-3.5V in 100mV steps */
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100428 if (selector <= WM831X_ALDO_MAX_SELECTOR)
429 return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW)
430 * 100000);
431 return -EINVAL;
432}
433
434static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000435 int min_uV, int max_uV,
436 unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100437{
438 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
439 struct wm831x *wm831x = ldo->wm831x;
440 int vsel, ret;
441
442 if (min_uV < 1000000)
443 vsel = 0;
444 else if (min_uV < 1700000)
445 vsel = ((min_uV - 1000000) / 50000);
446 else
447 vsel = ((min_uV - 1700000) / 100000)
448 + WM831X_ALDO_SELECTOR_LOW + 1;
449
450 ret = wm831x_aldo_list_voltage(rdev, vsel);
451 if (ret < 0)
452 return ret;
453 if (ret < min_uV || ret > max_uV)
454 return -EINVAL;
455
Mark Brown3a93f2a2010-11-10 14:38:29 +0000456 *selector = vsel;
457
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100458 return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
459}
460
461static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000462 int min_uV, int max_uV, unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100463{
464 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
465 int reg = ldo->base + WM831X_LDO_ON_CONTROL;
466
Mark Brown3a93f2a2010-11-10 14:38:29 +0000467 return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
468 selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100469}
470
471static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
472 int uV)
473{
474 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
475 int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000476 unsigned int selector;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100477
Mark Brown3a93f2a2010-11-10 14:38:29 +0000478 return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100479}
480
Mark Brownafb8bb82010-12-10 17:28:08 +0000481static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100482{
483 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
484 struct wm831x *wm831x = ldo->wm831x;
485 int reg = ldo->base + WM831X_LDO_ON_CONTROL;
486 int ret;
487
488 ret = wm831x_reg_read(wm831x, reg);
489 if (ret < 0)
490 return ret;
491
492 ret &= WM831X_LDO7_ON_VSEL_MASK;
493
Mark Brownafb8bb82010-12-10 17:28:08 +0000494 return ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100495}
496
497static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
498{
499 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
500 struct wm831x *wm831x = ldo->wm831x;
501 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
Roel Kluin6f17c652009-12-15 20:07:31 +0100502 int ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100503
504 ret = wm831x_reg_read(wm831x, on_reg);
505 if (ret < 0)
506 return 0;
507
508 if (ret & WM831X_LDO7_ON_MODE)
509 return REGULATOR_MODE_IDLE;
510 else
511 return REGULATOR_MODE_NORMAL;
512}
513
514static int wm831x_aldo_set_mode(struct regulator_dev *rdev,
515 unsigned int mode)
516{
517 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
518 struct wm831x *wm831x = ldo->wm831x;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100519 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
520 int ret;
521
522
523 switch (mode) {
524 case REGULATOR_MODE_NORMAL:
Axel Line841a362012-03-29 15:02:55 +0800525 ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100526 if (ret < 0)
527 return ret;
528 break;
529
530 case REGULATOR_MODE_IDLE:
Axel Line841a362012-03-29 15:02:55 +0800531 ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100532 WM831X_LDO7_ON_MODE);
533 if (ret < 0)
534 return ret;
535 break;
536
537 default:
538 return -EINVAL;
539 }
540
541 return 0;
542}
543
544static int wm831x_aldo_get_status(struct regulator_dev *rdev)
545{
546 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
547 struct wm831x *wm831x = ldo->wm831x;
548 int mask = 1 << rdev_get_id(rdev);
549 int ret;
550
551 /* Is the regulator on? */
552 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);
553 if (ret < 0)
554 return ret;
555 if (!(ret & mask))
556 return REGULATOR_STATUS_OFF;
557
558 /* Is it reporting under voltage? */
559 ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);
560 if (ret & mask)
561 return REGULATOR_STATUS_ERROR;
562
563 ret = wm831x_aldo_get_mode(rdev);
564 if (ret < 0)
565 return ret;
566 else
567 return regulator_mode_to_status(ret);
568}
569
570static struct regulator_ops wm831x_aldo_ops = {
571 .list_voltage = wm831x_aldo_list_voltage,
Mark Brownafb8bb82010-12-10 17:28:08 +0000572 .get_voltage_sel = wm831x_aldo_get_voltage_sel,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100573 .set_voltage = wm831x_aldo_set_voltage,
574 .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
575 .get_mode = wm831x_aldo_get_mode,
576 .set_mode = wm831x_aldo_set_mode,
577 .get_status = wm831x_aldo_get_status,
578
579 .is_enabled = wm831x_ldo_is_enabled,
580 .enable = wm831x_ldo_enable,
581 .disable = wm831x_ldo_disable,
582};
583
584static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
585{
586 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
587 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
Mark Brownc1727082012-04-04 00:50:22 +0100588 struct regulator_config config = { };
Mark Brown137a6352011-07-25 22:20:29 +0100589 int id;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100590 struct wm831x_ldo *ldo;
591 struct resource *res;
592 int ret, irq;
593
Mark Brown137a6352011-07-25 22:20:29 +0100594 if (pdata && pdata->wm831x_num)
595 id = (pdata->wm831x_num * 10) + 1;
596 else
597 id = 0;
598 id = pdev->id - id;
599
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100600 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
601
602 if (pdata == NULL || pdata->ldo[id] == NULL)
603 return -ENODEV;
604
Mark Brownfded2f42011-12-15 02:11:14 +0800605 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100606 if (ldo == NULL) {
607 dev_err(&pdev->dev, "Unable to allocate private data\n");
608 return -ENOMEM;
609 }
610
611 ldo->wm831x = wm831x;
612
613 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
614 if (res == NULL) {
615 dev_err(&pdev->dev, "No I/O resource\n");
616 ret = -EINVAL;
617 goto err;
618 }
619 ldo->base = res->start;
620
621 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
622 ldo->desc.name = ldo->name;
Mark Brownf1aba132012-03-28 21:40:20 +0100623
624 snprintf(ldo->supply_name, sizeof(ldo->supply_name),
625 "LDO%dVDD", id + 1);
626 ldo->desc.supply_name = ldo->supply_name;
627
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100628 ldo->desc.id = id;
629 ldo->desc.type = REGULATOR_VOLTAGE;
630 ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1;
631 ldo->desc.ops = &wm831x_aldo_ops;
632 ldo->desc.owner = THIS_MODULE;
633
Mark Brownc1727082012-04-04 00:50:22 +0100634 config.dev = pdev->dev.parent;
635 config.init_data = pdata->ldo[id];
636 config.driver_data = ldo;
637
638 ldo->regulator = regulator_register(&ldo->desc, &config);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100639 if (IS_ERR(ldo->regulator)) {
640 ret = PTR_ERR(ldo->regulator);
641 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
642 id + 1, ret);
643 goto err;
644 }
645
646 irq = platform_get_irq_byname(pdev, "UV");
Mark Browndfda9c22011-03-01 16:50:43 +0000647 ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
648 IRQF_TRIGGER_RISING, ldo->name, ldo);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100649 if (ret != 0) {
650 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
651 irq, ret);
652 goto err_regulator;
653 }
654
655 platform_set_drvdata(pdev, ldo);
656
657 return 0;
658
659err_regulator:
660 regulator_unregister(ldo->regulator);
661err:
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100662 return ret;
663}
664
665static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
666{
667 struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100668
Mark Browndfda9c22011-03-01 16:50:43 +0000669 free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100670 regulator_unregister(ldo->regulator);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100671
672 return 0;
673}
674
675static struct platform_driver wm831x_aldo_driver = {
676 .probe = wm831x_aldo_probe,
677 .remove = __devexit_p(wm831x_aldo_remove),
678 .driver = {
679 .name = "wm831x-aldo",
Dmitry Torokhoveb66d562010-02-23 23:38:39 -0800680 .owner = THIS_MODULE,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100681 },
682};
683
684/*
685 * Alive LDO
686 */
687
688#define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
689
690static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev,
691 unsigned int selector)
692{
693 /* 0.8-1.55V in 50mV steps */
694 if (selector <= WM831X_ALIVE_LDO_MAX_SELECTOR)
695 return 800000 + (selector * 50000);
696 return -EINVAL;
697}
698
699static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
700 int reg,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000701 int min_uV, int max_uV,
702 unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100703{
704 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
705 struct wm831x *wm831x = ldo->wm831x;
706 int vsel, ret;
707
708 vsel = (min_uV - 800000) / 50000;
709
710 ret = wm831x_alive_ldo_list_voltage(rdev, vsel);
711 if (ret < 0)
712 return ret;
713 if (ret < min_uV || ret > max_uV)
714 return -EINVAL;
715
Mark Brown3a93f2a2010-11-10 14:38:29 +0000716 *selector = vsel;
717
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100718 return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
719}
720
721static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000722 int min_uV, int max_uV,
723 unsigned *selector)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100724{
725 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
726 int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
727
Mark Brown3a93f2a2010-11-10 14:38:29 +0000728 return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
729 selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100730}
731
732static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
733 int uV)
734{
735 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
736 int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000737 unsigned selector;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100738
Mark Brown3a93f2a2010-11-10 14:38:29 +0000739 return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100740}
741
Mark Brownafb8bb82010-12-10 17:28:08 +0000742static int wm831x_alive_ldo_get_voltage_sel(struct regulator_dev *rdev)
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100743{
744 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
745 struct wm831x *wm831x = ldo->wm831x;
746 int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
747 int ret;
748
749 ret = wm831x_reg_read(wm831x, reg);
750 if (ret < 0)
751 return ret;
752
753 ret &= WM831X_LDO11_ON_VSEL_MASK;
754
Mark Brownafb8bb82010-12-10 17:28:08 +0000755 return ret;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100756}
757
758static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
759{
760 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
761 struct wm831x *wm831x = ldo->wm831x;
762 int mask = 1 << rdev_get_id(rdev);
763 int ret;
764
765 /* Is the regulator on? */
766 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);
767 if (ret < 0)
768 return ret;
769 if (ret & mask)
770 return REGULATOR_STATUS_ON;
771 else
772 return REGULATOR_STATUS_OFF;
773}
774
775static struct regulator_ops wm831x_alive_ldo_ops = {
776 .list_voltage = wm831x_alive_ldo_list_voltage,
Mark Brownafb8bb82010-12-10 17:28:08 +0000777 .get_voltage_sel = wm831x_alive_ldo_get_voltage_sel,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100778 .set_voltage = wm831x_alive_ldo_set_voltage,
779 .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
780 .get_status = wm831x_alive_ldo_get_status,
781
782 .is_enabled = wm831x_ldo_is_enabled,
783 .enable = wm831x_ldo_enable,
784 .disable = wm831x_ldo_disable,
785};
786
787static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
788{
789 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
790 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
Mark Brownc1727082012-04-04 00:50:22 +0100791 struct regulator_config config = { };
Mark Brown137a6352011-07-25 22:20:29 +0100792 int id;
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100793 struct wm831x_ldo *ldo;
794 struct resource *res;
795 int ret;
796
Mark Brown137a6352011-07-25 22:20:29 +0100797 if (pdata && pdata->wm831x_num)
798 id = (pdata->wm831x_num * 10) + 1;
799 else
800 id = 0;
801 id = pdev->id - id;
802
803
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100804 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
805
806 if (pdata == NULL || pdata->ldo[id] == NULL)
807 return -ENODEV;
808
Mark Brownfded2f42011-12-15 02:11:14 +0800809 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100810 if (ldo == NULL) {
811 dev_err(&pdev->dev, "Unable to allocate private data\n");
812 return -ENOMEM;
813 }
814
815 ldo->wm831x = wm831x;
816
817 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
818 if (res == NULL) {
819 dev_err(&pdev->dev, "No I/O resource\n");
820 ret = -EINVAL;
821 goto err;
822 }
823 ldo->base = res->start;
824
825 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
826 ldo->desc.name = ldo->name;
Mark Brownf1aba132012-03-28 21:40:20 +0100827
828 snprintf(ldo->supply_name, sizeof(ldo->supply_name),
829 "LDO%dVDD", id + 1);
830 ldo->desc.supply_name = ldo->supply_name;
831
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100832 ldo->desc.id = id;
833 ldo->desc.type = REGULATOR_VOLTAGE;
834 ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1;
835 ldo->desc.ops = &wm831x_alive_ldo_ops;
836 ldo->desc.owner = THIS_MODULE;
837
Mark Brownc1727082012-04-04 00:50:22 +0100838 config.dev = pdev->dev.parent;
839 config.init_data = pdata->ldo[id];
840 config.driver_data = ldo;
841
842 ldo->regulator = regulator_register(&ldo->desc, &config);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100843 if (IS_ERR(ldo->regulator)) {
844 ret = PTR_ERR(ldo->regulator);
845 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
846 id + 1, ret);
847 goto err;
848 }
849
850 platform_set_drvdata(pdev, ldo);
851
852 return 0;
853
854err:
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100855 return ret;
856}
857
858static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
859{
860 struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
861
862 regulator_unregister(ldo->regulator);
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100863
864 return 0;
865}
866
867static struct platform_driver wm831x_alive_ldo_driver = {
868 .probe = wm831x_alive_ldo_probe,
869 .remove = __devexit_p(wm831x_alive_ldo_remove),
870 .driver = {
871 .name = "wm831x-alive-ldo",
Dmitry Torokhoveb66d562010-02-23 23:38:39 -0800872 .owner = THIS_MODULE,
Mark Brownd1c6b4f2009-07-28 15:22:02 +0100873 },
874};
875
876static int __init wm831x_ldo_init(void)
877{
878 int ret;
879
880 ret = platform_driver_register(&wm831x_gp_ldo_driver);
881 if (ret != 0)
882 pr_err("Failed to register WM831x GP LDO driver: %d\n", ret);
883
884 ret = platform_driver_register(&wm831x_aldo_driver);
885 if (ret != 0)
886 pr_err("Failed to register WM831x ALDO driver: %d\n", ret);
887
888 ret = platform_driver_register(&wm831x_alive_ldo_driver);
889 if (ret != 0)
890 pr_err("Failed to register WM831x alive LDO driver: %d\n",
891 ret);
892
893 return 0;
894}
895subsys_initcall(wm831x_ldo_init);
896
897static void __exit wm831x_ldo_exit(void)
898{
899 platform_driver_unregister(&wm831x_alive_ldo_driver);
900 platform_driver_unregister(&wm831x_aldo_driver);
901 platform_driver_unregister(&wm831x_gp_ldo_driver);
902}
903module_exit(wm831x_ldo_exit);
904
905/* Module information */
906MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
907MODULE_DESCRIPTION("WM831x LDO driver");
908MODULE_LICENSE("GPL");
909MODULE_ALIAS("platform:wm831x-ldo");
910MODULE_ALIAS("platform:wm831x-aldo");
911MODULE_ALIAS("platform:wm831x-aliveldo");