1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2016 4 * Texas Instruments Incorporated, <www.ti.com> 5 * 6 * Keerthy <j-keerthy@ti.com> 7 */ 8 9#include <common.h> 10#include <fdtdec.h> 11#include <errno.h> 12#include <dm.h> 13#include <power/pmic.h> 14#include <power/regulator.h> 15#include <power/palmas.h> 16 17#define REGULATOR_ON 0x1 18#define REGULATOR_OFF 0x0 19 20#define SMPS_MODE_MASK 0x3 21#define SMPS_MODE_SHIFT 0x0 22#define LDO_MODE_MASK 0x1 23#define LDO_MODE_SHIFT 0x0 24 25static const char palmas_smps_ctrl[][PALMAS_SMPS_NUM] = { 26 {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c}, 27 {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38}, 28 {0x20, 0x24, 0x2c, 0x30, 0x38}, 29}; 30 31static const char palmas_smps_volt[][PALMAS_SMPS_NUM] = { 32 {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3c}, 33 {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b}, 34 {0x23, 0x27, 0x2f, 0x33, 0x3B} 35}; 36 37static const char palmas_ldo_ctrl[][PALMAS_LDO_NUM] = { 38 {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64}, 39 {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64}, 40 {0x50, 0x52, 0x54, 0x5e, 0x62} 41}; 42 43static const char palmas_ldo_volt[][PALMAS_LDO_NUM] = { 44 {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65}, 45 {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65}, 46 {0x51, 0x53, 0x55, 0x5f, 0x63} 47}; 48 49static int palmas_smps_enable(struct udevice *dev, int op, bool *enable) 50{ 51 int ret; 52 unsigned int adr; 53 struct dm_regulator_uclass_plat *uc_pdata; 54 55 uc_pdata = dev_get_uclass_plat(dev); 56 adr = uc_pdata->ctrl_reg; 57 58 ret = pmic_reg_read(dev->parent, adr); 59 if (ret < 0) 60 return ret; 61 62 if (op == PMIC_OP_GET) { 63 ret &= PALMAS_SMPS_STATUS_MASK; 64 65 if (ret) 66 *enable = true; 67 else 68 *enable = false; 69 70 return 0; 71 } else if (op == PMIC_OP_SET) { 72 if (*enable) 73 ret |= PALMAS_SMPS_MODE_MASK; 74 else 75 ret &= ~(PALMAS_SMPS_MODE_MASK); 76 77 ret = pmic_reg_write(dev->parent, adr, ret); 78 if (ret) 79 return ret; 80 } 81 82 return 0; 83} 84 85static int palmas_smps_volt2hex(int uV) 86{ 87 if (uV > PALMAS_LDO_VOLT_MAX) 88 return -EINVAL; 89 90 if (uV > 1650000) 91 return (uV - 1000000) / 20000 + 0x6; 92 93 if (uV == 500000) 94 return 0x6; 95 else 96 return 0x6 + ((uV - 500000) / 10000); 97} 98 99static int palmas_smps_hex2volt(int hex, bool range) 100{ 101 unsigned int uV = 0; 102 103 if (hex > PALMAS_SMPS_VOLT_MAX_HEX) 104 return -EINVAL; 105 106 if (hex < 0x7) 107 uV = 500000; 108 else 109 uV = 500000 + (hex - 0x6) * 10000; 110 111 if (range) 112 uV *= 2; 113 114 return uV; 115} 116 117static int palmas_smps_val(struct udevice *dev, int op, int *uV) 118{ 119 unsigned int hex, adr; 120 int ret; 121 bool range; 122 struct dm_regulator_uclass_plat *uc_pdata; 123 124 uc_pdata = dev_get_uclass_plat(dev); 125 126 if (op == PMIC_OP_GET) 127 *uV = 0; 128 129 adr = uc_pdata->volt_reg; 130 131 ret = pmic_reg_read(dev->parent, adr); 132 if (ret < 0) 133 return ret; 134 135 if (op == PMIC_OP_GET) { 136 if (ret & PALMAS_SMPS_RANGE_MASK) 137 range = true; 138 else 139 range = false; 140 141 ret &= PALMAS_SMPS_VOLT_MASK; 142 ret = palmas_smps_hex2volt(ret, range); 143 if (ret < 0) 144 return ret; 145 *uV = ret; 146 147 return 0; 148 } 149 150 hex = palmas_smps_volt2hex(*uV); 151 if (hex < 0) 152 return hex; 153 154 ret &= ~PALMAS_SMPS_VOLT_MASK; 155 ret |= hex; 156 if (*uV > 1650000) 157 ret |= PALMAS_SMPS_RANGE_MASK; 158 159 return pmic_reg_write(dev->parent, adr, ret); 160} 161 162static int palmas_ldo_bypass_enable(struct udevice *dev, bool enabled) 163{ 164 int type = dev_get_driver_data(dev_get_parent(dev)); 165 struct dm_regulator_uclass_plat *p; 166 unsigned int adr; 167 int reg; 168 169 if (type == TPS65917) { 170 /* bypass available only on LDO1 and LDO2 */ 171 if (dev->driver_data > 2) 172 return -ENOTSUPP; 173 } else if (type == TPS659038) { 174 /* bypass available only on LDO9 */ 175 if (dev->driver_data != 9) 176 return -ENOTSUPP; 177 } 178 179 p = dev_get_uclass_plat(dev); 180 adr = p->ctrl_reg; 181 182 reg = pmic_reg_read(dev->parent, adr); 183 if (reg < 0) 184 return reg; 185 186 if (enabled) 187 reg |= PALMAS_LDO_BYPASS_EN; 188 else 189 reg &= ~PALMAS_LDO_BYPASS_EN; 190 191 return pmic_reg_write(dev->parent, adr, reg); 192} 193 194static int palmas_ldo_enable(struct udevice *dev, int op, bool *enable) 195{ 196 int ret; 197 unsigned int adr; 198 struct dm_regulator_uclass_plat *uc_pdata; 199 200 uc_pdata = dev_get_uclass_plat(dev); 201 adr = uc_pdata->ctrl_reg; 202 203 ret = pmic_reg_read(dev->parent, adr); 204 if (ret < 0) 205 return ret; 206 207 if (op == PMIC_OP_GET) { 208 ret &= PALMAS_LDO_STATUS_MASK; 209 210 if (ret) 211 *enable = true; 212 else 213 *enable = false; 214 215 return 0; 216 } else if (op == PMIC_OP_SET) { 217 if (*enable) 218 ret |= PALMAS_LDO_MODE_MASK; 219 else 220 ret &= ~(PALMAS_LDO_MODE_MASK); 221 222 ret = pmic_reg_write(dev->parent, adr, ret); 223 if (ret) 224 return ret; 225 226 ret = palmas_ldo_bypass_enable(dev, false); 227 if (ret && (ret != -ENOTSUPP)) 228 return ret; 229 } 230 231 return 0; 232} 233 234static int palmas_ldo_volt2hex(int uV) 235{ 236 if (uV > PALMAS_LDO_VOLT_MAX) 237 return -EINVAL; 238 239 return (uV - 850000) / 50000; 240} 241 242static int palmas_ldo_hex2volt(int hex) 243{ 244 if (hex > PALMAS_LDO_VOLT_MAX_HEX) 245 return -EINVAL; 246 247 if (!hex) 248 return 0; 249 250 return (hex * 50000) + 850000; 251} 252 253static int palmas_ldo_val(struct udevice *dev, int op, int *uV) 254{ 255 unsigned int hex, adr; 256 int ret; 257 258 struct dm_regulator_uclass_plat *uc_pdata; 259 260 if (op == PMIC_OP_GET) 261 *uV = 0; 262 263 uc_pdata = dev_get_uclass_plat(dev); 264 265 adr = uc_pdata->volt_reg; 266 267 ret = pmic_reg_read(dev->parent, adr); 268 if (ret < 0) 269 return ret; 270 271 if (op == PMIC_OP_GET) { 272 ret &= PALMAS_LDO_VOLT_MASK; 273 ret = palmas_ldo_hex2volt(ret); 274 if (ret < 0) 275 return ret; 276 *uV = ret; 277 return 0; 278 } 279 280 hex = palmas_ldo_volt2hex(*uV); 281 if (hex < 0) 282 return hex; 283 284 ret &= ~PALMAS_LDO_VOLT_MASK; 285 ret |= hex; 286 if (*uV > 1650000) 287 ret |= 0x80; 288 289 return pmic_reg_write(dev->parent, adr, ret); 290} 291 292static int palmas_ldo_probe(struct udevice *dev) 293{ 294 struct dm_regulator_uclass_plat *uc_pdata; 295 struct udevice *parent; 296 297 uc_pdata = dev_get_uclass_plat(dev); 298 299 parent = dev_get_parent(dev); 300 int type = dev_get_driver_data(parent); 301 302 uc_pdata->type = REGULATOR_TYPE_LDO; 303 304 /* check for ldoln and ldousb cases */ 305 if (!strcmp("ldoln", dev->name)) { 306 uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9]; 307 uc_pdata->volt_reg = palmas_ldo_volt[type][9]; 308 return 0; 309 } 310 311 if (!strcmp("ldousb", dev->name)) { 312 uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10]; 313 uc_pdata->volt_reg = palmas_ldo_volt[type][10]; 314 return 0; 315 } 316 317 if (dev->driver_data > 0) { 318 u8 idx = dev->driver_data - 1; 319 uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx]; 320 uc_pdata->volt_reg = palmas_ldo_volt[type][idx]; 321 } 322 323 return 0; 324} 325 326static int ldo_get_value(struct udevice *dev) 327{ 328 int uV; 329 int ret; 330 331 ret = palmas_ldo_val(dev, PMIC_OP_GET, &uV); 332 if (ret) 333 return ret; 334 335 return uV; 336} 337 338static int ldo_set_value(struct udevice *dev, int uV) 339{ 340 return palmas_ldo_val(dev, PMIC_OP_SET, &uV); 341} 342 343static int ldo_get_enable(struct udevice *dev) 344{ 345 bool enable = false; 346 int ret; 347 348 ret = palmas_ldo_enable(dev, PMIC_OP_GET, &enable); 349 if (ret) 350 return ret; 351 352 return enable; 353} 354 355static int ldo_set_enable(struct udevice *dev, bool enable) 356{ 357 return palmas_ldo_enable(dev, PMIC_OP_SET, &enable); 358} 359 360static int palmas_smps_probe(struct udevice *dev) 361{ 362 struct dm_regulator_uclass_plat *uc_pdata; 363 struct udevice *parent; 364 int idx; 365 366 uc_pdata = dev_get_uclass_plat(dev); 367 368 parent = dev_get_parent(dev); 369 int type = dev_get_driver_data(parent); 370 371 uc_pdata->type = REGULATOR_TYPE_BUCK; 372 373 switch (type) { 374 case PALMAS: 375 case TPS659038: 376 switch (dev->driver_data) { 377 case 123: 378 case 12: 379 uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0]; 380 uc_pdata->volt_reg = palmas_smps_volt[type][0]; 381 break; 382 case 3: 383 uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1]; 384 uc_pdata->volt_reg = palmas_smps_volt[type][1]; 385 break; 386 case 45: 387 uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2]; 388 uc_pdata->volt_reg = palmas_smps_volt[type][2]; 389 break; 390 case 6: 391 case 7: 392 case 8: 393 case 9: 394 case 10: 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]; 398 break; 399 400 default: 401 printf("Wrong ID for regulator\n"); 402 } 403 break; 404 405 case TPS65917: 406 switch (dev->driver_data) { 407 case 1: 408 case 2: 409 case 3: 410 case 4: 411 case 5: 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]; 415 break; 416 case 12: 417 idx = 0; 418 uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx]; 419 uc_pdata->volt_reg = palmas_smps_volt[type][idx]; 420 break; 421 default: 422 printf("Wrong ID for regulator\n"); 423 } 424 break; 425 426 default: 427 printf("Invalid PMIC ID\n"); 428 } 429 430 return 0; 431} 432 433static int smps_get_value(struct udevice *dev) 434{ 435 int uV; 436 int ret; 437 438 ret = palmas_smps_val(dev, PMIC_OP_GET, &uV); 439 if (ret) 440 return ret; 441 442 return uV; 443} 444 445static int smps_set_value(struct udevice *dev, int uV) 446{ 447 return palmas_smps_val(dev, PMIC_OP_SET, &uV); 448} 449 450static int smps_get_enable(struct udevice *dev) 451{ 452 bool enable = false; 453 int ret; 454 455 ret = palmas_smps_enable(dev, PMIC_OP_GET, &enable); 456 if (ret) 457 return ret; 458 459 return enable; 460} 461 462static int smps_set_enable(struct udevice *dev, bool enable) 463{ 464 return palmas_smps_enable(dev, PMIC_OP_SET, &enable); 465} 466 467static 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, 472}; 473 474U_BOOT_DRIVER(palmas_ldo) = { 475 .name = PALMAS_LDO_DRIVER, 476 .id = UCLASS_REGULATOR, 477 .ops = &palmas_ldo_ops, 478 .probe = palmas_ldo_probe, 479}; 480 481static 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, 486}; 487 488U_BOOT_DRIVER(palmas_smps) = { 489 .name = PALMAS_SMPS_DRIVER, 490 .id = UCLASS_REGULATOR, 491 .ops = &palmas_smps_ops, 492 .probe = palmas_smps_probe, 493}; 494