1 // SPDX-License-Identifier: GPL-2.0+
3 // wm8350.c -- Voltage and current regulation for the Wolfson WM8350 PMIC
5 // Copyright 2007, 2008 Wolfson Microelectronics PLC.
7 // Author: Liam Girdwood
8 // linux@wolfsonmicro.com
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/init.h>
13 #include <linux/bitops.h>
14 #include <linux/err.h>
15 #include <linux/i2c.h>
16 #include <linux/mfd/wm8350/core.h>
17 #include <linux/mfd/wm8350/pmic.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/driver.h>
20 #include <linux/regulator/machine.h>
22 /* Maximum value possible for VSEL */
23 #define WM8350_DCDC_MAX_VSEL 0x66
26 static const unsigned int isink_cur
[] = {
93 /* turn on ISINK followed by DCDC */
94 static int wm8350_isink_enable(struct regulator_dev
*rdev
)
96 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
97 int isink
= rdev_get_id(rdev
);
101 switch (wm8350
->pmic
.isink_A_dcdc
) {
104 wm8350_set_bits(wm8350
, WM8350_POWER_MGMT_7
,
106 wm8350_set_bits(wm8350
, WM8350_CSA_FLASH_CONTROL
,
108 wm8350_set_bits(wm8350
, WM8350_DCDC_LDO_REQUESTED
,
109 1 << (wm8350
->pmic
.isink_A_dcdc
-
117 switch (wm8350
->pmic
.isink_B_dcdc
) {
120 wm8350_set_bits(wm8350
, WM8350_POWER_MGMT_7
,
122 wm8350_set_bits(wm8350
, WM8350_CSB_FLASH_CONTROL
,
124 wm8350_set_bits(wm8350
, WM8350_DCDC_LDO_REQUESTED
,
125 1 << (wm8350
->pmic
.isink_B_dcdc
-
138 static int wm8350_isink_disable(struct regulator_dev
*rdev
)
140 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
141 int isink
= rdev_get_id(rdev
);
145 switch (wm8350
->pmic
.isink_A_dcdc
) {
148 wm8350_clear_bits(wm8350
, WM8350_DCDC_LDO_REQUESTED
,
149 1 << (wm8350
->pmic
.isink_A_dcdc
-
151 wm8350_clear_bits(wm8350
, WM8350_POWER_MGMT_7
,
159 switch (wm8350
->pmic
.isink_B_dcdc
) {
162 wm8350_clear_bits(wm8350
, WM8350_DCDC_LDO_REQUESTED
,
163 1 << (wm8350
->pmic
.isink_B_dcdc
-
165 wm8350_clear_bits(wm8350
, WM8350_POWER_MGMT_7
,
178 static int wm8350_isink_is_enabled(struct regulator_dev
*rdev
)
180 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
181 int isink
= rdev_get_id(rdev
);
185 return wm8350_reg_read(wm8350
, WM8350_CURRENT_SINK_DRIVER_A
) &
188 return wm8350_reg_read(wm8350
, WM8350_CURRENT_SINK_DRIVER_B
) &
194 static int wm8350_isink_enable_time(struct regulator_dev
*rdev
)
196 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
197 int isink
= rdev_get_id(rdev
);
202 reg
= wm8350_reg_read(wm8350
, WM8350_CSA_FLASH_CONTROL
);
205 reg
= wm8350_reg_read(wm8350
, WM8350_CSB_FLASH_CONTROL
);
211 if (reg
& WM8350_CS1_FLASH_MODE
) {
212 switch (reg
& WM8350_CS1_ON_RAMP_MASK
) {
223 switch (reg
& WM8350_CS1_ON_RAMP_MASK
) {
239 int wm8350_isink_set_flash(struct wm8350
*wm8350
, int isink
, u16 mode
,
240 u16 trigger
, u16 duration
, u16 on_ramp
, u16 off_ramp
,
245 wm8350_reg_write(wm8350
, WM8350_CSA_FLASH_CONTROL
,
246 (mode
? WM8350_CS1_FLASH_MODE
: 0) |
247 (trigger
? WM8350_CS1_TRIGSRC
: 0) |
248 duration
| on_ramp
| off_ramp
| drive
);
251 wm8350_reg_write(wm8350
, WM8350_CSB_FLASH_CONTROL
,
252 (mode
? WM8350_CS2_FLASH_MODE
: 0) |
253 (trigger
? WM8350_CS2_TRIGSRC
: 0) |
254 duration
| on_ramp
| off_ramp
| drive
);
261 EXPORT_SYMBOL_GPL(wm8350_isink_set_flash
);
263 static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev
*rdev
, int uV
)
265 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
266 int sel
, volt_reg
, dcdc
= rdev_get_id(rdev
);
269 dev_dbg(wm8350
->dev
, "%s %d mV %d\n", __func__
, dcdc
, uV
/ 1000);
273 volt_reg
= WM8350_DCDC1_LOW_POWER
;
276 volt_reg
= WM8350_DCDC3_LOW_POWER
;
279 volt_reg
= WM8350_DCDC4_LOW_POWER
;
282 volt_reg
= WM8350_DCDC6_LOW_POWER
;
290 sel
= regulator_map_voltage_linear(rdev
, uV
, uV
);
294 /* all DCDCs have same mV bits */
295 val
= wm8350_reg_read(wm8350
, volt_reg
) & ~WM8350_DC1_VSEL_MASK
;
296 wm8350_reg_write(wm8350
, volt_reg
, val
| sel
);
300 static int wm8350_dcdc_set_suspend_enable(struct regulator_dev
*rdev
)
302 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
303 int dcdc
= rdev_get_id(rdev
);
308 val
= wm8350_reg_read(wm8350
, WM8350_DCDC1_LOW_POWER
)
309 & ~WM8350_DCDC_HIB_MODE_MASK
;
310 wm8350_reg_write(wm8350
, WM8350_DCDC1_LOW_POWER
,
311 val
| wm8350
->pmic
.dcdc1_hib_mode
);
314 val
= wm8350_reg_read(wm8350
, WM8350_DCDC3_LOW_POWER
)
315 & ~WM8350_DCDC_HIB_MODE_MASK
;
316 wm8350_reg_write(wm8350
, WM8350_DCDC3_LOW_POWER
,
317 val
| wm8350
->pmic
.dcdc3_hib_mode
);
320 val
= wm8350_reg_read(wm8350
, WM8350_DCDC4_LOW_POWER
)
321 & ~WM8350_DCDC_HIB_MODE_MASK
;
322 wm8350_reg_write(wm8350
, WM8350_DCDC4_LOW_POWER
,
323 val
| wm8350
->pmic
.dcdc4_hib_mode
);
326 val
= wm8350_reg_read(wm8350
, WM8350_DCDC6_LOW_POWER
)
327 & ~WM8350_DCDC_HIB_MODE_MASK
;
328 wm8350_reg_write(wm8350
, WM8350_DCDC6_LOW_POWER
,
329 val
| wm8350
->pmic
.dcdc6_hib_mode
);
340 static int wm8350_dcdc_set_suspend_disable(struct regulator_dev
*rdev
)
342 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
343 int dcdc
= rdev_get_id(rdev
);
348 val
= wm8350_reg_read(wm8350
, WM8350_DCDC1_LOW_POWER
);
349 wm8350
->pmic
.dcdc1_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
350 wm8350_reg_write(wm8350
, WM8350_DCDC1_LOW_POWER
,
351 val
| WM8350_DCDC_HIB_MODE_DIS
);
354 val
= wm8350_reg_read(wm8350
, WM8350_DCDC3_LOW_POWER
);
355 wm8350
->pmic
.dcdc3_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
356 wm8350_reg_write(wm8350
, WM8350_DCDC3_LOW_POWER
,
357 val
| WM8350_DCDC_HIB_MODE_DIS
);
360 val
= wm8350_reg_read(wm8350
, WM8350_DCDC4_LOW_POWER
);
361 wm8350
->pmic
.dcdc4_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
362 wm8350_reg_write(wm8350
, WM8350_DCDC4_LOW_POWER
,
363 val
| WM8350_DCDC_HIB_MODE_DIS
);
366 val
= wm8350_reg_read(wm8350
, WM8350_DCDC6_LOW_POWER
);
367 wm8350
->pmic
.dcdc6_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
368 wm8350_reg_write(wm8350
, WM8350_DCDC6_LOW_POWER
,
369 val
| WM8350_DCDC_HIB_MODE_DIS
);
380 static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev
*rdev
)
382 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
383 int dcdc
= rdev_get_id(rdev
);
388 val
= wm8350_reg_read(wm8350
, WM8350_DCDC2_CONTROL
)
389 & ~WM8350_DC2_HIB_MODE_MASK
;
390 wm8350_reg_write(wm8350
, WM8350_DCDC2_CONTROL
, val
|
391 (WM8350_DC2_HIB_MODE_ACTIVE
<< WM8350_DC2_HIB_MODE_SHIFT
));
394 val
= wm8350_reg_read(wm8350
, WM8350_DCDC5_CONTROL
)
395 & ~WM8350_DC5_HIB_MODE_MASK
;
396 wm8350_reg_write(wm8350
, WM8350_DCDC5_CONTROL
, val
|
397 (WM8350_DC5_HIB_MODE_ACTIVE
<< WM8350_DC5_HIB_MODE_SHIFT
));
405 static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev
*rdev
)
407 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
408 int dcdc
= rdev_get_id(rdev
);
413 val
= wm8350_reg_read(wm8350
, WM8350_DCDC2_CONTROL
)
414 & ~WM8350_DC2_HIB_MODE_MASK
;
415 wm8350_reg_write(wm8350
, WM8350_DCDC2_CONTROL
, val
|
416 (WM8350_DC2_HIB_MODE_DISABLE
<< WM8350_DC2_HIB_MODE_SHIFT
));
419 val
= wm8350_reg_read(wm8350
, WM8350_DCDC5_CONTROL
)
420 & ~WM8350_DC5_HIB_MODE_MASK
;
421 wm8350_reg_write(wm8350
, WM8350_DCDC5_CONTROL
, val
|
422 (WM8350_DC5_HIB_MODE_DISABLE
<< WM8350_DC5_HIB_MODE_SHIFT
));
430 static int wm8350_dcdc_set_suspend_mode(struct regulator_dev
*rdev
,
433 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
434 int dcdc
= rdev_get_id(rdev
);
439 hib_mode
= &wm8350
->pmic
.dcdc1_hib_mode
;
442 hib_mode
= &wm8350
->pmic
.dcdc3_hib_mode
;
445 hib_mode
= &wm8350
->pmic
.dcdc4_hib_mode
;
448 hib_mode
= &wm8350
->pmic
.dcdc6_hib_mode
;
457 case REGULATOR_MODE_NORMAL
:
458 *hib_mode
= WM8350_DCDC_HIB_MODE_IMAGE
;
460 case REGULATOR_MODE_IDLE
:
461 *hib_mode
= WM8350_DCDC_HIB_MODE_STANDBY
;
463 case REGULATOR_MODE_STANDBY
:
464 *hib_mode
= WM8350_DCDC_HIB_MODE_LDO_IM
;
473 static const struct regulator_linear_range wm8350_ldo_ranges
[] = {
474 REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
475 REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
478 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev
*rdev
, int uV
)
480 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
481 int sel
, volt_reg
, ldo
= rdev_get_id(rdev
);
484 dev_dbg(wm8350
->dev
, "%s %d mV %d\n", __func__
, ldo
, uV
/ 1000);
488 volt_reg
= WM8350_LDO1_LOW_POWER
;
491 volt_reg
= WM8350_LDO2_LOW_POWER
;
494 volt_reg
= WM8350_LDO3_LOW_POWER
;
497 volt_reg
= WM8350_LDO4_LOW_POWER
;
503 sel
= regulator_map_voltage_linear_range(rdev
, uV
, uV
);
507 /* all LDOs have same mV bits */
508 val
= wm8350_reg_read(wm8350
, volt_reg
) & ~WM8350_LDO1_VSEL_MASK
;
509 wm8350_reg_write(wm8350
, volt_reg
, val
| sel
);
513 static int wm8350_ldo_set_suspend_enable(struct regulator_dev
*rdev
)
515 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
516 int volt_reg
, ldo
= rdev_get_id(rdev
);
521 volt_reg
= WM8350_LDO1_LOW_POWER
;
524 volt_reg
= WM8350_LDO2_LOW_POWER
;
527 volt_reg
= WM8350_LDO3_LOW_POWER
;
530 volt_reg
= WM8350_LDO4_LOW_POWER
;
536 /* all LDOs have same mV bits */
537 val
= wm8350_reg_read(wm8350
, volt_reg
) & ~WM8350_LDO1_HIB_MODE_MASK
;
538 wm8350_reg_write(wm8350
, volt_reg
, val
);
542 static int wm8350_ldo_set_suspend_disable(struct regulator_dev
*rdev
)
544 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
545 int volt_reg
, ldo
= rdev_get_id(rdev
);
550 volt_reg
= WM8350_LDO1_LOW_POWER
;
553 volt_reg
= WM8350_LDO2_LOW_POWER
;
556 volt_reg
= WM8350_LDO3_LOW_POWER
;
559 volt_reg
= WM8350_LDO4_LOW_POWER
;
565 /* all LDOs have same mV bits */
566 val
= wm8350_reg_read(wm8350
, volt_reg
) & ~WM8350_LDO1_HIB_MODE_MASK
;
567 wm8350_reg_write(wm8350
, volt_reg
, val
| WM8350_LDO1_HIB_MODE_DIS
);
571 int wm8350_dcdc_set_slot(struct wm8350
*wm8350
, int dcdc
, u16 start
,
577 dev_dbg(wm8350
->dev
, "%s %d start %d stop %d\n",
578 __func__
, dcdc
, start
, stop
);
581 if (start
> 15 || stop
> 15)
586 slot_reg
= WM8350_DCDC1_TIMEOUTS
;
589 slot_reg
= WM8350_DCDC2_TIMEOUTS
;
592 slot_reg
= WM8350_DCDC3_TIMEOUTS
;
595 slot_reg
= WM8350_DCDC4_TIMEOUTS
;
598 slot_reg
= WM8350_DCDC5_TIMEOUTS
;
601 slot_reg
= WM8350_DCDC6_TIMEOUTS
;
607 val
= wm8350_reg_read(wm8350
, slot_reg
) &
608 ~(WM8350_DC1_ENSLOT_MASK
| WM8350_DC1_SDSLOT_MASK
|
609 WM8350_DC1_ERRACT_MASK
);
610 wm8350_reg_write(wm8350
, slot_reg
,
611 val
| (start
<< WM8350_DC1_ENSLOT_SHIFT
) |
612 (stop
<< WM8350_DC1_SDSLOT_SHIFT
) |
613 (fault
<< WM8350_DC1_ERRACT_SHIFT
));
617 EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot
);
619 int wm8350_ldo_set_slot(struct wm8350
*wm8350
, int ldo
, u16 start
, u16 stop
)
624 dev_dbg(wm8350
->dev
, "%s %d start %d stop %d\n",
625 __func__
, ldo
, start
, stop
);
628 if (start
> 15 || stop
> 15)
633 slot_reg
= WM8350_LDO1_TIMEOUTS
;
636 slot_reg
= WM8350_LDO2_TIMEOUTS
;
639 slot_reg
= WM8350_LDO3_TIMEOUTS
;
642 slot_reg
= WM8350_LDO4_TIMEOUTS
;
648 val
= wm8350_reg_read(wm8350
, slot_reg
) & ~WM8350_LDO1_SDSLOT_MASK
;
649 wm8350_reg_write(wm8350
, slot_reg
, val
| ((start
<< 10) | (stop
<< 6)));
652 EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot
);
654 int wm8350_dcdc25_set_mode(struct wm8350
*wm8350
, int dcdc
, u16 mode
,
655 u16 ilim
, u16 ramp
, u16 feedback
)
659 dev_dbg(wm8350
->dev
, "%s %d mode: %s %s\n", __func__
, dcdc
,
660 mode
? "normal" : "boost", ilim
? "low" : "normal");
664 val
= wm8350_reg_read(wm8350
, WM8350_DCDC2_CONTROL
)
665 & ~(WM8350_DC2_MODE_MASK
| WM8350_DC2_ILIM_MASK
|
666 WM8350_DC2_RMP_MASK
| WM8350_DC2_FBSRC_MASK
);
667 wm8350_reg_write(wm8350
, WM8350_DCDC2_CONTROL
, val
|
668 (mode
<< WM8350_DC2_MODE_SHIFT
) |
669 (ilim
<< WM8350_DC2_ILIM_SHIFT
) |
670 (ramp
<< WM8350_DC2_RMP_SHIFT
) |
671 (feedback
<< WM8350_DC2_FBSRC_SHIFT
));
674 val
= wm8350_reg_read(wm8350
, WM8350_DCDC5_CONTROL
)
675 & ~(WM8350_DC5_MODE_MASK
| WM8350_DC5_ILIM_MASK
|
676 WM8350_DC5_RMP_MASK
| WM8350_DC5_FBSRC_MASK
);
677 wm8350_reg_write(wm8350
, WM8350_DCDC5_CONTROL
, val
|
678 (mode
<< WM8350_DC5_MODE_SHIFT
) |
679 (ilim
<< WM8350_DC5_ILIM_SHIFT
) |
680 (ramp
<< WM8350_DC5_RMP_SHIFT
) |
681 (feedback
<< WM8350_DC5_FBSRC_SHIFT
));
689 EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode
);
691 static int force_continuous_enable(struct wm8350
*wm8350
, int dcdc
, int enable
)
697 reg
= WM8350_DCDC1_FORCE_PWM
;
700 reg
= WM8350_DCDC3_FORCE_PWM
;
703 reg
= WM8350_DCDC4_FORCE_PWM
;
706 reg
= WM8350_DCDC6_FORCE_PWM
;
713 ret
= wm8350_set_bits(wm8350
, reg
,
714 WM8350_DCDC1_FORCE_PWM_ENA
);
716 ret
= wm8350_clear_bits(wm8350
, reg
,
717 WM8350_DCDC1_FORCE_PWM_ENA
);
721 static int wm8350_dcdc_set_mode(struct regulator_dev
*rdev
, unsigned int mode
)
723 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
724 int dcdc
= rdev_get_id(rdev
);
727 if (dcdc
< WM8350_DCDC_1
|| dcdc
> WM8350_DCDC_6
)
730 if (dcdc
== WM8350_DCDC_2
|| dcdc
== WM8350_DCDC_5
)
733 val
= 1 << (dcdc
- WM8350_DCDC_1
);
736 case REGULATOR_MODE_FAST
:
737 /* force continuous mode */
738 wm8350_set_bits(wm8350
, WM8350_DCDC_ACTIVE_OPTIONS
, val
);
739 wm8350_clear_bits(wm8350
, WM8350_DCDC_SLEEP_OPTIONS
, val
);
740 force_continuous_enable(wm8350
, dcdc
, 1);
742 case REGULATOR_MODE_NORMAL
:
743 /* active / pulse skipping */
744 wm8350_set_bits(wm8350
, WM8350_DCDC_ACTIVE_OPTIONS
, val
);
745 wm8350_clear_bits(wm8350
, WM8350_DCDC_SLEEP_OPTIONS
, val
);
746 force_continuous_enable(wm8350
, dcdc
, 0);
748 case REGULATOR_MODE_IDLE
:
750 force_continuous_enable(wm8350
, dcdc
, 0);
751 wm8350_clear_bits(wm8350
, WM8350_DCDC_SLEEP_OPTIONS
, val
);
752 wm8350_clear_bits(wm8350
, WM8350_DCDC_ACTIVE_OPTIONS
, val
);
754 case REGULATOR_MODE_STANDBY
:
756 force_continuous_enable(wm8350
, dcdc
, 0);
757 wm8350_set_bits(wm8350
, WM8350_DCDC_SLEEP_OPTIONS
, val
);
764 static unsigned int wm8350_dcdc_get_mode(struct regulator_dev
*rdev
)
766 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
767 int dcdc
= rdev_get_id(rdev
);
768 u16 mask
, sleep
, active
, force
;
769 int mode
= REGULATOR_MODE_NORMAL
;
774 reg
= WM8350_DCDC1_FORCE_PWM
;
777 reg
= WM8350_DCDC3_FORCE_PWM
;
780 reg
= WM8350_DCDC4_FORCE_PWM
;
783 reg
= WM8350_DCDC6_FORCE_PWM
;
789 mask
= 1 << (dcdc
- WM8350_DCDC_1
);
790 active
= wm8350_reg_read(wm8350
, WM8350_DCDC_ACTIVE_OPTIONS
) & mask
;
791 force
= wm8350_reg_read(wm8350
, reg
) & WM8350_DCDC1_FORCE_PWM_ENA
;
792 sleep
= wm8350_reg_read(wm8350
, WM8350_DCDC_SLEEP_OPTIONS
) & mask
;
794 dev_dbg(wm8350
->dev
, "mask %x active %x sleep %x force %x",
795 mask
, active
, sleep
, force
);
797 if (active
&& !sleep
) {
799 mode
= REGULATOR_MODE_FAST
;
801 mode
= REGULATOR_MODE_NORMAL
;
802 } else if (!active
&& !sleep
)
803 mode
= REGULATOR_MODE_IDLE
;
805 mode
= REGULATOR_MODE_STANDBY
;
810 static unsigned int wm8350_ldo_get_mode(struct regulator_dev
*rdev
)
812 return REGULATOR_MODE_NORMAL
;
815 struct wm8350_dcdc_efficiency
{
821 static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency
[] = {
822 {0, 10000, REGULATOR_MODE_STANDBY
}, /* 0 - 10mA - LDO */
823 {10000, 100000, REGULATOR_MODE_IDLE
}, /* 10mA - 100mA - Standby */
824 {100000, 1000000, REGULATOR_MODE_NORMAL
}, /* > 100mA - Active */
825 {-1, -1, REGULATOR_MODE_NORMAL
},
828 static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency
[] = {
829 {0, 10000, REGULATOR_MODE_STANDBY
}, /* 0 - 10mA - LDO */
830 {10000, 100000, REGULATOR_MODE_IDLE
}, /* 10mA - 100mA - Standby */
831 {100000, 800000, REGULATOR_MODE_NORMAL
}, /* > 100mA - Active */
832 {-1, -1, REGULATOR_MODE_NORMAL
},
835 static unsigned int get_mode(int uA
, const struct wm8350_dcdc_efficiency
*eff
)
839 while (eff
[i
].uA_load_min
!= -1) {
840 if (uA
>= eff
[i
].uA_load_min
&& uA
<= eff
[i
].uA_load_max
)
844 return REGULATOR_MODE_NORMAL
;
847 /* Query the regulator for it's most efficient mode @ uV,uA
848 * WM8350 regulator efficiency is pretty similar over
849 * different input and output uV.
851 static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev
*rdev
,
852 int input_uV
, int output_uV
,
855 int dcdc
= rdev_get_id(rdev
), mode
;
860 mode
= get_mode(output_uA
, dcdc1_6_efficiency
);
864 mode
= get_mode(output_uA
, dcdc3_4_efficiency
);
867 mode
= REGULATOR_MODE_NORMAL
;
873 static const struct regulator_ops wm8350_dcdc_ops
= {
874 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
875 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
876 .list_voltage
= regulator_list_voltage_linear
,
877 .map_voltage
= regulator_map_voltage_linear
,
878 .enable
= regulator_enable_regmap
,
879 .disable
= regulator_disable_regmap
,
880 .is_enabled
= regulator_is_enabled_regmap
,
881 .get_mode
= wm8350_dcdc_get_mode
,
882 .set_mode
= wm8350_dcdc_set_mode
,
883 .get_optimum_mode
= wm8350_dcdc_get_optimum_mode
,
884 .set_suspend_voltage
= wm8350_dcdc_set_suspend_voltage
,
885 .set_suspend_enable
= wm8350_dcdc_set_suspend_enable
,
886 .set_suspend_disable
= wm8350_dcdc_set_suspend_disable
,
887 .set_suspend_mode
= wm8350_dcdc_set_suspend_mode
,
890 static const struct regulator_ops wm8350_dcdc2_5_ops
= {
891 .enable
= regulator_enable_regmap
,
892 .disable
= regulator_disable_regmap
,
893 .is_enabled
= regulator_is_enabled_regmap
,
894 .set_suspend_enable
= wm8350_dcdc25_set_suspend_enable
,
895 .set_suspend_disable
= wm8350_dcdc25_set_suspend_disable
,
898 static const struct regulator_ops wm8350_ldo_ops
= {
899 .map_voltage
= regulator_map_voltage_linear_range
,
900 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
901 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
902 .list_voltage
= regulator_list_voltage_linear_range
,
903 .enable
= regulator_enable_regmap
,
904 .disable
= regulator_disable_regmap
,
905 .is_enabled
= regulator_is_enabled_regmap
,
906 .get_mode
= wm8350_ldo_get_mode
,
907 .set_suspend_voltage
= wm8350_ldo_set_suspend_voltage
,
908 .set_suspend_enable
= wm8350_ldo_set_suspend_enable
,
909 .set_suspend_disable
= wm8350_ldo_set_suspend_disable
,
912 static const struct regulator_ops wm8350_isink_ops
= {
913 .set_current_limit
= regulator_set_current_limit_regmap
,
914 .get_current_limit
= regulator_get_current_limit_regmap
,
915 .enable
= wm8350_isink_enable
,
916 .disable
= wm8350_isink_disable
,
917 .is_enabled
= wm8350_isink_is_enabled
,
918 .enable_time
= wm8350_isink_enable_time
,
921 static const struct regulator_desc wm8350_reg
[NUM_WM8350_REGULATORS
] = {
925 .ops
= &wm8350_dcdc_ops
,
926 .irq
= WM8350_IRQ_UV_DC1
,
927 .type
= REGULATOR_VOLTAGE
,
928 .n_voltages
= WM8350_DCDC_MAX_VSEL
+ 1,
931 .vsel_reg
= WM8350_DCDC1_CONTROL
,
932 .vsel_mask
= WM8350_DC1_VSEL_MASK
,
933 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
934 .enable_mask
= WM8350_DC1_ENA
,
935 .owner
= THIS_MODULE
,
940 .ops
= &wm8350_dcdc2_5_ops
,
941 .irq
= WM8350_IRQ_UV_DC2
,
942 .type
= REGULATOR_VOLTAGE
,
943 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
944 .enable_mask
= WM8350_DC2_ENA
,
945 .owner
= THIS_MODULE
,
950 .ops
= &wm8350_dcdc_ops
,
951 .irq
= WM8350_IRQ_UV_DC3
,
952 .type
= REGULATOR_VOLTAGE
,
953 .n_voltages
= WM8350_DCDC_MAX_VSEL
+ 1,
956 .vsel_reg
= WM8350_DCDC3_CONTROL
,
957 .vsel_mask
= WM8350_DC3_VSEL_MASK
,
958 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
959 .enable_mask
= WM8350_DC3_ENA
,
960 .owner
= THIS_MODULE
,
965 .ops
= &wm8350_dcdc_ops
,
966 .irq
= WM8350_IRQ_UV_DC4
,
967 .type
= REGULATOR_VOLTAGE
,
968 .n_voltages
= WM8350_DCDC_MAX_VSEL
+ 1,
971 .vsel_reg
= WM8350_DCDC4_CONTROL
,
972 .vsel_mask
= WM8350_DC4_VSEL_MASK
,
973 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
974 .enable_mask
= WM8350_DC4_ENA
,
975 .owner
= THIS_MODULE
,
980 .ops
= &wm8350_dcdc2_5_ops
,
981 .irq
= WM8350_IRQ_UV_DC5
,
982 .type
= REGULATOR_VOLTAGE
,
983 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
984 .enable_mask
= WM8350_DC5_ENA
,
985 .owner
= THIS_MODULE
,
990 .ops
= &wm8350_dcdc_ops
,
991 .irq
= WM8350_IRQ_UV_DC6
,
992 .type
= REGULATOR_VOLTAGE
,
993 .n_voltages
= WM8350_DCDC_MAX_VSEL
+ 1,
996 .vsel_reg
= WM8350_DCDC6_CONTROL
,
997 .vsel_mask
= WM8350_DC6_VSEL_MASK
,
998 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
999 .enable_mask
= WM8350_DC6_ENA
,
1000 .owner
= THIS_MODULE
,
1005 .ops
= &wm8350_ldo_ops
,
1006 .irq
= WM8350_IRQ_UV_LDO1
,
1007 .type
= REGULATOR_VOLTAGE
,
1008 .n_voltages
= WM8350_LDO1_VSEL_MASK
+ 1,
1009 .linear_ranges
= wm8350_ldo_ranges
,
1010 .n_linear_ranges
= ARRAY_SIZE(wm8350_ldo_ranges
),
1011 .vsel_reg
= WM8350_LDO1_CONTROL
,
1012 .vsel_mask
= WM8350_LDO1_VSEL_MASK
,
1013 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
1014 .enable_mask
= WM8350_LDO1_ENA
,
1015 .owner
= THIS_MODULE
,
1020 .ops
= &wm8350_ldo_ops
,
1021 .irq
= WM8350_IRQ_UV_LDO2
,
1022 .type
= REGULATOR_VOLTAGE
,
1023 .n_voltages
= WM8350_LDO2_VSEL_MASK
+ 1,
1024 .linear_ranges
= wm8350_ldo_ranges
,
1025 .n_linear_ranges
= ARRAY_SIZE(wm8350_ldo_ranges
),
1026 .vsel_reg
= WM8350_LDO2_CONTROL
,
1027 .vsel_mask
= WM8350_LDO2_VSEL_MASK
,
1028 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
1029 .enable_mask
= WM8350_LDO2_ENA
,
1030 .owner
= THIS_MODULE
,
1035 .ops
= &wm8350_ldo_ops
,
1036 .irq
= WM8350_IRQ_UV_LDO3
,
1037 .type
= REGULATOR_VOLTAGE
,
1038 .n_voltages
= WM8350_LDO3_VSEL_MASK
+ 1,
1039 .linear_ranges
= wm8350_ldo_ranges
,
1040 .n_linear_ranges
= ARRAY_SIZE(wm8350_ldo_ranges
),
1041 .vsel_reg
= WM8350_LDO3_CONTROL
,
1042 .vsel_mask
= WM8350_LDO3_VSEL_MASK
,
1043 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
1044 .enable_mask
= WM8350_LDO3_ENA
,
1045 .owner
= THIS_MODULE
,
1050 .ops
= &wm8350_ldo_ops
,
1051 .irq
= WM8350_IRQ_UV_LDO4
,
1052 .type
= REGULATOR_VOLTAGE
,
1053 .n_voltages
= WM8350_LDO4_VSEL_MASK
+ 1,
1054 .linear_ranges
= wm8350_ldo_ranges
,
1055 .n_linear_ranges
= ARRAY_SIZE(wm8350_ldo_ranges
),
1056 .vsel_reg
= WM8350_LDO4_CONTROL
,
1057 .vsel_mask
= WM8350_LDO4_VSEL_MASK
,
1058 .enable_reg
= WM8350_DCDC_LDO_REQUESTED
,
1059 .enable_mask
= WM8350_LDO4_ENA
,
1060 .owner
= THIS_MODULE
,
1064 .id
= WM8350_ISINK_A
,
1065 .ops
= &wm8350_isink_ops
,
1066 .irq
= WM8350_IRQ_CS1
,
1067 .type
= REGULATOR_CURRENT
,
1068 .owner
= THIS_MODULE
,
1069 .curr_table
= isink_cur
,
1070 .n_current_limits
= ARRAY_SIZE(isink_cur
),
1071 .csel_reg
= WM8350_CURRENT_SINK_DRIVER_A
,
1072 .csel_mask
= WM8350_CS1_ISEL_MASK
,
1076 .id
= WM8350_ISINK_B
,
1077 .ops
= &wm8350_isink_ops
,
1078 .irq
= WM8350_IRQ_CS2
,
1079 .type
= REGULATOR_CURRENT
,
1080 .owner
= THIS_MODULE
,
1081 .curr_table
= isink_cur
,
1082 .n_current_limits
= ARRAY_SIZE(isink_cur
),
1083 .csel_reg
= WM8350_CURRENT_SINK_DRIVER_B
,
1084 .csel_mask
= WM8350_CS2_ISEL_MASK
,
1088 static irqreturn_t
pmic_uv_handler(int irq
, void *data
)
1090 struct regulator_dev
*rdev
= (struct regulator_dev
*)data
;
1092 regulator_lock(rdev
);
1093 if (irq
== WM8350_IRQ_CS1
|| irq
== WM8350_IRQ_CS2
)
1094 regulator_notifier_call_chain(rdev
,
1095 REGULATOR_EVENT_REGULATION_OUT
,
1098 regulator_notifier_call_chain(rdev
,
1099 REGULATOR_EVENT_UNDER_VOLTAGE
,
1101 regulator_unlock(rdev
);
1106 static int wm8350_regulator_probe(struct platform_device
*pdev
)
1108 struct wm8350
*wm8350
= dev_get_drvdata(&pdev
->dev
);
1109 struct regulator_config config
= { };
1110 struct regulator_dev
*rdev
;
1114 if (pdev
->id
< WM8350_DCDC_1
|| pdev
->id
> WM8350_ISINK_B
)
1117 /* do any regulatior specific init */
1120 val
= wm8350_reg_read(wm8350
, WM8350_DCDC1_LOW_POWER
);
1121 wm8350
->pmic
.dcdc1_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
1124 val
= wm8350_reg_read(wm8350
, WM8350_DCDC3_LOW_POWER
);
1125 wm8350
->pmic
.dcdc3_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
1128 val
= wm8350_reg_read(wm8350
, WM8350_DCDC4_LOW_POWER
);
1129 wm8350
->pmic
.dcdc4_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
1132 val
= wm8350_reg_read(wm8350
, WM8350_DCDC6_LOW_POWER
);
1133 wm8350
->pmic
.dcdc6_hib_mode
= val
& WM8350_DCDC_HIB_MODE_MASK
;
1137 config
.dev
= &pdev
->dev
;
1138 config
.init_data
= dev_get_platdata(&pdev
->dev
);
1139 config
.driver_data
= dev_get_drvdata(&pdev
->dev
);
1140 config
.regmap
= wm8350
->regmap
;
1142 /* register regulator */
1143 rdev
= devm_regulator_register(&pdev
->dev
, &wm8350_reg
[pdev
->id
],
1146 dev_err(&pdev
->dev
, "failed to register %s\n",
1147 wm8350_reg
[pdev
->id
].name
);
1148 return PTR_ERR(rdev
);
1151 /* register regulator IRQ */
1152 ret
= wm8350_register_irq(wm8350
, wm8350_reg
[pdev
->id
].irq
,
1153 pmic_uv_handler
, 0, "UV", rdev
);
1155 dev_err(&pdev
->dev
, "failed to register regulator %s IRQ\n",
1156 wm8350_reg
[pdev
->id
].name
);
1163 static int wm8350_regulator_remove(struct platform_device
*pdev
)
1165 struct regulator_dev
*rdev
= platform_get_drvdata(pdev
);
1166 struct wm8350
*wm8350
= rdev_get_drvdata(rdev
);
1168 wm8350_free_irq(wm8350
, wm8350_reg
[pdev
->id
].irq
, rdev
);
1173 int wm8350_register_regulator(struct wm8350
*wm8350
, int reg
,
1174 struct regulator_init_data
*initdata
)
1176 struct platform_device
*pdev
;
1178 if (reg
< 0 || reg
>= NUM_WM8350_REGULATORS
)
1181 if (wm8350
->pmic
.pdev
[reg
])
1184 if (reg
>= WM8350_DCDC_1
&& reg
<= WM8350_DCDC_6
&&
1185 reg
> wm8350
->pmic
.max_dcdc
)
1187 if (reg
>= WM8350_ISINK_A
&& reg
<= WM8350_ISINK_B
&&
1188 reg
> wm8350
->pmic
.max_isink
)
1191 pdev
= platform_device_alloc("wm8350-regulator", reg
);
1195 wm8350
->pmic
.pdev
[reg
] = pdev
;
1197 initdata
->driver_data
= wm8350
;
1199 pdev
->dev
.platform_data
= initdata
;
1200 pdev
->dev
.parent
= wm8350
->dev
;
1201 platform_set_drvdata(pdev
, wm8350
);
1203 ret
= platform_device_add(pdev
);
1206 dev_err(wm8350
->dev
, "Failed to register regulator %d: %d\n",
1208 platform_device_put(pdev
);
1209 wm8350
->pmic
.pdev
[reg
] = NULL
;
1214 EXPORT_SYMBOL_GPL(wm8350_register_regulator
);
1217 * wm8350_register_led - Register a WM8350 LED output
1219 * @param wm8350 The WM8350 device to configure.
1220 * @param lednum LED device index to create.
1221 * @param dcdc The DCDC to use for the LED.
1222 * @param isink The ISINK to use for the LED.
1223 * @param pdata Configuration for the LED.
1225 * The WM8350 supports the use of an ISINK together with a DCDC to
1226 * provide a power-efficient LED driver. This function registers the
1227 * regulators and instantiates the platform device for a LED. The
1228 * operating modes for the LED regulators must be configured using
1229 * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and
1230 * wm8350_dcdc_set_slot() prior to calling this function.
1232 int wm8350_register_led(struct wm8350
*wm8350
, int lednum
, int dcdc
, int isink
,
1233 struct wm8350_led_platform_data
*pdata
)
1235 struct wm8350_led
*led
;
1236 struct platform_device
*pdev
;
1239 if (lednum
>= ARRAY_SIZE(wm8350
->pmic
.led
) || lednum
< 0) {
1240 dev_err(wm8350
->dev
, "Invalid LED index %d\n", lednum
);
1244 led
= &wm8350
->pmic
.led
[lednum
];
1247 dev_err(wm8350
->dev
, "LED %d already allocated\n", lednum
);
1251 pdev
= platform_device_alloc("wm8350-led", lednum
);
1253 dev_err(wm8350
->dev
, "Failed to allocate LED %d\n", lednum
);
1257 led
->isink_consumer
.dev_name
= dev_name(&pdev
->dev
);
1258 led
->isink_consumer
.supply
= "led_isink";
1259 led
->isink_init
.num_consumer_supplies
= 1;
1260 led
->isink_init
.consumer_supplies
= &led
->isink_consumer
;
1261 led
->isink_init
.constraints
.min_uA
= 0;
1262 led
->isink_init
.constraints
.max_uA
= pdata
->max_uA
;
1263 led
->isink_init
.constraints
.valid_ops_mask
1264 = REGULATOR_CHANGE_CURRENT
| REGULATOR_CHANGE_STATUS
;
1265 led
->isink_init
.constraints
.valid_modes_mask
= REGULATOR_MODE_NORMAL
;
1266 ret
= wm8350_register_regulator(wm8350
, isink
, &led
->isink_init
);
1268 platform_device_put(pdev
);
1272 led
->dcdc_consumer
.dev_name
= dev_name(&pdev
->dev
);
1273 led
->dcdc_consumer
.supply
= "led_vcc";
1274 led
->dcdc_init
.num_consumer_supplies
= 1;
1275 led
->dcdc_init
.consumer_supplies
= &led
->dcdc_consumer
;
1276 led
->dcdc_init
.constraints
.valid_modes_mask
= REGULATOR_MODE_NORMAL
;
1277 led
->dcdc_init
.constraints
.valid_ops_mask
= REGULATOR_CHANGE_STATUS
;
1278 ret
= wm8350_register_regulator(wm8350
, dcdc
, &led
->dcdc_init
);
1280 platform_device_put(pdev
);
1285 case WM8350_ISINK_A
:
1286 wm8350
->pmic
.isink_A_dcdc
= dcdc
;
1288 case WM8350_ISINK_B
:
1289 wm8350
->pmic
.isink_B_dcdc
= dcdc
;
1293 pdev
->dev
.platform_data
= pdata
;
1294 pdev
->dev
.parent
= wm8350
->dev
;
1295 ret
= platform_device_add(pdev
);
1297 dev_err(wm8350
->dev
, "Failed to register LED %d: %d\n",
1299 platform_device_put(pdev
);
1307 EXPORT_SYMBOL_GPL(wm8350_register_led
);
1309 static struct platform_driver wm8350_regulator_driver
= {
1310 .probe
= wm8350_regulator_probe
,
1311 .remove
= wm8350_regulator_remove
,
1313 .name
= "wm8350-regulator",
1317 static int __init
wm8350_regulator_init(void)
1319 return platform_driver_register(&wm8350_regulator_driver
);
1321 subsys_initcall(wm8350_regulator_init
);
1323 static void __exit
wm8350_regulator_exit(void)
1325 platform_driver_unregister(&wm8350_regulator_driver
);
1327 module_exit(wm8350_regulator_exit
);
1329 /* Module information */
1330 MODULE_AUTHOR("Liam Girdwood");
1331 MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
1332 MODULE_LICENSE("GPL");
1333 MODULE_ALIAS("platform:wm8350-regulator");