1 // SPDX-License-Identifier: GPL-2.0+
4 * Texas Instruments Incorporated, <www.ti.com>
6 * Keerthy <j-keerthy@ti.com>
15 #include <power/pmic.h>
16 #include <power/regulator.h>
17 #include <power/tps65941.h>
19 static const char tps65941_buck_ctrl[TPS65941_BUCK_NUM] = {0x4, 0x6, 0x8, 0xA,
21 static const char tps65941_buck_vout[TPS65941_BUCK_NUM] = {0xE, 0x10, 0x12,
23 static const char tps65941_ldo_ctrl[TPS65941_BUCK_NUM] = {0x1D, 0x1E, 0x1F,
25 static const char tps65941_ldo_vout[TPS65941_BUCK_NUM] = {0x23, 0x24, 0x25,
28 static int tps65941_buck_enable(struct udevice *dev, int op, bool *enable)
32 struct dm_regulator_uclass_platdata *uc_pdata;
34 uc_pdata = dev_get_uclass_platdata(dev);
35 adr = uc_pdata->ctrl_reg;
37 ret = pmic_reg_read(dev->parent, adr);
41 if (op == PMIC_OP_GET) {
42 ret &= TPS65941_BUCK_MODE_MASK;
50 } else if (op == PMIC_OP_SET) {
52 ret |= TPS65941_BUCK_MODE_MASK;
54 ret &= ~TPS65941_BUCK_MODE_MASK;
55 ret = pmic_reg_write(dev->parent, adr, ret);
63 static int tps65941_buck_volt2val(int uV)
65 if (uV > TPS65941_BUCK_VOLT_MAX)
67 else if (uV > 1650000)
68 return (uV - 1660000) / 20000 + 0xAB;
69 else if (uV > 1110000)
70 return (uV - 1110000) / 10000 + 0x73;
72 return (uV - 600000) / 5000 + 0x0F;
73 else if (uV >= 300000)
74 return (uV - 300000) / 20000 + 0x00;
79 static int tps65941_buck_val2volt(int val)
81 if (val > TPS65941_BUCK_VOLT_MAX_HEX)
84 return 1660000 + (val - 0xAB) * 20000;
86 return 1100000 + (val - 0x73) * 10000;
88 return 600000 + (val - 0xF) * 5000;
90 return 300000 + val * 5000;
95 int tps65941_lookup_slew(int id)
119 static int tps65941_buck_val(struct udevice *dev, int op, int *uV)
121 unsigned int hex, adr;
122 int ret, delta, uwait, slew;
123 struct dm_regulator_uclass_platdata *uc_pdata;
125 uc_pdata = dev_get_uclass_platdata(dev);
127 if (op == PMIC_OP_GET)
130 adr = uc_pdata->volt_reg;
132 ret = pmic_reg_read(dev->parent, adr);
136 ret &= TPS65941_BUCK_VOLT_MASK;
137 ret = tps65941_buck_val2volt(ret);
141 if (op == PMIC_OP_GET) {
147 * Compute the delta voltage, find the slew rate and wait
148 * for the appropriate amount of time after voltage switch
155 slew = pmic_reg_read(dev->parent, uc_pdata->ctrl_reg + 1);
159 slew &= TP65941_BUCK_CONF_SLEW_MASK;
160 slew = tps65941_lookup_slew(slew);
164 uwait = delta / slew;
166 hex = tps65941_buck_volt2val(*uV);
173 ret = pmic_reg_write(dev->parent, adr, ret);
180 static int tps65941_ldo_enable(struct udevice *dev, int op, bool *enable)
184 struct dm_regulator_uclass_platdata *uc_pdata;
186 uc_pdata = dev_get_uclass_platdata(dev);
187 adr = uc_pdata->ctrl_reg;
189 ret = pmic_reg_read(dev->parent, adr);
193 if (op == PMIC_OP_GET) {
194 ret &= TPS65941_LDO_MODE_MASK;
202 } else if (op == PMIC_OP_SET) {
204 ret |= TPS65941_LDO_MODE_MASK;
206 ret &= ~TPS65941_LDO_MODE_MASK;
207 ret = pmic_reg_write(dev->parent, adr, ret);
215 static int tps65941_ldo_val2volt(int val)
217 if (val > TPS65941_LDO_VOLT_MAX_HEX || val < TPS65941_LDO_VOLT_MIN_HEX)
219 else if (val >= TPS65941_LDO_VOLT_MIN_HEX)
220 return 600000 + (val - TPS65941_LDO_VOLT_MIN_HEX) * 50000;
225 static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
227 unsigned int hex, adr;
229 struct dm_regulator_uclass_platdata *uc_pdata;
231 uc_pdata = dev_get_uclass_platdata(dev);
233 if (op == PMIC_OP_GET)
236 adr = uc_pdata->volt_reg;
238 ret = pmic_reg_read(dev->parent, adr);
242 ret &= TPS65941_LDO_VOLT_MASK;
243 ret = tps65941_ldo_val2volt(ret);
247 if (op == PMIC_OP_GET) {
252 hex = tps65941_buck_volt2val(*uV);
259 ret = pmic_reg_write(dev->parent, adr, ret);
264 static int tps65941_ldo_probe(struct udevice *dev)
266 struct dm_regulator_uclass_platdata *uc_pdata;
269 uc_pdata = dev_get_uclass_platdata(dev);
270 uc_pdata->type = REGULATOR_TYPE_LDO;
272 idx = dev->driver_data;
273 if (idx == 1 || idx == 2 || idx == 3 || idx == 4) {
274 debug("Single phase regulator\n");
276 printf("Wrong ID for regulator\n");
280 uc_pdata->ctrl_reg = tps65941_ldo_ctrl[idx - 1];
281 uc_pdata->volt_reg = tps65941_ldo_vout[idx - 1];
286 static int tps65941_buck_probe(struct udevice *dev)
288 struct dm_regulator_uclass_platdata *uc_pdata;
291 uc_pdata = dev_get_uclass_platdata(dev);
292 uc_pdata->type = REGULATOR_TYPE_BUCK;
294 idx = dev->driver_data;
295 if (idx == 1 || idx == 2 || idx == 3 || idx == 4 || idx == 5) {
296 debug("Single phase regulator\n");
297 } else if (idx == 12) {
299 } else if (idx == 34) {
301 } else if (idx == 1234) {
304 printf("Wrong ID for regulator\n");
308 uc_pdata->ctrl_reg = tps65941_buck_ctrl[idx - 1];
309 uc_pdata->volt_reg = tps65941_buck_vout[idx - 1];
314 static int ldo_get_value(struct udevice *dev)
319 ret = tps65941_ldo_val(dev, PMIC_OP_GET, &uV);
326 static int ldo_set_value(struct udevice *dev, int uV)
328 return tps65941_ldo_val(dev, PMIC_OP_SET, &uV);
331 static int ldo_get_enable(struct udevice *dev)
336 ret = tps65941_ldo_enable(dev, PMIC_OP_GET, &enable);
343 static int ldo_set_enable(struct udevice *dev, bool enable)
345 return tps65941_ldo_enable(dev, PMIC_OP_SET, &enable);
348 static int buck_get_value(struct udevice *dev)
353 ret = tps65941_buck_val(dev, PMIC_OP_GET, &uV);
360 static int buck_set_value(struct udevice *dev, int uV)
362 return tps65941_buck_val(dev, PMIC_OP_SET, &uV);
365 static int buck_get_enable(struct udevice *dev)
370 ret = tps65941_buck_enable(dev, PMIC_OP_GET, &enable);
377 static int buck_set_enable(struct udevice *dev, bool enable)
379 return tps65941_buck_enable(dev, PMIC_OP_SET, &enable);
382 static const struct dm_regulator_ops tps65941_ldo_ops = {
383 .get_value = ldo_get_value,
384 .set_value = ldo_set_value,
385 .get_enable = ldo_get_enable,
386 .set_enable = ldo_set_enable,
389 U_BOOT_DRIVER(tps65941_ldo) = {
390 .name = TPS65941_LDO_DRIVER,
391 .id = UCLASS_REGULATOR,
392 .ops = &tps65941_ldo_ops,
393 .probe = tps65941_ldo_probe,
396 static const struct dm_regulator_ops tps65941_buck_ops = {
397 .get_value = buck_get_value,
398 .set_value = buck_set_value,
399 .get_enable = buck_get_enable,
400 .set_enable = buck_set_enable,
403 U_BOOT_DRIVER(tps65941_buck) = {
404 .name = TPS65941_BUCK_DRIVER,
405 .id = UCLASS_REGULATOR,
406 .ops = &tps65941_buck_ops,
407 .probe = tps65941_buck_probe,