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