1 /* 2 * Copyright (C) 2024, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <drivers/st/stpmic2.h> 13 14 #define RET_SUCCESS 0 15 #define RET_ERROR_NOT_SUPPORTED -1 16 #define RET_ERROR_GENERIC -2 17 #define RET_ERROR_BAD_PARAMETERS -3 18 19 #define I2C_TIMEOUT_MS 25 20 21 #define VOLTAGE_INDEX_INVALID ((size_t)~0U) 22 23 struct regul_struct { 24 const char *name; 25 const uint16_t *volt_table; 26 uint8_t volt_table_size; 27 uint8_t volt_cr; 28 uint8_t volt_shift; 29 uint8_t en_cr; 30 uint8_t alt_en_cr; 31 uint8_t msrt_reg; 32 uint8_t msrt_mask; 33 uint8_t pd_reg; 34 uint8_t pd_val; 35 uint8_t ocp_reg; 36 uint8_t ocp_mask; 37 }; 38 39 /* Voltage tables in mV */ 40 static const uint16_t buck1236_volt_table[] = { 41 500U, 510U, 520U, 530U, 540U, 550U, 560U, 570U, 580U, 590U, 42 600U, 610U, 620U, 630U, 640U, 650U, 660U, 670U, 680U, 690U, 43 700U, 710U, 720U, 730U, 740U, 750U, 760U, 770U, 780U, 790U, 44 800U, 810U, 820U, 830U, 840U, 850U, 860U, 870U, 880U, 890U, 45 900U, 910U, 920U, 930U, 940U, 950U, 960U, 970U, 980U, 990U, 46 1000U, 1010U, 1020U, 1030U, 1040U, 1050U, 1060U, 1070U, 1080U, 1090U, 47 1100U, 1110U, 1120U, 1130U, 1140U, 1150U, 1160U, 1170U, 1180U, 1190U, 48 1200U, 1210U, 1220U, 1230U, 1240U, 1250U, 1260U, 1270U, 1280U, 1290U, 49 1300U, 1310U, 1320U, 1330U, 1340U, 1350U, 1360U, 1370U, 1380U, 1390U, 50 1400U, 1410U, 1420U, 1430U, 1440U, 1450U, 1460U, 1470U, 1480U, 1490U, 51 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 52 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 53 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U 54 }; 55 56 static const uint16_t buck457_volt_table[] = { 57 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 58 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 59 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 60 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 61 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 62 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 63 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 64 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 65 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 66 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 67 1500U, 1600U, 1700U, 1800U, 1900U, 2000U, 2100U, 2200U, 2300U, 2400U, 68 2500U, 2600U, 2700U, 2800U, 2900U, 3000U, 3100U, 3200U, 3300U, 3400U, 69 3500U, 3600U, 3700U, 3800U, 3900U, 4000U, 4100U, 4200U 70 }; 71 72 static const uint16_t ldo235678_volt_table[] = { 73 900U, 1000U, 1100U, 1200U, 1300U, 1400U, 1500U, 1600U, 1700U, 1800U, 74 1900U, 2000U, 2100U, 2200U, 2300U, 2400U, 2500U, 2600U, 2700U, 2800U, 75 2900U, 3000U, 3100U, 3200U, 3300U, 3400U, 3500U, 3600U, 3700U, 3800U, 76 3900U, 4000U 77 }; 78 79 static const uint16_t ldo1_volt_table[] = { 80 1800U, 81 }; 82 83 static const uint16_t ldo4_volt_table[] = { 84 3300U, 85 }; 86 87 static const uint16_t refddr_volt_table[] = { 88 0, 89 }; 90 91 #define DEFINE_BUCK(regu_name, ID, pd, table) { \ 92 .name = regu_name, \ 93 .volt_table = table, \ 94 .volt_table_size = ARRAY_SIZE(table), \ 95 .en_cr = ID ## _MAIN_CR2, \ 96 .volt_cr = ID ## _MAIN_CR1, \ 97 .alt_en_cr = ID ## _ALT_CR2, \ 98 .msrt_reg = BUCKS_MRST_CR, \ 99 .msrt_mask = ID ## _MRST, \ 100 .pd_reg = pd, \ 101 .pd_val = ID ## _PD_FAST, \ 102 .ocp_reg = FS_OCP_CR1, \ 103 .ocp_mask = FS_OCP_ ## ID, \ 104 } 105 106 #define DEFINE_LDOx(regu_name, ID, table) { \ 107 .name = regu_name, \ 108 .volt_table = table, \ 109 .volt_table_size = ARRAY_SIZE(table), \ 110 .volt_shift = LDO_VOLT_SHIFT, \ 111 .en_cr = ID ## _MAIN_CR, \ 112 .volt_cr = ID ## _MAIN_CR, \ 113 .alt_en_cr = ID ## _ALT_CR, \ 114 .msrt_reg = LDOS_MRST_CR, \ 115 .msrt_mask = ID ## _MRST, \ 116 .pd_reg = LDOS_PD_CR1, \ 117 .pd_val = ID ## _PD, \ 118 .ocp_reg = FS_OCP_CR2, \ 119 .ocp_mask = FS_OCP_ ## ID, \ 120 } 121 122 #define DEFINE_REFDDR(regu_name, ID, table) { \ 123 .name = regu_name, \ 124 .volt_table = table, \ 125 .volt_table_size = ARRAY_SIZE(table), \ 126 .en_cr = ID ## _MAIN_CR, \ 127 .volt_cr = ID ## _MAIN_CR, \ 128 .alt_en_cr = ID ## _ALT_CR, \ 129 .msrt_reg = BUCKS_MRST_CR, \ 130 .msrt_mask = ID ## _MRST, \ 131 .pd_reg = LDOS_PD_CR2, \ 132 .pd_val = ID ## _PD, \ 133 .ocp_reg = FS_OCP_CR1, \ 134 .ocp_mask = FS_OCP_ ## ID, \ 135 } 136 137 /* Table of Regulators in PMIC SoC */ 138 static const struct regul_struct regul_table[STPMIC2_NB_REG] = { 139 [STPMIC2_BUCK1] = DEFINE_BUCK("buck1", BUCK1, BUCKS_PD_CR1, 140 buck1236_volt_table), 141 [STPMIC2_BUCK2] = DEFINE_BUCK("buck2", BUCK2, BUCKS_PD_CR1, 142 buck1236_volt_table), 143 [STPMIC2_BUCK3] = DEFINE_BUCK("buck3", BUCK3, BUCKS_PD_CR1, 144 buck1236_volt_table), 145 [STPMIC2_BUCK4] = DEFINE_BUCK("buck4", BUCK4, BUCKS_PD_CR1, 146 buck457_volt_table), 147 [STPMIC2_BUCK5] = DEFINE_BUCK("buck5", BUCK5, BUCKS_PD_CR2, 148 buck457_volt_table), 149 [STPMIC2_BUCK6] = DEFINE_BUCK("buck6", BUCK6, BUCKS_PD_CR2, 150 buck1236_volt_table), 151 [STPMIC2_BUCK7] = DEFINE_BUCK("buck7", BUCK7, BUCKS_PD_CR2, 152 buck457_volt_table), 153 154 [STPMIC2_REFDDR] = DEFINE_REFDDR("refddr", REFDDR, refddr_volt_table), 155 156 [STPMIC2_LDO1] = DEFINE_LDOx("ldo1", LDO1, ldo1_volt_table), 157 [STPMIC2_LDO2] = DEFINE_LDOx("ldo2", LDO2, ldo235678_volt_table), 158 [STPMIC2_LDO3] = DEFINE_LDOx("ldo3", LDO3, ldo235678_volt_table), 159 [STPMIC2_LDO4] = DEFINE_LDOx("ldo4", LDO4, ldo4_volt_table), 160 [STPMIC2_LDO5] = DEFINE_LDOx("ldo5", LDO5, ldo235678_volt_table), 161 [STPMIC2_LDO6] = DEFINE_LDOx("ldo6", LDO6, ldo235678_volt_table), 162 [STPMIC2_LDO7] = DEFINE_LDOx("ldo7", LDO7, ldo235678_volt_table), 163 [STPMIC2_LDO8] = DEFINE_LDOx("ldo8", LDO8, ldo235678_volt_table), 164 165 }; 166 167 int stpmic2_register_read(struct pmic_handle_s *pmic, 168 uint8_t register_id, uint8_t *value) 169 { 170 int ret = stm32_i2c_mem_read(pmic->i2c_handle, 171 pmic->i2c_addr, 172 (uint16_t)register_id, 173 I2C_MEMADD_SIZE_8BIT, value, 174 1, I2C_TIMEOUT_MS); 175 if (ret != 0) { 176 ERROR("Failed to read reg:0x%x\n", register_id); 177 } 178 179 return ret; 180 } 181 182 int stpmic2_register_write(struct pmic_handle_s *pmic, 183 uint8_t register_id, uint8_t value) 184 { 185 uint8_t val = value; 186 int ret = stm32_i2c_mem_write(pmic->i2c_handle, 187 pmic->i2c_addr, 188 (uint16_t)register_id, 189 I2C_MEMADD_SIZE_8BIT, &val, 190 1, I2C_TIMEOUT_MS); 191 if (ret != 0) { 192 ERROR("Failed to write reg:0x%x\n", register_id); 193 } 194 195 return ret; 196 } 197 198 int stpmic2_register_update(struct pmic_handle_s *pmic, 199 uint8_t register_id, uint8_t value, uint8_t mask) 200 { 201 int status; 202 uint8_t val = 0U; 203 204 status = stpmic2_register_read(pmic, register_id, &val); 205 if (status != 0) { 206 return status; 207 } 208 209 val = (val & ((uint8_t)~mask)) | (value & mask); 210 211 VERBOSE("REG:0x%x v=0x%x mask=0x%x -> 0x%x\n", 212 register_id, value, mask, val); 213 214 return stpmic2_register_write(pmic, register_id, val); 215 } 216 217 int stpmic2_regulator_set_state(struct pmic_handle_s *pmic, 218 uint8_t id, bool enable) 219 { 220 const struct regul_struct *regul = ®ul_table[id]; 221 222 if (enable) { 223 return stpmic2_register_update(pmic, regul->en_cr, 1U, 1U); 224 } else { 225 return stpmic2_register_update(pmic, regul->en_cr, 0, 1U); 226 } 227 } 228 229 int stpmic2_regulator_get_state(struct pmic_handle_s *pmic, 230 uint8_t id, bool *enabled) 231 { 232 const struct regul_struct *regul = ®ul_table[id]; 233 uint8_t val; 234 235 if (stpmic2_register_read(pmic, regul->en_cr, &val) != 0) { 236 return RET_ERROR_GENERIC; 237 } 238 239 *enabled = (val & 1U) == 1U; 240 241 return RET_SUCCESS; 242 } 243 244 int stpmic2_regulator_levels_mv(struct pmic_handle_s *pmic, 245 uint8_t id, const uint16_t **levels, 246 size_t *levels_count) 247 { 248 const struct regul_struct *regul = ®ul_table[id]; 249 250 if (regul == NULL) { 251 return RET_ERROR_BAD_PARAMETERS; 252 } 253 254 if (levels_count != NULL) { 255 *levels_count = regul->volt_table_size; 256 } 257 if (levels != NULL) { 258 *levels = regul->volt_table; 259 } 260 261 return RET_SUCCESS; 262 } 263 264 int stpmic2_regulator_get_voltage(struct pmic_handle_s *pmic, 265 uint8_t id, uint16_t *val) 266 { 267 const struct regul_struct *regul = ®ul_table[id]; 268 uint8_t value = 0U; 269 uint8_t mask; 270 271 if (regul->volt_table_size == 0U) { 272 return RET_ERROR_GENERIC; 273 } 274 275 mask = regul->volt_table_size - 1U; 276 if (mask != 0U) { 277 if (stpmic2_register_read(pmic, regul->volt_cr, &value) != 0) { 278 return RET_ERROR_GENERIC; 279 } 280 281 value = (value >> regul->volt_shift) & mask; 282 } 283 284 if (value > regul->volt_table_size) { 285 return RET_ERROR_GENERIC; 286 } 287 288 *val = regul->volt_table[value]; 289 290 return RET_SUCCESS; 291 } 292 293 static size_t voltage_to_index(const struct regul_struct *regul, 294 uint16_t millivolts) 295 { 296 unsigned int i; 297 298 assert(regul->volt_table); 299 for (i = 0U; i < regul->volt_table_size; i++) { 300 if (regul->volt_table[i] == millivolts) { 301 return i; 302 } 303 } 304 305 return VOLTAGE_INDEX_INVALID; 306 } 307 308 int stpmic2_regulator_set_voltage(struct pmic_handle_s *pmic, 309 uint8_t id, uint16_t millivolts) 310 { 311 const struct regul_struct *regul = ®ul_table[id]; 312 size_t index; 313 uint8_t mask; 314 315 if (!regul->volt_table_size) { 316 return RET_SUCCESS; 317 } 318 319 mask = regul->volt_table_size - 1U; 320 321 index = voltage_to_index(regul, millivolts); 322 if (index == VOLTAGE_INDEX_INVALID) { 323 return RET_ERROR_GENERIC; 324 } 325 326 return stpmic2_register_update(pmic, regul->volt_cr, 327 index << regul->volt_shift, 328 mask << regul->volt_shift); 329 } 330 331 /* update both normal and alternate register */ 332 static int stpmic2_update_en_crs(struct pmic_handle_s *pmic, uint8_t id, 333 uint8_t value, uint8_t mask) 334 { 335 const struct regul_struct *regul = ®ul_table[id]; 336 337 if (stpmic2_register_update(pmic, regul->en_cr, value, mask) != 0) { 338 return RET_ERROR_GENERIC; 339 } 340 341 if (stpmic2_register_update(pmic, regul->alt_en_cr, value, mask) != 0) { 342 return RET_ERROR_GENERIC; 343 } 344 345 return RET_SUCCESS; 346 } 347 348 int stpmic2_regulator_get_prop(struct pmic_handle_s *pmic, uint8_t id, 349 enum stpmic2_prop_id prop) 350 { 351 const struct regul_struct *regul = ®ul_table[id]; 352 uint8_t val; 353 354 VERBOSE("%s: get prop 0x%x\n", regul->name, prop); 355 356 switch (prop) { 357 case STPMIC2_BYPASS: 358 if ((id <= STPMIC2_BUCK7) || (id == STPMIC2_LDO1) || 359 (id == STPMIC2_LDO4) || (id == STPMIC2_REFDDR)) { 360 return 0; 361 } 362 363 if (stpmic2_register_read(pmic, regul->en_cr, &val) != 0) { 364 return -EIO; 365 } 366 367 if ((val & LDO_BYPASS) != 0) { 368 return 1; 369 } 370 371 break; 372 default: 373 ERROR("Invalid prop %u\n", prop); 374 panic(); 375 } 376 377 return 0; 378 } 379 380 int stpmic2_regulator_set_prop(struct pmic_handle_s *pmic, uint8_t id, 381 enum stpmic2_prop_id prop, uint32_t arg) 382 { 383 const struct regul_struct *regul = ®ul_table[id]; 384 385 VERBOSE("%s: set prop 0x%x arg=%u\n", regul->name, prop, arg); 386 387 switch (prop) { 388 case STPMIC2_PULL_DOWN: 389 return stpmic2_register_update(pmic, regul->pd_reg, 390 regul->pd_val, 391 regul->pd_val); 392 case STPMIC2_MASK_RESET: 393 if (!regul->msrt_mask) { 394 return RET_ERROR_NOT_SUPPORTED; 395 } 396 /* enable mask reset */ 397 return stpmic2_register_update(pmic, regul->msrt_reg, 398 regul->msrt_mask, 399 regul->msrt_mask); 400 case STPMIC2_BYPASS: 401 if ((id <= STPMIC2_BUCK7) || (id == STPMIC2_LDO1) || 402 (id == STPMIC2_LDO4) || (id == STPMIC2_REFDDR)) { 403 return RET_ERROR_NOT_SUPPORTED; 404 } 405 406 /* clear sink source mode */ 407 if ((id == STPMIC2_LDO3) && (arg != 0U)) { 408 if (stpmic2_update_en_crs(pmic, id, 0, LDO3_SNK_SRC) != 0) { 409 return RET_ERROR_GENERIC; 410 } 411 } 412 413 /* enable bypass mode */ 414 return stpmic2_update_en_crs(pmic, id, 415 (arg != 0U) ? LDO_BYPASS : 0, 416 LDO_BYPASS); 417 case STPMIC2_SINK_SOURCE: 418 if (id != STPMIC2_LDO3) { 419 return RET_ERROR_NOT_SUPPORTED; 420 } 421 422 /* clear bypass mode */ 423 if (stpmic2_update_en_crs(pmic, id, 0, LDO_BYPASS) != 0) { 424 return RET_ERROR_GENERIC; 425 } 426 427 return stpmic2_update_en_crs(pmic, id, LDO3_SNK_SRC, 428 LDO3_SNK_SRC); 429 case STPMIC2_OCP: 430 return stpmic2_register_update(pmic, regul->ocp_reg, 431 regul->ocp_mask, 432 regul->ocp_mask); 433 default: 434 ERROR("Invalid prop %u\n", prop); 435 panic(); 436 } 437 438 return -EPERM; 439 } 440 441 #if EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE 442 void stpmic2_dump_regulators(struct pmic_handle_s *pmic) 443 { 444 size_t i; 445 char const *name; 446 447 for (i = 0U; i < ARRAY_SIZE(regul_table); i++) { 448 uint16_t val; 449 bool state; 450 451 if (!regul_table[i].volt_cr) { 452 continue; 453 } 454 455 stpmic2_regulator_get_voltage(pmic, i, &val); 456 stpmic2_regulator_get_state(pmic, i, &state); 457 458 name = regul_table[i].name; 459 460 VERBOSE("PMIC regul %s: %s, %dmV\n", 461 name, state ? "EN" : "DIS", val); 462 } 463 } 464 #endif 465 466 int stpmic2_get_version(struct pmic_handle_s *pmic, uint8_t *val) 467 { 468 return stpmic2_register_read(pmic, VERSION_SR, val); 469 } 470 471 int stpmic2_get_product_id(struct pmic_handle_s *pmic, uint8_t *val) 472 { 473 return stpmic2_register_read(pmic, PRODUCT_ID, val); 474 } 475