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