blob: 7e45b0ddd710c606dfa54fdae7c650753d70df05 [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
Mark Brown75c8ac22010-01-04 17:24:01 +0000293static int wm8350_isink_enable_time(struct regulator_dev *rdev)
294{
295 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
296 int isink = rdev_get_id(rdev);
297 int reg;
298
299 switch (isink) {
300 case WM8350_ISINK_A:
301 reg = wm8350_reg_read(wm8350, WM8350_CSA_FLASH_CONTROL);
302 break;
303 case WM8350_ISINK_B:
304 reg = wm8350_reg_read(wm8350, WM8350_CSB_FLASH_CONTROL);
305 break;
306 default:
307 return -EINVAL;
308 }
309
310 if (reg & WM8350_CS1_FLASH_MODE) {
311 switch (reg & WM8350_CS1_ON_RAMP_MASK) {
312 case 0:
313 return 0;
314 case 1:
315 return 1950;
316 case 2:
317 return 3910;
318 case 3:
319 return 7800;
320 }
321 } else {
322 switch (reg & WM8350_CS1_ON_RAMP_MASK) {
323 case 0:
324 return 0;
325 case 1:
326 return 250000;
327 case 2:
328 return 500000;
329 case 3:
330 return 1000000;
331 }
332 }
333
334 return -EINVAL;
335}
336
337
Mark Brownda091552008-10-10 15:58:15 +0100338int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
339 u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
340 u16 drive)
341{
342 switch (isink) {
343 case WM8350_ISINK_A:
344 wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL,
345 (mode ? WM8350_CS1_FLASH_MODE : 0) |
346 (trigger ? WM8350_CS1_TRIGSRC : 0) |
347 duration | on_ramp | off_ramp | drive);
348 break;
349 case WM8350_ISINK_B:
350 wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL,
351 (mode ? WM8350_CS2_FLASH_MODE : 0) |
352 (trigger ? WM8350_CS2_TRIGSRC : 0) |
353 duration | on_ramp | off_ramp | drive);
354 break;
355 default:
356 return -EINVAL;
357 }
358 return 0;
359}
360EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
361
362static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000363 int max_uV, unsigned *selector)
Mark Brownda091552008-10-10 15:58:15 +0100364{
365 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
366 int volt_reg, dcdc = rdev_get_id(rdev), mV,
367 min_mV = min_uV / 1000, max_mV = max_uV / 1000;
368 u16 val;
369
370 if (min_mV < 850 || min_mV > 4025)
371 return -EINVAL;
372 if (max_mV < 850 || max_mV > 4025)
373 return -EINVAL;
374
375 /* step size is 25mV */
376 mV = (min_mV - 826) / 25;
377 if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
378 return -EINVAL;
379 BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
380
381 switch (dcdc) {
382 case WM8350_DCDC_1:
383 volt_reg = WM8350_DCDC1_CONTROL;
384 break;
385 case WM8350_DCDC_3:
386 volt_reg = WM8350_DCDC3_CONTROL;
387 break;
388 case WM8350_DCDC_4:
389 volt_reg = WM8350_DCDC4_CONTROL;
390 break;
391 case WM8350_DCDC_6:
392 volt_reg = WM8350_DCDC6_CONTROL;
393 break;
394 case WM8350_DCDC_2:
395 case WM8350_DCDC_5:
396 default:
397 return -EINVAL;
398 }
399
Mark Brown3a93f2a2010-11-10 14:38:29 +0000400 *selector = mV;
401
Mark Brownda091552008-10-10 15:58:15 +0100402 /* all DCDCs have same mV bits */
403 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
404 wm8350_reg_write(wm8350, volt_reg, val | mV);
405 return 0;
406}
407
408static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
409{
410 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
411 int volt_reg, dcdc = rdev_get_id(rdev);
412 u16 val;
413
414 switch (dcdc) {
415 case WM8350_DCDC_1:
416 volt_reg = WM8350_DCDC1_CONTROL;
417 break;
418 case WM8350_DCDC_3:
419 volt_reg = WM8350_DCDC3_CONTROL;
420 break;
421 case WM8350_DCDC_4:
422 volt_reg = WM8350_DCDC4_CONTROL;
423 break;
424 case WM8350_DCDC_6:
425 volt_reg = WM8350_DCDC6_CONTROL;
426 break;
427 case WM8350_DCDC_2:
428 case WM8350_DCDC_5:
429 default:
430 return -EINVAL;
431 }
432
433 /* all DCDCs have same mV bits */
434 val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
435 return wm8350_dcdc_val_to_mvolts(val) * 1000;
436}
437
Mark Brown221a7c72009-03-02 16:32:47 +0000438static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
439 unsigned selector)
440{
441 if (selector > WM8350_DCDC_MAX_VSEL)
442 return -EINVAL;
443 return wm8350_dcdc_val_to_mvolts(selector) * 1000;
444}
445
Mark Brownda091552008-10-10 15:58:15 +0100446static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
447{
448 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
449 int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
450 u16 val;
451
452 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
453
454 if (mV && (mV < 850 || mV > 4025)) {
455 dev_err(wm8350->dev,
456 "DCDC%d suspend voltage %d mV out of range\n",
457 dcdc, mV);
458 return -EINVAL;
459 }
460 if (mV == 0)
461 mV = 850;
462
463 switch (dcdc) {
464 case WM8350_DCDC_1:
465 volt_reg = WM8350_DCDC1_LOW_POWER;
466 break;
467 case WM8350_DCDC_3:
468 volt_reg = WM8350_DCDC3_LOW_POWER;
469 break;
470 case WM8350_DCDC_4:
471 volt_reg = WM8350_DCDC4_LOW_POWER;
472 break;
473 case WM8350_DCDC_6:
474 volt_reg = WM8350_DCDC6_LOW_POWER;
475 break;
476 case WM8350_DCDC_2:
477 case WM8350_DCDC_5:
478 default:
479 return -EINVAL;
480 }
481
482 /* all DCDCs have same mV bits */
483 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
484 wm8350_reg_write(wm8350, volt_reg,
485 val | wm8350_dcdc_mvolts_to_val(mV));
486 return 0;
487}
488
489static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
490{
491 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
492 int dcdc = rdev_get_id(rdev);
493 u16 val;
494
495 switch (dcdc) {
496 case WM8350_DCDC_1:
497 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
498 & ~WM8350_DCDC_HIB_MODE_MASK;
499 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
500 wm8350->pmic.dcdc1_hib_mode);
501 break;
502 case WM8350_DCDC_3:
503 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
504 & ~WM8350_DCDC_HIB_MODE_MASK;
505 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
506 wm8350->pmic.dcdc3_hib_mode);
507 break;
508 case WM8350_DCDC_4:
509 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
510 & ~WM8350_DCDC_HIB_MODE_MASK;
511 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
512 wm8350->pmic.dcdc4_hib_mode);
513 break;
514 case WM8350_DCDC_6:
515 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
516 & ~WM8350_DCDC_HIB_MODE_MASK;
517 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
518 wm8350->pmic.dcdc6_hib_mode);
519 break;
520 case WM8350_DCDC_2:
521 case WM8350_DCDC_5:
522 default:
523 return -EINVAL;
524 }
525
526 return 0;
527}
528
529static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
530{
531 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
532 int dcdc = rdev_get_id(rdev);
533 u16 val;
534
535 switch (dcdc) {
536 case WM8350_DCDC_1:
537 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
538 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
539 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
540 WM8350_DCDC_HIB_MODE_DIS);
541 break;
542 case WM8350_DCDC_3:
543 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
544 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
545 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
546 WM8350_DCDC_HIB_MODE_DIS);
547 break;
548 case WM8350_DCDC_4:
549 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
550 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
551 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
552 WM8350_DCDC_HIB_MODE_DIS);
553 break;
554 case WM8350_DCDC_6:
555 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
556 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
557 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
558 WM8350_DCDC_HIB_MODE_DIS);
559 break;
560 case WM8350_DCDC_2:
561 case WM8350_DCDC_5:
562 default:
563 return -EINVAL;
564 }
565
566 return 0;
567}
568
569static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
570{
571 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
572 int dcdc = rdev_get_id(rdev);
573 u16 val;
574
575 switch (dcdc) {
576 case WM8350_DCDC_2:
577 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
578 & ~WM8350_DC2_HIB_MODE_MASK;
579 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
580 WM8350_DC2_HIB_MODE_ACTIVE);
581 break;
582 case WM8350_DCDC_5:
583 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
584 & ~WM8350_DC2_HIB_MODE_MASK;
585 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
586 WM8350_DC5_HIB_MODE_ACTIVE);
587 break;
588 default:
589 return -EINVAL;
590 }
591 return 0;
592}
593
594static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
595{
596 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
597 int dcdc = rdev_get_id(rdev);
598 u16 val;
599
600 switch (dcdc) {
601 case WM8350_DCDC_2:
602 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
603 & ~WM8350_DC2_HIB_MODE_MASK;
604 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
605 WM8350_DC2_HIB_MODE_DISABLE);
606 break;
607 case WM8350_DCDC_5:
608 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
609 & ~WM8350_DC2_HIB_MODE_MASK;
610 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
611 WM8350_DC2_HIB_MODE_DISABLE);
612 break;
613 default:
614 return -EINVAL;
615 }
616 return 0;
617}
618
619static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
620 unsigned int mode)
621{
622 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
623 int dcdc = rdev_get_id(rdev);
624 u16 *hib_mode;
625
626 switch (dcdc) {
627 case WM8350_DCDC_1:
628 hib_mode = &wm8350->pmic.dcdc1_hib_mode;
629 break;
630 case WM8350_DCDC_3:
631 hib_mode = &wm8350->pmic.dcdc3_hib_mode;
632 break;
633 case WM8350_DCDC_4:
634 hib_mode = &wm8350->pmic.dcdc4_hib_mode;
635 break;
636 case WM8350_DCDC_6:
637 hib_mode = &wm8350->pmic.dcdc6_hib_mode;
638 break;
639 case WM8350_DCDC_2:
640 case WM8350_DCDC_5:
641 default:
642 return -EINVAL;
643 }
644
645 switch (mode) {
646 case REGULATOR_MODE_NORMAL:
647 *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
648 break;
649 case REGULATOR_MODE_IDLE:
650 *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
651 break;
652 case REGULATOR_MODE_STANDBY:
653 *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
654 break;
655 default:
656 return -EINVAL;
657 }
658
659 return 0;
660}
661
662static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
663{
664 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
665 int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
666 u16 val;
667
668 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
669
670 if (mV < 900 || mV > 3300) {
671 dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
672 ldo, mV);
673 return -EINVAL;
674 }
675
676 switch (ldo) {
677 case WM8350_LDO_1:
678 volt_reg = WM8350_LDO1_LOW_POWER;
679 break;
680 case WM8350_LDO_2:
681 volt_reg = WM8350_LDO2_LOW_POWER;
682 break;
683 case WM8350_LDO_3:
684 volt_reg = WM8350_LDO3_LOW_POWER;
685 break;
686 case WM8350_LDO_4:
687 volt_reg = WM8350_LDO4_LOW_POWER;
688 break;
689 default:
690 return -EINVAL;
691 }
692
693 /* all LDOs have same mV bits */
694 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
695 wm8350_reg_write(wm8350, volt_reg,
696 val | wm8350_ldo_mvolts_to_val(mV));
697 return 0;
698}
699
700static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
701{
702 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
703 int volt_reg, ldo = rdev_get_id(rdev);
704 u16 val;
705
706 switch (ldo) {
707 case WM8350_LDO_1:
708 volt_reg = WM8350_LDO1_LOW_POWER;
709 break;
710 case WM8350_LDO_2:
711 volt_reg = WM8350_LDO2_LOW_POWER;
712 break;
713 case WM8350_LDO_3:
714 volt_reg = WM8350_LDO3_LOW_POWER;
715 break;
716 case WM8350_LDO_4:
717 volt_reg = WM8350_LDO4_LOW_POWER;
718 break;
719 default:
720 return -EINVAL;
721 }
722
723 /* all LDOs have same mV bits */
724 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
725 wm8350_reg_write(wm8350, volt_reg, val);
726 return 0;
727}
728
729static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
730{
731 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
732 int volt_reg, ldo = rdev_get_id(rdev);
733 u16 val;
734
735 switch (ldo) {
736 case WM8350_LDO_1:
737 volt_reg = WM8350_LDO1_LOW_POWER;
738 break;
739 case WM8350_LDO_2:
740 volt_reg = WM8350_LDO2_LOW_POWER;
741 break;
742 case WM8350_LDO_3:
743 volt_reg = WM8350_LDO3_LOW_POWER;
744 break;
745 case WM8350_LDO_4:
746 volt_reg = WM8350_LDO4_LOW_POWER;
747 break;
748 default:
749 return -EINVAL;
750 }
751
752 /* all LDOs have same mV bits */
753 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
754 wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
755 return 0;
756}
757
758static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000759 int max_uV, unsigned *selector)
Mark Brownda091552008-10-10 15:58:15 +0100760{
761 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
762 int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
763 max_mV = max_uV / 1000;
764 u16 val;
765
766 if (min_mV < 900 || min_mV > 3300)
767 return -EINVAL;
768 if (max_mV < 900 || max_mV > 3300)
769 return -EINVAL;
770
771 if (min_mV < 1800) {
772 /* step size is 50mV < 1800mV */
773 mV = (min_mV - 851) / 50;
774 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
775 return -EINVAL;
776 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
777 } else {
778 /* step size is 100mV > 1800mV */
779 mV = ((min_mV - 1701) / 100) + 16;
780 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
781 return -EINVAL;
782 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
783 }
784
785 switch (ldo) {
786 case WM8350_LDO_1:
787 volt_reg = WM8350_LDO1_CONTROL;
788 break;
789 case WM8350_LDO_2:
790 volt_reg = WM8350_LDO2_CONTROL;
791 break;
792 case WM8350_LDO_3:
793 volt_reg = WM8350_LDO3_CONTROL;
794 break;
795 case WM8350_LDO_4:
796 volt_reg = WM8350_LDO4_CONTROL;
797 break;
798 default:
799 return -EINVAL;
800 }
801
Mark Brown3a93f2a2010-11-10 14:38:29 +0000802 *selector = mV;
803
Mark Brownda091552008-10-10 15:58:15 +0100804 /* all LDOs have same mV bits */
805 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
806 wm8350_reg_write(wm8350, volt_reg, val | mV);
807 return 0;
808}
809
810static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
811{
812 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
813 int volt_reg, ldo = rdev_get_id(rdev);
814 u16 val;
815
816 switch (ldo) {
817 case WM8350_LDO_1:
818 volt_reg = WM8350_LDO1_CONTROL;
819 break;
820 case WM8350_LDO_2:
821 volt_reg = WM8350_LDO2_CONTROL;
822 break;
823 case WM8350_LDO_3:
824 volt_reg = WM8350_LDO3_CONTROL;
825 break;
826 case WM8350_LDO_4:
827 volt_reg = WM8350_LDO4_CONTROL;
828 break;
829 default:
830 return -EINVAL;
831 }
832
833 /* all LDOs have same mV bits */
834 val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
835 return wm8350_ldo_val_to_mvolts(val) * 1000;
836}
837
Mark Brown221a7c72009-03-02 16:32:47 +0000838static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
839 unsigned selector)
840{
841 if (selector > WM8350_LDO1_VSEL_MASK)
842 return -EINVAL;
843 return wm8350_ldo_val_to_mvolts(selector) * 1000;
844}
845
Mark Brownda091552008-10-10 15:58:15 +0100846int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
847 u16 stop, u16 fault)
848{
849 int slot_reg;
850 u16 val;
851
852 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
853 __func__, dcdc, start, stop);
854
855 /* slot valid ? */
856 if (start > 15 || stop > 15)
857 return -EINVAL;
858
859 switch (dcdc) {
860 case WM8350_DCDC_1:
861 slot_reg = WM8350_DCDC1_TIMEOUTS;
862 break;
863 case WM8350_DCDC_2:
864 slot_reg = WM8350_DCDC2_TIMEOUTS;
865 break;
866 case WM8350_DCDC_3:
867 slot_reg = WM8350_DCDC3_TIMEOUTS;
868 break;
869 case WM8350_DCDC_4:
870 slot_reg = WM8350_DCDC4_TIMEOUTS;
871 break;
872 case WM8350_DCDC_5:
873 slot_reg = WM8350_DCDC5_TIMEOUTS;
874 break;
875 case WM8350_DCDC_6:
876 slot_reg = WM8350_DCDC6_TIMEOUTS;
877 break;
878 default:
879 return -EINVAL;
880 }
881
882 val = wm8350_reg_read(wm8350, slot_reg) &
883 ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
884 WM8350_DC1_ERRACT_MASK);
885 wm8350_reg_write(wm8350, slot_reg,
886 val | (start << WM8350_DC1_ENSLOT_SHIFT) |
887 (stop << WM8350_DC1_SDSLOT_SHIFT) |
888 (fault << WM8350_DC1_ERRACT_SHIFT));
889
890 return 0;
891}
892EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
893
894int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
895{
896 int slot_reg;
897 u16 val;
898
899 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
900 __func__, ldo, start, stop);
901
902 /* slot valid ? */
903 if (start > 15 || stop > 15)
904 return -EINVAL;
905
906 switch (ldo) {
907 case WM8350_LDO_1:
908 slot_reg = WM8350_LDO1_TIMEOUTS;
909 break;
910 case WM8350_LDO_2:
911 slot_reg = WM8350_LDO2_TIMEOUTS;
912 break;
913 case WM8350_LDO_3:
914 slot_reg = WM8350_LDO3_TIMEOUTS;
915 break;
916 case WM8350_LDO_4:
917 slot_reg = WM8350_LDO4_TIMEOUTS;
918 break;
919 default:
920 return -EINVAL;
921 }
922
923 val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
924 wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
925 return 0;
926}
927EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
928
929int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
930 u16 ilim, u16 ramp, u16 feedback)
931{
932 u16 val;
933
934 dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
935 mode ? "normal" : "boost", ilim ? "low" : "normal");
936
937 switch (dcdc) {
938 case WM8350_DCDC_2:
939 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
940 & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
941 WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
942 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
943 (mode << WM8350_DC2_MODE_SHIFT) |
944 (ilim << WM8350_DC2_ILIM_SHIFT) |
945 (ramp << WM8350_DC2_RMP_SHIFT) |
946 (feedback << WM8350_DC2_FBSRC_SHIFT));
947 break;
948 case WM8350_DCDC_5:
949 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
950 & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
951 WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
952 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
953 (mode << WM8350_DC5_MODE_SHIFT) |
954 (ilim << WM8350_DC5_ILIM_SHIFT) |
955 (ramp << WM8350_DC5_RMP_SHIFT) |
956 (feedback << WM8350_DC5_FBSRC_SHIFT));
957 break;
958 default:
959 return -EINVAL;
960 }
961
962 return 0;
963}
964EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
965
966static int wm8350_dcdc_enable(struct regulator_dev *rdev)
967{
968 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
969 int dcdc = rdev_get_id(rdev);
970 u16 shift;
971
972 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
973 return -EINVAL;
974
975 shift = dcdc - WM8350_DCDC_1;
976 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
977 return 0;
978}
979
980static int wm8350_dcdc_disable(struct regulator_dev *rdev)
981{
982 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
983 int dcdc = rdev_get_id(rdev);
984 u16 shift;
985
986 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
987 return -EINVAL;
988
989 shift = dcdc - WM8350_DCDC_1;
990 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
991
992 return 0;
993}
994
995static int wm8350_ldo_enable(struct regulator_dev *rdev)
996{
997 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
998 int ldo = rdev_get_id(rdev);
999 u16 shift;
1000
1001 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
1002 return -EINVAL;
1003
1004 shift = (ldo - WM8350_LDO_1) + 8;
1005 wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
1006 return 0;
1007}
1008
1009static int wm8350_ldo_disable(struct regulator_dev *rdev)
1010{
1011 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1012 int ldo = rdev_get_id(rdev);
1013 u16 shift;
1014
1015 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
1016 return -EINVAL;
1017
1018 shift = (ldo - WM8350_LDO_1) + 8;
1019 wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
1020 return 0;
1021}
1022
1023static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
1024{
1025 int reg = 0, ret;
1026
1027 switch (dcdc) {
1028 case WM8350_DCDC_1:
1029 reg = WM8350_DCDC1_FORCE_PWM;
1030 break;
1031 case WM8350_DCDC_3:
1032 reg = WM8350_DCDC3_FORCE_PWM;
1033 break;
1034 case WM8350_DCDC_4:
1035 reg = WM8350_DCDC4_FORCE_PWM;
1036 break;
1037 case WM8350_DCDC_6:
1038 reg = WM8350_DCDC6_FORCE_PWM;
1039 break;
1040 default:
1041 return -EINVAL;
1042 }
1043
1044 if (enable)
1045 ret = wm8350_set_bits(wm8350, reg,
1046 WM8350_DCDC1_FORCE_PWM_ENA);
1047 else
1048 ret = wm8350_clear_bits(wm8350, reg,
1049 WM8350_DCDC1_FORCE_PWM_ENA);
1050 return ret;
1051}
1052
1053static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
1054{
1055 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1056 int dcdc = rdev_get_id(rdev);
1057 u16 val;
1058
1059 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
1060 return -EINVAL;
1061
1062 if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
1063 return -EINVAL;
1064
1065 val = 1 << (dcdc - WM8350_DCDC_1);
1066
1067 switch (mode) {
1068 case REGULATOR_MODE_FAST:
1069 /* force continuous mode */
1070 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1071 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1072 force_continuous_enable(wm8350, dcdc, 1);
1073 break;
1074 case REGULATOR_MODE_NORMAL:
1075 /* active / pulse skipping */
1076 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1077 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1078 force_continuous_enable(wm8350, dcdc, 0);
1079 break;
1080 case REGULATOR_MODE_IDLE:
1081 /* standby mode */
1082 force_continuous_enable(wm8350, dcdc, 0);
1083 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1084 wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
1085 break;
1086 case REGULATOR_MODE_STANDBY:
1087 /* LDO mode */
1088 force_continuous_enable(wm8350, dcdc, 0);
1089 wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
1090 break;
1091 }
1092
1093 return 0;
1094}
1095
1096static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
1097{
1098 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1099 int dcdc = rdev_get_id(rdev);
1100 u16 mask, sleep, active, force;
1101 int mode = REGULATOR_MODE_NORMAL;
Mark Brown33f301a2009-02-26 19:24:20 +00001102 int reg;
Mark Brownda091552008-10-10 15:58:15 +01001103
Mark Brown33f301a2009-02-26 19:24:20 +00001104 switch (dcdc) {
1105 case WM8350_DCDC_1:
1106 reg = WM8350_DCDC1_FORCE_PWM;
1107 break;
1108 case WM8350_DCDC_3:
1109 reg = WM8350_DCDC3_FORCE_PWM;
1110 break;
1111 case WM8350_DCDC_4:
1112 reg = WM8350_DCDC4_FORCE_PWM;
1113 break;
1114 case WM8350_DCDC_6:
1115 reg = WM8350_DCDC6_FORCE_PWM;
1116 break;
1117 default:
Mark Brownda091552008-10-10 15:58:15 +01001118 return -EINVAL;
Mark Brown33f301a2009-02-26 19:24:20 +00001119 }
Mark Brownda091552008-10-10 15:58:15 +01001120
1121 mask = 1 << (dcdc - WM8350_DCDC_1);
1122 active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +00001123 force = wm8350_reg_read(wm8350, reg) & WM8350_DCDC1_FORCE_PWM_ENA;
Mark Brownda091552008-10-10 15:58:15 +01001124 sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +00001125
Mark Brownda091552008-10-10 15:58:15 +01001126 dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
1127 mask, active, sleep, force);
1128
1129 if (active && !sleep) {
1130 if (force)
1131 mode = REGULATOR_MODE_FAST;
1132 else
1133 mode = REGULATOR_MODE_NORMAL;
1134 } else if (!active && !sleep)
1135 mode = REGULATOR_MODE_IDLE;
Axel Lin8ecee362010-09-06 14:06:07 +08001136 else if (sleep)
Mark Brownda091552008-10-10 15:58:15 +01001137 mode = REGULATOR_MODE_STANDBY;
1138
1139 return mode;
1140}
1141
1142static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
1143{
1144 return REGULATOR_MODE_NORMAL;
1145}
1146
1147struct wm8350_dcdc_efficiency {
1148 int uA_load_min;
1149 int uA_load_max;
1150 unsigned int mode;
1151};
1152
1153static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
1154 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
1155 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
1156 {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
1157 {-1, -1, REGULATOR_MODE_NORMAL},
1158};
1159
1160static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
1161 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
1162 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
1163 {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
1164 {-1, -1, REGULATOR_MODE_NORMAL},
1165};
1166
1167static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
1168{
1169 int i = 0;
1170
1171 while (eff[i].uA_load_min != -1) {
1172 if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
1173 return eff[i].mode;
1174 }
1175 return REGULATOR_MODE_NORMAL;
1176}
1177
1178/* Query the regulator for it's most efficient mode @ uV,uA
1179 * WM8350 regulator efficiency is pretty similar over
1180 * different input and output uV.
1181 */
1182static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
1183 int input_uV, int output_uV,
1184 int output_uA)
1185{
1186 int dcdc = rdev_get_id(rdev), mode;
1187
1188 switch (dcdc) {
1189 case WM8350_DCDC_1:
1190 case WM8350_DCDC_6:
1191 mode = get_mode(output_uA, dcdc1_6_efficiency);
1192 break;
1193 case WM8350_DCDC_3:
1194 case WM8350_DCDC_4:
1195 mode = get_mode(output_uA, dcdc3_4_efficiency);
1196 break;
1197 default:
1198 mode = REGULATOR_MODE_NORMAL;
1199 break;
1200 }
1201 return mode;
1202}
1203
1204static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
1205{
1206 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1207 int dcdc = rdev_get_id(rdev), shift;
1208
1209 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
1210 return -EINVAL;
1211
1212 shift = dcdc - WM8350_DCDC_1;
1213 return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
1214 & (1 << shift);
1215}
1216
1217static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
1218{
1219 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1220 int ldo = rdev_get_id(rdev), shift;
1221
1222 if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
1223 return -EINVAL;
1224
1225 shift = (ldo - WM8350_LDO_1) + 8;
1226 return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
1227 & (1 << shift);
1228}
1229
1230static struct regulator_ops wm8350_dcdc_ops = {
1231 .set_voltage = wm8350_dcdc_set_voltage,
1232 .get_voltage = wm8350_dcdc_get_voltage,
Mark Brown221a7c72009-03-02 16:32:47 +00001233 .list_voltage = wm8350_dcdc_list_voltage,
Mark Brownda091552008-10-10 15:58:15 +01001234 .enable = wm8350_dcdc_enable,
1235 .disable = wm8350_dcdc_disable,
1236 .get_mode = wm8350_dcdc_get_mode,
1237 .set_mode = wm8350_dcdc_set_mode,
1238 .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
1239 .is_enabled = wm8350_dcdc_is_enabled,
1240 .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
1241 .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
1242 .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
1243 .set_suspend_mode = wm8350_dcdc_set_suspend_mode,
1244};
1245
1246static struct regulator_ops wm8350_dcdc2_5_ops = {
1247 .enable = wm8350_dcdc_enable,
1248 .disable = wm8350_dcdc_disable,
1249 .is_enabled = wm8350_dcdc_is_enabled,
1250 .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
1251 .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
1252};
1253
1254static struct regulator_ops wm8350_ldo_ops = {
1255 .set_voltage = wm8350_ldo_set_voltage,
1256 .get_voltage = wm8350_ldo_get_voltage,
Mark Brown221a7c72009-03-02 16:32:47 +00001257 .list_voltage = wm8350_ldo_list_voltage,
Mark Brownda091552008-10-10 15:58:15 +01001258 .enable = wm8350_ldo_enable,
1259 .disable = wm8350_ldo_disable,
1260 .is_enabled = wm8350_ldo_is_enabled,
1261 .get_mode = wm8350_ldo_get_mode,
1262 .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
1263 .set_suspend_enable = wm8350_ldo_set_suspend_enable,
1264 .set_suspend_disable = wm8350_ldo_set_suspend_disable,
1265};
1266
1267static struct regulator_ops wm8350_isink_ops = {
1268 .set_current_limit = wm8350_isink_set_current,
1269 .get_current_limit = wm8350_isink_get_current,
1270 .enable = wm8350_isink_enable,
1271 .disable = wm8350_isink_disable,
1272 .is_enabled = wm8350_isink_is_enabled,
Mark Brown75c8ac22010-01-04 17:24:01 +00001273 .enable_time = wm8350_isink_enable_time,
Mark Brownda091552008-10-10 15:58:15 +01001274};
1275
1276static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
1277 {
1278 .name = "DCDC1",
1279 .id = WM8350_DCDC_1,
1280 .ops = &wm8350_dcdc_ops,
1281 .irq = WM8350_IRQ_UV_DC1,
1282 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001283 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001284 .owner = THIS_MODULE,
1285 },
1286 {
1287 .name = "DCDC2",
1288 .id = WM8350_DCDC_2,
1289 .ops = &wm8350_dcdc2_5_ops,
1290 .irq = WM8350_IRQ_UV_DC2,
1291 .type = REGULATOR_VOLTAGE,
1292 .owner = THIS_MODULE,
1293 },
1294 {
1295 .name = "DCDC3",
1296 .id = WM8350_DCDC_3,
1297 .ops = &wm8350_dcdc_ops,
1298 .irq = WM8350_IRQ_UV_DC3,
1299 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001300 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001301 .owner = THIS_MODULE,
1302 },
1303 {
1304 .name = "DCDC4",
1305 .id = WM8350_DCDC_4,
1306 .ops = &wm8350_dcdc_ops,
1307 .irq = WM8350_IRQ_UV_DC4,
1308 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001309 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001310 .owner = THIS_MODULE,
1311 },
1312 {
1313 .name = "DCDC5",
1314 .id = WM8350_DCDC_5,
1315 .ops = &wm8350_dcdc2_5_ops,
1316 .irq = WM8350_IRQ_UV_DC5,
1317 .type = REGULATOR_VOLTAGE,
1318 .owner = THIS_MODULE,
1319 },
1320 {
1321 .name = "DCDC6",
1322 .id = WM8350_DCDC_6,
1323 .ops = &wm8350_dcdc_ops,
1324 .irq = WM8350_IRQ_UV_DC6,
1325 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001326 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownda091552008-10-10 15:58:15 +01001327 .owner = THIS_MODULE,
1328 },
1329 {
1330 .name = "LDO1",
1331 .id = WM8350_LDO_1,
1332 .ops = &wm8350_ldo_ops,
1333 .irq = WM8350_IRQ_UV_LDO1,
1334 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001335 .n_voltages = WM8350_LDO1_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001336 .owner = THIS_MODULE,
1337 },
1338 {
1339 .name = "LDO2",
1340 .id = WM8350_LDO_2,
1341 .ops = &wm8350_ldo_ops,
1342 .irq = WM8350_IRQ_UV_LDO2,
1343 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001344 .n_voltages = WM8350_LDO2_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001345 .owner = THIS_MODULE,
1346 },
1347 {
1348 .name = "LDO3",
1349 .id = WM8350_LDO_3,
1350 .ops = &wm8350_ldo_ops,
1351 .irq = WM8350_IRQ_UV_LDO3,
1352 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001353 .n_voltages = WM8350_LDO3_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001354 .owner = THIS_MODULE,
1355 },
1356 {
1357 .name = "LDO4",
1358 .id = WM8350_LDO_4,
1359 .ops = &wm8350_ldo_ops,
1360 .irq = WM8350_IRQ_UV_LDO4,
1361 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001362 .n_voltages = WM8350_LDO4_VSEL_MASK + 1,
Mark Brownda091552008-10-10 15:58:15 +01001363 .owner = THIS_MODULE,
1364 },
1365 {
1366 .name = "ISINKA",
1367 .id = WM8350_ISINK_A,
1368 .ops = &wm8350_isink_ops,
1369 .irq = WM8350_IRQ_CS1,
1370 .type = REGULATOR_CURRENT,
1371 .owner = THIS_MODULE,
1372 },
1373 {
1374 .name = "ISINKB",
1375 .id = WM8350_ISINK_B,
1376 .ops = &wm8350_isink_ops,
1377 .irq = WM8350_IRQ_CS2,
1378 .type = REGULATOR_CURRENT,
1379 .owner = THIS_MODULE,
1380 },
1381};
1382
Mark Brown5a65edb2009-11-04 16:10:51 +00001383static irqreturn_t pmic_uv_handler(int irq, void *data)
Mark Brownda091552008-10-10 15:58:15 +01001384{
1385 struct regulator_dev *rdev = (struct regulator_dev *)data;
Mark Brown5a65edb2009-11-04 16:10:51 +00001386 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
Mark Brownda091552008-10-10 15:58:15 +01001387
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001388 mutex_lock(&rdev->mutex);
Mark Brownda091552008-10-10 15:58:15 +01001389 if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
1390 regulator_notifier_call_chain(rdev,
1391 REGULATOR_EVENT_REGULATION_OUT,
1392 wm8350);
1393 else
1394 regulator_notifier_call_chain(rdev,
1395 REGULATOR_EVENT_UNDER_VOLTAGE,
1396 wm8350);
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001397 mutex_unlock(&rdev->mutex);
Mark Brown5a65edb2009-11-04 16:10:51 +00001398
1399 return IRQ_HANDLED;
Mark Brownda091552008-10-10 15:58:15 +01001400}
1401
1402static int wm8350_regulator_probe(struct platform_device *pdev)
1403{
1404 struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
1405 struct regulator_dev *rdev;
1406 int ret;
1407 u16 val;
1408
1409 if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
1410 return -ENODEV;
1411
1412 /* do any regulatior specific init */
1413 switch (pdev->id) {
1414 case WM8350_DCDC_1:
1415 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
1416 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1417 break;
1418 case WM8350_DCDC_3:
1419 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
1420 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1421 break;
1422 case WM8350_DCDC_4:
1423 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
1424 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1425 break;
1426 case WM8350_DCDC_6:
1427 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
1428 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1429 break;
1430 }
1431
Mark Brownda091552008-10-10 15:58:15 +01001432 /* register regulator */
1433 rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
Mark Brown05271002009-01-19 13:37:02 +00001434 pdev->dev.platform_data,
Mark Brownda091552008-10-10 15:58:15 +01001435 dev_get_drvdata(&pdev->dev));
1436 if (IS_ERR(rdev)) {
1437 dev_err(&pdev->dev, "failed to register %s\n",
1438 wm8350_reg[pdev->id].name);
1439 return PTR_ERR(rdev);
1440 }
1441
1442 /* register regulator IRQ */
1443 ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
Mark Brown5a65edb2009-11-04 16:10:51 +00001444 pmic_uv_handler, 0, "UV", rdev);
Mark Brownda091552008-10-10 15:58:15 +01001445 if (ret < 0) {
1446 regulator_unregister(rdev);
1447 dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
1448 wm8350_reg[pdev->id].name);
1449 return ret;
1450 }
1451
Mark Brownda091552008-10-10 15:58:15 +01001452 return 0;
1453}
1454
1455static int wm8350_regulator_remove(struct platform_device *pdev)
1456{
1457 struct regulator_dev *rdev = platform_get_drvdata(pdev);
1458 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1459
Mark Brownf99344f2010-01-05 13:59:07 +00001460 wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
Mark Brownda091552008-10-10 15:58:15 +01001461
1462 regulator_unregister(rdev);
1463
1464 return 0;
1465}
1466
1467int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
1468 struct regulator_init_data *initdata)
1469{
1470 struct platform_device *pdev;
1471 int ret;
Roel Kluin4dee4d42009-06-15 22:30:39 +02001472 if (reg < 0 || reg >= NUM_WM8350_REGULATORS)
1473 return -EINVAL;
Mark Brownda091552008-10-10 15:58:15 +01001474
1475 if (wm8350->pmic.pdev[reg])
1476 return -EBUSY;
1477
Mark Brown645524a2008-12-18 23:12:16 +01001478 if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 &&
1479 reg > wm8350->pmic.max_dcdc)
1480 return -ENODEV;
1481 if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B &&
1482 reg > wm8350->pmic.max_isink)
1483 return -ENODEV;
1484
Mark Brownda091552008-10-10 15:58:15 +01001485 pdev = platform_device_alloc("wm8350-regulator", reg);
1486 if (!pdev)
1487 return -ENOMEM;
1488
1489 wm8350->pmic.pdev[reg] = pdev;
1490
1491 initdata->driver_data = wm8350;
1492
1493 pdev->dev.platform_data = initdata;
1494 pdev->dev.parent = wm8350->dev;
1495 platform_set_drvdata(pdev, wm8350);
1496
1497 ret = platform_device_add(pdev);
1498
1499 if (ret != 0) {
1500 dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
1501 reg, ret);
Axel Line9a1c512010-07-26 10:41:58 +08001502 platform_device_put(pdev);
Mark Brownda091552008-10-10 15:58:15 +01001503 wm8350->pmic.pdev[reg] = NULL;
1504 }
1505
1506 return ret;
1507}
1508EXPORT_SYMBOL_GPL(wm8350_register_regulator);
1509
Mark Brown0081e802008-12-04 16:52:33 +00001510/**
1511 * wm8350_register_led - Register a WM8350 LED output
1512 *
1513 * @param wm8350 The WM8350 device to configure.
1514 * @param lednum LED device index to create.
1515 * @param dcdc The DCDC to use for the LED.
1516 * @param isink The ISINK to use for the LED.
1517 * @param pdata Configuration for the LED.
1518 *
1519 * The WM8350 supports the use of an ISINK together with a DCDC to
1520 * provide a power-efficient LED driver. This function registers the
1521 * regulators and instantiates the platform device for a LED. The
1522 * operating modes for the LED regulators must be configured using
1523 * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and
1524 * wm8350_dcdc_set_slot() prior to calling this function.
1525 */
1526int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink,
1527 struct wm8350_led_platform_data *pdata)
1528{
1529 struct wm8350_led *led;
1530 struct platform_device *pdev;
1531 int ret;
1532
Roel Kluin8dd2c9e2009-01-17 16:06:40 +01001533 if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) {
Mark Brown0081e802008-12-04 16:52:33 +00001534 dev_err(wm8350->dev, "Invalid LED index %d\n", lednum);
1535 return -ENODEV;
1536 }
1537
1538 led = &wm8350->pmic.led[lednum];
1539
1540 if (led->pdev) {
1541 dev_err(wm8350->dev, "LED %d already allocated\n", lednum);
1542 return -EINVAL;
1543 }
1544
1545 pdev = platform_device_alloc("wm8350-led", lednum);
1546 if (pdev == NULL) {
1547 dev_err(wm8350->dev, "Failed to allocate LED %d\n", lednum);
1548 return -ENOMEM;
1549 }
1550
1551 led->isink_consumer.dev = &pdev->dev;
1552 led->isink_consumer.supply = "led_isink";
1553 led->isink_init.num_consumer_supplies = 1;
1554 led->isink_init.consumer_supplies = &led->isink_consumer;
1555 led->isink_init.constraints.min_uA = 0;
1556 led->isink_init.constraints.max_uA = pdata->max_uA;
Mark Browna2fad9b2010-01-04 15:30:54 +00001557 led->isink_init.constraints.valid_ops_mask
1558 = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001559 led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
1560 ret = wm8350_register_regulator(wm8350, isink, &led->isink_init);
1561 if (ret != 0) {
1562 platform_device_put(pdev);
1563 return ret;
1564 }
1565
1566 led->dcdc_consumer.dev = &pdev->dev;
1567 led->dcdc_consumer.supply = "led_vcc";
1568 led->dcdc_init.num_consumer_supplies = 1;
1569 led->dcdc_init.consumer_supplies = &led->dcdc_consumer;
1570 led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
Mark Browna2fad9b2010-01-04 15:30:54 +00001571 led->dcdc_init.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001572 ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init);
1573 if (ret != 0) {
1574 platform_device_put(pdev);
1575 return ret;
1576 }
1577
1578 switch (isink) {
1579 case WM8350_ISINK_A:
1580 wm8350->pmic.isink_A_dcdc = dcdc;
1581 break;
1582 case WM8350_ISINK_B:
1583 wm8350->pmic.isink_B_dcdc = dcdc;
1584 break;
1585 }
1586
1587 pdev->dev.platform_data = pdata;
1588 pdev->dev.parent = wm8350->dev;
1589 ret = platform_device_add(pdev);
1590 if (ret != 0) {
1591 dev_err(wm8350->dev, "Failed to register LED %d: %d\n",
1592 lednum, ret);
1593 platform_device_put(pdev);
1594 return ret;
1595 }
1596
1597 led->pdev = pdev;
1598
1599 return 0;
1600}
1601EXPORT_SYMBOL_GPL(wm8350_register_led);
1602
Mark Brownda091552008-10-10 15:58:15 +01001603static struct platform_driver wm8350_regulator_driver = {
1604 .probe = wm8350_regulator_probe,
1605 .remove = wm8350_regulator_remove,
1606 .driver = {
1607 .name = "wm8350-regulator",
1608 },
1609};
1610
1611static int __init wm8350_regulator_init(void)
1612{
1613 return platform_driver_register(&wm8350_regulator_driver);
1614}
1615subsys_initcall(wm8350_regulator_init);
1616
1617static void __exit wm8350_regulator_exit(void)
1618{
1619 platform_driver_unregister(&wm8350_regulator_driver);
1620}
1621module_exit(wm8350_regulator_exit);
1622
1623/* Module information */
1624MODULE_AUTHOR("Liam Girdwood");
1625MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
1626MODULE_LICENSE("GPL");
Mark Brown38c53c82009-04-28 11:13:55 +01001627MODULE_ALIAS("platform:wm8350-regulator");