blob: a618284fc45e57f73e5fe8f2deb65f52ff66cf3d [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
Axel Lin3a744032012-03-27 15:20:08 +0800102 for (i = 0; i < ARRAY_SIZE(isink_cur); i++) {
Mark Brownda091552008-10-10 15:58:15 +0100103 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
Axel Linfa5a97b2012-03-27 15:21:45 +0800189 return isink_cur[val];
Mark Brownda091552008-10-10 15:58:15 +0100190}
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
Mark Brownda091552008-10-10 15:58:15 +0100362static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
363{
364 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
365 int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
366 u16 val;
367
368 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
369
370 if (mV && (mV < 850 || mV > 4025)) {
371 dev_err(wm8350->dev,
372 "DCDC%d suspend voltage %d mV out of range\n",
373 dcdc, mV);
374 return -EINVAL;
375 }
376 if (mV == 0)
377 mV = 850;
378
379 switch (dcdc) {
380 case WM8350_DCDC_1:
381 volt_reg = WM8350_DCDC1_LOW_POWER;
382 break;
383 case WM8350_DCDC_3:
384 volt_reg = WM8350_DCDC3_LOW_POWER;
385 break;
386 case WM8350_DCDC_4:
387 volt_reg = WM8350_DCDC4_LOW_POWER;
388 break;
389 case WM8350_DCDC_6:
390 volt_reg = WM8350_DCDC6_LOW_POWER;
391 break;
392 case WM8350_DCDC_2:
393 case WM8350_DCDC_5:
394 default:
395 return -EINVAL;
396 }
397
398 /* all DCDCs have same mV bits */
399 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
400 wm8350_reg_write(wm8350, volt_reg,
401 val | wm8350_dcdc_mvolts_to_val(mV));
402 return 0;
403}
404
405static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
406{
407 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
408 int dcdc = rdev_get_id(rdev);
409 u16 val;
410
411 switch (dcdc) {
412 case WM8350_DCDC_1:
413 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
414 & ~WM8350_DCDC_HIB_MODE_MASK;
415 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
Axel Lineb416812012-03-23 06:25:05 +0800416 val | wm8350->pmic.dcdc1_hib_mode);
Mark Brownda091552008-10-10 15:58:15 +0100417 break;
418 case WM8350_DCDC_3:
419 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
420 & ~WM8350_DCDC_HIB_MODE_MASK;
421 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
Axel Lineb416812012-03-23 06:25:05 +0800422 val | wm8350->pmic.dcdc3_hib_mode);
Mark Brownda091552008-10-10 15:58:15 +0100423 break;
424 case WM8350_DCDC_4:
425 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
426 & ~WM8350_DCDC_HIB_MODE_MASK;
427 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
Axel Lineb416812012-03-23 06:25:05 +0800428 val | wm8350->pmic.dcdc4_hib_mode);
Mark Brownda091552008-10-10 15:58:15 +0100429 break;
430 case WM8350_DCDC_6:
431 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
432 & ~WM8350_DCDC_HIB_MODE_MASK;
433 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
Axel Lineb416812012-03-23 06:25:05 +0800434 val | wm8350->pmic.dcdc6_hib_mode);
Mark Brownda091552008-10-10 15:58:15 +0100435 break;
436 case WM8350_DCDC_2:
437 case WM8350_DCDC_5:
438 default:
439 return -EINVAL;
440 }
441
442 return 0;
443}
444
445static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
446{
447 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
448 int dcdc = rdev_get_id(rdev);
449 u16 val;
450
451 switch (dcdc) {
452 case WM8350_DCDC_1:
453 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
454 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
455 wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
Axel Lincee1a792012-03-29 10:47:36 +0800456 val | WM8350_DCDC_HIB_MODE_DIS);
Mark Brownda091552008-10-10 15:58:15 +0100457 break;
458 case WM8350_DCDC_3:
459 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
460 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
461 wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
Axel Lincee1a792012-03-29 10:47:36 +0800462 val | WM8350_DCDC_HIB_MODE_DIS);
Mark Brownda091552008-10-10 15:58:15 +0100463 break;
464 case WM8350_DCDC_4:
465 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
466 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
467 wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
Axel Lincee1a792012-03-29 10:47:36 +0800468 val | WM8350_DCDC_HIB_MODE_DIS);
Mark Brownda091552008-10-10 15:58:15 +0100469 break;
470 case WM8350_DCDC_6:
471 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
472 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
473 wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
Axel Lincee1a792012-03-29 10:47:36 +0800474 val | WM8350_DCDC_HIB_MODE_DIS);
Mark Brownda091552008-10-10 15:58:15 +0100475 break;
476 case WM8350_DCDC_2:
477 case WM8350_DCDC_5:
478 default:
479 return -EINVAL;
480 }
481
482 return 0;
483}
484
485static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
486{
487 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
488 int dcdc = rdev_get_id(rdev);
489 u16 val;
490
491 switch (dcdc) {
492 case WM8350_DCDC_2:
493 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
494 & ~WM8350_DC2_HIB_MODE_MASK;
495 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
Axel Lin93009282012-03-23 06:27:10 +0800496 (WM8350_DC2_HIB_MODE_ACTIVE << WM8350_DC2_HIB_MODE_SHIFT));
Mark Brownda091552008-10-10 15:58:15 +0100497 break;
498 case WM8350_DCDC_5:
499 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
Axel Lin93009282012-03-23 06:27:10 +0800500 & ~WM8350_DC5_HIB_MODE_MASK;
Mark Brownda091552008-10-10 15:58:15 +0100501 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
Axel Lin93009282012-03-23 06:27:10 +0800502 (WM8350_DC5_HIB_MODE_ACTIVE << WM8350_DC5_HIB_MODE_SHIFT));
Mark Brownda091552008-10-10 15:58:15 +0100503 break;
504 default:
505 return -EINVAL;
506 }
507 return 0;
508}
509
510static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
511{
512 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
513 int dcdc = rdev_get_id(rdev);
514 u16 val;
515
516 switch (dcdc) {
517 case WM8350_DCDC_2:
518 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
519 & ~WM8350_DC2_HIB_MODE_MASK;
520 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
Axel Lin93009282012-03-23 06:27:10 +0800521 (WM8350_DC2_HIB_MODE_DISABLE << WM8350_DC2_HIB_MODE_SHIFT));
Mark Brownda091552008-10-10 15:58:15 +0100522 break;
523 case WM8350_DCDC_5:
524 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
Axel Lin93009282012-03-23 06:27:10 +0800525 & ~WM8350_DC5_HIB_MODE_MASK;
Mark Brownda091552008-10-10 15:58:15 +0100526 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
Axel Lin93009282012-03-23 06:27:10 +0800527 (WM8350_DC5_HIB_MODE_DISABLE << WM8350_DC5_HIB_MODE_SHIFT));
Mark Brownda091552008-10-10 15:58:15 +0100528 break;
529 default:
530 return -EINVAL;
531 }
532 return 0;
533}
534
535static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
536 unsigned int mode)
537{
538 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
539 int dcdc = rdev_get_id(rdev);
540 u16 *hib_mode;
541
542 switch (dcdc) {
543 case WM8350_DCDC_1:
544 hib_mode = &wm8350->pmic.dcdc1_hib_mode;
545 break;
546 case WM8350_DCDC_3:
547 hib_mode = &wm8350->pmic.dcdc3_hib_mode;
548 break;
549 case WM8350_DCDC_4:
550 hib_mode = &wm8350->pmic.dcdc4_hib_mode;
551 break;
552 case WM8350_DCDC_6:
553 hib_mode = &wm8350->pmic.dcdc6_hib_mode;
554 break;
555 case WM8350_DCDC_2:
556 case WM8350_DCDC_5:
557 default:
558 return -EINVAL;
559 }
560
561 switch (mode) {
562 case REGULATOR_MODE_NORMAL:
563 *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
564 break;
565 case REGULATOR_MODE_IDLE:
566 *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
567 break;
568 case REGULATOR_MODE_STANDBY:
569 *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
570 break;
571 default:
572 return -EINVAL;
573 }
574
575 return 0;
576}
577
578static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
579{
580 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
581 int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
582 u16 val;
583
584 dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
585
586 if (mV < 900 || mV > 3300) {
587 dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
588 ldo, mV);
589 return -EINVAL;
590 }
591
592 switch (ldo) {
593 case WM8350_LDO_1:
594 volt_reg = WM8350_LDO1_LOW_POWER;
595 break;
596 case WM8350_LDO_2:
597 volt_reg = WM8350_LDO2_LOW_POWER;
598 break;
599 case WM8350_LDO_3:
600 volt_reg = WM8350_LDO3_LOW_POWER;
601 break;
602 case WM8350_LDO_4:
603 volt_reg = WM8350_LDO4_LOW_POWER;
604 break;
605 default:
606 return -EINVAL;
607 }
608
609 /* all LDOs have same mV bits */
610 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
611 wm8350_reg_write(wm8350, volt_reg,
612 val | wm8350_ldo_mvolts_to_val(mV));
613 return 0;
614}
615
616static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
617{
618 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
619 int volt_reg, ldo = rdev_get_id(rdev);
620 u16 val;
621
622 switch (ldo) {
623 case WM8350_LDO_1:
624 volt_reg = WM8350_LDO1_LOW_POWER;
625 break;
626 case WM8350_LDO_2:
627 volt_reg = WM8350_LDO2_LOW_POWER;
628 break;
629 case WM8350_LDO_3:
630 volt_reg = WM8350_LDO3_LOW_POWER;
631 break;
632 case WM8350_LDO_4:
633 volt_reg = WM8350_LDO4_LOW_POWER;
634 break;
635 default:
636 return -EINVAL;
637 }
638
639 /* all LDOs have same mV bits */
640 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
641 wm8350_reg_write(wm8350, volt_reg, val);
642 return 0;
643}
644
645static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
646{
647 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
648 int volt_reg, ldo = rdev_get_id(rdev);
649 u16 val;
650
651 switch (ldo) {
652 case WM8350_LDO_1:
653 volt_reg = WM8350_LDO1_LOW_POWER;
654 break;
655 case WM8350_LDO_2:
656 volt_reg = WM8350_LDO2_LOW_POWER;
657 break;
658 case WM8350_LDO_3:
659 volt_reg = WM8350_LDO3_LOW_POWER;
660 break;
661 case WM8350_LDO_4:
662 volt_reg = WM8350_LDO4_LOW_POWER;
663 break;
664 default:
665 return -EINVAL;
666 }
667
668 /* all LDOs have same mV bits */
669 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
Axel Lincee1a792012-03-29 10:47:36 +0800670 wm8350_reg_write(wm8350, volt_reg, val | WM8350_LDO1_HIB_MODE_DIS);
Mark Brownda091552008-10-10 15:58:15 +0100671 return 0;
672}
673
674static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000675 int max_uV, unsigned *selector)
Mark Brownda091552008-10-10 15:58:15 +0100676{
677 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
678 int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
679 max_mV = max_uV / 1000;
680 u16 val;
681
682 if (min_mV < 900 || min_mV > 3300)
683 return -EINVAL;
684 if (max_mV < 900 || max_mV > 3300)
685 return -EINVAL;
686
687 if (min_mV < 1800) {
688 /* step size is 50mV < 1800mV */
689 mV = (min_mV - 851) / 50;
690 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
691 return -EINVAL;
692 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
693 } else {
694 /* step size is 100mV > 1800mV */
695 mV = ((min_mV - 1701) / 100) + 16;
696 if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
697 return -EINVAL;
698 BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
699 }
700
701 switch (ldo) {
702 case WM8350_LDO_1:
703 volt_reg = WM8350_LDO1_CONTROL;
704 break;
705 case WM8350_LDO_2:
706 volt_reg = WM8350_LDO2_CONTROL;
707 break;
708 case WM8350_LDO_3:
709 volt_reg = WM8350_LDO3_CONTROL;
710 break;
711 case WM8350_LDO_4:
712 volt_reg = WM8350_LDO4_CONTROL;
713 break;
714 default:
715 return -EINVAL;
716 }
717
Mark Brown3a93f2a2010-11-10 14:38:29 +0000718 *selector = mV;
719
Mark Brownda091552008-10-10 15:58:15 +0100720 /* all LDOs have same mV bits */
721 val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
722 wm8350_reg_write(wm8350, volt_reg, val | mV);
723 return 0;
724}
725
Mark Brown221a7c72009-03-02 16:32:47 +0000726static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
727 unsigned selector)
728{
729 if (selector > WM8350_LDO1_VSEL_MASK)
730 return -EINVAL;
731 return wm8350_ldo_val_to_mvolts(selector) * 1000;
732}
733
Mark Brownda091552008-10-10 15:58:15 +0100734int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
735 u16 stop, u16 fault)
736{
737 int slot_reg;
738 u16 val;
739
740 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
741 __func__, dcdc, start, stop);
742
743 /* slot valid ? */
744 if (start > 15 || stop > 15)
745 return -EINVAL;
746
747 switch (dcdc) {
748 case WM8350_DCDC_1:
749 slot_reg = WM8350_DCDC1_TIMEOUTS;
750 break;
751 case WM8350_DCDC_2:
752 slot_reg = WM8350_DCDC2_TIMEOUTS;
753 break;
754 case WM8350_DCDC_3:
755 slot_reg = WM8350_DCDC3_TIMEOUTS;
756 break;
757 case WM8350_DCDC_4:
758 slot_reg = WM8350_DCDC4_TIMEOUTS;
759 break;
760 case WM8350_DCDC_5:
761 slot_reg = WM8350_DCDC5_TIMEOUTS;
762 break;
763 case WM8350_DCDC_6:
764 slot_reg = WM8350_DCDC6_TIMEOUTS;
765 break;
766 default:
767 return -EINVAL;
768 }
769
770 val = wm8350_reg_read(wm8350, slot_reg) &
771 ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
772 WM8350_DC1_ERRACT_MASK);
773 wm8350_reg_write(wm8350, slot_reg,
774 val | (start << WM8350_DC1_ENSLOT_SHIFT) |
775 (stop << WM8350_DC1_SDSLOT_SHIFT) |
776 (fault << WM8350_DC1_ERRACT_SHIFT));
777
778 return 0;
779}
780EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
781
782int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
783{
784 int slot_reg;
785 u16 val;
786
787 dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
788 __func__, ldo, start, stop);
789
790 /* slot valid ? */
791 if (start > 15 || stop > 15)
792 return -EINVAL;
793
794 switch (ldo) {
795 case WM8350_LDO_1:
796 slot_reg = WM8350_LDO1_TIMEOUTS;
797 break;
798 case WM8350_LDO_2:
799 slot_reg = WM8350_LDO2_TIMEOUTS;
800 break;
801 case WM8350_LDO_3:
802 slot_reg = WM8350_LDO3_TIMEOUTS;
803 break;
804 case WM8350_LDO_4:
805 slot_reg = WM8350_LDO4_TIMEOUTS;
806 break;
807 default:
808 return -EINVAL;
809 }
810
811 val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
812 wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
813 return 0;
814}
815EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
816
817int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
818 u16 ilim, u16 ramp, u16 feedback)
819{
820 u16 val;
821
822 dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
823 mode ? "normal" : "boost", ilim ? "low" : "normal");
824
825 switch (dcdc) {
826 case WM8350_DCDC_2:
827 val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
828 & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
829 WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
830 wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
831 (mode << WM8350_DC2_MODE_SHIFT) |
832 (ilim << WM8350_DC2_ILIM_SHIFT) |
833 (ramp << WM8350_DC2_RMP_SHIFT) |
834 (feedback << WM8350_DC2_FBSRC_SHIFT));
835 break;
836 case WM8350_DCDC_5:
837 val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
838 & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
839 WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
840 wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
841 (mode << WM8350_DC5_MODE_SHIFT) |
842 (ilim << WM8350_DC5_ILIM_SHIFT) |
843 (ramp << WM8350_DC5_RMP_SHIFT) |
844 (feedback << WM8350_DC5_FBSRC_SHIFT));
845 break;
846 default:
847 return -EINVAL;
848 }
849
850 return 0;
851}
852EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
853
Mark Brownda091552008-10-10 15:58:15 +0100854static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
855{
856 int reg = 0, ret;
857
858 switch (dcdc) {
859 case WM8350_DCDC_1:
860 reg = WM8350_DCDC1_FORCE_PWM;
861 break;
862 case WM8350_DCDC_3:
863 reg = WM8350_DCDC3_FORCE_PWM;
864 break;
865 case WM8350_DCDC_4:
866 reg = WM8350_DCDC4_FORCE_PWM;
867 break;
868 case WM8350_DCDC_6:
869 reg = WM8350_DCDC6_FORCE_PWM;
870 break;
871 default:
872 return -EINVAL;
873 }
874
875 if (enable)
876 ret = wm8350_set_bits(wm8350, reg,
877 WM8350_DCDC1_FORCE_PWM_ENA);
878 else
879 ret = wm8350_clear_bits(wm8350, reg,
880 WM8350_DCDC1_FORCE_PWM_ENA);
881 return ret;
882}
883
884static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
885{
886 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
887 int dcdc = rdev_get_id(rdev);
888 u16 val;
889
890 if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
891 return -EINVAL;
892
893 if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
894 return -EINVAL;
895
896 val = 1 << (dcdc - WM8350_DCDC_1);
897
898 switch (mode) {
899 case REGULATOR_MODE_FAST:
900 /* force continuous mode */
901 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
902 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
903 force_continuous_enable(wm8350, dcdc, 1);
904 break;
905 case REGULATOR_MODE_NORMAL:
906 /* active / pulse skipping */
907 wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
908 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
909 force_continuous_enable(wm8350, dcdc, 0);
910 break;
911 case REGULATOR_MODE_IDLE:
912 /* standby mode */
913 force_continuous_enable(wm8350, dcdc, 0);
914 wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
915 wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
916 break;
917 case REGULATOR_MODE_STANDBY:
918 /* LDO mode */
919 force_continuous_enable(wm8350, dcdc, 0);
920 wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
921 break;
922 }
923
924 return 0;
925}
926
927static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
928{
929 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
930 int dcdc = rdev_get_id(rdev);
931 u16 mask, sleep, active, force;
932 int mode = REGULATOR_MODE_NORMAL;
Mark Brown33f301a2009-02-26 19:24:20 +0000933 int reg;
Mark Brownda091552008-10-10 15:58:15 +0100934
Mark Brown33f301a2009-02-26 19:24:20 +0000935 switch (dcdc) {
936 case WM8350_DCDC_1:
937 reg = WM8350_DCDC1_FORCE_PWM;
938 break;
939 case WM8350_DCDC_3:
940 reg = WM8350_DCDC3_FORCE_PWM;
941 break;
942 case WM8350_DCDC_4:
943 reg = WM8350_DCDC4_FORCE_PWM;
944 break;
945 case WM8350_DCDC_6:
946 reg = WM8350_DCDC6_FORCE_PWM;
947 break;
948 default:
Mark Brownda091552008-10-10 15:58:15 +0100949 return -EINVAL;
Mark Brown33f301a2009-02-26 19:24:20 +0000950 }
Mark Brownda091552008-10-10 15:58:15 +0100951
952 mask = 1 << (dcdc - WM8350_DCDC_1);
953 active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +0000954 force = wm8350_reg_read(wm8350, reg) & WM8350_DCDC1_FORCE_PWM_ENA;
Mark Brownda091552008-10-10 15:58:15 +0100955 sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
Mark Brown33f301a2009-02-26 19:24:20 +0000956
Mark Brownda091552008-10-10 15:58:15 +0100957 dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
958 mask, active, sleep, force);
959
960 if (active && !sleep) {
961 if (force)
962 mode = REGULATOR_MODE_FAST;
963 else
964 mode = REGULATOR_MODE_NORMAL;
965 } else if (!active && !sleep)
966 mode = REGULATOR_MODE_IDLE;
Axel Lin8ecee362010-09-06 14:06:07 +0800967 else if (sleep)
Mark Brownda091552008-10-10 15:58:15 +0100968 mode = REGULATOR_MODE_STANDBY;
969
970 return mode;
971}
972
973static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
974{
975 return REGULATOR_MODE_NORMAL;
976}
977
978struct wm8350_dcdc_efficiency {
979 int uA_load_min;
980 int uA_load_max;
981 unsigned int mode;
982};
983
984static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
985 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
986 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
987 {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
988 {-1, -1, REGULATOR_MODE_NORMAL},
989};
990
991static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
992 {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
993 {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
994 {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
995 {-1, -1, REGULATOR_MODE_NORMAL},
996};
997
998static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
999{
1000 int i = 0;
1001
1002 while (eff[i].uA_load_min != -1) {
1003 if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
1004 return eff[i].mode;
1005 }
1006 return REGULATOR_MODE_NORMAL;
1007}
1008
1009/* Query the regulator for it's most efficient mode @ uV,uA
1010 * WM8350 regulator efficiency is pretty similar over
1011 * different input and output uV.
1012 */
1013static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
1014 int input_uV, int output_uV,
1015 int output_uA)
1016{
1017 int dcdc = rdev_get_id(rdev), mode;
1018
1019 switch (dcdc) {
1020 case WM8350_DCDC_1:
1021 case WM8350_DCDC_6:
1022 mode = get_mode(output_uA, dcdc1_6_efficiency);
1023 break;
1024 case WM8350_DCDC_3:
1025 case WM8350_DCDC_4:
1026 mode = get_mode(output_uA, dcdc3_4_efficiency);
1027 break;
1028 default:
1029 mode = REGULATOR_MODE_NORMAL;
1030 break;
1031 }
1032 return mode;
1033}
1034
Mark Brownda091552008-10-10 15:58:15 +01001035static struct regulator_ops wm8350_dcdc_ops = {
Mark Brown107a3962012-05-09 22:22:30 +01001036 .set_voltage_sel = regulator_set_voltage_sel_regmap,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001037 .get_voltage_sel = regulator_get_voltage_sel_regmap,
Mark Brown107a3962012-05-09 22:22:30 +01001038 .list_voltage = regulator_list_voltage_linear,
Mark Browna540f682012-04-30 21:08:59 +01001039 .enable = regulator_enable_regmap,
1040 .disable = regulator_disable_regmap,
1041 .is_enabled = regulator_is_enabled_regmap,
Mark Brownda091552008-10-10 15:58:15 +01001042 .get_mode = wm8350_dcdc_get_mode,
1043 .set_mode = wm8350_dcdc_set_mode,
1044 .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
Mark Brownda091552008-10-10 15:58:15 +01001045 .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
1046 .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
1047 .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
1048 .set_suspend_mode = wm8350_dcdc_set_suspend_mode,
1049};
1050
1051static struct regulator_ops wm8350_dcdc2_5_ops = {
Mark Browna540f682012-04-30 21:08:59 +01001052 .enable = regulator_enable_regmap,
1053 .disable = regulator_disable_regmap,
1054 .is_enabled = regulator_is_enabled_regmap,
Mark Brownda091552008-10-10 15:58:15 +01001055 .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
1056 .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
1057};
1058
1059static struct regulator_ops wm8350_ldo_ops = {
1060 .set_voltage = wm8350_ldo_set_voltage,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001061 .get_voltage_sel = regulator_get_voltage_sel_regmap,
Mark Brown221a7c72009-03-02 16:32:47 +00001062 .list_voltage = wm8350_ldo_list_voltage,
Mark Browna540f682012-04-30 21:08:59 +01001063 .enable = regulator_enable_regmap,
1064 .disable = regulator_disable_regmap,
1065 .is_enabled = regulator_is_enabled_regmap,
Mark Brownda091552008-10-10 15:58:15 +01001066 .get_mode = wm8350_ldo_get_mode,
1067 .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
1068 .set_suspend_enable = wm8350_ldo_set_suspend_enable,
1069 .set_suspend_disable = wm8350_ldo_set_suspend_disable,
1070};
1071
1072static struct regulator_ops wm8350_isink_ops = {
1073 .set_current_limit = wm8350_isink_set_current,
1074 .get_current_limit = wm8350_isink_get_current,
1075 .enable = wm8350_isink_enable,
1076 .disable = wm8350_isink_disable,
1077 .is_enabled = wm8350_isink_is_enabled,
Mark Brown75c8ac22010-01-04 17:24:01 +00001078 .enable_time = wm8350_isink_enable_time,
Mark Brownda091552008-10-10 15:58:15 +01001079};
1080
Mark Brown47924b62012-04-03 20:47:15 +01001081static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
Mark Brownda091552008-10-10 15:58:15 +01001082 {
1083 .name = "DCDC1",
1084 .id = WM8350_DCDC_1,
1085 .ops = &wm8350_dcdc_ops,
1086 .irq = WM8350_IRQ_UV_DC1,
1087 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001088 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brown107a3962012-05-09 22:22:30 +01001089 .min_uV = 850000,
1090 .uV_step = 25000,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001091 .vsel_reg = WM8350_DCDC1_CONTROL,
1092 .vsel_mask = WM8350_DC1_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001093 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1094 .enable_mask = WM8350_DC1_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001095 .owner = THIS_MODULE,
1096 },
1097 {
1098 .name = "DCDC2",
1099 .id = WM8350_DCDC_2,
1100 .ops = &wm8350_dcdc2_5_ops,
1101 .irq = WM8350_IRQ_UV_DC2,
1102 .type = REGULATOR_VOLTAGE,
Mark Browna540f682012-04-30 21:08:59 +01001103 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1104 .enable_mask = WM8350_DC2_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001105 .owner = THIS_MODULE,
1106 },
1107 {
1108 .name = "DCDC3",
1109 .id = WM8350_DCDC_3,
1110 .ops = &wm8350_dcdc_ops,
1111 .irq = WM8350_IRQ_UV_DC3,
1112 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001113 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brown107a3962012-05-09 22:22:30 +01001114 .min_uV = 850000,
1115 .uV_step = 25000,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001116 .vsel_reg = WM8350_DCDC3_CONTROL,
1117 .vsel_mask = WM8350_DC3_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001118 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1119 .enable_mask = WM8350_DC3_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001120 .owner = THIS_MODULE,
1121 },
1122 {
1123 .name = "DCDC4",
1124 .id = WM8350_DCDC_4,
1125 .ops = &wm8350_dcdc_ops,
1126 .irq = WM8350_IRQ_UV_DC4,
1127 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001128 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001129 .vsel_reg = WM8350_DCDC4_CONTROL,
1130 .vsel_mask = WM8350_DC4_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001131 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1132 .enable_mask = WM8350_DC4_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001133 .owner = THIS_MODULE,
1134 },
1135 {
1136 .name = "DCDC5",
1137 .id = WM8350_DCDC_5,
1138 .ops = &wm8350_dcdc2_5_ops,
1139 .irq = WM8350_IRQ_UV_DC5,
1140 .type = REGULATOR_VOLTAGE,
Mark Browna540f682012-04-30 21:08:59 +01001141 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1142 .enable_mask = WM8350_DC5_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001143 .owner = THIS_MODULE,
1144 },
1145 {
1146 .name = "DCDC6",
1147 .id = WM8350_DCDC_6,
1148 .ops = &wm8350_dcdc_ops,
1149 .irq = WM8350_IRQ_UV_DC6,
1150 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001151 .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
Mark Brown107a3962012-05-09 22:22:30 +01001152 .min_uV = 850000,
1153 .uV_step = 25000,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001154 .vsel_reg = WM8350_DCDC6_CONTROL,
1155 .vsel_mask = WM8350_DC6_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001156 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1157 .enable_mask = WM8350_DC6_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001158 .owner = THIS_MODULE,
1159 },
1160 {
1161 .name = "LDO1",
1162 .id = WM8350_LDO_1,
1163 .ops = &wm8350_ldo_ops,
1164 .irq = WM8350_IRQ_UV_LDO1,
1165 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001166 .n_voltages = WM8350_LDO1_VSEL_MASK + 1,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001167 .vsel_reg = WM8350_LDO1_CONTROL,
1168 .vsel_mask = WM8350_LDO1_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001169 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1170 .enable_mask = WM8350_LDO1_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001171 .owner = THIS_MODULE,
1172 },
1173 {
1174 .name = "LDO2",
1175 .id = WM8350_LDO_2,
1176 .ops = &wm8350_ldo_ops,
1177 .irq = WM8350_IRQ_UV_LDO2,
1178 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001179 .n_voltages = WM8350_LDO2_VSEL_MASK + 1,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001180 .vsel_reg = WM8350_LDO2_CONTROL,
1181 .vsel_mask = WM8350_LDO2_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001182 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1183 .enable_mask = WM8350_LDO2_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001184 .owner = THIS_MODULE,
1185 },
1186 {
1187 .name = "LDO3",
1188 .id = WM8350_LDO_3,
1189 .ops = &wm8350_ldo_ops,
1190 .irq = WM8350_IRQ_UV_LDO3,
1191 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001192 .n_voltages = WM8350_LDO3_VSEL_MASK + 1,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001193 .vsel_reg = WM8350_LDO3_CONTROL,
1194 .vsel_mask = WM8350_LDO3_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001195 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1196 .enable_mask = WM8350_LDO3_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001197 .owner = THIS_MODULE,
1198 },
1199 {
1200 .name = "LDO4",
1201 .id = WM8350_LDO_4,
1202 .ops = &wm8350_ldo_ops,
1203 .irq = WM8350_IRQ_UV_LDO4,
1204 .type = REGULATOR_VOLTAGE,
Mark Brown221a7c72009-03-02 16:32:47 +00001205 .n_voltages = WM8350_LDO4_VSEL_MASK + 1,
Mark Brownb4ec87a2012-04-30 21:00:10 +01001206 .vsel_reg = WM8350_LDO4_CONTROL,
1207 .vsel_mask = WM8350_LDO4_VSEL_MASK,
Mark Browna540f682012-04-30 21:08:59 +01001208 .enable_reg = WM8350_DCDC_LDO_REQUESTED,
1209 .enable_mask = WM8350_LDO4_ENA,
Mark Brownda091552008-10-10 15:58:15 +01001210 .owner = THIS_MODULE,
1211 },
1212 {
1213 .name = "ISINKA",
1214 .id = WM8350_ISINK_A,
1215 .ops = &wm8350_isink_ops,
1216 .irq = WM8350_IRQ_CS1,
1217 .type = REGULATOR_CURRENT,
1218 .owner = THIS_MODULE,
1219 },
1220 {
1221 .name = "ISINKB",
1222 .id = WM8350_ISINK_B,
1223 .ops = &wm8350_isink_ops,
1224 .irq = WM8350_IRQ_CS2,
1225 .type = REGULATOR_CURRENT,
1226 .owner = THIS_MODULE,
1227 },
1228};
1229
Mark Brown5a65edb2009-11-04 16:10:51 +00001230static irqreturn_t pmic_uv_handler(int irq, void *data)
Mark Brownda091552008-10-10 15:58:15 +01001231{
1232 struct regulator_dev *rdev = (struct regulator_dev *)data;
Mark Brown5a65edb2009-11-04 16:10:51 +00001233 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
Mark Brownda091552008-10-10 15:58:15 +01001234
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001235 mutex_lock(&rdev->mutex);
Mark Brownda091552008-10-10 15:58:15 +01001236 if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
1237 regulator_notifier_call_chain(rdev,
1238 REGULATOR_EVENT_REGULATION_OUT,
1239 wm8350);
1240 else
1241 regulator_notifier_call_chain(rdev,
1242 REGULATOR_EVENT_UNDER_VOLTAGE,
1243 wm8350);
Jonathan Cameronb136fb42009-01-19 18:20:58 +00001244 mutex_unlock(&rdev->mutex);
Mark Brown5a65edb2009-11-04 16:10:51 +00001245
1246 return IRQ_HANDLED;
Mark Brownda091552008-10-10 15:58:15 +01001247}
1248
1249static int wm8350_regulator_probe(struct platform_device *pdev)
1250{
1251 struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
Mark Brownc1727082012-04-04 00:50:22 +01001252 struct regulator_config config = { };
Mark Brownda091552008-10-10 15:58:15 +01001253 struct regulator_dev *rdev;
1254 int ret;
1255 u16 val;
1256
1257 if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
1258 return -ENODEV;
1259
1260 /* do any regulatior specific init */
1261 switch (pdev->id) {
1262 case WM8350_DCDC_1:
1263 val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
1264 wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1265 break;
1266 case WM8350_DCDC_3:
1267 val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
1268 wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1269 break;
1270 case WM8350_DCDC_4:
1271 val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
1272 wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1273 break;
1274 case WM8350_DCDC_6:
1275 val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
1276 wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
1277 break;
1278 }
1279
Mark Brownc1727082012-04-04 00:50:22 +01001280 config.dev = &pdev->dev;
1281 config.init_data = pdev->dev.platform_data;
1282 config.driver_data = dev_get_drvdata(&pdev->dev);
Mark Brownb4ec87a2012-04-30 21:00:10 +01001283 config.regmap = wm8350->regmap;
Mark Brownc1727082012-04-04 00:50:22 +01001284
Mark Brownda091552008-10-10 15:58:15 +01001285 /* register regulator */
Mark Brownc1727082012-04-04 00:50:22 +01001286 rdev = regulator_register(&wm8350_reg[pdev->id], &config);
Mark Brownda091552008-10-10 15:58:15 +01001287 if (IS_ERR(rdev)) {
1288 dev_err(&pdev->dev, "failed to register %s\n",
1289 wm8350_reg[pdev->id].name);
1290 return PTR_ERR(rdev);
1291 }
1292
1293 /* register regulator IRQ */
1294 ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
Mark Brown5a65edb2009-11-04 16:10:51 +00001295 pmic_uv_handler, 0, "UV", rdev);
Mark Brownda091552008-10-10 15:58:15 +01001296 if (ret < 0) {
1297 regulator_unregister(rdev);
1298 dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
1299 wm8350_reg[pdev->id].name);
1300 return ret;
1301 }
1302
Mark Brownda091552008-10-10 15:58:15 +01001303 return 0;
1304}
1305
1306static int wm8350_regulator_remove(struct platform_device *pdev)
1307{
1308 struct regulator_dev *rdev = platform_get_drvdata(pdev);
1309 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1310
Mark Brownf99344f2010-01-05 13:59:07 +00001311 wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
Mark Brownda091552008-10-10 15:58:15 +01001312
1313 regulator_unregister(rdev);
1314
1315 return 0;
1316}
1317
1318int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
1319 struct regulator_init_data *initdata)
1320{
1321 struct platform_device *pdev;
1322 int ret;
Roel Kluin4dee4d42009-06-15 22:30:39 +02001323 if (reg < 0 || reg >= NUM_WM8350_REGULATORS)
1324 return -EINVAL;
Mark Brownda091552008-10-10 15:58:15 +01001325
1326 if (wm8350->pmic.pdev[reg])
1327 return -EBUSY;
1328
Mark Brown645524a2008-12-18 23:12:16 +01001329 if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 &&
1330 reg > wm8350->pmic.max_dcdc)
1331 return -ENODEV;
1332 if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B &&
1333 reg > wm8350->pmic.max_isink)
1334 return -ENODEV;
1335
Mark Brownda091552008-10-10 15:58:15 +01001336 pdev = platform_device_alloc("wm8350-regulator", reg);
1337 if (!pdev)
1338 return -ENOMEM;
1339
1340 wm8350->pmic.pdev[reg] = pdev;
1341
1342 initdata->driver_data = wm8350;
1343
1344 pdev->dev.platform_data = initdata;
1345 pdev->dev.parent = wm8350->dev;
1346 platform_set_drvdata(pdev, wm8350);
1347
1348 ret = platform_device_add(pdev);
1349
1350 if (ret != 0) {
1351 dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
1352 reg, ret);
Axel Line9a1c512010-07-26 10:41:58 +08001353 platform_device_put(pdev);
Mark Brownda091552008-10-10 15:58:15 +01001354 wm8350->pmic.pdev[reg] = NULL;
1355 }
1356
1357 return ret;
1358}
1359EXPORT_SYMBOL_GPL(wm8350_register_regulator);
1360
Mark Brown0081e802008-12-04 16:52:33 +00001361/**
1362 * wm8350_register_led - Register a WM8350 LED output
1363 *
1364 * @param wm8350 The WM8350 device to configure.
1365 * @param lednum LED device index to create.
1366 * @param dcdc The DCDC to use for the LED.
1367 * @param isink The ISINK to use for the LED.
1368 * @param pdata Configuration for the LED.
1369 *
1370 * The WM8350 supports the use of an ISINK together with a DCDC to
1371 * provide a power-efficient LED driver. This function registers the
1372 * regulators and instantiates the platform device for a LED. The
1373 * operating modes for the LED regulators must be configured using
1374 * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and
1375 * wm8350_dcdc_set_slot() prior to calling this function.
1376 */
1377int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink,
1378 struct wm8350_led_platform_data *pdata)
1379{
1380 struct wm8350_led *led;
1381 struct platform_device *pdev;
1382 int ret;
1383
Roel Kluin8dd2c9e2009-01-17 16:06:40 +01001384 if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) {
Mark Brown0081e802008-12-04 16:52:33 +00001385 dev_err(wm8350->dev, "Invalid LED index %d\n", lednum);
1386 return -ENODEV;
1387 }
1388
1389 led = &wm8350->pmic.led[lednum];
1390
1391 if (led->pdev) {
1392 dev_err(wm8350->dev, "LED %d already allocated\n", lednum);
1393 return -EINVAL;
1394 }
1395
1396 pdev = platform_device_alloc("wm8350-led", lednum);
1397 if (pdev == NULL) {
1398 dev_err(wm8350->dev, "Failed to allocate LED %d\n", lednum);
1399 return -ENOMEM;
1400 }
1401
Mark Brown34ce8d02012-02-02 13:45:09 +00001402 led->isink_consumer.dev_name = dev_name(&pdev->dev);
Mark Brown0081e802008-12-04 16:52:33 +00001403 led->isink_consumer.supply = "led_isink";
1404 led->isink_init.num_consumer_supplies = 1;
1405 led->isink_init.consumer_supplies = &led->isink_consumer;
1406 led->isink_init.constraints.min_uA = 0;
1407 led->isink_init.constraints.max_uA = pdata->max_uA;
Mark Browna2fad9b2010-01-04 15:30:54 +00001408 led->isink_init.constraints.valid_ops_mask
1409 = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001410 led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
1411 ret = wm8350_register_regulator(wm8350, isink, &led->isink_init);
1412 if (ret != 0) {
1413 platform_device_put(pdev);
1414 return ret;
1415 }
1416
Mark Brown34ce8d02012-02-02 13:45:09 +00001417 led->dcdc_consumer.dev_name = dev_name(&pdev->dev);
Mark Brown0081e802008-12-04 16:52:33 +00001418 led->dcdc_consumer.supply = "led_vcc";
1419 led->dcdc_init.num_consumer_supplies = 1;
1420 led->dcdc_init.consumer_supplies = &led->dcdc_consumer;
1421 led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
Mark Browna2fad9b2010-01-04 15:30:54 +00001422 led->dcdc_init.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
Mark Brown0081e802008-12-04 16:52:33 +00001423 ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init);
1424 if (ret != 0) {
1425 platform_device_put(pdev);
1426 return ret;
1427 }
1428
1429 switch (isink) {
1430 case WM8350_ISINK_A:
1431 wm8350->pmic.isink_A_dcdc = dcdc;
1432 break;
1433 case WM8350_ISINK_B:
1434 wm8350->pmic.isink_B_dcdc = dcdc;
1435 break;
1436 }
1437
1438 pdev->dev.platform_data = pdata;
1439 pdev->dev.parent = wm8350->dev;
1440 ret = platform_device_add(pdev);
1441 if (ret != 0) {
1442 dev_err(wm8350->dev, "Failed to register LED %d: %d\n",
1443 lednum, ret);
1444 platform_device_put(pdev);
1445 return ret;
1446 }
1447
1448 led->pdev = pdev;
1449
1450 return 0;
1451}
1452EXPORT_SYMBOL_GPL(wm8350_register_led);
1453
Mark Brownda091552008-10-10 15:58:15 +01001454static struct platform_driver wm8350_regulator_driver = {
1455 .probe = wm8350_regulator_probe,
1456 .remove = wm8350_regulator_remove,
1457 .driver = {
1458 .name = "wm8350-regulator",
1459 },
1460};
1461
1462static int __init wm8350_regulator_init(void)
1463{
1464 return platform_driver_register(&wm8350_regulator_driver);
1465}
1466subsys_initcall(wm8350_regulator_init);
1467
1468static void __exit wm8350_regulator_exit(void)
1469{
1470 platform_driver_unregister(&wm8350_regulator_driver);
1471}
1472module_exit(wm8350_regulator_exit);
1473
1474/* Module information */
1475MODULE_AUTHOR("Liam Girdwood");
1476MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
1477MODULE_LICENSE("GPL");
Mark Brown38c53c82009-04-28 11:13:55 +01001478MODULE_ALIAS("platform:wm8350-regulator");