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