1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Split TWL6030 logic from twl-regulator.c:
4 * Copyright (C) 2008 David Brownell
5 *
6 * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
7 */
8
9#include <linux/module.h>
10#include <linux/string.h>
11#include <linux/slab.h>
12#include <linux/init.h>
13#include <linux/err.h>
14#include <linux/platform_device.h>
15#include <linux/of.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
18#include <linux/regulator/of_regulator.h>
19#include <linux/mfd/twl.h>
20#include <linux/delay.h>
21
22struct twlreg_info {
23 /* start of regulator's PM_RECEIVER control register bank */
24 u8 base;
25
26 /* twl resource ID, for resource control state machine */
27 u8 id;
28
29 u8 flags;
30
31 /* used by regulator core */
32 struct regulator_desc desc;
33
34 /* chip specific features */
35 unsigned long features;
36
37 /* data passed from board for external get/set voltage */
38 void *data;
39};
40
41
42/* LDO control registers ... offset is from the base of its register bank.
43 * The first three registers of all power resource banks help hardware to
44 * manage the various resource groups.
45 */
46/* Common offset in TWL4030/6030 */
47#define VREG_GRP 0
48/* TWL6030 register offsets */
49#define VREG_TRANS 1
50#define VREG_STATE 2
51#define VREG_VOLTAGE 3
52#define VREG_VOLTAGE_SMPS 4
53/* TWL6030 Misc register offsets */
54#define VREG_BC_ALL 1
55#define VREG_BC_REF 2
56#define VREG_BC_PROC 3
57#define VREG_BC_CLK_RST 4
58
59/* TWL6030 LDO register values for VREG_VOLTAGE */
60#define TWL6030_VREG_VOLTAGE_WR_S BIT(7)
61
62/* TWL6030 LDO register values for CFG_STATE */
63#define TWL6030_CFG_STATE_OFF 0x00
64#define TWL6030_CFG_STATE_ON 0x01
65#define TWL6030_CFG_STATE_OFF2 0x02
66#define TWL6030_CFG_STATE_SLEEP 0x03
67#define TWL6030_CFG_STATE_GRP_SHIFT 5
68#define TWL6030_CFG_STATE_APP_SHIFT 2
69#define TWL6030_CFG_STATE_MASK 0x03
70#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
71#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
72 TWL6030_CFG_STATE_APP_SHIFT)
73
74/* Flags for SMPS Voltage reading and LDO reading*/
75#define SMPS_OFFSET_EN BIT(0)
76#define SMPS_EXTENDED_EN BIT(1)
77#define TWL_6030_WARM_RESET BIT(3)
78
79/* twl6032 SMPS EPROM values */
80#define TWL6030_SMPS_OFFSET 0xB0
81#define TWL6030_SMPS_MULT 0xB3
82#define SMPS_MULTOFFSET_SMPS4 BIT(0)
83#define SMPS_MULTOFFSET_VIO BIT(1)
84#define SMPS_MULTOFFSET_SMPS3 BIT(6)
85
86static inline int
87twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
88{
89 u8 value;
90 int status;
91
92 status = twl_i2c_read_u8(mod_no: slave_subgp,
93 val: &value, reg: info->base + offset);
94 return (status < 0) ? status : value;
95}
96
97static inline int
98twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset,
99 u8 value)
100{
101 return twl_i2c_write_u8(mod_no: slave_subgp,
102 val: value, reg: info->base + offset);
103}
104
105/* generic power resource operations, which work on all regulators */
106static int twlreg_grp(struct regulator_dev *rdev)
107{
108 return twlreg_read(info: rdev_get_drvdata(rdev), slave_subgp: TWL_MODULE_PM_RECEIVER,
109 VREG_GRP);
110}
111
112/*
113 * Enable/disable regulators by joining/leaving the P1 (processor) group.
114 * We assume nobody else is updating the DEV_GRP registers.
115 */
116/* definition for 6030 family */
117#define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */
118#define P2_GRP_6030 BIT(1) /* "peripherals" */
119#define P1_GRP_6030 BIT(0) /* CPU/Linux */
120
121static int twl6030reg_is_enabled(struct regulator_dev *rdev)
122{
123 struct twlreg_info *info = rdev_get_drvdata(rdev);
124 int grp = 0, val;
125
126 if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) {
127 grp = twlreg_grp(rdev);
128 if (grp < 0)
129 return grp;
130 grp &= P1_GRP_6030;
131 val = twlreg_read(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE);
132 val = TWL6030_CFG_STATE_APP(val);
133 } else {
134 val = twlreg_read(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE);
135 val &= TWL6030_CFG_STATE_MASK;
136 grp = 1;
137 }
138
139 return grp && (val == TWL6030_CFG_STATE_ON);
140}
141
142#define PB_I2C_BUSY BIT(0)
143#define PB_I2C_BWEN BIT(1)
144
145
146static int twl6030reg_enable(struct regulator_dev *rdev)
147{
148 struct twlreg_info *info = rdev_get_drvdata(rdev);
149 int grp = 0;
150 int ret;
151
152 if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
153 grp = twlreg_grp(rdev);
154 if (grp < 0)
155 return grp;
156
157 ret = twlreg_write(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE,
158 value: grp << TWL6030_CFG_STATE_GRP_SHIFT |
159 TWL6030_CFG_STATE_ON);
160 return ret;
161}
162
163static int twl6030reg_disable(struct regulator_dev *rdev)
164{
165 struct twlreg_info *info = rdev_get_drvdata(rdev);
166 int grp = 0;
167 int ret;
168
169 if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
170 grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
171
172 /* For 6030, set the off state for all grps enabled */
173 ret = twlreg_write(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE,
174 value: (grp) << TWL6030_CFG_STATE_GRP_SHIFT |
175 TWL6030_CFG_STATE_OFF);
176
177 return ret;
178}
179
180static int twl6030reg_get_status(struct regulator_dev *rdev)
181{
182 struct twlreg_info *info = rdev_get_drvdata(rdev);
183 int val;
184
185 val = twlreg_grp(rdev);
186 if (val < 0)
187 return val;
188
189 val = twlreg_read(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE);
190
191 if (info->features & TWL6032_SUBCLASS)
192 val &= TWL6030_CFG_STATE_MASK;
193 else
194 val = TWL6030_CFG_STATE_APP(val);
195
196 switch (val) {
197 case TWL6030_CFG_STATE_ON:
198 return REGULATOR_STATUS_NORMAL;
199
200 case TWL6030_CFG_STATE_SLEEP:
201 return REGULATOR_STATUS_STANDBY;
202
203 case TWL6030_CFG_STATE_OFF:
204 case TWL6030_CFG_STATE_OFF2:
205 default:
206 break;
207 }
208
209 return REGULATOR_STATUS_OFF;
210}
211
212static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
213{
214 struct twlreg_info *info = rdev_get_drvdata(rdev);
215 int grp = 0;
216 int val;
217
218 if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
219 grp = twlreg_grp(rdev);
220
221 if (grp < 0)
222 return grp;
223
224 /* Compose the state register settings */
225 val = grp << TWL6030_CFG_STATE_GRP_SHIFT;
226 /* We can only set the mode through state machine commands... */
227 switch (mode) {
228 case REGULATOR_MODE_NORMAL:
229 val |= TWL6030_CFG_STATE_ON;
230 break;
231 case REGULATOR_MODE_STANDBY:
232 val |= TWL6030_CFG_STATE_SLEEP;
233 break;
234
235 default:
236 return -EINVAL;
237 }
238
239 return twlreg_write(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_STATE, value: val);
240}
241
242static int twl6030coresmps_set_voltage(struct regulator_dev *rdev, int min_uV,
243 int max_uV, unsigned *selector)
244{
245 return -ENODEV;
246}
247
248static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
249{
250 return -ENODEV;
251}
252
253static const struct regulator_ops twl6030coresmps_ops = {
254 .set_voltage = twl6030coresmps_set_voltage,
255 .get_voltage = twl6030coresmps_get_voltage,
256};
257
258static int
259twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
260{
261 struct twlreg_info *info = rdev_get_drvdata(rdev);
262
263 if (info->flags & TWL_6030_WARM_RESET)
264 selector |= TWL6030_VREG_VOLTAGE_WR_S;
265
266 return twlreg_write(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
267 value: selector);
268}
269
270static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
271{
272 struct twlreg_info *info = rdev_get_drvdata(rdev);
273 int vsel = twlreg_read(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
274
275 if (info->flags & TWL_6030_WARM_RESET)
276 vsel &= ~TWL6030_VREG_VOLTAGE_WR_S;
277
278 return vsel;
279}
280
281static const struct regulator_ops twl6030ldo_ops = {
282 .list_voltage = regulator_list_voltage_linear_range,
283
284 .set_voltage_sel = twl6030ldo_set_voltage_sel,
285 .get_voltage_sel = twl6030ldo_get_voltage_sel,
286
287 .enable = twl6030reg_enable,
288 .disable = twl6030reg_disable,
289 .is_enabled = twl6030reg_is_enabled,
290
291 .set_mode = twl6030reg_set_mode,
292
293 .get_status = twl6030reg_get_status,
294};
295
296static const struct regulator_ops twl6030fixed_ops = {
297 .list_voltage = regulator_list_voltage_linear,
298
299 .enable = twl6030reg_enable,
300 .disable = twl6030reg_disable,
301 .is_enabled = twl6030reg_is_enabled,
302
303 .set_mode = twl6030reg_set_mode,
304
305 .get_status = twl6030reg_get_status,
306};
307
308/*
309 * SMPS status and control
310 */
311
312static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
313{
314 struct twlreg_info *info = rdev_get_drvdata(rdev);
315
316 int voltage = 0;
317
318 switch (info->flags) {
319 case SMPS_OFFSET_EN:
320 voltage = 100000;
321 fallthrough;
322 case 0:
323 switch (index) {
324 case 0:
325 voltage = 0;
326 break;
327 case 58:
328 voltage = 1350 * 1000;
329 break;
330 case 59:
331 voltage = 1500 * 1000;
332 break;
333 case 60:
334 voltage = 1800 * 1000;
335 break;
336 case 61:
337 voltage = 1900 * 1000;
338 break;
339 case 62:
340 voltage = 2100 * 1000;
341 break;
342 default:
343 voltage += (600000 + (12500 * (index - 1)));
344 }
345 break;
346 case SMPS_EXTENDED_EN:
347 switch (index) {
348 case 0:
349 voltage = 0;
350 break;
351 case 58:
352 voltage = 2084 * 1000;
353 break;
354 case 59:
355 voltage = 2315 * 1000;
356 break;
357 case 60:
358 voltage = 2778 * 1000;
359 break;
360 case 61:
361 voltage = 2932 * 1000;
362 break;
363 case 62:
364 voltage = 3241 * 1000;
365 break;
366 default:
367 voltage = (1852000 + (38600 * (index - 1)));
368 }
369 break;
370 case SMPS_OFFSET_EN | SMPS_EXTENDED_EN:
371 switch (index) {
372 case 0:
373 voltage = 0;
374 break;
375 case 58:
376 voltage = 4167 * 1000;
377 break;
378 case 59:
379 voltage = 2315 * 1000;
380 break;
381 case 60:
382 voltage = 2778 * 1000;
383 break;
384 case 61:
385 voltage = 2932 * 1000;
386 break;
387 case 62:
388 voltage = 3241 * 1000;
389 break;
390 default:
391 voltage = (2161000 + (38600 * (index - 1)));
392 }
393 break;
394 }
395
396 return voltage;
397}
398
399static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV,
400 int max_uV)
401{
402 struct twlreg_info *info = rdev_get_drvdata(rdev);
403 int vsel = 0;
404
405 switch (info->flags) {
406 case 0:
407 if (min_uV == 0)
408 vsel = 0;
409 else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
410 vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
411 vsel++;
412 }
413 /* Values 1..57 for vsel are linear and can be calculated
414 * values 58..62 are non linear.
415 */
416 else if ((min_uV > 1900000) && (min_uV <= 2100000))
417 vsel = 62;
418 else if ((min_uV > 1800000) && (min_uV <= 1900000))
419 vsel = 61;
420 else if ((min_uV > 1500000) && (min_uV <= 1800000))
421 vsel = 60;
422 else if ((min_uV > 1350000) && (min_uV <= 1500000))
423 vsel = 59;
424 else if ((min_uV > 1300000) && (min_uV <= 1350000))
425 vsel = 58;
426 else
427 return -EINVAL;
428 break;
429 case SMPS_OFFSET_EN:
430 if (min_uV == 0)
431 vsel = 0;
432 else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
433 vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
434 vsel++;
435 }
436 /* Values 1..57 for vsel are linear and can be calculated
437 * values 58..62 are non linear.
438 */
439 else if ((min_uV > 1900000) && (min_uV <= 2100000))
440 vsel = 62;
441 else if ((min_uV > 1800000) && (min_uV <= 1900000))
442 vsel = 61;
443 else if ((min_uV > 1500000) && (min_uV <= 1800000))
444 vsel = 60;
445 else if ((min_uV > 1350000) && (min_uV <= 1500000))
446 vsel = 59;
447 else
448 return -EINVAL;
449 break;
450 case SMPS_EXTENDED_EN:
451 if (min_uV == 0) {
452 vsel = 0;
453 } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
454 vsel = DIV_ROUND_UP(min_uV - 1852000, 38600);
455 vsel++;
456 }
457 break;
458 case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
459 if (min_uV == 0) {
460 vsel = 0;
461 } else if ((min_uV >= 2161000) && (min_uV <= 4321000)) {
462 vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
463 vsel++;
464 }
465 break;
466 }
467
468 return vsel;
469}
470
471static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev,
472 unsigned int selector)
473{
474 struct twlreg_info *info = rdev_get_drvdata(rdev);
475
476 return twlreg_write(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
477 value: selector);
478}
479
480static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
481{
482 struct twlreg_info *info = rdev_get_drvdata(rdev);
483
484 return twlreg_read(info, slave_subgp: TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
485}
486
487static const struct regulator_ops twlsmps_ops = {
488 .list_voltage = twl6030smps_list_voltage,
489 .map_voltage = twl6030smps_map_voltage,
490
491 .set_voltage_sel = twl6030smps_set_voltage_sel,
492 .get_voltage_sel = twl6030smps_get_voltage_sel,
493
494 .enable = twl6030reg_enable,
495 .disable = twl6030reg_disable,
496 .is_enabled = twl6030reg_is_enabled,
497
498 .set_mode = twl6030reg_set_mode,
499
500 .get_status = twl6030reg_get_status,
501};
502
503/*----------------------------------------------------------------------*/
504static const struct linear_range twl6030ldo_linear_range[] = {
505 REGULATOR_LINEAR_RANGE(0, 0, 0, 0),
506 REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000),
507 REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0),
508};
509
510#define TWL6030_ADJUSTABLE_SMPS(label) \
511static const struct twlreg_info TWL6030_INFO_##label = { \
512 .desc = { \
513 .name = #label, \
514 .id = TWL6030_REG_##label, \
515 .ops = &twl6030coresmps_ops, \
516 .type = REGULATOR_VOLTAGE, \
517 .owner = THIS_MODULE, \
518 }, \
519 }
520
521#define TWL6030_ADJUSTABLE_LDO(label, offset) \
522static const struct twlreg_info TWL6030_INFO_##label = { \
523 .base = offset, \
524 .desc = { \
525 .name = #label, \
526 .id = TWL6030_REG_##label, \
527 .n_voltages = 32, \
528 .linear_ranges = twl6030ldo_linear_range, \
529 .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
530 .ops = &twl6030ldo_ops, \
531 .type = REGULATOR_VOLTAGE, \
532 .owner = THIS_MODULE, \
533 }, \
534 }
535
536#define TWL6032_ADJUSTABLE_LDO(label, offset) \
537static const struct twlreg_info TWL6032_INFO_##label = { \
538 .base = offset, \
539 .features = TWL6032_SUBCLASS, \
540 .desc = { \
541 .name = #label, \
542 .id = TWL6032_REG_##label, \
543 .n_voltages = 32, \
544 .linear_ranges = twl6030ldo_linear_range, \
545 .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
546 .ops = &twl6030ldo_ops, \
547 .type = REGULATOR_VOLTAGE, \
548 .owner = THIS_MODULE, \
549 }, \
550 }
551
552#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
553static const struct twlreg_info TWLFIXED_INFO_##label = { \
554 .base = offset, \
555 .id = 0, \
556 .desc = { \
557 .name = #label, \
558 .id = TWL6030##_REG_##label, \
559 .n_voltages = 1, \
560 .ops = &twl6030fixed_ops, \
561 .type = REGULATOR_VOLTAGE, \
562 .owner = THIS_MODULE, \
563 .min_uV = mVolts * 1000, \
564 .enable_time = turnon_delay, \
565 .of_map_mode = NULL, \
566 }, \
567 }
568
569#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
570static const struct twlreg_info TWLSMPS_INFO_##label = { \
571 .base = offset, \
572 .features = TWL6032_SUBCLASS, \
573 .desc = { \
574 .name = #label, \
575 .id = TWL6032_REG_##label, \
576 .n_voltages = 63, \
577 .ops = &twlsmps_ops, \
578 .type = REGULATOR_VOLTAGE, \
579 .owner = THIS_MODULE, \
580 }, \
581 }
582
583/* VUSBCP is managed *only* by the USB subchip */
584/* 6030 REG with base as PMC Slave Misc : 0x0030 */
585/* Turnon-delay and remap configuration values for 6030 are not
586 verified since the specification is not public */
587TWL6030_ADJUSTABLE_SMPS(VDD1);
588TWL6030_ADJUSTABLE_SMPS(VDD2);
589TWL6030_ADJUSTABLE_SMPS(VDD3);
590TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54);
591TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58);
592TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c);
593TWL6030_ADJUSTABLE_LDO(VMMC, 0x68);
594TWL6030_ADJUSTABLE_LDO(VPP, 0x6c);
595TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74);
596/* 6025 are renamed compared to 6030 versions */
597TWL6032_ADJUSTABLE_LDO(LDO2, 0x54);
598TWL6032_ADJUSTABLE_LDO(LDO4, 0x58);
599TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c);
600TWL6032_ADJUSTABLE_LDO(LDO5, 0x68);
601TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c);
602TWL6032_ADJUSTABLE_LDO(LDO7, 0x74);
603TWL6032_ADJUSTABLE_LDO(LDO6, 0x60);
604TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64);
605TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70);
606TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
607TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
608TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
609TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
610TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
611TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
612TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34);
613TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10);
614TWL6032_ADJUSTABLE_SMPS(VIO, 0x16);
615
616static u8 twl_get_smps_offset(void)
617{
618 u8 value;
619
620 twl_i2c_read_u8(mod_no: TWL_MODULE_PM_RECEIVER, val: &value,
621 TWL6030_SMPS_OFFSET);
622 return value;
623}
624
625static u8 twl_get_smps_mult(void)
626{
627 u8 value;
628
629 twl_i2c_read_u8(mod_no: TWL_MODULE_PM_RECEIVER, val: &value,
630 TWL6030_SMPS_MULT);
631 return value;
632}
633
634#define TWL_OF_MATCH(comp, family, label) \
635 { \
636 .compatible = comp, \
637 .data = &family##_INFO_##label, \
638 }
639
640#define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
641#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
642#define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
643#define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
644
645static const struct of_device_id twl_of_match[] = {
646 TWL6030_OF_MATCH("ti,twl6030-vdd1", VDD1),
647 TWL6030_OF_MATCH("ti,twl6030-vdd2", VDD2),
648 TWL6030_OF_MATCH("ti,twl6030-vdd3", VDD3),
649 TWL6030_OF_MATCH("ti,twl6030-vaux1", VAUX1_6030),
650 TWL6030_OF_MATCH("ti,twl6030-vaux2", VAUX2_6030),
651 TWL6030_OF_MATCH("ti,twl6030-vaux3", VAUX3_6030),
652 TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
653 TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
654 TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
655 TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2),
656 TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4),
657 TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3),
658 TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5),
659 TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1),
660 TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7),
661 TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6),
662 TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN),
663 TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB),
664 TWLFIXED_OF_MATCH("ti,twl6030-vana", VANA),
665 TWLFIXED_OF_MATCH("ti,twl6030-vcxio", VCXIO),
666 TWLFIXED_OF_MATCH("ti,twl6030-vdac", VDAC),
667 TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
668 TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
669 TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
670 TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3),
671 TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4),
672 TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
673 {},
674};
675MODULE_DEVICE_TABLE(of, twl_of_match);
676
677static int twlreg_probe(struct platform_device *pdev)
678{
679 int id;
680 struct twlreg_info *info;
681 const struct twlreg_info *template;
682 struct regulator_init_data *initdata;
683 struct regulation_constraints *c;
684 struct regulator_dev *rdev;
685 struct regulator_config config = { };
686 struct device_node *np = pdev->dev.of_node;
687
688 template = of_device_get_match_data(dev: &pdev->dev);
689 if (!template)
690 return -ENODEV;
691
692 id = template->desc.id;
693 initdata = of_get_regulator_init_data(dev: &pdev->dev, node: np, desc: &template->desc);
694 if (!initdata)
695 return -EINVAL;
696
697 info = devm_kmemdup(dev: &pdev->dev, src: template, len: sizeof(*info), GFP_KERNEL);
698 if (!info)
699 return -ENOMEM;
700
701 /* Constrain board-specific capabilities according to what
702 * this driver and the chip itself can actually do.
703 */
704 c = &initdata->constraints;
705 c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
706 c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
707 | REGULATOR_CHANGE_MODE
708 | REGULATOR_CHANGE_STATUS;
709
710 switch (id) {
711 case TWL6032_REG_SMPS3:
712 if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
713 info->flags |= SMPS_EXTENDED_EN;
714 if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
715 info->flags |= SMPS_OFFSET_EN;
716 break;
717 case TWL6032_REG_SMPS4:
718 if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
719 info->flags |= SMPS_EXTENDED_EN;
720 if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
721 info->flags |= SMPS_OFFSET_EN;
722 break;
723 case TWL6032_REG_VIO:
724 if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
725 info->flags |= SMPS_EXTENDED_EN;
726 if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
727 info->flags |= SMPS_OFFSET_EN;
728 break;
729 }
730
731 if (of_property_read_bool(np, propname: "ti,retain-on-reset"))
732 info->flags |= TWL_6030_WARM_RESET;
733
734 config.dev = &pdev->dev;
735 config.init_data = initdata;
736 config.driver_data = info;
737 config.of_node = np;
738
739 rdev = devm_regulator_register(dev: &pdev->dev, regulator_desc: &info->desc, config: &config);
740 if (IS_ERR(ptr: rdev)) {
741 dev_err(&pdev->dev, "can't register %s, %ld\n",
742 info->desc.name, PTR_ERR(rdev));
743 return PTR_ERR(ptr: rdev);
744 }
745 platform_set_drvdata(pdev, data: rdev);
746
747 /* NOTE: many regulators support short-circuit IRQs (presentable
748 * as REGULATOR_OVER_CURRENT notifications?) configured via:
749 * - SC_CONFIG
750 * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
751 * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
752 * - IT_CONFIG
753 */
754
755 return 0;
756}
757
758MODULE_ALIAS("platform:twl6030_reg");
759
760static struct platform_driver twlreg_driver = {
761 .probe = twlreg_probe,
762 /* NOTE: short name, to work around driver model truncation of
763 * "twl_regulator.12" (and friends) to "twl_regulator.1".
764 */
765 .driver = {
766 .name = "twl6030_reg",
767 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
768 .of_match_table = of_match_ptr(twl_of_match),
769 },
770};
771
772static int __init twlreg_init(void)
773{
774 return platform_driver_register(&twlreg_driver);
775}
776subsys_initcall(twlreg_init);
777
778static void __exit twlreg_exit(void)
779{
780 platform_driver_unregister(&twlreg_driver);
781}
782module_exit(twlreg_exit)
783
784MODULE_DESCRIPTION("TWL6030 regulator driver");
785MODULE_LICENSE("GPL");
786

source code of linux/drivers/regulator/twl6030-regulator.c