]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/regulator/twl4030-regulator.c
twl4030 regulator uses new get_status() op
[linux-2.6-omap-h63xx.git] / drivers / regulator / twl4030-regulator.c
1 /*
2  * twl4030-regulator.c -- support regulators in twl4030 family chips
3  *
4  * Copyright (C) 2008 David Brownell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/err.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/driver.h>
17 #include <linux/regulator/machine.h>
18 #include <linux/i2c/twl4030.h>
19
20
21 /*
22  * The TWL4030/TW5030/TPS659x0 family chips include power management, a
23  * USB OTG transceiver, an RTC, ADC, PWM, and lots more.  Some versions
24  * include an audio codec, battery charger, and more voltage regulators.
25  * These chips are often used in OMAP-based systems.
26  *
27  * This driver implements software-based resource control for various
28  * voltage regulators.  This is usually augmented with state machine
29  * based control.
30  */
31
32 struct twlreg_info {
33         /* start of regulator's PM_RECEIVER control register bank */
34         u8                      base;
35
36         /* twl4030 resource ID, for resource control state machine */
37         u8                      id;
38
39         /* voltage in mV = table[VSEL]; table_len must be a power-of-two */
40         u8                      table_len;
41         const u16               *table;
42
43         /* chip constraints on regulator behavior */
44         u16                     min_mV;
45         u16                     max_mV;
46
47         /* used by regulator core */
48         struct regulator_desc   desc;
49 };
50
51 #ifndef REGULATOR_MODE_OFF
52 #define REGULATOR_MODE_OFF 0
53 #endif
54
55
56 /* LDO control registers ... offset is from the base of its register bank.
57  * The first three registers of all power resource banks help hardware to
58  * manage the various resource groups.
59  */
60 #define VREG_GRP                0
61 #define VREG_TYPE               1
62 #define VREG_REMAP              2
63 #define VREG_DEDICATED          3       /* LDO control */
64
65
66 static inline int
67 twl4030reg_read(struct twlreg_info *info, unsigned offset)
68 {
69         u8 value;
70         int status;
71
72         status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER,
73                         &value, info->base + offset);
74         return (status < 0) ? status : value;
75 }
76
77 static inline int
78 twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value)
79 {
80         return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
81                         value, info->base + offset);
82 }
83
84 /*----------------------------------------------------------------------*/
85
86 /* generic power resource operations, which work on all regulators */
87
88 static int twl4030reg_grp(struct regulator_dev *rdev)
89 {
90         return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP);
91 }
92
93 /*
94  * Enable/disable regulators by joining/leaving the P1 (processor) group.
95  * We assume nobody else is updating the DEV_GRP registers.
96  */
97
98 #define P3_GRP          BIT(7)          /* "peripherals" */
99 #define P2_GRP          BIT(6)          /* secondary processor, modem, etc */
100 #define P1_GRP          BIT(5)          /* CPU/Linux */
101
102 static int twl4030reg_is_enabled(struct regulator_dev *rdev)
103 {
104         int     state = twl4030reg_grp(rdev);
105
106         if (state < 0)
107                 return state;
108
109         return (state & P1_GRP) != 0;
110 }
111
112 static int twl4030reg_enable(struct regulator_dev *rdev)
113 {
114         struct twlreg_info      *info = rdev_get_drvdata(rdev);
115         int                     grp;
116
117         grp = twl4030reg_read(info, VREG_GRP);
118         if (grp < 0)
119                 return grp;
120
121         grp |= P1_GRP;
122         return twl4030reg_write(info, VREG_GRP, grp);
123 }
124
125 static int twl4030reg_disable(struct regulator_dev *rdev)
126 {
127         struct twlreg_info      *info = rdev_get_drvdata(rdev);
128         int                     grp;
129
130         grp = twl4030reg_read(info, VREG_GRP);
131         if (grp < 0)
132                 return grp;
133
134         grp &= ~P1_GRP;
135         return twl4030reg_write(info, VREG_GRP, grp);
136 }
137
138 static int twl4030reg_get_status(struct regulator_dev *rdev)
139 {
140         int     state = twl4030reg_grp(rdev);
141
142         if (state < 0)
143                 return state;
144         state &= 0x0f;
145
146         /* assume state != WARM_RESET; we'd not be running...  */
147         if (!state)
148                 return REGULATOR_STATUS_OFF;
149         return (state & BIT(3))
150                 ? REGULATOR_STATUS_NORMAL
151                 : REGULATOR_STATUS_STANDBY;
152 }
153
154 static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
155 {
156         struct twlreg_info      *info = rdev_get_drvdata(rdev);
157         unsigned                message;
158         int                     status;
159
160         /* We can only set the mode through state machine commands... */
161         switch (mode) {
162         case REGULATOR_MODE_NORMAL:
163                 message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_ACTIVE);
164                 break;
165         case REGULATOR_MODE_STANDBY:
166                 message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_SLEEP);
167                 break;
168         default:
169                 return -EINVAL;
170         }
171
172         /* Ensure the resource is associated with some group */
173         status = twl4030reg_grp(rdev);
174         if (status < 0)
175                 return status;
176         if (!(status & (P3_GRP | P2_GRP | P1_GRP)))
177                 return -EACCES;
178
179         status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
180                         message >> 8, 0x15 /* PB_WORD_MSB */ );
181         if (status >= 0)
182                 return status;
183
184         return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
185                         message, 0x16 /* PB_WORD_LSB */ );
186 }
187
188 /*----------------------------------------------------------------------*/
189
190 /*
191  * Support for adjustable-voltage LDOs uses a four bit (or less) voltage
192  * select field in its control register.   We use tables indexed by VSEL
193  * to record voltages in milliVolts.  (Accuracy is about three percent.)
194  *
195  * Note that VSEL values for VAUX2 changed in twl5030 and newer silicon;
196  * currently handled by listing two slightly different VAUX2 regulators,
197  * only one of which will be configured.
198  *
199  * VSEL values documented as "TI cannot support these values" are flagged
200  * in these tables as UNSUP() values; we normally won't assign them.
201  */
202 #ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED
203 #define UNSUP_MASK      0x0000
204 #else
205 #define UNSUP_MASK      0x8000
206 #endif
207
208 #define UNSUP(x)        (UNSUP_MASK | (x))
209 #define IS_UNSUP(x)     (UNSUP_MASK & (x))
210 #define LDO_MV(x)       (~UNSUP_MASK & (x))
211
212
213 static const u16 VAUX1_VSEL_table[] = {
214         UNSUP(1500), UNSUP(1800), 2500, 2800,
215         3000, 3000, 3000, 3000,
216 };
217 static const u16 VAUX2_4030_VSEL_table[] = {
218         UNSUP(1000), UNSUP(1000), UNSUP(1200), 1300,
219         1500, 1800, UNSUP(1850), 2500,
220         UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000),
221         UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
222 };
223 static const u16 VAUX2_VSEL_table[] = {
224         1700, 1700, 1900, 1300,
225         1500, 1800, 2000, 2500,
226         2100, 2800, 2200, 2300,
227         2400, 2400, 2400, 2400,
228 };
229 static const u16 VAUX3_VSEL_table[] = {
230         1500, 1800, 2500, 2800,
231         UNSUP(3000), UNSUP(3000), UNSUP(3000), UNSUP(3000),
232 };
233 static const u16 VAUX4_VSEL_table[] = {
234         700, 1000, 1200, UNSUP(1300),
235         1500, 1800, UNSUP(1850), 2500,
236 };
237 static const u16 VMMC1_VSEL_table[] = {
238         1850, 2850, 3000, 3150,
239 };
240 static const u16 VMMC2_VSEL_table[] = {
241         UNSUP(1000), UNSUP(1000), UNSUP(1200), UNSUP(1300),
242         UNSUP(1500), UNSUP(1800), 1850, UNSUP(2500),
243         2600, 2800, 2850, 3000,
244         3150, 3150, 3150, 3150,
245 };
246 static const u16 VPLL1_VSEL_table[] = {
247         1000, 1200, 1300, 1800,
248         UNSUP(2800), UNSUP(3000), UNSUP(3000), UNSUP(3000),
249 };
250 static const u16 VPLL2_VSEL_table[] = {
251         700, 1000, 1200, 1300,
252         UNSUP(1500), 1800, UNSUP(1850), UNSUP(2500),
253         UNSUP(2600), UNSUP(2800), UNSUP(2850), UNSUP(3000),
254         UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
255 };
256 static const u16 VSIM_VSEL_table[] = {
257         UNSUP(1000), UNSUP(1200), UNSUP(1300), 1800,
258         2800, 3000, 3000, 3000,
259 };
260 static const u16 VDAC_VSEL_table[] = {
261         1200, 1300, 1800, 1800,
262 };
263
264
265 static int
266 twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
267 {
268         struct twlreg_info      *info = rdev_get_drvdata(rdev);
269         int                     vsel;
270
271         for (vsel = 0; vsel < info->table_len; vsel++) {
272                 int mV = info->table[vsel];
273                 int uV;
274
275                 if (IS_UNSUP(mV))
276                         continue;
277                 uV = LDO_MV(mV) * 1000;
278
279                 /* use the first in-range value */
280                 if (min_uV <= uV && uV <= max_uV)
281                         return twl4030reg_write(info, VREG_DEDICATED, vsel);
282         }
283
284         return -EDOM;
285 }
286
287 static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
288 {
289         struct twlreg_info      *info = rdev_get_drvdata(rdev);
290         int                     vsel = twl4030reg_read(info, VREG_DEDICATED);
291
292         if (vsel < 0)
293                 return vsel;
294
295         vsel &= info->table_len - 1;
296         return LDO_MV(info->table[vsel]) * 1000;
297 }
298
299 static struct regulator_ops twl4030ldo_ops = {
300         .set_voltage    = twl4030ldo_set_voltage,
301         .get_voltage    = twl4030ldo_get_voltage,
302
303         .enable         = twl4030reg_enable,
304         .disable        = twl4030reg_disable,
305         .is_enabled     = twl4030reg_is_enabled,
306
307         .set_mode       = twl4030reg_set_mode,
308
309         .get_status     = twl4030reg_get_status,
310 };
311
312 /*----------------------------------------------------------------------*/
313
314 /*
315  * Fixed voltage LDOs don't have a VSEL field to update.
316  */
317 static int twl4030fixed_get_voltage(struct regulator_dev *rdev)
318 {
319         struct twlreg_info      *info = rdev_get_drvdata(rdev);
320
321         return info->min_mV * 1000;
322 }
323
324 static struct regulator_ops twl4030fixed_ops = {
325         .get_voltage    = twl4030fixed_get_voltage,
326
327         .enable         = twl4030reg_enable,
328         .disable        = twl4030reg_disable,
329         .is_enabled     = twl4030reg_is_enabled,
330
331         .set_mode       = twl4030reg_set_mode,
332
333         .get_status     = twl4030reg_get_status,
334 };
335
336 /*----------------------------------------------------------------------*/
337
338 #define TWL_ADJUSTABLE_LDO(label, offset, num) { \
339         .base = offset, \
340         .id = num, \
341         .table_len = ARRAY_SIZE(label##_VSEL_table), \
342         .table = label##_VSEL_table, \
343         .desc = { \
344                 .name = #label, \
345                 .id = TWL4030_REG_##label, \
346                 .ops = &twl4030ldo_ops, \
347                 .type = REGULATOR_VOLTAGE, \
348                 .owner = THIS_MODULE, \
349                 }, \
350         }
351
352 #define TWL_FIXED_LDO(label, offset, mVolts, num) { \
353         .base = offset, \
354         .id = num, \
355         .min_mV = mVolts, \
356         .max_mV = mVolts, \
357         .desc = { \
358                 .name = #label, \
359                 .id = TWL4030_REG_##label, \
360                 .ops = &twl4030fixed_ops, \
361                 .type = REGULATOR_VOLTAGE, \
362                 .owner = THIS_MODULE, \
363                 }, \
364         }
365
366 /*
367  * We list regulators here if systems need some level of
368  * software control over them after boot.
369  */
370 static struct twlreg_info twl4030_regs[] = {
371         TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
372         TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
373         TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
374         TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
375         TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
376         TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
377         TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
378         /*
379         TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
380         TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
381         */
382         TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9),
383         TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
384         /*
385         TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
386         TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
387         TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
388         TWL_SMPS(VIO, 0x4b, 14),
389         TWL_SMPS(VDD1, 0x55, 15),
390         TWL_SMPS(VDD2, 0x63, 16),
391          */
392         TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
393         TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
394         TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
395         /* VUSBCP is managed *only* by the USB subchip */
396 };
397
398 static int twl4030reg_probe(struct platform_device *pdev)
399 {
400         int                             i;
401         struct twlreg_info              *info;
402         struct regulator_init_data      *initdata;
403         struct regulation_constraints   *c;
404         struct regulator_dev            *rdev;
405         int                             min_uV, max_uV;
406
407         for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) {
408                 if (twl4030_regs[i].desc.id != pdev->id)
409                         continue;
410                 info = twl4030_regs + i;
411                 min_uV = info->min_mV * 1000;
412                 max_uV = info->max_mV * 1000;
413                 break;
414         }
415         if (!info)
416                 return -ENODEV;
417
418         initdata = pdev->dev.platform_data;
419         if (!initdata)
420                 return -EINVAL;
421
422         /* Constrain board-specific capabilities according to what
423          * this driver and the chip itself can actually do.
424          */
425         c = &initdata->constraints;
426         if (!c->min_uV || c->min_uV < min_uV)
427                 c->min_uV = min_uV;
428         if (!c->max_uV || c->max_uV > max_uV)
429                 c->max_uV = max_uV;
430         c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
431         c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
432                                 | REGULATOR_CHANGE_MODE
433                                 | REGULATOR_CHANGE_STATUS;
434
435         rdev = regulator_register(&info->desc, &pdev->dev, info);
436         if (IS_ERR(rdev)) {
437                 dev_err(&pdev->dev, "can't register %s, %ld\n",
438                                 info->desc.name, PTR_ERR(rdev));
439                 return PTR_ERR(rdev);
440         }
441         platform_set_drvdata(pdev, rdev);
442
443         /* NOTE:  many regulators support short-circuit IRQs (presentable
444          * as REGULATOR_OVER_CURRENT notifications?) configured via:
445          *  - SC_CONFIG
446          *  - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
447          *  - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
448          *  - IT_CONFIG
449          */
450
451         return 0;
452 }
453
454 static int __devexit twl4030reg_remove(struct platform_device *pdev)
455 {
456         regulator_unregister(platform_get_drvdata(pdev));
457         return 0;
458 }
459
460 MODULE_ALIAS("platform:twl4030_reg");
461
462 static struct platform_driver twl4030reg_driver = {
463         .probe          = twl4030reg_probe,
464         .remove         = __devexit_p(twl4030reg_remove),
465         /* NOTE: short name, to work around driver model truncation of
466          * "twl4030_regulator.12" (and friends) to "twl4030_regulator.1".
467          */
468         .driver.name    = "twl4030_reg",
469         .driver.owner   = THIS_MODULE,
470 };
471
472 static int __init twl4030reg_init(void)
473 {
474         unsigned i, j;
475
476         /* determine min/max voltage constraints, taking into account
477          * whether set_voltage() will use the "unsupported" settings
478          */
479         for (i = 0; i < ARRAY_SIZE(twl4030_regs); i++) {
480                 struct twlreg_info      *info = twl4030_regs + i;
481                 const u16               *table;
482
483                 /* fixed-voltage regulators */
484                 if (!info->table_len)
485                         continue;
486
487                 /* LDO regulators: */
488                 for (j = 0, table = info->table;
489                                 j < info->table_len;
490                                 j++, table++) {
491                         u16             mV = *table;
492
493                         if (IS_UNSUP(mV))
494                                 continue;
495                         mV = LDO_MV(mV);
496
497                         if (info->min_mV == 0 || info->min_mV > mV)
498                                 info->min_mV = mV;
499                         if (info->max_mV < mV)
500                                 info->max_mV = mV;
501                 }
502         }
503
504         return platform_driver_register(&twl4030reg_driver);
505 }
506 subsys_initcall(twl4030reg_init);
507
508 static void __exit twl4030reg_exit(void)
509 {
510         platform_driver_unregister(&twl4030reg_driver);
511 }
512 module_exit(twl4030reg_exit)
513
514 MODULE_DESCRIPTION("TWL4030 regulator driver");
515 MODULE_LICENSE("GPL");