blob: e7b89e704af671aeabe8ff193022af8048fbd0bc [file] [log] [blame]
Mark Brownda091552008-10-10 15:58:15 +01001/*
2 * wm8350.c -- Voltage and current regulation for the Wolfson WM8350 PMIC
3 *
4 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Liam Girdwood
7 * linux@wolfsonmicro.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/bitops.h>
19#include <linux/err.h>
20#include <linux/i2c.h>
21#include <linux/mfd/wm8350/core.h>
22#include <linux/mfd/wm8350/pmic.h>
23#include <linux/platform_device.h>
24#include <linux/regulator/driver.h>
25#include <linux/regulator/machine.h>
26
Mark Brown221a7c72009-03-02 16:32:47 +000027/* Maximum value possible for VSEL */
28#define WM8350_DCDC_MAX_VSEL 0x66
29
Mark Brownda091552008-10-10 15:58:15 +010030/* Microamps */
31static const int isink_cur[] = {
32 4,
33 5,
34 6,
35 7,
36 8,
37 10,
38 11,
39 14,
40 16,
41 19,
42 23,
43 27,
44 32,
45 39,
46 46,
47 54,
48 65,
49 77,
50 92,
51 109,
52 130,
53 154,
54 183,
55 218,
56 259,
57 308,
58 367,
59 436,
60 518,
61 616,
62 733,
63 872,
64 1037,
65 1233,
66 1466,
67 1744,
68 2073,
69 2466,
70 2933,
71 3487,
72 4147,
73 4932,
74 5865,
75 6975,
76 8294,
77 9864,
78 11730,
79 13949,
80 16589,
81 19728,
82 23460,
83 27899,
84 33178,
85 39455,
86 46920,
87 55798,
88 66355,
89 78910,
90 93840,
91 111596,
92 132710,
93 157820,
94 187681,
95 223191
96};
97
98static int get_isink_val(int min_uA, int max_uA, u16 *setting)
99{
100 int i;
101
102 for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
103 if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
104 *setting = i;
105 return 0;
106 }
107 }
108 return -EINVAL;
109}
110
111static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
112{
113 if (val < 16)
114 return (val * 50) + 900;
115 else
116 return ((val - 16) * 100) + 1800;
117
118}
119
120static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
121{
122 if (mV < 1800)
123 return (mV - 900) / 50;
124 else
125 return ((mV - 1800) / 100) + 16;
126}
127
128static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
129{
130 return (val * 25) + 850;
131}
132
133static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
134{
135 return (mV - 850) / 25;
136}
137
138static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
139 int max_uA)
140{
141 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
142 int isink = rdev_get_id(rdev);
143 u16 val, setting;
144 int ret;
145
146 ret = get_isink_val(min_uA, max_uA, &setting);
147 if (ret != 0)
148 return ret;
149
150 switch (isink) {
151 case WM8350_ISINK_A:
152 val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
153 ~WM8350_CS1_ISEL_MASK;
154 wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_A,
155 val | setting);
156 break;
157 case WM8350_ISINK_B:
158 val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
159 ~WM8350_CS1_ISEL_MASK;
160 wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_B,
161 val | setting);
162 break;
163 default:
164 return -EINVAL;
165 }
166
167 return 0;
168}
169
170static int wm8350_isink_get_current(struct regulator_dev *rdev)
171{
172 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
173 int isink = rdev_get_id(rdev);
174 u16 val;
175
176 switch (isink) {
177 case WM8350_ISINK_A:
178 val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
179 WM8350_CS1_ISEL_MASK;
180 break;
181 case WM8350_ISINK_B:
182 val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
183 WM8350_CS1_ISEL_MASK;
184 break;
185 default:
186 return 0;
187 }
188
189 return (isink_cur[val] + 50) / 100;
190}
191
192/* turn on ISINK followed by DCDC */
193static int wm8350_isink_enable(struct regulator_dev *rdev)
194{
195 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
196 int isink = rdev_get_id(rdev);
197
198 switch (isink) {
199 case WM8350_ISINK_A:
200 switch (wm8350->pmic.isink_A_dcdc) {
201 case WM8350_DCDC_2:
202 case WM8350_DCDC_5:
203 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
204 WM8350_CS1_ENA);
205 wm8350_set_bits(wm8350, WM8350_CSA_FLASH_CONTROL,
206 WM8350_CS1_DRIVE);
207 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
208 1 << (wm8350->pmic.isink_A_dcdc -
209 WM8350_DCDC_1));
210 break;
211 default:
212 return -EINVAL;
213 }
214 break;
215 case WM8350_ISINK_B:
216 switch (wm8350->pmic.isink_B_dcdc) {
217 case WM8350_DCDC_2:
218 case WM8350_DCDC_5:
219 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
220 WM8350_CS2_ENA);
221 wm8350_set_bits(wm8350, WM8350_CSB_FLASH_CONTROL,
222 WM8350_CS2_DRIVE);
223 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
224 1 << (wm8350->pmic.isink_B_dcdc -
225 WM8350_DCDC_1));
226 break;
227 default:
228 return -EINVAL;
229 }
230 break;
231 default:
232 return -EINVAL;
233 }
234 return 0;
235}
236
237static int wm8350_isink_disable(struct regulator_dev *rdev)
238{
239 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
240 int isink = rdev_get_id(rdev);
241
242 switch (isink) {
243 case WM8350_ISINK_A:
244 switch (wm8350->pmic.isink_A_dcdc) {
245 case WM8350_DCDC_2:
246 case WM8350_DCDC_5:
247 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
248 1 << (wm8350->pmic.isink_A_dcdc -
249 WM8350_DCDC_1));
250 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
251 WM8350_CS1_ENA);
252 break;
253 default:
254 return -EINVAL;
255 }
256 break;
257 case WM8350_ISINK_B:
258 switch (wm8350->pmic.isink_B_dcdc) {
259 case WM8350_DCDC_2:
260 case WM8350_DCDC_5:
261 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
262 1 << (wm8350->pmic.isink_B_dcdc -
263 WM8350_DCDC_1));
264 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
265 WM8350_CS2_ENA);
266 break;
267 default:
268 return -EINVAL;
269 }
270 break;
271 default:
272 return -EINVAL;
273 }
274 return 0;
275}
276
277static int wm8350_isink_is_enabled(struct regulator_dev *rdev)
278{
279 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
280 int isink = rdev_get_id(rdev);
281
282 switch (isink) {
283 case WM8350_ISINK_A:
284 return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
285 0x8000;
286 case WM8350_ISINK_B:
287 return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
288 0x8000;
289 }
290 return -EINVAL;
291}
292
293int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
294 u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
295 u16 drive)
296{
297 switch (isink) {
298 case WM8350_ISINK_A:
299 wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL,
300 (mode ? WM8350_CS1_FLASH_MODE : 0) |
301 (trigger ? WM8350_CS1_TRIGSRC : 0) |
302 duration | on_ramp | off_ramp | drive);
303 break;
304 case WM8350_ISINK_B:
305 wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL,
306 (mode ? WM8350_CS2_FLASH_MODE : 0) |
307 (trigger ? WM8350_CS2_TRIGSRC : 0) |
308 duration | on_ramp | off_ramp | drive);
309 break;
310 default:
311 return -EINVAL;
312 }
313 return 0;
314}
315EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
316
317static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
318 int max_uV)
319{
320 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
321 int volt_reg, dcdc = rdev_get_id(rdev), mV,
322 min_mV = min_uV / 1000, max_mV = max_uV / 1000;
323 u16 val;
324
325 if (min_mV < 850 || min_mV > 4025)
326 return -EINVAL;
327 if (max_mV < 850 || max_mV > 4025)
328 return -EINVAL;
329
330 /* step size is 25mV */
331 mV = (min_mV - 826) / 25;
332 if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
333 return -EINVAL;
334 BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
335
336 switch (dcdc) {
337 case WM8350_DCDC_1:
338 volt_reg = WM8350_DCDC1_CONTROL;
339 break;
340 case WM8350_DCDC_3:
341 volt_reg = WM8350_DCDC3_CONTROL;
342 break;
343 case WM8350_DCDC_4:
344 volt_reg = WM8350_DCDC4_CONTROL;
345 break;
346 case WM8350_DCDC_6:
347 volt_reg = WM8350_DCDC6_CONTROL;
348 break;
349 case WM8350_DCDC_2:
350 case WM8350_DCDC_5:
351 default:
352 return -EINVAL;
353 }
354
355 /* all DCDCs have same mV bits */
356 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
357 wm8350_reg_write(wm8350, volt_reg, val | mV);
358 return 0;
359}
360
361static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
362{
363 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
364 int volt_reg, dcdc = rdev_get_id(rdev);
365 u16 val;
366
367 switch (dcdc) {
368 case WM8350_DCDC_1:
369 volt_reg = WM8350_DCDC1_CONTROL;
370 break;
371 case WM8350_DCDC_3:
372 volt_reg = WM8350_DCDC3_CONTROL;
373 break;
374 case WM8350_DCDC_4:
375 volt_reg = WM8350_DCDC4_CONTROL;
376 break;
377 case WM8350_DCDC_6:
378 volt_reg = WM8350_DCDC6_CONTROL;
379 break;
380 case WM8350_DCDC_2:
381 case WM8350_DCDC_5:
382 default:
383 return -EINVAL;
384 }
385
386 /* all DCDCs have same mV bits */
387 val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
388 return wm8350_dcdc_val_to_mvolts(val) * 1000;
389}
390
Mark Brown221a7c72009-03-02 16:32:47 +0000391static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
392 unsigned selector)
393{
394 if (selector > WM8350_DCDC_MAX_VSEL)
395 return -EINVAL;
396 return wm8350_dcdc_val_to_mvolts(selector) * 1000;
397}
398
Mark Brownda091552008-10-10 15:58:15 +0100399static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
400{
401 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
402 int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
403 u16 val;
404
405 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
406
407 if (mV && (mV < 850 || mV > 4025)) {
408 dev_err(wm8350->dev,
409 "DCDC%d suspend voltage %d mV out of range\n",
410 dcdc, mV);
411 return -EINVAL;
412 }
413 if (mV == 0)
414 mV = 850;
415
416 switch (dcdc) {
417 case WM8350_DCDC_1:
418 volt_reg = WM8350_DCDC1_LOW_POWER;
419 break;
420 case WM8350_DCDC_3:
421 volt_reg = WM8350_DCDC3_LOW_POWER;
422 break;
423 case WM8350_DCDC_4:
424 volt_reg = WM8350_DCDC4_LOW_POWER;
425 break;
426 case WM8350_DCDC_6:
427 volt_reg = WM8350_DCDC6_LOW_POWER;
428 break;
429 case WM8350_DCDC_2:
430 case WM8350_DCDC_5:
431 default:
432 return -EINVAL;
433 }
434
435 /* all DCDCs have same mV bits */
436 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
437 wm8350_reg_write(wm8350, volt_reg,
438 val | wm8350_dcdc_mvolts_to_val(mV));
439 return 0;
440}
441
442static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
443{
444 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
445 int dcdc = rdev_get_id(rdev);
446 u16 val;
447
448 switch (dcdc) {
449 case WM8350_DCDC_1:
450 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
451 & ~WM8350_DCDC_HIB_MODE_MASK;
452 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
453 wm8350->pmic.dcdc1_hib_mode);
454 break;
455 case WM8350_DCDC_3:
456 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
457 & ~WM8350_DCDC_HIB_MODE_MASK;
458 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
459 wm8350->pmic.dcdc3_hib_mode);
460 break;
461 case WM8350_DCDC_4:
462 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
463 & ~WM8350_DCDC_HIB_MODE_MASK;
464 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
465 wm8350->pmic.dcdc4_hib_mode);
466 break;
467 case WM8350_DCDC_6:
468 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
469 & ~WM8350_DCDC_HIB_MODE_MASK;
470 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
471 wm8350->pmic.dcdc6_hib_mode);
472 break;
473 case WM8350_DCDC_2:
474 case WM8350_DCDC_5:
475 default:
476 return -EINVAL;
477 }
478
479 return 0;
480}
481
482static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
483{
484 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
485 int dcdc = rdev_get_id(rdev);
486 u16 val;
487
488 switch (dcdc) {
489 case WM8350_DCDC_1:
490 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
491 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
492 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
493 WM8350_DCDC_HIB_MODE_DIS);
494 break;
495 case WM8350_DCDC_3:
496 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
497 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
498 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
499 WM8350_DCDC_HIB_MODE_DIS);
500 break;
501 case WM8350_DCDC_4:
502 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
503 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
504 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
505 WM8350_DCDC_HIB_MODE_DIS);
506 break;
507 case WM8350_DCDC_6:
508 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
509 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
510 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
511 WM8350_DCDC_HIB_MODE_DIS);
512 break;
513 case WM8350_DCDC_2:
514 case WM8350_DCDC_5:
515 default:
516 return -EINVAL;
517 }
518
519 return 0;
520}
521
522static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
523{
524 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
525 int dcdc = rdev_get_id(rdev);
526 u16 val;
527
528 switch (dcdc) {
529 case WM8350_DCDC_2:
530 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
531 & ~WM8350_DC2_HIB_MODE_MASK;
532 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
533 WM8350_DC2_HIB_MODE_ACTIVE);
534 break;
535 case WM8350_DCDC_5:
536 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
537 & ~WM8350_DC2_HIB_MODE_MASK;
538 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
539 WM8350_DC5_HIB_MODE_ACTIVE);
540 break;
541 default:
542 return -EINVAL;
543 }
544 return 0;
545}
546
547static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
548{
549 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
550 int dcdc = rdev_get_id(rdev);
551 u16 val;
552
553 switch (dcdc) {
554 case WM8350_DCDC_2:
555 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
556 & ~WM8350_DC2_HIB_MODE_MASK;
557 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
558 WM8350_DC2_HIB_MODE_DISABLE);
559 break;
560 case WM8350_DCDC_5:
561 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
562 & ~WM8350_DC2_HIB_MODE_MASK;
563 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
564 WM8350_DC2_HIB_MODE_DISABLE);
565 break;
566 default:
567 return -EINVAL;
568 }
569 return 0;
570}
571
572static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
573 unsigned int mode)
574{
575 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
576 int dcdc = rdev_get_id(rdev);
577 u16 *hib_mode;
578
579 switch (dcdc) {
580 case WM8350_DCDC_1:
581 hib_mode = &wm8350->pmic.dcdc1_hib_mode;
582 break;
583 case WM8350_DCDC_3:
584 hib_mode = &wm8350->pmic.dcdc3_hib_mode;
585 break;
586 case WM8350_DCDC_4:
587 hib_mode = &wm8350->pmic.dcdc4_hib_mode;
588 break;
589 case WM8350_DCDC_6:
590 hib_mode = &wm8350->pmic.dcdc6_hib_mode;
591 break;
592 case WM8350_DCDC_2:
593 case WM8350_DCDC_5:
594 default:
595 return -EINVAL;
596 }
597
598 switch (mode) {
599 case REGULATOR_MODE_NORMAL:
600 *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
601 break;
602 case REGULATOR_MODE_IDLE:
603 *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
604 break;
605 case REGULATOR_MODE_STANDBY:
606 *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
607 break;
608 default:
609 return -EINVAL;
610 }
611
612 return 0;
613}
614
615static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
616{
617 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
618 int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
619 u16 val;
620
621 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
622
623 if (mV < 900 || mV > 3300) {
624 dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
625 ldo, mV);
626 return -EINVAL;
627 }
628
629 switch (ldo) {
630 case WM8350_LDO_1:
631 volt_reg = WM8350_LDO1_LOW_POWER;
632 break;
633 case WM8350_LDO_2:
634 volt_reg = WM8350_LDO2_LOW_POWER;
635 break;
636 case WM8350_LDO_3:
637 volt_reg = WM8350_LDO3_LOW_POWER;
638 break;
639 case WM8350_LDO_4:
640 volt_reg = WM8350_LDO4_LOW_POWER;
641 break;
642 default:
643 return -EINVAL;
644 }
645
646 /* all LDOs have same mV bits */
647 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
648 wm8350_reg_write(wm8350, volt_reg,
649 val | wm8350_ldo_mvolts_to_val(mV));
650 return 0;
651}
652
653static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
654{
655 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
656 int volt_reg, ldo = rdev_get_id(rdev);
657 u16 val;
658
659 switch (ldo) {
660 case WM8350_LDO_1:
661 volt_reg = WM8350_LDO1_LOW_POWER;
662 break;
663 case WM8350_LDO_2:
664 volt_reg = WM8350_LDO2_LOW_POWER;
665 break;
666 case WM8350_LDO_3:
667 volt_reg = WM8350_LDO3_LOW_POWER;
668 break;
669 case WM8350_LDO_4:
670 volt_reg = WM8350_LDO4_LOW_POWER;
671 break;
672 default:
673 return -EINVAL;
674 }
675
676 /* all LDOs have same mV bits */
677 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
678 wm8350_reg_write(wm8350, volt_reg, val);
679 return 0;
680}
681
682static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
683{
684 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
685 int volt_reg, ldo = rdev_get_id(rdev);
686 u16 val;
687
688 switch (ldo) {
689 case WM8350_LDO_1:
690 volt_reg = WM8350_LDO1_LOW_POWER;
691 break;
692 case WM8350_LDO_2:
693 volt_reg = WM8350_LDO2_LOW_POWER;
694 break;
695 case WM8350_LDO_3:
696 volt_reg = WM8350_LDO3_LOW_POWER;
697 break;
698 case WM8350_LDO_4:
699 volt_reg = WM8350_LDO4_LOW_POWER;
700 break;
701 default:
702 return -EINVAL;
703 }
704
705 /* all LDOs have same mV bits */
706 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
707 wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
708 return 0;
709}
710
711static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
712 int max_uV)
713{
714 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
715 int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
716 max_mV = max_uV / 1000;
717 u16 val;
718
719 if (min_mV < 900 || min_mV > 3300)
720 return -EINVAL;
721 if (max_mV < 900 || max_mV > 3300)
722 return -EINVAL;
723
724 if (min_mV < 1800) {
725 /* step size is 50mV < 1800mV */
726 mV = (min_mV - 851) / 50;
727 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
728 return -EINVAL;
729 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
730 } else {
731 /* step size is 100mV > 1800mV */
732 mV = ((min_mV - 1701) / 100) + 16;
733 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
734 return -EINVAL;
735 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
736 }
737
738 switch (ldo) {
739 case WM8350_LDO_1:
740 volt_reg = WM8350_LDO1_CONTROL;
741 break;
742 case WM8350_LDO_2:
743 volt_reg = WM8350_LDO2_CONTROL;
744 break;
745 case WM8350_LDO_3:
746 volt_reg = WM8350_LDO3_CONTROL;
747 break;
748 case WM8350_LDO_4:
749 volt_reg = WM8350_LDO4_CONTROL;
750 break;
751 default:
752 return -EINVAL;
753 }
754
755 /* all LDOs have same mV bits */
756 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
757 wm8350_reg_write(wm8350, volt_reg, val | mV);
758 return 0;
759}
760
761static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
762{
763 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
764 int volt_reg, ldo = rdev_get_id(rdev);
765 u16 val;
766
767 switch (ldo) {
768 case WM8350_LDO_1:
769 volt_reg = WM8350_LDO1_CONTROL;
770 break;
771 case WM8350_LDO_2:
772 volt_reg = WM8350_LDO2_CONTROL;
773 break;
774 case WM8350_LDO_3:
775 volt_reg = WM8350_LDO3_CONTROL;
776 break;
777 case WM8350_LDO_4:
778 volt_reg = WM8350_LDO4_CONTROL;
779 break;
780 default:
781 return -EINVAL;
782 }
783
784 /* all LDOs have same mV bits */
785 val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
786 return wm8350_ldo_val_to_mvolts(val) * 1000;
787}
788
Mark Brown221a7c72009-03-02 16:32:47 +0000789static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
790 unsigned selector)
791{
792 if (selector > WM8350_LDO1_VSEL_MASK)
793 return -EINVAL;
794 return wm8350_ldo_val_to_mvolts(selector) * 1000;
795}
796
Mark Brownda091552008-10-10 15:58:15 +0100797int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
798 u16 stop, u16 fault)
799{
800 int slot_reg;
801 u16 val;
802
803 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
804 __func__, dcdc, start, stop);
805
806 /* slot valid ? */
807 if (start > 15 || stop > 15)
808 return -EINVAL;
809
810 switch (dcdc) {
811 case WM8350_DCDC_1:
812 slot_reg = WM8350_DCDC1_TIMEOUTS;
813 break;
814 case WM8350_DCDC_2:
815 slot_reg = WM8350_DCDC2_TIMEOUTS;
816 break;
817 case WM8350_DCDC_3:
818 slot_reg = WM8350_DCDC3_TIMEOUTS;
819 break;
820 case WM8350_DCDC_4:
821 slot_reg = WM8350_DCDC4_TIMEOUTS;
822 break;
823 case WM8350_DCDC_5:
824 slot_reg = WM8350_DCDC5_TIMEOUTS;
825 break;
826 case WM8350_DCDC_6:
827 slot_reg = WM8350_DCDC6_TIMEOUTS;
828 break;
829 default:
830 return -EINVAL;
831 }
832
833 val = wm8350_reg_read(wm8350, slot_reg) &
834 ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
835 WM8350_DC1_ERRACT_MASK);
836 wm8350_reg_write(wm8350, slot_reg,
837 val | (start << WM8350_DC1_ENSLOT_SHIFT) |
838 (stop << WM8350_DC1_SDSLOT_SHIFT) |
839 (fault << WM8350_DC1_ERRACT_SHIFT));
840
841 return 0;
842}
843EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
844
845int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
846{
847 int slot_reg;
848 u16 val;
849
850 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
851 __func__, ldo, start, stop);
852
853 /* slot valid ? */
854 if (start > 15 || stop > 15)
855 return -EINVAL;
856
857 switch (ldo) {
858 case WM8350_LDO_1:
859 slot_reg = WM8350_LDO1_TIMEOUTS;
860 break;
861 case WM8350_LDO_2:
862 slot_reg = WM8350_LDO2_TIMEOUTS;
863 break;
864 case WM8350_LDO_3:
865 slot_reg = WM8350_LDO3_TIMEOUTS;
866 break;
867 case WM8350_LDO_4:
868 slot_reg = WM8350_LDO4_TIMEOUTS;
869 break;
870 default:
871 return -EINVAL;
872 }
873
874 val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
875 wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
876 return 0;
877}
878EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
879
880int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
881 u16 ilim, u16 ramp, u16 feedback)
882{
883 u16 val;
884
885 dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
886 mode ? "normal" : "boost", ilim ? "low" : "normal");
887
888 switch (dcdc) {
889 case WM8350_DCDC_2:
890 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
891 & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
892 WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
893 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
894 (mode << WM8350_DC2_MODE_SHIFT) |
895 (ilim << WM8350_DC2_ILIM_SHIFT) |
896 (ramp << WM8350_DC2_RMP_SHIFT) |
897 (feedback << WM8350_DC2_FBSRC_SHIFT));
898 break;
899 case WM8350_DCDC_5:
900 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
901 & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
902 WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
903 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
904 (mode << WM8350_DC5_MODE_SHIFT) |
905 (ilim << WM8350_DC5_ILIM_SHIFT) |
906 (ramp << WM8350_DC5_RMP_SHIFT) |
907 (feedback << WM8350_DC5_FBSRC_SHIFT));
908 break;
909 default:
910 return -EINVAL;
911 }
912
913 return 0;
914}
915EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
916
917static int wm8350_dcdc_enable(struct regulator_dev *rdev)
918{
919 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
920 int dcdc = rdev_get_id(rdev);
921 u16 shift;
922
923 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
924 return -EINVAL;
925
926 shift = dcdc - WM8350_DCDC_1;
927 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
928 return 0;
929}
930
931static int wm8350_dcdc_disable(struct regulator_dev *rdev)
932{
933 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
934 int dcdc = rdev_get_id(rdev);
935 u16 shift;
936
937 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
938 return -EINVAL;
939
940 shift = dcdc - WM8350_DCDC_1;
941 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
942
943 return 0;
944}
945
946static int wm8350_ldo_enable(struct regulator_dev *rdev)
947{
948 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
949 int ldo = rdev_get_id(rdev);
950 u16 shift;
951
952 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
953 return -EINVAL;
954
955 shift = (ldo - WM8350_LDO_1) + 8;
956 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
957 return 0;
958}
959
960static int wm8350_ldo_disable(struct regulator_dev *rdev)
961{
962 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
963 int ldo = rdev_get_id(rdev);
964 u16 shift;
965
966 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
967 return -EINVAL;
968
969 shift = (ldo - WM8350_LDO_1) + 8;
970 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
971 return 0;
972}
973
974static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
975{
976 int reg = 0, ret;
977
978 switch (dcdc) {
979 case WM8350_DCDC_1:
980 reg = WM8350_DCDC1_FORCE_PWM;
981 break;
982 case WM8350_DCDC_3:
983 reg = WM8350_DCDC3_FORCE_PWM;
984 break;
985 case WM8350_DCDC_4:
986 reg = WM8350_DCDC4_FORCE_PWM;
987 break;
988 case WM8350_DCDC_6:
989 reg = WM8350_DCDC6_FORCE_PWM;
990 break;
991 default:
992 return -EINVAL;
993 }
994
995 if (enable)
996 ret = wm8350_set_bits(wm8350, reg,
997 WM8350_DCDC1_FORCE_PWM_ENA);
998 else
999 ret = wm8350_clear_bits(wm8350, reg,
1000 WM8350_DCDC1_FORCE_PWM_ENA);
1001 return ret;
1002}
1003
1004static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
1005{
1006 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1007 int dcdc = rdev_get_id(rdev);
1008 u16 val;
1009
1010 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
1011 return -EINVAL;
1012
1013 if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
1014 return -EINVAL;
1015
1016 val = 1 << (dcdc - WM8350_DCDC_1);
1017
1018 switch (mode) {
1019 case REGULATOR_MODE_FAST:
1020 /* force continuous mode */
1021 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1022 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1023 force_continuous_enable(wm8350, dcdc, 1);
1024 break;
1025 case REGULATOR_MODE_NORMAL:
1026 /* active / pulse skipping */
1027 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1028 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1029 force_continuous_enable(wm8350, dcdc, 0);
1030 break;
1031 case REGULATOR_MODE_IDLE:
1032 /* standby mode */
1033 force_continuous_enable(wm8350, dcdc, 0);
1034 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1035 wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1036 break;
1037 case REGULATOR_MODE_STANDBY:
1038 /* LDO mode */
1039 force_continuous_enable(wm8350, dcdc, 0);
1040 wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1041 break;
1042 }
1043
1044 return 0;
1045}
1046
1047static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
1048{
1049 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1050 int dcdc = rdev_get_id(rdev);
1051 u16 mask, sleep, active, force;
1052 int mode = REGULATOR_MODE_NORMAL;
Mark Brown33f301a2009-02-26 19:24:20 +00001053 int reg;
Mark Brownda091552008-10-10 15:58:15 +01001054
Mark Brown33f301a2009-02-26 19:24:20 +00001055 switch (dcdc) {
1056 case WM8350_DCDC_1:
1057 reg = WM8350_DCDC1_FORCE_PWM;
1058 break;
1059 case WM8350_DCDC_3:
1060 reg = WM8350_DCDC3_FORCE_PWM;
1061 break;
1062 case WM8350_DCDC_4:
1063 reg = WM8350_DCDC4_FORCE_PWM;
1064 break;
1065 case WM8350_DCDC_6:
1066 reg = WM8350_DCDC6_FORCE_PWM;
1067 break;
1068 default:
Mark Brownda091552008-10-10 15:58:15 +01001069 return -EINVAL;
Mark Brown33f301a2009-02-26 19:24:20 +00001070 }
Mark Brownda091552008-10-10 15:58:15 +01001071
1072 mask = 1 << (dcdc - WM8350_DCDC_1);
1073 active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +00001074 force = wm8350_reg_read(wm8350, reg) & WM8350_DCDC1_FORCE_PWM_ENA;
Mark Brownda091552008-10-10 15:58:15 +01001075 sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +00001076
Mark Brownda091552008-10-10 15:58:15 +01001077 dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
1078 mask, active, sleep, force);
1079
1080 if (active && !sleep) {
1081 if (force)
1082 mode = REGULATOR_MODE_FAST;
1083 else
1084 mode = REGULATOR_MODE_NORMAL;
1085 } else if (!active && !sleep)
1086 mode = REGULATOR_MODE_IDLE;
1087 else if (!sleep)
1088 mode = REGULATOR_MODE_STANDBY;
1089
1090 return mode;
1091}
1092
1093static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
1094{
1095 return REGULATOR_MODE_NORMAL;
1096}
1097
1098struct wm8350_dcdc_efficiency {
1099 int uA_load_min;
1100 int uA_load_max;
1101 unsigned int mode;
1102};
1103
1104static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
1105 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
1106 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
1107 {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
1108 {-1, -1, REGULATOR_MODE_NORMAL},
1109};
1110
1111static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
1112 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
1113 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
1114 {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
1115 {-1, -1, REGULATOR_MODE_NORMAL},
1116};
1117
1118static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
1119{
1120 int i = 0;
1121
1122 while (eff[i].uA_load_min != -1) {
1123 if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
1124 return eff[i].mode;
1125 }
1126 return REGULATOR_MODE_NORMAL;
1127}
1128
1129/* Query the regulator for it's most efficient mode @ uV,uA
1130 * WM8350 regulator efficiency is pretty similar over
1131 * different input and output uV.
1132 */
1133static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
1134 int input_uV, int output_uV,
1135 int output_uA)
1136{
1137 int dcdc = rdev_get_id(rdev), mode;
1138
1139 switch (dcdc) {
1140 case WM8350_DCDC_1:
1141 case WM8350_DCDC_6:
1142 mode = get_mode(output_uA, dcdc1_6_efficiency);
1143 break;
1144 case WM8350_DCDC_3:
1145 case WM8350_DCDC_4:
1146 mode = get_mode(output_uA, dcdc3_4_efficiency);
1147 break;
1148 default:
1149 mode = REGULATOR_MODE_NORMAL;
1150 break;
1151 }
1152 return mode;
1153}
1154
1155static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
1156{
1157 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1158 int dcdc = rdev_get_id(rdev), shift;
1159
1160 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
1161 return -EINVAL;
1162
1163 shift = dcdc - WM8350_DCDC_1;
1164 return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
1165 & (1 << shift);
1166}
1167
1168static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
1169{
1170 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1171 int ldo = rdev_get_id(rdev), shift;
1172
1173 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
1174 return -EINVAL;
1175
1176 shift = (ldo - WM8350_LDO_1) + 8;
1177 return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
1178 & (1 << shift);
1179}
1180
1181static struct regulator_ops wm8350_dcdc_ops = {
1182 .set_voltage = wm8350_dcdc_set_voltage,
1183 .get_voltage = wm8350_dcdc_get_voltage,
Mark Brown221a7c72009-03-02 16:32:47 +00001184 .list_voltage = wm8350_dcdc_list_voltage,
Mark Brownda091552008-10-10 15:58:15 +01001185 .enable = wm8350_dcdc_enable,
1186 .disable = wm8350_dcdc_disable,
1187 .get_mode = wm8350_dcdc_get_mode,
1188 .set_mode = wm8350_dcdc_set_mode,
1189 .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
1190 .is_enabled = wm8350_dcdc_is_enabled,
1191 .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
1192 .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
1193 .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
1194 .set_suspend_mode = wm8350_dcdc_set_suspend_mode,
1195};
1196
1197static struct regulator_ops wm8350_dcdc2_5_ops = {
1198 .enable = wm8350_dcdc_enable,
1199 .disable = wm8350_dcdc_disable,
1200 .is_enabled = wm8350_dcdc_is_enabled,
1201 .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
1202 .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
1203};
1204
1205static struct regulator_ops wm8350_ldo_ops = {
1206 .set_voltage = wm8350_ldo_set_voltage,
1207 .get_voltage = wm8350_ldo_get_voltage,
Mark Brown221a7c72009-03-02 16:32:47 +00001208 .list_voltage = wm8350_ldo_list_voltage,
Mark Brownda091552008-10-10 15:58:15 +01001209 .enable = wm8350_ldo_enable,
1210 .disable = wm8350_ldo_disable,
1211 .is_enabled = wm8350_ldo_is_enabled,
1212 .get_mode = wm8350_ldo_get_mode,
1213 .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
1214 .set_suspend_enable = wm8350_ldo_set_suspend_enable,
1215 .set_suspend_disable = wm8350_ldo_set_suspend_disable,
1216};
1217
1218static struct regulator_ops wm8350_isink_ops = {
1219 .set_current_limit = wm8350_isink_set_current,
1220 .get_current_limit = wm8350_isink_get_current,
1221 .enable = wm8350_isink_enable,
1222 .disable = wm8350_isink_disable,
1223 .is_enabled = wm8350_isink_is_enabled,
1224};
1225
1226static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
1227 {
1228 .name = "DCDC1",
1229 .id = WM8350_DCDC_1,
1230 .ops = &wm8350_dcdc_ops,
1231 .irq = WM8350_IRQ_UV_DC1,
1232 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001233 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001234 .owner = THIS_MODULE,
1235 },
1236 {
1237 .name = "DCDC2",
1238 .id = WM8350_DCDC_2,
1239 .ops = &wm8350_dcdc2_5_ops,
1240 .irq = WM8350_IRQ_UV_DC2,
1241 .type = REGULATOR_VOLTAGE,
1242 .owner = THIS_MODULE,
1243 },
1244 {
1245 .name = "DCDC3",
1246 .id = WM8350_DCDC_3,
1247 .ops = &wm8350_dcdc_ops,
1248 .irq = WM8350_IRQ_UV_DC3,
1249 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001250 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001251 .owner = THIS_MODULE,
1252 },
1253 {
1254 .name = "DCDC4",
1255 .id = WM8350_DCDC_4,
1256 .ops = &wm8350_dcdc_ops,
1257 .irq = WM8350_IRQ_UV_DC4,
1258 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001259 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001260 .owner = THIS_MODULE,
1261 },
1262 {
1263 .name = "DCDC5",
1264 .id = WM8350_DCDC_5,
1265 .ops = &wm8350_dcdc2_5_ops,
1266 .irq = WM8350_IRQ_UV_DC5,
1267 .type = REGULATOR_VOLTAGE,
1268 .owner = THIS_MODULE,
1269 },
1270 {
1271 .name = "DCDC6",
1272 .id = WM8350_DCDC_6,
1273 .ops = &wm8350_dcdc_ops,
1274 .irq = WM8350_IRQ_UV_DC6,
1275 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001276 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001277 .owner = THIS_MODULE,
1278 },
1279 {
1280 .name = "LDO1",
1281 .id = WM8350_LDO_1,
1282 .ops = &wm8350_ldo_ops,
1283 .irq = WM8350_IRQ_UV_LDO1,
1284 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001285 .n_voltages = WM8350_LDO1_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001286 .owner = THIS_MODULE,
1287 },
1288 {
1289 .name = "LDO2",
1290 .id = WM8350_LDO_2,
1291 .ops = &wm8350_ldo_ops,
1292 .irq = WM8350_IRQ_UV_LDO2,
1293 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001294 .n_voltages = WM8350_LDO2_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001295 .owner = THIS_MODULE,
1296 },
1297 {
1298 .name = "LDO3",
1299 .id = WM8350_LDO_3,
1300 .ops = &wm8350_ldo_ops,
1301 .irq = WM8350_IRQ_UV_LDO3,
1302 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001303 .n_voltages = WM8350_LDO3_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001304 .owner = THIS_MODULE,
1305 },
1306 {
1307 .name = "LDO4",
1308 .id = WM8350_LDO_4,
1309 .ops = &wm8350_ldo_ops,
1310 .irq = WM8350_IRQ_UV_LDO4,
1311 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001312 .n_voltages = WM8350_LDO4_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001313 .owner = THIS_MODULE,
1314 },
1315 {
1316 .name = "ISINKA",
1317 .id = WM8350_ISINK_A,
1318 .ops = &wm8350_isink_ops,
1319 .irq = WM8350_IRQ_CS1,
1320 .type = REGULATOR_CURRENT,
1321 .owner = THIS_MODULE,
1322 },
1323 {
1324 .name = "ISINKB",
1325 .id = WM8350_ISINK_B,
1326 .ops = &wm8350_isink_ops,
1327 .irq = WM8350_IRQ_CS2,
1328 .type = REGULATOR_CURRENT,
1329 .owner = THIS_MODULE,
1330 },
1331};
1332
Mark Brown5a65edb2009-11-04 16:10:51 +00001333static irqreturn_t pmic_uv_handler(int irq, void *data)
Mark Brownda091552008-10-10 15:58:15 +01001334{
1335 struct regulator_dev *rdev = (struct regulator_dev *)data;
Mark Brown5a65edb2009-11-04 16:10:51 +00001336 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
Mark Brownda091552008-10-10 15:58:15 +01001337
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001338 mutex_lock(&rdev->mutex);
Mark Brownda091552008-10-10 15:58:15 +01001339 if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
1340 regulator_notifier_call_chain(rdev,
1341 REGULATOR_EVENT_REGULATION_OUT,
1342 wm8350);
1343 else
1344 regulator_notifier_call_chain(rdev,
1345 REGULATOR_EVENT_UNDER_VOLTAGE,
1346 wm8350);
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001347 mutex_unlock(&rdev->mutex);
Mark Brown5a65edb2009-11-04 16:10:51 +00001348
1349 return IRQ_HANDLED;
Mark Brownda091552008-10-10 15:58:15 +01001350}
1351
1352static int wm8350_regulator_probe(struct platform_device *pdev)
1353{
1354 struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
1355 struct regulator_dev *rdev;
1356 int ret;
1357 u16 val;
1358
1359 if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
1360 return -ENODEV;
1361
1362 /* do any regulatior specific init */
1363 switch (pdev->id) {
1364 case WM8350_DCDC_1:
1365 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
1366 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1367 break;
1368 case WM8350_DCDC_3:
1369 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
1370 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1371 break;
1372 case WM8350_DCDC_4:
1373 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
1374 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1375 break;
1376 case WM8350_DCDC_6:
1377 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
1378 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1379 break;
1380 }
1381
Mark Brownda091552008-10-10 15:58:15 +01001382 /* register regulator */
1383 rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
Mark Brown05271002009-01-19 13:37:02 +00001384 pdev->dev.platform_data,
Mark Brownda091552008-10-10 15:58:15 +01001385 dev_get_drvdata(&pdev->dev));
1386 if (IS_ERR(rdev)) {
1387 dev_err(&pdev->dev, "failed to register %s\n",
1388 wm8350_reg[pdev->id].name);
1389 return PTR_ERR(rdev);
1390 }
1391
1392 /* register regulator IRQ */
1393 ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
Mark Brown5a65edb2009-11-04 16:10:51 +00001394 pmic_uv_handler, 0, "UV", rdev);
Mark Brownda091552008-10-10 15:58:15 +01001395 if (ret < 0) {
1396 regulator_unregister(rdev);
1397 dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
1398 wm8350_reg[pdev->id].name);
1399 return ret;
1400 }
1401
Mark Brownda091552008-10-10 15:58:15 +01001402 return 0;
1403}
1404
1405static int wm8350_regulator_remove(struct platform_device *pdev)
1406{
1407 struct regulator_dev *rdev = platform_get_drvdata(pdev);
1408 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1409
Mark Brownda091552008-10-10 15:58:15 +01001410 wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
1411
1412 regulator_unregister(rdev);
1413
1414 return 0;
1415}
1416
1417int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
1418 struct regulator_init_data *initdata)
1419{
1420 struct platform_device *pdev;
1421 int ret;
Roel Kluin4dee4d42009-06-15 22:30:39 +02001422 if (reg < 0 || reg >= NUM_WM8350_REGULATORS)
1423 return -EINVAL;
Mark Brownda091552008-10-10 15:58:15 +01001424
1425 if (wm8350->pmic.pdev[reg])
1426 return -EBUSY;
1427
Mark Brown645524a2008-12-18 23:12:16 +01001428 if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 &&
1429 reg > wm8350->pmic.max_dcdc)
1430 return -ENODEV;
1431 if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B &&
1432 reg > wm8350->pmic.max_isink)
1433 return -ENODEV;
1434
Mark Brownda091552008-10-10 15:58:15 +01001435 pdev = platform_device_alloc("wm8350-regulator", reg);
1436 if (!pdev)
1437 return -ENOMEM;
1438
1439 wm8350->pmic.pdev[reg] = pdev;
1440
1441 initdata->driver_data = wm8350;
1442
1443 pdev->dev.platform_data = initdata;
1444 pdev->dev.parent = wm8350->dev;
1445 platform_set_drvdata(pdev, wm8350);
1446
1447 ret = platform_device_add(pdev);
1448
1449 if (ret != 0) {
1450 dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
1451 reg, ret);
1452 platform_device_del(pdev);
1453 wm8350->pmic.pdev[reg] = NULL;
1454 }
1455
1456 return ret;
1457}
1458EXPORT_SYMBOL_GPL(wm8350_register_regulator);
1459
Mark Brown0081e802008-12-04 16:52:33 +00001460/**
1461 * wm8350_register_led - Register a WM8350 LED output
1462 *
1463 * @param wm8350 The WM8350 device to configure.
1464 * @param lednum LED device index to create.
1465 * @param dcdc The DCDC to use for the LED.
1466 * @param isink The ISINK to use for the LED.
1467 * @param pdata Configuration for the LED.
1468 *
1469 * The WM8350 supports the use of an ISINK together with a DCDC to
1470 * provide a power-efficient LED driver. This function registers the
1471 * regulators and instantiates the platform device for a LED. The
1472 * operating modes for the LED regulators must be configured using
1473 * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and
1474 * wm8350_dcdc_set_slot() prior to calling this function.
1475 */
1476int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink,
1477 struct wm8350_led_platform_data *pdata)
1478{
1479 struct wm8350_led *led;
1480 struct platform_device *pdev;
1481 int ret;
1482
Roel Kluin8dd2c9e2009-01-17 16:06:40 +01001483 if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) {
Mark Brown0081e802008-12-04 16:52:33 +00001484 dev_err(wm8350->dev, "Invalid LED index %d\n", lednum);
1485 return -ENODEV;
1486 }
1487
1488 led = &wm8350->pmic.led[lednum];
1489
1490 if (led->pdev) {
1491 dev_err(wm8350->dev, "LED %d already allocated\n", lednum);
1492 return -EINVAL;
1493 }
1494
1495 pdev = platform_device_alloc("wm8350-led", lednum);
1496 if (pdev == NULL) {
1497 dev_err(wm8350->dev, "Failed to allocate LED %d\n", lednum);
1498 return -ENOMEM;
1499 }
1500
1501 led->isink_consumer.dev = &pdev->dev;
1502 led->isink_consumer.supply = "led_isink";
1503 led->isink_init.num_consumer_supplies = 1;
1504 led->isink_init.consumer_supplies = &led->isink_consumer;
1505 led->isink_init.constraints.min_uA = 0;
1506 led->isink_init.constraints.max_uA = pdata->max_uA;
Mark Browna2fad9b2010-01-04 15:30:54 +00001507 led->isink_init.constraints.valid_ops_mask
1508 = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001509 led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
1510 ret = wm8350_register_regulator(wm8350, isink, &led->isink_init);
1511 if (ret != 0) {
1512 platform_device_put(pdev);
1513 return ret;
1514 }
1515
1516 led->dcdc_consumer.dev = &pdev->dev;
1517 led->dcdc_consumer.supply = "led_vcc";
1518 led->dcdc_init.num_consumer_supplies = 1;
1519 led->dcdc_init.consumer_supplies = &led->dcdc_consumer;
1520 led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
Mark Browna2fad9b2010-01-04 15:30:54 +00001521 led->dcdc_init.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001522 ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init);
1523 if (ret != 0) {
1524 platform_device_put(pdev);
1525 return ret;
1526 }
1527
1528 switch (isink) {
1529 case WM8350_ISINK_A:
1530 wm8350->pmic.isink_A_dcdc = dcdc;
1531 break;
1532 case WM8350_ISINK_B:
1533 wm8350->pmic.isink_B_dcdc = dcdc;
1534 break;
1535 }
1536
1537 pdev->dev.platform_data = pdata;
1538 pdev->dev.parent = wm8350->dev;
1539 ret = platform_device_add(pdev);
1540 if (ret != 0) {
1541 dev_err(wm8350->dev, "Failed to register LED %d: %d\n",
1542 lednum, ret);
1543 platform_device_put(pdev);
1544 return ret;
1545 }
1546
1547 led->pdev = pdev;
1548
1549 return 0;
1550}
1551EXPORT_SYMBOL_GPL(wm8350_register_led);
1552
Mark Brownda091552008-10-10 15:58:15 +01001553static struct platform_driver wm8350_regulator_driver = {
1554 .probe = wm8350_regulator_probe,
1555 .remove = wm8350_regulator_remove,
1556 .driver = {
1557 .name = "wm8350-regulator",
1558 },
1559};
1560
1561static int __init wm8350_regulator_init(void)
1562{
1563 return platform_driver_register(&wm8350_regulator_driver);
1564}
1565subsys_initcall(wm8350_regulator_init);
1566
1567static void __exit wm8350_regulator_exit(void)
1568{
1569 platform_driver_unregister(&wm8350_regulator_driver);
1570}
1571module_exit(wm8350_regulator_exit);
1572
1573/* Module information */
1574MODULE_AUTHOR("Liam Girdwood");
1575MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
1576MODULE_LICENSE("GPL");
Mark Brown38c53c82009-04-28 11:13:55 +01001577MODULE_ALIAS("platform:wm8350-regulator");