1817f42f0SPascal Paillet /*
2bdbbf48fSMaxime Méré * Copyright (C) 2024-2025, STMicroelectronics - All Rights Reserved
3817f42f0SPascal Paillet *
4817f42f0SPascal Paillet * SPDX-License-Identifier: BSD-3-Clause
5817f42f0SPascal Paillet */
6817f42f0SPascal Paillet
7817f42f0SPascal Paillet #include <assert.h>
8817f42f0SPascal Paillet #include <errno.h>
9817f42f0SPascal Paillet #include <string.h>
10817f42f0SPascal Paillet
11817f42f0SPascal Paillet #include <common/debug.h>
12817f42f0SPascal Paillet #include <drivers/st/stpmic2.h>
13817f42f0SPascal Paillet
14817f42f0SPascal Paillet #define RET_SUCCESS 0
15817f42f0SPascal Paillet #define RET_ERROR_NOT_SUPPORTED -1
16817f42f0SPascal Paillet #define RET_ERROR_GENERIC -2
17817f42f0SPascal Paillet #define RET_ERROR_BAD_PARAMETERS -3
18817f42f0SPascal Paillet
19817f42f0SPascal Paillet #define I2C_TIMEOUT_MS 25
20817f42f0SPascal Paillet
21817f42f0SPascal Paillet #define VOLTAGE_INDEX_INVALID ((size_t)~0U)
22817f42f0SPascal Paillet
23817f42f0SPascal Paillet struct regul_struct {
24817f42f0SPascal Paillet const char *name;
25817f42f0SPascal Paillet const uint16_t *volt_table;
26817f42f0SPascal Paillet uint8_t volt_table_size;
27817f42f0SPascal Paillet uint8_t volt_cr;
28817f42f0SPascal Paillet uint8_t volt_shift;
29817f42f0SPascal Paillet uint8_t en_cr;
30817f42f0SPascal Paillet uint8_t alt_en_cr;
31817f42f0SPascal Paillet uint8_t msrt_reg;
32817f42f0SPascal Paillet uint8_t msrt_mask;
33817f42f0SPascal Paillet uint8_t pd_reg;
34817f42f0SPascal Paillet uint8_t pd_val;
35817f42f0SPascal Paillet uint8_t ocp_reg;
36817f42f0SPascal Paillet uint8_t ocp_mask;
37817f42f0SPascal Paillet };
38817f42f0SPascal Paillet
39817f42f0SPascal Paillet /* Voltage tables in mV */
40817f42f0SPascal Paillet static const uint16_t buck1236_volt_table[] = {
41817f42f0SPascal Paillet 500U, 510U, 520U, 530U, 540U, 550U, 560U, 570U, 580U, 590U,
42817f42f0SPascal Paillet 600U, 610U, 620U, 630U, 640U, 650U, 660U, 670U, 680U, 690U,
43817f42f0SPascal Paillet 700U, 710U, 720U, 730U, 740U, 750U, 760U, 770U, 780U, 790U,
44817f42f0SPascal Paillet 800U, 810U, 820U, 830U, 840U, 850U, 860U, 870U, 880U, 890U,
45817f42f0SPascal Paillet 900U, 910U, 920U, 930U, 940U, 950U, 960U, 970U, 980U, 990U,
46817f42f0SPascal Paillet 1000U, 1010U, 1020U, 1030U, 1040U, 1050U, 1060U, 1070U, 1080U, 1090U,
47817f42f0SPascal Paillet 1100U, 1110U, 1120U, 1130U, 1140U, 1150U, 1160U, 1170U, 1180U, 1190U,
48817f42f0SPascal Paillet 1200U, 1210U, 1220U, 1230U, 1240U, 1250U, 1260U, 1270U, 1280U, 1290U,
49817f42f0SPascal Paillet 1300U, 1310U, 1320U, 1330U, 1340U, 1350U, 1360U, 1370U, 1380U, 1390U,
50817f42f0SPascal Paillet 1400U, 1410U, 1420U, 1430U, 1440U, 1450U, 1460U, 1470U, 1480U, 1490U,
51817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
52817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
53817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U
54817f42f0SPascal Paillet };
55817f42f0SPascal Paillet
56817f42f0SPascal Paillet static const uint16_t buck457_volt_table[] = {
57817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
58817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
59817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
60817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
61817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
62817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
63817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
64817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
65817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
66817f42f0SPascal Paillet 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U, 1500U,
67817f42f0SPascal Paillet 1500U, 1600U, 1700U, 1800U, 1900U, 2000U, 2100U, 2200U, 2300U, 2400U,
68817f42f0SPascal Paillet 2500U, 2600U, 2700U, 2800U, 2900U, 3000U, 3100U, 3200U, 3300U, 3400U,
69817f42f0SPascal Paillet 3500U, 3600U, 3700U, 3800U, 3900U, 4000U, 4100U, 4200U
70817f42f0SPascal Paillet };
71817f42f0SPascal Paillet
72817f42f0SPascal Paillet static const uint16_t ldo235678_volt_table[] = {
73817f42f0SPascal Paillet 900U, 1000U, 1100U, 1200U, 1300U, 1400U, 1500U, 1600U, 1700U, 1800U,
74817f42f0SPascal Paillet 1900U, 2000U, 2100U, 2200U, 2300U, 2400U, 2500U, 2600U, 2700U, 2800U,
75817f42f0SPascal Paillet 2900U, 3000U, 3100U, 3200U, 3300U, 3400U, 3500U, 3600U, 3700U, 3800U,
76817f42f0SPascal Paillet 3900U, 4000U
77817f42f0SPascal Paillet };
78817f42f0SPascal Paillet
79817f42f0SPascal Paillet static const uint16_t ldo1_volt_table[] = {
80817f42f0SPascal Paillet 1800U,
81817f42f0SPascal Paillet };
82817f42f0SPascal Paillet
83817f42f0SPascal Paillet static const uint16_t ldo4_volt_table[] = {
84817f42f0SPascal Paillet 3300U,
85817f42f0SPascal Paillet };
86817f42f0SPascal Paillet
87817f42f0SPascal Paillet static const uint16_t refddr_volt_table[] = {
88817f42f0SPascal Paillet 0,
89817f42f0SPascal Paillet };
90817f42f0SPascal Paillet
91817f42f0SPascal Paillet #define DEFINE_BUCK(regu_name, ID, pd, table) { \
92817f42f0SPascal Paillet .name = regu_name, \
93817f42f0SPascal Paillet .volt_table = table, \
94817f42f0SPascal Paillet .volt_table_size = ARRAY_SIZE(table), \
95817f42f0SPascal Paillet .en_cr = ID ## _MAIN_CR2, \
96817f42f0SPascal Paillet .volt_cr = ID ## _MAIN_CR1, \
97817f42f0SPascal Paillet .alt_en_cr = ID ## _ALT_CR2, \
98817f42f0SPascal Paillet .msrt_reg = BUCKS_MRST_CR, \
99817f42f0SPascal Paillet .msrt_mask = ID ## _MRST, \
100817f42f0SPascal Paillet .pd_reg = pd, \
101817f42f0SPascal Paillet .pd_val = ID ## _PD_FAST, \
102817f42f0SPascal Paillet .ocp_reg = FS_OCP_CR1, \
103817f42f0SPascal Paillet .ocp_mask = FS_OCP_ ## ID, \
104817f42f0SPascal Paillet }
105817f42f0SPascal Paillet
106817f42f0SPascal Paillet #define DEFINE_LDOx(regu_name, ID, table) { \
107817f42f0SPascal Paillet .name = regu_name, \
108817f42f0SPascal Paillet .volt_table = table, \
109817f42f0SPascal Paillet .volt_table_size = ARRAY_SIZE(table), \
110817f42f0SPascal Paillet .volt_shift = LDO_VOLT_SHIFT, \
111817f42f0SPascal Paillet .en_cr = ID ## _MAIN_CR, \
112817f42f0SPascal Paillet .volt_cr = ID ## _MAIN_CR, \
113817f42f0SPascal Paillet .alt_en_cr = ID ## _ALT_CR, \
114817f42f0SPascal Paillet .msrt_reg = LDOS_MRST_CR, \
115817f42f0SPascal Paillet .msrt_mask = ID ## _MRST, \
116817f42f0SPascal Paillet .pd_reg = LDOS_PD_CR1, \
117817f42f0SPascal Paillet .pd_val = ID ## _PD, \
118817f42f0SPascal Paillet .ocp_reg = FS_OCP_CR2, \
119817f42f0SPascal Paillet .ocp_mask = FS_OCP_ ## ID, \
120817f42f0SPascal Paillet }
121817f42f0SPascal Paillet
122817f42f0SPascal Paillet #define DEFINE_REFDDR(regu_name, ID, table) { \
123817f42f0SPascal Paillet .name = regu_name, \
124817f42f0SPascal Paillet .volt_table = table, \
125817f42f0SPascal Paillet .volt_table_size = ARRAY_SIZE(table), \
126817f42f0SPascal Paillet .en_cr = ID ## _MAIN_CR, \
127817f42f0SPascal Paillet .volt_cr = ID ## _MAIN_CR, \
128817f42f0SPascal Paillet .alt_en_cr = ID ## _ALT_CR, \
129817f42f0SPascal Paillet .msrt_reg = BUCKS_MRST_CR, \
130817f42f0SPascal Paillet .msrt_mask = ID ## _MRST, \
131817f42f0SPascal Paillet .pd_reg = LDOS_PD_CR2, \
132817f42f0SPascal Paillet .pd_val = ID ## _PD, \
133817f42f0SPascal Paillet .ocp_reg = FS_OCP_CR1, \
134817f42f0SPascal Paillet .ocp_mask = FS_OCP_ ## ID, \
135817f42f0SPascal Paillet }
136817f42f0SPascal Paillet
137817f42f0SPascal Paillet /* Table of Regulators in PMIC SoC */
138817f42f0SPascal Paillet static const struct regul_struct regul_table[STPMIC2_NB_REG] = {
139817f42f0SPascal Paillet [STPMIC2_BUCK1] = DEFINE_BUCK("buck1", BUCK1, BUCKS_PD_CR1,
140817f42f0SPascal Paillet buck1236_volt_table),
141817f42f0SPascal Paillet [STPMIC2_BUCK2] = DEFINE_BUCK("buck2", BUCK2, BUCKS_PD_CR1,
142817f42f0SPascal Paillet buck1236_volt_table),
143817f42f0SPascal Paillet [STPMIC2_BUCK3] = DEFINE_BUCK("buck3", BUCK3, BUCKS_PD_CR1,
144817f42f0SPascal Paillet buck1236_volt_table),
145817f42f0SPascal Paillet [STPMIC2_BUCK4] = DEFINE_BUCK("buck4", BUCK4, BUCKS_PD_CR1,
146817f42f0SPascal Paillet buck457_volt_table),
147817f42f0SPascal Paillet [STPMIC2_BUCK5] = DEFINE_BUCK("buck5", BUCK5, BUCKS_PD_CR2,
148817f42f0SPascal Paillet buck457_volt_table),
149817f42f0SPascal Paillet [STPMIC2_BUCK6] = DEFINE_BUCK("buck6", BUCK6, BUCKS_PD_CR2,
150817f42f0SPascal Paillet buck1236_volt_table),
151817f42f0SPascal Paillet [STPMIC2_BUCK7] = DEFINE_BUCK("buck7", BUCK7, BUCKS_PD_CR2,
152817f42f0SPascal Paillet buck457_volt_table),
153817f42f0SPascal Paillet
154817f42f0SPascal Paillet [STPMIC2_REFDDR] = DEFINE_REFDDR("refddr", REFDDR, refddr_volt_table),
155817f42f0SPascal Paillet
156817f42f0SPascal Paillet [STPMIC2_LDO1] = DEFINE_LDOx("ldo1", LDO1, ldo1_volt_table),
157817f42f0SPascal Paillet [STPMIC2_LDO2] = DEFINE_LDOx("ldo2", LDO2, ldo235678_volt_table),
158817f42f0SPascal Paillet [STPMIC2_LDO3] = DEFINE_LDOx("ldo3", LDO3, ldo235678_volt_table),
159817f42f0SPascal Paillet [STPMIC2_LDO4] = DEFINE_LDOx("ldo4", LDO4, ldo4_volt_table),
160817f42f0SPascal Paillet [STPMIC2_LDO5] = DEFINE_LDOx("ldo5", LDO5, ldo235678_volt_table),
161817f42f0SPascal Paillet [STPMIC2_LDO6] = DEFINE_LDOx("ldo6", LDO6, ldo235678_volt_table),
162817f42f0SPascal Paillet [STPMIC2_LDO7] = DEFINE_LDOx("ldo7", LDO7, ldo235678_volt_table),
163817f42f0SPascal Paillet [STPMIC2_LDO8] = DEFINE_LDOx("ldo8", LDO8, ldo235678_volt_table),
164817f42f0SPascal Paillet
165817f42f0SPascal Paillet };
166817f42f0SPascal Paillet
stpmic2_register_read(struct pmic_handle_s * pmic,uint8_t register_id,uint8_t * value)167817f42f0SPascal Paillet int stpmic2_register_read(struct pmic_handle_s *pmic,
168817f42f0SPascal Paillet uint8_t register_id, uint8_t *value)
169817f42f0SPascal Paillet {
170817f42f0SPascal Paillet int ret = stm32_i2c_mem_read(pmic->i2c_handle,
171817f42f0SPascal Paillet pmic->i2c_addr,
172817f42f0SPascal Paillet (uint16_t)register_id,
173817f42f0SPascal Paillet I2C_MEMADD_SIZE_8BIT, value,
174817f42f0SPascal Paillet 1, I2C_TIMEOUT_MS);
175817f42f0SPascal Paillet if (ret != 0) {
176817f42f0SPascal Paillet ERROR("Failed to read reg:0x%x\n", register_id);
177817f42f0SPascal Paillet }
178817f42f0SPascal Paillet
179817f42f0SPascal Paillet return ret;
180817f42f0SPascal Paillet }
181817f42f0SPascal Paillet
stpmic2_register_write(struct pmic_handle_s * pmic,uint8_t register_id,uint8_t value)182817f42f0SPascal Paillet int stpmic2_register_write(struct pmic_handle_s *pmic,
183817f42f0SPascal Paillet uint8_t register_id, uint8_t value)
184817f42f0SPascal Paillet {
185817f42f0SPascal Paillet uint8_t val = value;
186817f42f0SPascal Paillet int ret = stm32_i2c_mem_write(pmic->i2c_handle,
187817f42f0SPascal Paillet pmic->i2c_addr,
188817f42f0SPascal Paillet (uint16_t)register_id,
189817f42f0SPascal Paillet I2C_MEMADD_SIZE_8BIT, &val,
190817f42f0SPascal Paillet 1, I2C_TIMEOUT_MS);
191817f42f0SPascal Paillet if (ret != 0) {
192817f42f0SPascal Paillet ERROR("Failed to write reg:0x%x\n", register_id);
193817f42f0SPascal Paillet }
194817f42f0SPascal Paillet
195817f42f0SPascal Paillet return ret;
196817f42f0SPascal Paillet }
197817f42f0SPascal Paillet
stpmic2_register_update(struct pmic_handle_s * pmic,uint8_t register_id,uint8_t value,uint8_t mask)198817f42f0SPascal Paillet int stpmic2_register_update(struct pmic_handle_s *pmic,
199817f42f0SPascal Paillet uint8_t register_id, uint8_t value, uint8_t mask)
200817f42f0SPascal Paillet {
201817f42f0SPascal Paillet int status;
202817f42f0SPascal Paillet uint8_t val = 0U;
203817f42f0SPascal Paillet
204817f42f0SPascal Paillet status = stpmic2_register_read(pmic, register_id, &val);
205817f42f0SPascal Paillet if (status != 0) {
206817f42f0SPascal Paillet return status;
207817f42f0SPascal Paillet }
208817f42f0SPascal Paillet
209817f42f0SPascal Paillet val = (val & ((uint8_t)~mask)) | (value & mask);
210817f42f0SPascal Paillet
211817f42f0SPascal Paillet VERBOSE("REG:0x%x v=0x%x mask=0x%x -> 0x%x\n",
212817f42f0SPascal Paillet register_id, value, mask, val);
213817f42f0SPascal Paillet
214817f42f0SPascal Paillet return stpmic2_register_write(pmic, register_id, val);
215817f42f0SPascal Paillet }
216817f42f0SPascal Paillet
stpmic2_regulator_set_state(struct pmic_handle_s * pmic,uint8_t id,bool enable)217817f42f0SPascal Paillet int stpmic2_regulator_set_state(struct pmic_handle_s *pmic,
218817f42f0SPascal Paillet uint8_t id, bool enable)
219817f42f0SPascal Paillet {
220817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
221817f42f0SPascal Paillet
222817f42f0SPascal Paillet if (enable) {
223817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->en_cr, 1U, 1U);
224817f42f0SPascal Paillet } else {
225817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->en_cr, 0, 1U);
226817f42f0SPascal Paillet }
227817f42f0SPascal Paillet }
228817f42f0SPascal Paillet
stpmic2_regulator_get_state(struct pmic_handle_s * pmic,uint8_t id,bool * enabled)229817f42f0SPascal Paillet int stpmic2_regulator_get_state(struct pmic_handle_s *pmic,
230817f42f0SPascal Paillet uint8_t id, bool *enabled)
231817f42f0SPascal Paillet {
232817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
233817f42f0SPascal Paillet uint8_t val;
234817f42f0SPascal Paillet
235817f42f0SPascal Paillet if (stpmic2_register_read(pmic, regul->en_cr, &val) != 0) {
236817f42f0SPascal Paillet return RET_ERROR_GENERIC;
237817f42f0SPascal Paillet }
238817f42f0SPascal Paillet
239817f42f0SPascal Paillet *enabled = (val & 1U) == 1U;
240817f42f0SPascal Paillet
241817f42f0SPascal Paillet return RET_SUCCESS;
242817f42f0SPascal Paillet }
243817f42f0SPascal Paillet
stpmic2_regulator_levels_mv(struct pmic_handle_s * pmic,uint8_t id,const uint16_t ** levels,size_t * levels_count)244817f42f0SPascal Paillet int stpmic2_regulator_levels_mv(struct pmic_handle_s *pmic,
245817f42f0SPascal Paillet uint8_t id, const uint16_t **levels,
246817f42f0SPascal Paillet size_t *levels_count)
247817f42f0SPascal Paillet {
248817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
249817f42f0SPascal Paillet
250817f42f0SPascal Paillet if (levels_count != NULL) {
251817f42f0SPascal Paillet *levels_count = regul->volt_table_size;
252817f42f0SPascal Paillet }
253817f42f0SPascal Paillet if (levels != NULL) {
254817f42f0SPascal Paillet *levels = regul->volt_table;
255817f42f0SPascal Paillet }
256817f42f0SPascal Paillet
257817f42f0SPascal Paillet return RET_SUCCESS;
258817f42f0SPascal Paillet }
259817f42f0SPascal Paillet
stpmic2_regulator_get_voltage(struct pmic_handle_s * pmic,uint8_t id,uint16_t * val)260817f42f0SPascal Paillet int stpmic2_regulator_get_voltage(struct pmic_handle_s *pmic,
261817f42f0SPascal Paillet uint8_t id, uint16_t *val)
262817f42f0SPascal Paillet {
263817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
264817f42f0SPascal Paillet uint8_t value = 0U;
265817f42f0SPascal Paillet uint8_t mask;
266817f42f0SPascal Paillet
267817f42f0SPascal Paillet if (regul->volt_table_size == 0U) {
268817f42f0SPascal Paillet return RET_ERROR_GENERIC;
269817f42f0SPascal Paillet }
270817f42f0SPascal Paillet
271817f42f0SPascal Paillet mask = regul->volt_table_size - 1U;
272817f42f0SPascal Paillet if (mask != 0U) {
273817f42f0SPascal Paillet if (stpmic2_register_read(pmic, regul->volt_cr, &value) != 0) {
274817f42f0SPascal Paillet return RET_ERROR_GENERIC;
275817f42f0SPascal Paillet }
276817f42f0SPascal Paillet
277817f42f0SPascal Paillet value = (value >> regul->volt_shift) & mask;
278817f42f0SPascal Paillet }
279817f42f0SPascal Paillet
280817f42f0SPascal Paillet if (value > regul->volt_table_size) {
281817f42f0SPascal Paillet return RET_ERROR_GENERIC;
282817f42f0SPascal Paillet }
283817f42f0SPascal Paillet
284817f42f0SPascal Paillet *val = regul->volt_table[value];
285817f42f0SPascal Paillet
286817f42f0SPascal Paillet return RET_SUCCESS;
287817f42f0SPascal Paillet }
288817f42f0SPascal Paillet
voltage_to_index(const struct regul_struct * regul,uint16_t millivolts)289817f42f0SPascal Paillet static size_t voltage_to_index(const struct regul_struct *regul,
290817f42f0SPascal Paillet uint16_t millivolts)
291817f42f0SPascal Paillet {
292817f42f0SPascal Paillet unsigned int i;
293817f42f0SPascal Paillet
294817f42f0SPascal Paillet assert(regul->volt_table);
295817f42f0SPascal Paillet for (i = 0U; i < regul->volt_table_size; i++) {
296817f42f0SPascal Paillet if (regul->volt_table[i] == millivolts) {
297817f42f0SPascal Paillet return i;
298817f42f0SPascal Paillet }
299817f42f0SPascal Paillet }
300817f42f0SPascal Paillet
301817f42f0SPascal Paillet return VOLTAGE_INDEX_INVALID;
302817f42f0SPascal Paillet }
303817f42f0SPascal Paillet
stpmic2_regulator_set_voltage(struct pmic_handle_s * pmic,uint8_t id,uint16_t millivolts)304817f42f0SPascal Paillet int stpmic2_regulator_set_voltage(struct pmic_handle_s *pmic,
305817f42f0SPascal Paillet uint8_t id, uint16_t millivolts)
306817f42f0SPascal Paillet {
307817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
308817f42f0SPascal Paillet size_t index;
309817f42f0SPascal Paillet uint8_t mask;
310817f42f0SPascal Paillet
311817f42f0SPascal Paillet if (!regul->volt_table_size) {
312817f42f0SPascal Paillet return RET_SUCCESS;
313817f42f0SPascal Paillet }
314817f42f0SPascal Paillet
315817f42f0SPascal Paillet mask = regul->volt_table_size - 1U;
316817f42f0SPascal Paillet
317817f42f0SPascal Paillet index = voltage_to_index(regul, millivolts);
318817f42f0SPascal Paillet if (index == VOLTAGE_INDEX_INVALID) {
319817f42f0SPascal Paillet return RET_ERROR_GENERIC;
320817f42f0SPascal Paillet }
321817f42f0SPascal Paillet
322817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->volt_cr,
323817f42f0SPascal Paillet index << regul->volt_shift,
324817f42f0SPascal Paillet mask << regul->volt_shift);
325817f42f0SPascal Paillet }
326817f42f0SPascal Paillet
327817f42f0SPascal Paillet /* update both normal and alternate register */
stpmic2_update_en_crs(struct pmic_handle_s * pmic,uint8_t id,uint8_t value,uint8_t mask)328817f42f0SPascal Paillet static int stpmic2_update_en_crs(struct pmic_handle_s *pmic, uint8_t id,
329817f42f0SPascal Paillet uint8_t value, uint8_t mask)
330817f42f0SPascal Paillet {
331817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
332817f42f0SPascal Paillet
333817f42f0SPascal Paillet if (stpmic2_register_update(pmic, regul->en_cr, value, mask) != 0) {
334817f42f0SPascal Paillet return RET_ERROR_GENERIC;
335817f42f0SPascal Paillet }
336817f42f0SPascal Paillet
337817f42f0SPascal Paillet if (stpmic2_register_update(pmic, regul->alt_en_cr, value, mask) != 0) {
338817f42f0SPascal Paillet return RET_ERROR_GENERIC;
339817f42f0SPascal Paillet }
340817f42f0SPascal Paillet
341817f42f0SPascal Paillet return RET_SUCCESS;
342817f42f0SPascal Paillet }
343817f42f0SPascal Paillet
stpmic2_regulator_get_prop(struct pmic_handle_s * pmic,uint8_t id,enum stpmic2_prop_id prop)344817f42f0SPascal Paillet int stpmic2_regulator_get_prop(struct pmic_handle_s *pmic, uint8_t id,
345817f42f0SPascal Paillet enum stpmic2_prop_id prop)
346817f42f0SPascal Paillet {
347817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
348817f42f0SPascal Paillet uint8_t val;
349817f42f0SPascal Paillet
350817f42f0SPascal Paillet VERBOSE("%s: get prop 0x%x\n", regul->name, prop);
351817f42f0SPascal Paillet
352817f42f0SPascal Paillet switch (prop) {
353817f42f0SPascal Paillet case STPMIC2_BYPASS:
354817f42f0SPascal Paillet if ((id <= STPMIC2_BUCK7) || (id == STPMIC2_LDO1) ||
355817f42f0SPascal Paillet (id == STPMIC2_LDO4) || (id == STPMIC2_REFDDR)) {
356817f42f0SPascal Paillet return 0;
357817f42f0SPascal Paillet }
358817f42f0SPascal Paillet
359817f42f0SPascal Paillet if (stpmic2_register_read(pmic, regul->en_cr, &val) != 0) {
360817f42f0SPascal Paillet return -EIO;
361817f42f0SPascal Paillet }
362817f42f0SPascal Paillet
363817f42f0SPascal Paillet if ((val & LDO_BYPASS) != 0) {
364817f42f0SPascal Paillet return 1;
365817f42f0SPascal Paillet }
366817f42f0SPascal Paillet
367817f42f0SPascal Paillet break;
368817f42f0SPascal Paillet default:
369817f42f0SPascal Paillet ERROR("Invalid prop %u\n", prop);
370817f42f0SPascal Paillet panic();
371817f42f0SPascal Paillet }
372817f42f0SPascal Paillet
373817f42f0SPascal Paillet return 0;
374817f42f0SPascal Paillet }
375817f42f0SPascal Paillet
stpmic2_regulator_set_prop(struct pmic_handle_s * pmic,uint8_t id,enum stpmic2_prop_id prop,uint32_t arg)376817f42f0SPascal Paillet int stpmic2_regulator_set_prop(struct pmic_handle_s *pmic, uint8_t id,
377817f42f0SPascal Paillet enum stpmic2_prop_id prop, uint32_t arg)
378817f42f0SPascal Paillet {
379817f42f0SPascal Paillet const struct regul_struct *regul = ®ul_table[id];
380817f42f0SPascal Paillet
381817f42f0SPascal Paillet VERBOSE("%s: set prop 0x%x arg=%u\n", regul->name, prop, arg);
382817f42f0SPascal Paillet
383817f42f0SPascal Paillet switch (prop) {
384817f42f0SPascal Paillet case STPMIC2_PULL_DOWN:
385817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->pd_reg,
386817f42f0SPascal Paillet regul->pd_val,
387817f42f0SPascal Paillet regul->pd_val);
388817f42f0SPascal Paillet case STPMIC2_MASK_RESET:
389817f42f0SPascal Paillet if (!regul->msrt_mask) {
390817f42f0SPascal Paillet return RET_ERROR_NOT_SUPPORTED;
391817f42f0SPascal Paillet }
392817f42f0SPascal Paillet /* enable mask reset */
393817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->msrt_reg,
394817f42f0SPascal Paillet regul->msrt_mask,
395817f42f0SPascal Paillet regul->msrt_mask);
396817f42f0SPascal Paillet case STPMIC2_BYPASS:
397817f42f0SPascal Paillet if ((id <= STPMIC2_BUCK7) || (id == STPMIC2_LDO1) ||
398817f42f0SPascal Paillet (id == STPMIC2_LDO4) || (id == STPMIC2_REFDDR)) {
399817f42f0SPascal Paillet return RET_ERROR_NOT_SUPPORTED;
400817f42f0SPascal Paillet }
401817f42f0SPascal Paillet
402817f42f0SPascal Paillet /* clear sink source mode */
403817f42f0SPascal Paillet if ((id == STPMIC2_LDO3) && (arg != 0U)) {
404817f42f0SPascal Paillet if (stpmic2_update_en_crs(pmic, id, 0, LDO3_SNK_SRC) != 0) {
405817f42f0SPascal Paillet return RET_ERROR_GENERIC;
406817f42f0SPascal Paillet }
407817f42f0SPascal Paillet }
408817f42f0SPascal Paillet
409817f42f0SPascal Paillet /* enable bypass mode */
410817f42f0SPascal Paillet return stpmic2_update_en_crs(pmic, id,
411817f42f0SPascal Paillet (arg != 0U) ? LDO_BYPASS : 0,
412817f42f0SPascal Paillet LDO_BYPASS);
413817f42f0SPascal Paillet case STPMIC2_SINK_SOURCE:
414817f42f0SPascal Paillet if (id != STPMIC2_LDO3) {
415817f42f0SPascal Paillet return RET_ERROR_NOT_SUPPORTED;
416817f42f0SPascal Paillet }
417817f42f0SPascal Paillet
418817f42f0SPascal Paillet /* clear bypass mode */
419817f42f0SPascal Paillet if (stpmic2_update_en_crs(pmic, id, 0, LDO_BYPASS) != 0) {
420817f42f0SPascal Paillet return RET_ERROR_GENERIC;
421817f42f0SPascal Paillet }
422817f42f0SPascal Paillet
423817f42f0SPascal Paillet return stpmic2_update_en_crs(pmic, id, LDO3_SNK_SRC,
424817f42f0SPascal Paillet LDO3_SNK_SRC);
425817f42f0SPascal Paillet case STPMIC2_OCP:
426817f42f0SPascal Paillet return stpmic2_register_update(pmic, regul->ocp_reg,
427817f42f0SPascal Paillet regul->ocp_mask,
428817f42f0SPascal Paillet regul->ocp_mask);
429817f42f0SPascal Paillet default:
430817f42f0SPascal Paillet ERROR("Invalid prop %u\n", prop);
431817f42f0SPascal Paillet panic();
432817f42f0SPascal Paillet }
433817f42f0SPascal Paillet
434817f42f0SPascal Paillet return -EPERM;
435817f42f0SPascal Paillet }
436817f42f0SPascal Paillet
stpmic2_dump_regulators(struct pmic_handle_s * pmic)437817f42f0SPascal Paillet void stpmic2_dump_regulators(struct pmic_handle_s *pmic)
438817f42f0SPascal Paillet {
439*f08f6fbfSBoerge Struempfel #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
440817f42f0SPascal Paillet size_t i;
441817f42f0SPascal Paillet char const *name;
442817f42f0SPascal Paillet
443817f42f0SPascal Paillet for (i = 0U; i < ARRAY_SIZE(regul_table); i++) {
444817f42f0SPascal Paillet uint16_t val;
445817f42f0SPascal Paillet bool state;
446817f42f0SPascal Paillet
447817f42f0SPascal Paillet if (!regul_table[i].volt_cr) {
448817f42f0SPascal Paillet continue;
449817f42f0SPascal Paillet }
450817f42f0SPascal Paillet
451817f42f0SPascal Paillet stpmic2_regulator_get_voltage(pmic, i, &val);
452817f42f0SPascal Paillet stpmic2_regulator_get_state(pmic, i, &state);
453817f42f0SPascal Paillet
454817f42f0SPascal Paillet name = regul_table[i].name;
455817f42f0SPascal Paillet
456817f42f0SPascal Paillet VERBOSE("PMIC regul %s: %s, %dmV\n",
457817f42f0SPascal Paillet name, state ? "EN" : "DIS", val);
458817f42f0SPascal Paillet }
459817f42f0SPascal Paillet #endif
460*f08f6fbfSBoerge Struempfel }
461817f42f0SPascal Paillet
stpmic2_get_version(struct pmic_handle_s * pmic,uint8_t * val)462817f42f0SPascal Paillet int stpmic2_get_version(struct pmic_handle_s *pmic, uint8_t *val)
463817f42f0SPascal Paillet {
464817f42f0SPascal Paillet return stpmic2_register_read(pmic, VERSION_SR, val);
465817f42f0SPascal Paillet }
466817f42f0SPascal Paillet
stpmic2_get_product_id(struct pmic_handle_s * pmic,uint8_t * val)467817f42f0SPascal Paillet int stpmic2_get_product_id(struct pmic_handle_s *pmic, uint8_t *val)
468817f42f0SPascal Paillet {
469817f42f0SPascal Paillet return stpmic2_register_read(pmic, PRODUCT_ID, val);
470817f42f0SPascal Paillet }
471