xref: /arm-trusted-firmware/drivers/st/pmic/stpmic1.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <errno.h>
8*91f16700Schasinglulu #include <string.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <drivers/st/stpmic1.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #define I2C_TIMEOUT_MS		25
14*91f16700Schasinglulu 
15*91f16700Schasinglulu struct regul_struct {
16*91f16700Schasinglulu 	const char *dt_node_name;
17*91f16700Schasinglulu 	const uint16_t *voltage_table;
18*91f16700Schasinglulu 	uint8_t voltage_table_size;
19*91f16700Schasinglulu 	uint8_t control_reg;
20*91f16700Schasinglulu 	uint8_t enable_mask;
21*91f16700Schasinglulu 	uint8_t low_power_reg;
22*91f16700Schasinglulu 	uint8_t pull_down_reg;
23*91f16700Schasinglulu 	uint8_t pull_down;
24*91f16700Schasinglulu 	uint8_t mask_reset_reg;
25*91f16700Schasinglulu 	uint8_t mask_reset;
26*91f16700Schasinglulu 	uint8_t icc_reg;
27*91f16700Schasinglulu 	uint8_t icc_mask;
28*91f16700Schasinglulu };
29*91f16700Schasinglulu 
30*91f16700Schasinglulu static struct i2c_handle_s *pmic_i2c_handle;
31*91f16700Schasinglulu static uint16_t pmic_i2c_addr;
32*91f16700Schasinglulu /*
33*91f16700Schasinglulu  * Special mode corresponds to LDO3 in sink source mode or in bypass mode.
34*91f16700Schasinglulu  * LDO3 doesn't switch back from special to normal mode.
35*91f16700Schasinglulu  */
36*91f16700Schasinglulu static bool ldo3_special_mode;
37*91f16700Schasinglulu 
38*91f16700Schasinglulu /* Voltage tables in mV */
39*91f16700Schasinglulu static const uint16_t buck1_voltage_table[] = {
40*91f16700Schasinglulu 	725,
41*91f16700Schasinglulu 	725,
42*91f16700Schasinglulu 	725,
43*91f16700Schasinglulu 	725,
44*91f16700Schasinglulu 	725,
45*91f16700Schasinglulu 	725,
46*91f16700Schasinglulu 	750,
47*91f16700Schasinglulu 	775,
48*91f16700Schasinglulu 	800,
49*91f16700Schasinglulu 	825,
50*91f16700Schasinglulu 	850,
51*91f16700Schasinglulu 	875,
52*91f16700Schasinglulu 	900,
53*91f16700Schasinglulu 	925,
54*91f16700Schasinglulu 	950,
55*91f16700Schasinglulu 	975,
56*91f16700Schasinglulu 	1000,
57*91f16700Schasinglulu 	1025,
58*91f16700Schasinglulu 	1050,
59*91f16700Schasinglulu 	1075,
60*91f16700Schasinglulu 	1100,
61*91f16700Schasinglulu 	1125,
62*91f16700Schasinglulu 	1150,
63*91f16700Schasinglulu 	1175,
64*91f16700Schasinglulu 	1200,
65*91f16700Schasinglulu 	1225,
66*91f16700Schasinglulu 	1250,
67*91f16700Schasinglulu 	1275,
68*91f16700Schasinglulu 	1300,
69*91f16700Schasinglulu 	1325,
70*91f16700Schasinglulu 	1350,
71*91f16700Schasinglulu 	1375,
72*91f16700Schasinglulu 	1400,
73*91f16700Schasinglulu 	1425,
74*91f16700Schasinglulu 	1450,
75*91f16700Schasinglulu 	1475,
76*91f16700Schasinglulu 	1500,
77*91f16700Schasinglulu 	1500,
78*91f16700Schasinglulu 	1500,
79*91f16700Schasinglulu 	1500,
80*91f16700Schasinglulu 	1500,
81*91f16700Schasinglulu 	1500,
82*91f16700Schasinglulu 	1500,
83*91f16700Schasinglulu 	1500,
84*91f16700Schasinglulu 	1500,
85*91f16700Schasinglulu 	1500,
86*91f16700Schasinglulu 	1500,
87*91f16700Schasinglulu 	1500,
88*91f16700Schasinglulu 	1500,
89*91f16700Schasinglulu 	1500,
90*91f16700Schasinglulu 	1500,
91*91f16700Schasinglulu 	1500,
92*91f16700Schasinglulu 	1500,
93*91f16700Schasinglulu 	1500,
94*91f16700Schasinglulu 	1500,
95*91f16700Schasinglulu 	1500,
96*91f16700Schasinglulu 	1500,
97*91f16700Schasinglulu 	1500,
98*91f16700Schasinglulu 	1500,
99*91f16700Schasinglulu 	1500,
100*91f16700Schasinglulu 	1500,
101*91f16700Schasinglulu 	1500,
102*91f16700Schasinglulu 	1500,
103*91f16700Schasinglulu 	1500,
104*91f16700Schasinglulu };
105*91f16700Schasinglulu 
106*91f16700Schasinglulu static const uint16_t buck2_voltage_table[] = {
107*91f16700Schasinglulu 	1000,
108*91f16700Schasinglulu 	1000,
109*91f16700Schasinglulu 	1000,
110*91f16700Schasinglulu 	1000,
111*91f16700Schasinglulu 	1000,
112*91f16700Schasinglulu 	1000,
113*91f16700Schasinglulu 	1000,
114*91f16700Schasinglulu 	1000,
115*91f16700Schasinglulu 	1000,
116*91f16700Schasinglulu 	1000,
117*91f16700Schasinglulu 	1000,
118*91f16700Schasinglulu 	1000,
119*91f16700Schasinglulu 	1000,
120*91f16700Schasinglulu 	1000,
121*91f16700Schasinglulu 	1000,
122*91f16700Schasinglulu 	1000,
123*91f16700Schasinglulu 	1000,
124*91f16700Schasinglulu 	1000,
125*91f16700Schasinglulu 	1050,
126*91f16700Schasinglulu 	1050,
127*91f16700Schasinglulu 	1100,
128*91f16700Schasinglulu 	1100,
129*91f16700Schasinglulu 	1150,
130*91f16700Schasinglulu 	1150,
131*91f16700Schasinglulu 	1200,
132*91f16700Schasinglulu 	1200,
133*91f16700Schasinglulu 	1250,
134*91f16700Schasinglulu 	1250,
135*91f16700Schasinglulu 	1300,
136*91f16700Schasinglulu 	1300,
137*91f16700Schasinglulu 	1350,
138*91f16700Schasinglulu 	1350,
139*91f16700Schasinglulu 	1400,
140*91f16700Schasinglulu 	1400,
141*91f16700Schasinglulu 	1450,
142*91f16700Schasinglulu 	1450,
143*91f16700Schasinglulu 	1500,
144*91f16700Schasinglulu };
145*91f16700Schasinglulu 
146*91f16700Schasinglulu static const uint16_t buck3_voltage_table[] = {
147*91f16700Schasinglulu 	1000,
148*91f16700Schasinglulu 	1000,
149*91f16700Schasinglulu 	1000,
150*91f16700Schasinglulu 	1000,
151*91f16700Schasinglulu 	1000,
152*91f16700Schasinglulu 	1000,
153*91f16700Schasinglulu 	1000,
154*91f16700Schasinglulu 	1000,
155*91f16700Schasinglulu 	1000,
156*91f16700Schasinglulu 	1000,
157*91f16700Schasinglulu 	1000,
158*91f16700Schasinglulu 	1000,
159*91f16700Schasinglulu 	1000,
160*91f16700Schasinglulu 	1000,
161*91f16700Schasinglulu 	1000,
162*91f16700Schasinglulu 	1000,
163*91f16700Schasinglulu 	1000,
164*91f16700Schasinglulu 	1000,
165*91f16700Schasinglulu 	1000,
166*91f16700Schasinglulu 	1000,
167*91f16700Schasinglulu 	1100,
168*91f16700Schasinglulu 	1100,
169*91f16700Schasinglulu 	1100,
170*91f16700Schasinglulu 	1100,
171*91f16700Schasinglulu 	1200,
172*91f16700Schasinglulu 	1200,
173*91f16700Schasinglulu 	1200,
174*91f16700Schasinglulu 	1200,
175*91f16700Schasinglulu 	1300,
176*91f16700Schasinglulu 	1300,
177*91f16700Schasinglulu 	1300,
178*91f16700Schasinglulu 	1300,
179*91f16700Schasinglulu 	1400,
180*91f16700Schasinglulu 	1400,
181*91f16700Schasinglulu 	1400,
182*91f16700Schasinglulu 	1400,
183*91f16700Schasinglulu 	1500,
184*91f16700Schasinglulu 	1600,
185*91f16700Schasinglulu 	1700,
186*91f16700Schasinglulu 	1800,
187*91f16700Schasinglulu 	1900,
188*91f16700Schasinglulu 	2000,
189*91f16700Schasinglulu 	2100,
190*91f16700Schasinglulu 	2200,
191*91f16700Schasinglulu 	2300,
192*91f16700Schasinglulu 	2400,
193*91f16700Schasinglulu 	2500,
194*91f16700Schasinglulu 	2600,
195*91f16700Schasinglulu 	2700,
196*91f16700Schasinglulu 	2800,
197*91f16700Schasinglulu 	2900,
198*91f16700Schasinglulu 	3000,
199*91f16700Schasinglulu 	3100,
200*91f16700Schasinglulu 	3200,
201*91f16700Schasinglulu 	3300,
202*91f16700Schasinglulu 	3400,
203*91f16700Schasinglulu };
204*91f16700Schasinglulu 
205*91f16700Schasinglulu static const uint16_t buck4_voltage_table[] = {
206*91f16700Schasinglulu 	600,
207*91f16700Schasinglulu 	625,
208*91f16700Schasinglulu 	650,
209*91f16700Schasinglulu 	675,
210*91f16700Schasinglulu 	700,
211*91f16700Schasinglulu 	725,
212*91f16700Schasinglulu 	750,
213*91f16700Schasinglulu 	775,
214*91f16700Schasinglulu 	800,
215*91f16700Schasinglulu 	825,
216*91f16700Schasinglulu 	850,
217*91f16700Schasinglulu 	875,
218*91f16700Schasinglulu 	900,
219*91f16700Schasinglulu 	925,
220*91f16700Schasinglulu 	950,
221*91f16700Schasinglulu 	975,
222*91f16700Schasinglulu 	1000,
223*91f16700Schasinglulu 	1025,
224*91f16700Schasinglulu 	1050,
225*91f16700Schasinglulu 	1075,
226*91f16700Schasinglulu 	1100,
227*91f16700Schasinglulu 	1125,
228*91f16700Schasinglulu 	1150,
229*91f16700Schasinglulu 	1175,
230*91f16700Schasinglulu 	1200,
231*91f16700Schasinglulu 	1225,
232*91f16700Schasinglulu 	1250,
233*91f16700Schasinglulu 	1275,
234*91f16700Schasinglulu 	1300,
235*91f16700Schasinglulu 	1300,
236*91f16700Schasinglulu 	1350,
237*91f16700Schasinglulu 	1350,
238*91f16700Schasinglulu 	1400,
239*91f16700Schasinglulu 	1400,
240*91f16700Schasinglulu 	1450,
241*91f16700Schasinglulu 	1450,
242*91f16700Schasinglulu 	1500,
243*91f16700Schasinglulu 	1600,
244*91f16700Schasinglulu 	1700,
245*91f16700Schasinglulu 	1800,
246*91f16700Schasinglulu 	1900,
247*91f16700Schasinglulu 	2000,
248*91f16700Schasinglulu 	2100,
249*91f16700Schasinglulu 	2200,
250*91f16700Schasinglulu 	2300,
251*91f16700Schasinglulu 	2400,
252*91f16700Schasinglulu 	2500,
253*91f16700Schasinglulu 	2600,
254*91f16700Schasinglulu 	2700,
255*91f16700Schasinglulu 	2800,
256*91f16700Schasinglulu 	2900,
257*91f16700Schasinglulu 	3000,
258*91f16700Schasinglulu 	3100,
259*91f16700Schasinglulu 	3200,
260*91f16700Schasinglulu 	3300,
261*91f16700Schasinglulu 	3400,
262*91f16700Schasinglulu 	3500,
263*91f16700Schasinglulu 	3600,
264*91f16700Schasinglulu 	3700,
265*91f16700Schasinglulu 	3800,
266*91f16700Schasinglulu 	3900,
267*91f16700Schasinglulu };
268*91f16700Schasinglulu 
269*91f16700Schasinglulu static const uint16_t ldo1_voltage_table[] = {
270*91f16700Schasinglulu 	1700,
271*91f16700Schasinglulu 	1700,
272*91f16700Schasinglulu 	1700,
273*91f16700Schasinglulu 	1700,
274*91f16700Schasinglulu 	1700,
275*91f16700Schasinglulu 	1700,
276*91f16700Schasinglulu 	1700,
277*91f16700Schasinglulu 	1700,
278*91f16700Schasinglulu 	1700,
279*91f16700Schasinglulu 	1800,
280*91f16700Schasinglulu 	1900,
281*91f16700Schasinglulu 	2000,
282*91f16700Schasinglulu 	2100,
283*91f16700Schasinglulu 	2200,
284*91f16700Schasinglulu 	2300,
285*91f16700Schasinglulu 	2400,
286*91f16700Schasinglulu 	2500,
287*91f16700Schasinglulu 	2600,
288*91f16700Schasinglulu 	2700,
289*91f16700Schasinglulu 	2800,
290*91f16700Schasinglulu 	2900,
291*91f16700Schasinglulu 	3000,
292*91f16700Schasinglulu 	3100,
293*91f16700Schasinglulu 	3200,
294*91f16700Schasinglulu 	3300,
295*91f16700Schasinglulu };
296*91f16700Schasinglulu 
297*91f16700Schasinglulu static const uint16_t ldo2_voltage_table[] = {
298*91f16700Schasinglulu 	1700,
299*91f16700Schasinglulu 	1700,
300*91f16700Schasinglulu 	1700,
301*91f16700Schasinglulu 	1700,
302*91f16700Schasinglulu 	1700,
303*91f16700Schasinglulu 	1700,
304*91f16700Schasinglulu 	1700,
305*91f16700Schasinglulu 	1700,
306*91f16700Schasinglulu 	1700,
307*91f16700Schasinglulu 	1800,
308*91f16700Schasinglulu 	1900,
309*91f16700Schasinglulu 	2000,
310*91f16700Schasinglulu 	2100,
311*91f16700Schasinglulu 	2200,
312*91f16700Schasinglulu 	2300,
313*91f16700Schasinglulu 	2400,
314*91f16700Schasinglulu 	2500,
315*91f16700Schasinglulu 	2600,
316*91f16700Schasinglulu 	2700,
317*91f16700Schasinglulu 	2800,
318*91f16700Schasinglulu 	2900,
319*91f16700Schasinglulu 	3000,
320*91f16700Schasinglulu 	3100,
321*91f16700Schasinglulu 	3200,
322*91f16700Schasinglulu 	3300,
323*91f16700Schasinglulu };
324*91f16700Schasinglulu 
325*91f16700Schasinglulu static const uint16_t ldo3_voltage_table[] = {
326*91f16700Schasinglulu 	1700,
327*91f16700Schasinglulu 	1700,
328*91f16700Schasinglulu 	1700,
329*91f16700Schasinglulu 	1700,
330*91f16700Schasinglulu 	1700,
331*91f16700Schasinglulu 	1700,
332*91f16700Schasinglulu 	1700,
333*91f16700Schasinglulu 	1700,
334*91f16700Schasinglulu 	1700,
335*91f16700Schasinglulu 	1800,
336*91f16700Schasinglulu 	1900,
337*91f16700Schasinglulu 	2000,
338*91f16700Schasinglulu 	2100,
339*91f16700Schasinglulu 	2200,
340*91f16700Schasinglulu 	2300,
341*91f16700Schasinglulu 	2400,
342*91f16700Schasinglulu 	2500,
343*91f16700Schasinglulu 	2600,
344*91f16700Schasinglulu 	2700,
345*91f16700Schasinglulu 	2800,
346*91f16700Schasinglulu 	2900,
347*91f16700Schasinglulu 	3000,
348*91f16700Schasinglulu 	3100,
349*91f16700Schasinglulu 	3200,
350*91f16700Schasinglulu 	3300,
351*91f16700Schasinglulu 	3300,
352*91f16700Schasinglulu 	3300,
353*91f16700Schasinglulu 	3300,
354*91f16700Schasinglulu 	3300,
355*91f16700Schasinglulu 	3300,
356*91f16700Schasinglulu 	3300,
357*91f16700Schasinglulu };
358*91f16700Schasinglulu 
359*91f16700Schasinglulu /* Special mode table is used for sink source OR bypass mode */
360*91f16700Schasinglulu static const uint16_t ldo3_special_mode_table[] = {
361*91f16700Schasinglulu 	0,
362*91f16700Schasinglulu };
363*91f16700Schasinglulu 
364*91f16700Schasinglulu static const uint16_t ldo5_voltage_table[] = {
365*91f16700Schasinglulu 	1700,
366*91f16700Schasinglulu 	1700,
367*91f16700Schasinglulu 	1700,
368*91f16700Schasinglulu 	1700,
369*91f16700Schasinglulu 	1700,
370*91f16700Schasinglulu 	1700,
371*91f16700Schasinglulu 	1700,
372*91f16700Schasinglulu 	1700,
373*91f16700Schasinglulu 	1700,
374*91f16700Schasinglulu 	1800,
375*91f16700Schasinglulu 	1900,
376*91f16700Schasinglulu 	2000,
377*91f16700Schasinglulu 	2100,
378*91f16700Schasinglulu 	2200,
379*91f16700Schasinglulu 	2300,
380*91f16700Schasinglulu 	2400,
381*91f16700Schasinglulu 	2500,
382*91f16700Schasinglulu 	2600,
383*91f16700Schasinglulu 	2700,
384*91f16700Schasinglulu 	2800,
385*91f16700Schasinglulu 	2900,
386*91f16700Schasinglulu 	3000,
387*91f16700Schasinglulu 	3100,
388*91f16700Schasinglulu 	3200,
389*91f16700Schasinglulu 	3300,
390*91f16700Schasinglulu 	3400,
391*91f16700Schasinglulu 	3500,
392*91f16700Schasinglulu 	3600,
393*91f16700Schasinglulu 	3700,
394*91f16700Schasinglulu 	3800,
395*91f16700Schasinglulu 	3900,
396*91f16700Schasinglulu };
397*91f16700Schasinglulu 
398*91f16700Schasinglulu static const uint16_t ldo6_voltage_table[] = {
399*91f16700Schasinglulu 	900,
400*91f16700Schasinglulu 	1000,
401*91f16700Schasinglulu 	1100,
402*91f16700Schasinglulu 	1200,
403*91f16700Schasinglulu 	1300,
404*91f16700Schasinglulu 	1400,
405*91f16700Schasinglulu 	1500,
406*91f16700Schasinglulu 	1600,
407*91f16700Schasinglulu 	1700,
408*91f16700Schasinglulu 	1800,
409*91f16700Schasinglulu 	1900,
410*91f16700Schasinglulu 	2000,
411*91f16700Schasinglulu 	2100,
412*91f16700Schasinglulu 	2200,
413*91f16700Schasinglulu 	2300,
414*91f16700Schasinglulu 	2400,
415*91f16700Schasinglulu 	2500,
416*91f16700Schasinglulu 	2600,
417*91f16700Schasinglulu 	2700,
418*91f16700Schasinglulu 	2800,
419*91f16700Schasinglulu 	2900,
420*91f16700Schasinglulu 	3000,
421*91f16700Schasinglulu 	3100,
422*91f16700Schasinglulu 	3200,
423*91f16700Schasinglulu 	3300,
424*91f16700Schasinglulu };
425*91f16700Schasinglulu 
426*91f16700Schasinglulu static const uint16_t ldo4_voltage_table[] = {
427*91f16700Schasinglulu 	3300,
428*91f16700Schasinglulu };
429*91f16700Schasinglulu 
430*91f16700Schasinglulu static const uint16_t vref_ddr_voltage_table[] = {
431*91f16700Schasinglulu 	3300,
432*91f16700Schasinglulu };
433*91f16700Schasinglulu 
434*91f16700Schasinglulu static const uint16_t fixed_5v_voltage_table[] = {
435*91f16700Schasinglulu 	5000,
436*91f16700Schasinglulu };
437*91f16700Schasinglulu 
438*91f16700Schasinglulu /* Table of Regulators in PMIC SoC */
439*91f16700Schasinglulu static const struct regul_struct regulators_table[] = {
440*91f16700Schasinglulu 	{
441*91f16700Schasinglulu 		.dt_node_name	= "buck1",
442*91f16700Schasinglulu 		.voltage_table	= buck1_voltage_table,
443*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
444*91f16700Schasinglulu 		.control_reg	= BUCK1_CONTROL_REG,
445*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
446*91f16700Schasinglulu 		.low_power_reg	= BUCK1_PWRCTRL_REG,
447*91f16700Schasinglulu 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
448*91f16700Schasinglulu 		.pull_down	= BUCK1_PULL_DOWN_SHIFT,
449*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
450*91f16700Schasinglulu 		.mask_reset	= BUCK1_MASK_RESET,
451*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
452*91f16700Schasinglulu 		.icc_mask	= BUCK1_ICC_SHIFT,
453*91f16700Schasinglulu 	},
454*91f16700Schasinglulu 	{
455*91f16700Schasinglulu 		.dt_node_name	= "buck2",
456*91f16700Schasinglulu 		.voltage_table	= buck2_voltage_table,
457*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
458*91f16700Schasinglulu 		.control_reg	= BUCK2_CONTROL_REG,
459*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
460*91f16700Schasinglulu 		.low_power_reg	= BUCK2_PWRCTRL_REG,
461*91f16700Schasinglulu 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
462*91f16700Schasinglulu 		.pull_down	= BUCK2_PULL_DOWN_SHIFT,
463*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
464*91f16700Schasinglulu 		.mask_reset	= BUCK2_MASK_RESET,
465*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
466*91f16700Schasinglulu 		.icc_mask	= BUCK2_ICC_SHIFT,
467*91f16700Schasinglulu 	},
468*91f16700Schasinglulu 	{
469*91f16700Schasinglulu 		.dt_node_name	= "buck3",
470*91f16700Schasinglulu 		.voltage_table	= buck3_voltage_table,
471*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
472*91f16700Schasinglulu 		.control_reg	= BUCK3_CONTROL_REG,
473*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
474*91f16700Schasinglulu 		.low_power_reg	= BUCK3_PWRCTRL_REG,
475*91f16700Schasinglulu 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
476*91f16700Schasinglulu 		.pull_down	= BUCK3_PULL_DOWN_SHIFT,
477*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
478*91f16700Schasinglulu 		.mask_reset	= BUCK3_MASK_RESET,
479*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
480*91f16700Schasinglulu 		.icc_mask	= BUCK3_ICC_SHIFT,
481*91f16700Schasinglulu 	},
482*91f16700Schasinglulu 	{
483*91f16700Schasinglulu 		.dt_node_name	= "buck4",
484*91f16700Schasinglulu 		.voltage_table	= buck4_voltage_table,
485*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
486*91f16700Schasinglulu 		.control_reg	= BUCK4_CONTROL_REG,
487*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
488*91f16700Schasinglulu 		.low_power_reg	= BUCK4_PWRCTRL_REG,
489*91f16700Schasinglulu 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
490*91f16700Schasinglulu 		.pull_down	= BUCK4_PULL_DOWN_SHIFT,
491*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
492*91f16700Schasinglulu 		.mask_reset	= BUCK4_MASK_RESET,
493*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
494*91f16700Schasinglulu 		.icc_mask	= BUCK4_ICC_SHIFT,
495*91f16700Schasinglulu 	},
496*91f16700Schasinglulu 	{
497*91f16700Schasinglulu 		.dt_node_name	= "ldo1",
498*91f16700Schasinglulu 		.voltage_table	= ldo1_voltage_table,
499*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
500*91f16700Schasinglulu 		.control_reg	= LDO1_CONTROL_REG,
501*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
502*91f16700Schasinglulu 		.low_power_reg	= LDO1_PWRCTRL_REG,
503*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
504*91f16700Schasinglulu 		.mask_reset	= LDO1_MASK_RESET,
505*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
506*91f16700Schasinglulu 		.icc_mask	= LDO1_ICC_SHIFT,
507*91f16700Schasinglulu 	},
508*91f16700Schasinglulu 	{
509*91f16700Schasinglulu 		.dt_node_name	= "ldo2",
510*91f16700Schasinglulu 		.voltage_table	= ldo2_voltage_table,
511*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
512*91f16700Schasinglulu 		.control_reg	= LDO2_CONTROL_REG,
513*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
514*91f16700Schasinglulu 		.low_power_reg	= LDO2_PWRCTRL_REG,
515*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
516*91f16700Schasinglulu 		.mask_reset	= LDO2_MASK_RESET,
517*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
518*91f16700Schasinglulu 		.icc_mask	= LDO2_ICC_SHIFT,
519*91f16700Schasinglulu 	},
520*91f16700Schasinglulu 	{
521*91f16700Schasinglulu 		.dt_node_name	= "ldo3",
522*91f16700Schasinglulu 		.voltage_table	= ldo3_voltage_table,
523*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
524*91f16700Schasinglulu 		.control_reg	= LDO3_CONTROL_REG,
525*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
526*91f16700Schasinglulu 		.low_power_reg	= LDO3_PWRCTRL_REG,
527*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
528*91f16700Schasinglulu 		.mask_reset	= LDO3_MASK_RESET,
529*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
530*91f16700Schasinglulu 		.icc_mask	= LDO3_ICC_SHIFT,
531*91f16700Schasinglulu 	},
532*91f16700Schasinglulu 	{
533*91f16700Schasinglulu 		.dt_node_name	= "ldo4",
534*91f16700Schasinglulu 		.voltage_table	= ldo4_voltage_table,
535*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
536*91f16700Schasinglulu 		.control_reg	= LDO4_CONTROL_REG,
537*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
538*91f16700Schasinglulu 		.low_power_reg	= LDO4_PWRCTRL_REG,
539*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
540*91f16700Schasinglulu 		.mask_reset	= LDO4_MASK_RESET,
541*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
542*91f16700Schasinglulu 		.icc_mask	= LDO4_ICC_SHIFT,
543*91f16700Schasinglulu 	},
544*91f16700Schasinglulu 	{
545*91f16700Schasinglulu 		.dt_node_name	= "ldo5",
546*91f16700Schasinglulu 		.voltage_table	= ldo5_voltage_table,
547*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
548*91f16700Schasinglulu 		.control_reg	= LDO5_CONTROL_REG,
549*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
550*91f16700Schasinglulu 		.low_power_reg	= LDO5_PWRCTRL_REG,
551*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
552*91f16700Schasinglulu 		.mask_reset	= LDO5_MASK_RESET,
553*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
554*91f16700Schasinglulu 		.icc_mask	= LDO5_ICC_SHIFT,
555*91f16700Schasinglulu 	},
556*91f16700Schasinglulu 	{
557*91f16700Schasinglulu 		.dt_node_name	= "ldo6",
558*91f16700Schasinglulu 		.voltage_table	= ldo6_voltage_table,
559*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
560*91f16700Schasinglulu 		.control_reg	= LDO6_CONTROL_REG,
561*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
562*91f16700Schasinglulu 		.low_power_reg	= LDO6_PWRCTRL_REG,
563*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
564*91f16700Schasinglulu 		.mask_reset	= LDO6_MASK_RESET,
565*91f16700Schasinglulu 		.icc_reg	= LDO_ICC_TURNOFF_REG,
566*91f16700Schasinglulu 		.icc_mask	= LDO6_ICC_SHIFT,
567*91f16700Schasinglulu 	},
568*91f16700Schasinglulu 	{
569*91f16700Schasinglulu 		.dt_node_name	= "vref_ddr",
570*91f16700Schasinglulu 		.voltage_table	= vref_ddr_voltage_table,
571*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
572*91f16700Schasinglulu 		.control_reg	= VREF_DDR_CONTROL_REG,
573*91f16700Schasinglulu 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
574*91f16700Schasinglulu 		.low_power_reg	= VREF_DDR_PWRCTRL_REG,
575*91f16700Schasinglulu 		.mask_reset_reg	= MASK_RESET_LDO_REG,
576*91f16700Schasinglulu 		.mask_reset	= VREF_DDR_MASK_RESET,
577*91f16700Schasinglulu 	},
578*91f16700Schasinglulu 	{
579*91f16700Schasinglulu 		.dt_node_name	= "boost",
580*91f16700Schasinglulu 		.voltage_table	= fixed_5v_voltage_table,
581*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
582*91f16700Schasinglulu 		.control_reg	= USB_CONTROL_REG,
583*91f16700Schasinglulu 		.enable_mask	= BOOST_ENABLED,
584*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
585*91f16700Schasinglulu 		.icc_mask	= BOOST_ICC_SHIFT,
586*91f16700Schasinglulu 	},
587*91f16700Schasinglulu 	{
588*91f16700Schasinglulu 		.dt_node_name	= "pwr_sw1",
589*91f16700Schasinglulu 		.voltage_table	= fixed_5v_voltage_table,
590*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
591*91f16700Schasinglulu 		.control_reg	= USB_CONTROL_REG,
592*91f16700Schasinglulu 		.enable_mask	= USBSW_OTG_SWITCH_ENABLED,
593*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
594*91f16700Schasinglulu 		.icc_mask	= PWR_SW1_ICC_SHIFT,
595*91f16700Schasinglulu 	},
596*91f16700Schasinglulu 	{
597*91f16700Schasinglulu 		.dt_node_name	= "pwr_sw2",
598*91f16700Schasinglulu 		.voltage_table	= fixed_5v_voltage_table,
599*91f16700Schasinglulu 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
600*91f16700Schasinglulu 		.control_reg	= USB_CONTROL_REG,
601*91f16700Schasinglulu 		.enable_mask	= SWIN_SWOUT_ENABLED,
602*91f16700Schasinglulu 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
603*91f16700Schasinglulu 		.icc_mask	= PWR_SW2_ICC_SHIFT,
604*91f16700Schasinglulu 	},
605*91f16700Schasinglulu };
606*91f16700Schasinglulu 
607*91f16700Schasinglulu #define MAX_REGUL	ARRAY_SIZE(regulators_table)
608*91f16700Schasinglulu 
609*91f16700Schasinglulu static const struct regul_struct *get_regulator_data(const char *name)
610*91f16700Schasinglulu {
611*91f16700Schasinglulu 	uint8_t i;
612*91f16700Schasinglulu 
613*91f16700Schasinglulu 	for (i = 0 ; i < MAX_REGUL ; i++) {
614*91f16700Schasinglulu 		if (strncmp(name, regulators_table[i].dt_node_name,
615*91f16700Schasinglulu 			    strlen(regulators_table[i].dt_node_name)) == 0) {
616*91f16700Schasinglulu 			return &regulators_table[i];
617*91f16700Schasinglulu 		}
618*91f16700Schasinglulu 	}
619*91f16700Schasinglulu 
620*91f16700Schasinglulu 	/* Regulator not found */
621*91f16700Schasinglulu 	panic();
622*91f16700Schasinglulu 	return NULL;
623*91f16700Schasinglulu }
624*91f16700Schasinglulu 
625*91f16700Schasinglulu static uint8_t voltage_to_index(const char *name, uint16_t millivolts)
626*91f16700Schasinglulu {
627*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
628*91f16700Schasinglulu 	uint8_t i;
629*91f16700Schasinglulu 
630*91f16700Schasinglulu 	for (i = 0 ; i < regul->voltage_table_size ; i++) {
631*91f16700Schasinglulu 		if (regul->voltage_table[i] == millivolts) {
632*91f16700Schasinglulu 			return i;
633*91f16700Schasinglulu 		}
634*91f16700Schasinglulu 	}
635*91f16700Schasinglulu 
636*91f16700Schasinglulu 	/* Voltage not found */
637*91f16700Schasinglulu 	panic();
638*91f16700Schasinglulu 
639*91f16700Schasinglulu 	return 0;
640*91f16700Schasinglulu }
641*91f16700Schasinglulu 
642*91f16700Schasinglulu int stpmic1_powerctrl_on(void)
643*91f16700Schasinglulu {
644*91f16700Schasinglulu 	return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID,
645*91f16700Schasinglulu 				       PWRCTRL_PIN_VALID);
646*91f16700Schasinglulu }
647*91f16700Schasinglulu 
648*91f16700Schasinglulu int stpmic1_switch_off(void)
649*91f16700Schasinglulu {
650*91f16700Schasinglulu 	return stpmic1_register_update(MAIN_CONTROL_REG, 1,
651*91f16700Schasinglulu 				       SOFTWARE_SWITCH_OFF_ENABLED);
652*91f16700Schasinglulu }
653*91f16700Schasinglulu 
654*91f16700Schasinglulu int stpmic1_regulator_enable(const char *name)
655*91f16700Schasinglulu {
656*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
657*91f16700Schasinglulu 
658*91f16700Schasinglulu 	return stpmic1_register_update(regul->control_reg, regul->enable_mask,
659*91f16700Schasinglulu 				       regul->enable_mask);
660*91f16700Schasinglulu }
661*91f16700Schasinglulu 
662*91f16700Schasinglulu int stpmic1_regulator_disable(const char *name)
663*91f16700Schasinglulu {
664*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
665*91f16700Schasinglulu 
666*91f16700Schasinglulu 	return stpmic1_register_update(regul->control_reg, 0,
667*91f16700Schasinglulu 				       regul->enable_mask);
668*91f16700Schasinglulu }
669*91f16700Schasinglulu 
670*91f16700Schasinglulu bool stpmic1_is_regulator_enabled(const char *name)
671*91f16700Schasinglulu {
672*91f16700Schasinglulu 	uint8_t val;
673*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
674*91f16700Schasinglulu 
675*91f16700Schasinglulu 	if (stpmic1_register_read(regul->control_reg, &val) != 0) {
676*91f16700Schasinglulu 		panic();
677*91f16700Schasinglulu 	}
678*91f16700Schasinglulu 
679*91f16700Schasinglulu 	return (val & regul->enable_mask) == regul->enable_mask;
680*91f16700Schasinglulu }
681*91f16700Schasinglulu 
682*91f16700Schasinglulu int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
683*91f16700Schasinglulu {
684*91f16700Schasinglulu 	uint8_t voltage_index = voltage_to_index(name, millivolts);
685*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
686*91f16700Schasinglulu 	uint8_t mask;
687*91f16700Schasinglulu 
688*91f16700Schasinglulu 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
689*91f16700Schasinglulu 		/*
690*91f16700Schasinglulu 		 * when the LDO3 is in special mode, we do not change voltage,
691*91f16700Schasinglulu 		 * because by setting voltage, the LDO would leaves sink-source
692*91f16700Schasinglulu 		 * mode. There is obviously no reason to leave sink-source mode
693*91f16700Schasinglulu 		 * at runtime.
694*91f16700Schasinglulu 		 */
695*91f16700Schasinglulu 		return 0;
696*91f16700Schasinglulu 	}
697*91f16700Schasinglulu 
698*91f16700Schasinglulu 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
699*91f16700Schasinglulu 	if (strncmp(name, "buck", 4) == 0) {
700*91f16700Schasinglulu 		mask = BUCK_VOLTAGE_MASK;
701*91f16700Schasinglulu 	} else if ((strncmp(name, "ldo", 3) == 0) &&
702*91f16700Schasinglulu 		   (strncmp(name, "ldo4", 5) != 0)) {
703*91f16700Schasinglulu 		mask = LDO_VOLTAGE_MASK;
704*91f16700Schasinglulu 	} else {
705*91f16700Schasinglulu 		return 0;
706*91f16700Schasinglulu 	}
707*91f16700Schasinglulu 
708*91f16700Schasinglulu 	return stpmic1_register_update(regul->control_reg,
709*91f16700Schasinglulu 				       voltage_index << LDO_BUCK_VOLTAGE_SHIFT,
710*91f16700Schasinglulu 				       mask);
711*91f16700Schasinglulu }
712*91f16700Schasinglulu 
713*91f16700Schasinglulu int stpmic1_regulator_pull_down_set(const char *name)
714*91f16700Schasinglulu {
715*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
716*91f16700Schasinglulu 
717*91f16700Schasinglulu 	if (regul->pull_down_reg != 0) {
718*91f16700Schasinglulu 		return stpmic1_register_update(regul->pull_down_reg,
719*91f16700Schasinglulu 					       BIT(regul->pull_down),
720*91f16700Schasinglulu 					       LDO_BUCK_PULL_DOWN_MASK <<
721*91f16700Schasinglulu 					       regul->pull_down);
722*91f16700Schasinglulu 	}
723*91f16700Schasinglulu 
724*91f16700Schasinglulu 	return 0;
725*91f16700Schasinglulu }
726*91f16700Schasinglulu 
727*91f16700Schasinglulu int stpmic1_regulator_mask_reset_set(const char *name)
728*91f16700Schasinglulu {
729*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
730*91f16700Schasinglulu 
731*91f16700Schasinglulu 	if (regul->mask_reset_reg == 0U) {
732*91f16700Schasinglulu 		return -EPERM;
733*91f16700Schasinglulu 	}
734*91f16700Schasinglulu 
735*91f16700Schasinglulu 	return stpmic1_register_update(regul->mask_reset_reg,
736*91f16700Schasinglulu 				       BIT(regul->mask_reset),
737*91f16700Schasinglulu 				       LDO_BUCK_RESET_MASK <<
738*91f16700Schasinglulu 				       regul->mask_reset);
739*91f16700Schasinglulu }
740*91f16700Schasinglulu 
741*91f16700Schasinglulu int stpmic1_regulator_icc_set(const char *name)
742*91f16700Schasinglulu {
743*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
744*91f16700Schasinglulu 
745*91f16700Schasinglulu 	if (regul->mask_reset_reg == 0U) {
746*91f16700Schasinglulu 		return -EPERM;
747*91f16700Schasinglulu 	}
748*91f16700Schasinglulu 
749*91f16700Schasinglulu 	return stpmic1_register_update(regul->icc_reg,
750*91f16700Schasinglulu 				       BIT(regul->icc_mask),
751*91f16700Schasinglulu 				       BIT(regul->icc_mask));
752*91f16700Schasinglulu }
753*91f16700Schasinglulu 
754*91f16700Schasinglulu int stpmic1_regulator_sink_mode_set(const char *name)
755*91f16700Schasinglulu {
756*91f16700Schasinglulu 	if (strncmp(name, "ldo3", 5) != 0) {
757*91f16700Schasinglulu 		return -EPERM;
758*91f16700Schasinglulu 	}
759*91f16700Schasinglulu 
760*91f16700Schasinglulu 	ldo3_special_mode = true;
761*91f16700Schasinglulu 
762*91f16700Schasinglulu 	/* disable bypass mode, enable sink mode */
763*91f16700Schasinglulu 	return stpmic1_register_update(LDO3_CONTROL_REG,
764*91f16700Schasinglulu 				       LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT,
765*91f16700Schasinglulu 				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
766*91f16700Schasinglulu }
767*91f16700Schasinglulu 
768*91f16700Schasinglulu int stpmic1_regulator_bypass_mode_set(const char *name)
769*91f16700Schasinglulu {
770*91f16700Schasinglulu 	if (strncmp(name, "ldo3", 5) != 0) {
771*91f16700Schasinglulu 		return -EPERM;
772*91f16700Schasinglulu 	}
773*91f16700Schasinglulu 
774*91f16700Schasinglulu 	ldo3_special_mode = true;
775*91f16700Schasinglulu 
776*91f16700Schasinglulu 	/* enable bypass mode, disable sink mode */
777*91f16700Schasinglulu 	return stpmic1_register_update(LDO3_CONTROL_REG,
778*91f16700Schasinglulu 				       LDO3_BYPASS,
779*91f16700Schasinglulu 				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
780*91f16700Schasinglulu }
781*91f16700Schasinglulu 
782*91f16700Schasinglulu int stpmic1_active_discharge_mode_set(const char *name)
783*91f16700Schasinglulu {
784*91f16700Schasinglulu 	if (strncmp(name, "pwr_sw1", 8) == 0) {
785*91f16700Schasinglulu 		return stpmic1_register_update(USB_CONTROL_REG,
786*91f16700Schasinglulu 					       VBUS_OTG_DISCHARGE,
787*91f16700Schasinglulu 					       VBUS_OTG_DISCHARGE);
788*91f16700Schasinglulu 	}
789*91f16700Schasinglulu 
790*91f16700Schasinglulu 	if (strncmp(name, "pwr_sw2", 8) == 0) {
791*91f16700Schasinglulu 		return stpmic1_register_update(USB_CONTROL_REG,
792*91f16700Schasinglulu 					       SW_OUT_DISCHARGE,
793*91f16700Schasinglulu 					       SW_OUT_DISCHARGE);
794*91f16700Schasinglulu 	}
795*91f16700Schasinglulu 
796*91f16700Schasinglulu 	return -EPERM;
797*91f16700Schasinglulu }
798*91f16700Schasinglulu 
799*91f16700Schasinglulu int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels,
800*91f16700Schasinglulu 				size_t *levels_count)
801*91f16700Schasinglulu {
802*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
803*91f16700Schasinglulu 
804*91f16700Schasinglulu 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
805*91f16700Schasinglulu 		*levels_count = ARRAY_SIZE(ldo3_special_mode_table);
806*91f16700Schasinglulu 		*levels = ldo3_special_mode_table;
807*91f16700Schasinglulu 	} else {
808*91f16700Schasinglulu 		*levels_count = regul->voltage_table_size;
809*91f16700Schasinglulu 		*levels = regul->voltage_table;
810*91f16700Schasinglulu 	}
811*91f16700Schasinglulu 
812*91f16700Schasinglulu 	return 0;
813*91f16700Schasinglulu }
814*91f16700Schasinglulu 
815*91f16700Schasinglulu int stpmic1_regulator_voltage_get(const char *name)
816*91f16700Schasinglulu {
817*91f16700Schasinglulu 	const struct regul_struct *regul = get_regulator_data(name);
818*91f16700Schasinglulu 	uint8_t value;
819*91f16700Schasinglulu 	uint8_t mask;
820*91f16700Schasinglulu 	int status;
821*91f16700Schasinglulu 
822*91f16700Schasinglulu 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
823*91f16700Schasinglulu 		return 0;
824*91f16700Schasinglulu 	}
825*91f16700Schasinglulu 
826*91f16700Schasinglulu 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
827*91f16700Schasinglulu 	if (strncmp(name, "buck", 4) == 0) {
828*91f16700Schasinglulu 		mask = BUCK_VOLTAGE_MASK;
829*91f16700Schasinglulu 	} else if ((strncmp(name, "ldo", 3) == 0) &&
830*91f16700Schasinglulu 		   (strncmp(name, "ldo4", 5) != 0)) {
831*91f16700Schasinglulu 		mask = LDO_VOLTAGE_MASK;
832*91f16700Schasinglulu 	} else {
833*91f16700Schasinglulu 		return 0;
834*91f16700Schasinglulu 	}
835*91f16700Schasinglulu 
836*91f16700Schasinglulu 	status = stpmic1_register_read(regul->control_reg, &value);
837*91f16700Schasinglulu 	if (status < 0) {
838*91f16700Schasinglulu 		return status;
839*91f16700Schasinglulu 	}
840*91f16700Schasinglulu 
841*91f16700Schasinglulu 	value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT;
842*91f16700Schasinglulu 
843*91f16700Schasinglulu 	if (value > regul->voltage_table_size) {
844*91f16700Schasinglulu 		return -ERANGE;
845*91f16700Schasinglulu 	}
846*91f16700Schasinglulu 
847*91f16700Schasinglulu 	return (int)regul->voltage_table[value];
848*91f16700Schasinglulu }
849*91f16700Schasinglulu 
850*91f16700Schasinglulu int stpmic1_register_read(uint8_t register_id,  uint8_t *value)
851*91f16700Schasinglulu {
852*91f16700Schasinglulu 	return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr,
853*91f16700Schasinglulu 				  (uint16_t)register_id,
854*91f16700Schasinglulu 				  I2C_MEMADD_SIZE_8BIT, value,
855*91f16700Schasinglulu 				  1, I2C_TIMEOUT_MS);
856*91f16700Schasinglulu }
857*91f16700Schasinglulu 
858*91f16700Schasinglulu int stpmic1_register_write(uint8_t register_id, uint8_t value)
859*91f16700Schasinglulu {
860*91f16700Schasinglulu 	int status;
861*91f16700Schasinglulu 
862*91f16700Schasinglulu 	status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr,
863*91f16700Schasinglulu 				     (uint16_t)register_id,
864*91f16700Schasinglulu 				     I2C_MEMADD_SIZE_8BIT, &value,
865*91f16700Schasinglulu 				     1, I2C_TIMEOUT_MS);
866*91f16700Schasinglulu 
867*91f16700Schasinglulu #if ENABLE_ASSERTIONS
868*91f16700Schasinglulu 	if (status != 0) {
869*91f16700Schasinglulu 		return status;
870*91f16700Schasinglulu 	}
871*91f16700Schasinglulu 
872*91f16700Schasinglulu 	if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
873*91f16700Schasinglulu 		uint8_t readval;
874*91f16700Schasinglulu 
875*91f16700Schasinglulu 		status = stpmic1_register_read(register_id, &readval);
876*91f16700Schasinglulu 		if (status != 0) {
877*91f16700Schasinglulu 			return status;
878*91f16700Schasinglulu 		}
879*91f16700Schasinglulu 
880*91f16700Schasinglulu 		if (readval != value) {
881*91f16700Schasinglulu 			return -EIO;
882*91f16700Schasinglulu 		}
883*91f16700Schasinglulu 	}
884*91f16700Schasinglulu #endif
885*91f16700Schasinglulu 
886*91f16700Schasinglulu 	return status;
887*91f16700Schasinglulu }
888*91f16700Schasinglulu 
889*91f16700Schasinglulu int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
890*91f16700Schasinglulu {
891*91f16700Schasinglulu 	int status;
892*91f16700Schasinglulu 	uint8_t val;
893*91f16700Schasinglulu 
894*91f16700Schasinglulu 	status = stpmic1_register_read(register_id, &val);
895*91f16700Schasinglulu 	if (status != 0) {
896*91f16700Schasinglulu 		return status;
897*91f16700Schasinglulu 	}
898*91f16700Schasinglulu 
899*91f16700Schasinglulu 	val = (val & ~mask) | (value & mask);
900*91f16700Schasinglulu 
901*91f16700Schasinglulu 	return stpmic1_register_write(register_id, val);
902*91f16700Schasinglulu }
903*91f16700Schasinglulu 
904*91f16700Schasinglulu void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
905*91f16700Schasinglulu {
906*91f16700Schasinglulu 	pmic_i2c_handle = i2c_handle;
907*91f16700Schasinglulu 	pmic_i2c_addr = i2c_addr;
908*91f16700Schasinglulu }
909*91f16700Schasinglulu 
910*91f16700Schasinglulu void stpmic1_dump_regulators(void)
911*91f16700Schasinglulu {
912*91f16700Schasinglulu 	uint32_t i;
913*91f16700Schasinglulu 
914*91f16700Schasinglulu 	for (i = 0U; i < MAX_REGUL; i++) {
915*91f16700Schasinglulu 		const char *name __unused = regulators_table[i].dt_node_name;
916*91f16700Schasinglulu 
917*91f16700Schasinglulu 		VERBOSE("PMIC regul %s: %sable, %dmV",
918*91f16700Schasinglulu 			name,
919*91f16700Schasinglulu 			stpmic1_is_regulator_enabled(name) ? "en" : "dis",
920*91f16700Schasinglulu 			stpmic1_regulator_voltage_get(name));
921*91f16700Schasinglulu 	}
922*91f16700Schasinglulu }
923*91f16700Schasinglulu 
924*91f16700Schasinglulu int stpmic1_get_version(unsigned long *version)
925*91f16700Schasinglulu {
926*91f16700Schasinglulu 	uint8_t read_val;
927*91f16700Schasinglulu 	int status;
928*91f16700Schasinglulu 
929*91f16700Schasinglulu 	status = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
930*91f16700Schasinglulu 	if (status < 0) {
931*91f16700Schasinglulu 		return status;
932*91f16700Schasinglulu 	}
933*91f16700Schasinglulu 
934*91f16700Schasinglulu 	*version = (unsigned long)read_val;
935*91f16700Schasinglulu 
936*91f16700Schasinglulu 	return 0;
937*91f16700Schasinglulu }
938