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