3 * Texas Instruments Incorporated, <www.ti.com>
5 * Keerthy <j-keerthy@ti.com>
7 * SPDX-License-Identifier: GPL-2.0+
15 #include <power/pmic.h>
16 #include <power/regulator.h>
17 #include <power/palmas.h>
19 DECLARE_GLOBAL_DATA_PTR
;
21 #define REGULATOR_ON 0x1
22 #define REGULATOR_OFF 0x0
24 #define SMPS_MODE_MASK 0x3
25 #define SMPS_MODE_SHIFT 0x0
26 #define LDO_MODE_MASK 0x1
27 #define LDO_MODE_SHIFT 0x0
29 static const char palmas_smps_ctrl
[][PALMAS_SMPS_NUM
] = {
30 {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c},
31 {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38},
32 {0x20, 0x24, 0x2c, 0x30, 0x38},
35 static const char palmas_smps_volt
[][PALMAS_SMPS_NUM
] = {
36 {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3c},
37 {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b},
38 {0x23, 0x27, 0x2f, 0x33, 0x3B}
41 static const char palmas_ldo_ctrl
[][PALMAS_LDO_NUM
] = {
42 {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
43 {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
44 {0x50, 0x52, 0x54, 0x5e, 0x62}
47 static const char palmas_ldo_volt
[][PALMAS_LDO_NUM
] = {
48 {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
49 {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
50 {0x51, 0x53, 0x55, 0x5f, 0x63}
53 static int palmas_smps_enable(struct udevice
*dev
, int op
, bool *enable
)
57 struct dm_regulator_uclass_platdata
*uc_pdata
;
59 uc_pdata
= dev_get_uclass_platdata(dev
);
60 adr
= uc_pdata
->ctrl_reg
;
62 ret
= pmic_reg_read(dev
->parent
, adr
);
66 if (op
== PMIC_OP_GET
) {
67 ret
&= PALMAS_SMPS_STATUS_MASK
;
75 } else if (op
== PMIC_OP_SET
) {
77 ret
|= PALMAS_SMPS_MODE_MASK
;
79 ret
&= ~(PALMAS_SMPS_MODE_MASK
);
81 ret
= pmic_reg_write(dev
->parent
, adr
, ret
);
89 static int palmas_smps_volt2hex(int uV
)
91 if (uV
> PALMAS_LDO_VOLT_MAX
)
95 return (uV
- 1000000) / 20000 + 0x6;
100 return 0x6 + ((uV
- 500000) / 10000);
103 static int palmas_smps_hex2volt(int hex
, bool range
)
107 if (hex
> PALMAS_SMPS_VOLT_MAX_HEX
)
113 uV
= 500000 + (hex
- 0x6) * 10000;
121 static int palmas_smps_val(struct udevice
*dev
, int op
, int *uV
)
123 unsigned int hex
, adr
;
126 struct dm_regulator_uclass_platdata
*uc_pdata
;
128 uc_pdata
= dev_get_uclass_platdata(dev
);
130 if (op
== PMIC_OP_GET
)
133 adr
= uc_pdata
->volt_reg
;
135 ret
= pmic_reg_read(dev
->parent
, adr
);
139 if (op
== PMIC_OP_GET
) {
140 if (ret
& PALMAS_SMPS_RANGE_MASK
)
145 ret
&= PALMAS_SMPS_VOLT_MASK
;
146 ret
= palmas_smps_hex2volt(ret
, range
);
154 hex
= palmas_smps_volt2hex(*uV
);
158 ret
&= ~PALMAS_SMPS_VOLT_MASK
;
161 ret
|= PALMAS_SMPS_RANGE_MASK
;
163 return pmic_reg_write(dev
->parent
, adr
, ret
);
166 static int palmas_ldo_bypass_enable(struct udevice
*dev
, bool enabled
)
168 int type
= dev_get_driver_data(dev_get_parent(dev
));
169 struct dm_regulator_uclass_platdata
*p
;
173 if (type
== TPS65917
) {
174 /* bypass available only on LDO1 and LDO2 */
175 if (dev
->driver_data
> 2)
177 } else if (type
== TPS659038
) {
178 /* bypass available only on LDO9 */
179 if (dev
->driver_data
!= 9)
183 p
= dev_get_uclass_platdata(dev
);
186 reg
= pmic_reg_read(dev
->parent
, adr
);
191 reg
|= PALMAS_LDO_BYPASS_EN
;
193 reg
&= ~PALMAS_LDO_BYPASS_EN
;
195 return pmic_reg_write(dev
->parent
, adr
, reg
);
198 static int palmas_ldo_enable(struct udevice
*dev
, int op
, bool *enable
)
202 struct dm_regulator_uclass_platdata
*uc_pdata
;
204 uc_pdata
= dev_get_uclass_platdata(dev
);
205 adr
= uc_pdata
->ctrl_reg
;
207 ret
= pmic_reg_read(dev
->parent
, adr
);
211 if (op
== PMIC_OP_GET
) {
212 ret
&= PALMAS_LDO_STATUS_MASK
;
220 } else if (op
== PMIC_OP_SET
) {
222 ret
|= PALMAS_LDO_MODE_MASK
;
224 ret
&= ~(PALMAS_LDO_MODE_MASK
);
226 ret
= pmic_reg_write(dev
->parent
, adr
, ret
);
230 ret
= palmas_ldo_bypass_enable(dev
, false);
231 if (ret
&& (ret
!= -ENOTSUPP
))
238 static int palmas_ldo_volt2hex(int uV
)
240 if (uV
> PALMAS_LDO_VOLT_MAX
)
243 return (uV
- 850000) / 50000;
246 static int palmas_ldo_hex2volt(int hex
)
248 if (hex
> PALMAS_LDO_VOLT_MAX_HEX
)
254 return (hex
* 50000) + 850000;
257 static int palmas_ldo_val(struct udevice
*dev
, int op
, int *uV
)
259 unsigned int hex
, adr
;
262 struct dm_regulator_uclass_platdata
*uc_pdata
;
264 if (op
== PMIC_OP_GET
)
267 uc_pdata
= dev_get_uclass_platdata(dev
);
269 adr
= uc_pdata
->volt_reg
;
271 ret
= pmic_reg_read(dev
->parent
, adr
);
275 if (op
== PMIC_OP_GET
) {
276 ret
&= PALMAS_LDO_VOLT_MASK
;
277 ret
= palmas_ldo_hex2volt(ret
);
284 hex
= palmas_ldo_volt2hex(*uV
);
288 ret
&= ~PALMAS_LDO_VOLT_MASK
;
293 return pmic_reg_write(dev
->parent
, adr
, ret
);
296 static int palmas_ldo_probe(struct udevice
*dev
)
298 struct dm_regulator_uclass_platdata
*uc_pdata
;
299 struct udevice
*parent
;
301 uc_pdata
= dev_get_uclass_platdata(dev
);
303 parent
= dev_get_parent(dev
);
304 int type
= dev_get_driver_data(parent
);
306 uc_pdata
->type
= REGULATOR_TYPE_LDO
;
308 if (dev
->driver_data
) {
309 u8 idx
= dev
->driver_data
- 1;
310 uc_pdata
->ctrl_reg
= palmas_ldo_ctrl
[type
][idx
];
311 uc_pdata
->volt_reg
= palmas_ldo_volt
[type
][idx
];
313 /* check for ldoln and ldousb cases */
314 if (!strcmp("ldoln", dev
->name
)) {
315 uc_pdata
->ctrl_reg
= palmas_ldo_ctrl
[type
][9];
316 uc_pdata
->volt_reg
= palmas_ldo_volt
[type
][9];
317 } else if (!strcmp("ldousb", dev
->name
)) {
318 uc_pdata
->ctrl_reg
= palmas_ldo_ctrl
[type
][10];
319 uc_pdata
->volt_reg
= palmas_ldo_volt
[type
][10];
326 static int ldo_get_value(struct udevice
*dev
)
331 ret
= palmas_ldo_val(dev
, PMIC_OP_GET
, &uV
);
338 static int ldo_set_value(struct udevice
*dev
, int uV
)
340 return palmas_ldo_val(dev
, PMIC_OP_SET
, &uV
);
343 static int ldo_get_enable(struct udevice
*dev
)
348 ret
= palmas_ldo_enable(dev
, PMIC_OP_GET
, &enable
);
355 static int ldo_set_enable(struct udevice
*dev
, bool enable
)
357 return palmas_ldo_enable(dev
, PMIC_OP_SET
, &enable
);
360 static int palmas_smps_probe(struct udevice
*dev
)
362 struct dm_regulator_uclass_platdata
*uc_pdata
;
363 struct udevice
*parent
;
366 uc_pdata
= dev_get_uclass_platdata(dev
);
368 parent
= dev_get_parent(dev
);
369 int type
= dev_get_driver_data(parent
);
371 uc_pdata
->type
= REGULATOR_TYPE_BUCK
;
376 switch (dev
->driver_data
) {
379 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][0];
380 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][0];
383 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][1];
384 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][1];
387 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][2];
388 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][2];
395 idx
= dev
->driver_data
- 3;
396 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][idx
];
397 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][idx
];
401 printf("Wrong ID for regulator\n");
406 switch (dev
->driver_data
) {
412 idx
= dev
->driver_data
- 1;
413 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][idx
];
414 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][idx
];
418 uc_pdata
->ctrl_reg
= palmas_smps_ctrl
[type
][idx
];
419 uc_pdata
->volt_reg
= palmas_smps_volt
[type
][idx
];
422 printf("Wrong ID for regulator\n");
427 printf("Invalid PMIC ID\n");
433 static int smps_get_value(struct udevice
*dev
)
438 ret
= palmas_smps_val(dev
, PMIC_OP_GET
, &uV
);
445 static int smps_set_value(struct udevice
*dev
, int uV
)
447 return palmas_smps_val(dev
, PMIC_OP_SET
, &uV
);
450 static int smps_get_enable(struct udevice
*dev
)
455 ret
= palmas_smps_enable(dev
, PMIC_OP_GET
, &enable
);
462 static int smps_set_enable(struct udevice
*dev
, bool enable
)
464 return palmas_smps_enable(dev
, PMIC_OP_SET
, &enable
);
467 static const struct dm_regulator_ops palmas_ldo_ops
= {
468 .get_value
= ldo_get_value
,
469 .set_value
= ldo_set_value
,
470 .get_enable
= ldo_get_enable
,
471 .set_enable
= ldo_set_enable
,
474 U_BOOT_DRIVER(palmas_ldo
) = {
475 .name
= PALMAS_LDO_DRIVER
,
476 .id
= UCLASS_REGULATOR
,
477 .ops
= &palmas_ldo_ops
,
478 .probe
= palmas_ldo_probe
,
481 static const struct dm_regulator_ops palmas_smps_ops
= {
482 .get_value
= smps_get_value
,
483 .set_value
= smps_set_value
,
484 .get_enable
= smps_get_enable
,
485 .set_enable
= smps_set_enable
,
488 U_BOOT_DRIVER(palmas_smps
) = {
489 .name
= PALMAS_SMPS_DRIVER
,
490 .id
= UCLASS_REGULATOR
,
491 .ops
= &palmas_smps_ops
,
492 .probe
= palmas_smps_probe
,