xref: /rk3399_ARM-atf/drivers/st/pmic/stpmic1.c (revision 93b153b5bf3f76d482257a52b7a082b8c42f35d0)
123684d0eSYann Gautier /*
2ed6a8523SYann Gautier  * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
323684d0eSYann Gautier  *
423684d0eSYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
523684d0eSYann Gautier  */
623684d0eSYann Gautier 
7ed6a8523SYann Gautier #include <errno.h>
823684d0eSYann Gautier #include <string.h>
923684d0eSYann Gautier 
1023684d0eSYann Gautier #include <common/debug.h>
1123684d0eSYann Gautier #include <drivers/st/stpmic1.h>
12d82d4ff0SYann Gautier 
13d82d4ff0SYann Gautier #define I2C_TIMEOUT_MS		25
1423684d0eSYann Gautier 
1523684d0eSYann Gautier struct regul_struct {
1623684d0eSYann Gautier 	const char *dt_node_name;
1723684d0eSYann Gautier 	const uint16_t *voltage_table;
1823684d0eSYann Gautier 	uint8_t voltage_table_size;
1923684d0eSYann Gautier 	uint8_t control_reg;
2001619911SPascal Paillet 	uint8_t enable_mask;
2123684d0eSYann Gautier 	uint8_t low_power_reg;
22077f6828SYann Gautier 	uint8_t pull_down_reg;
23077f6828SYann Gautier 	uint8_t pull_down;
24077f6828SYann Gautier 	uint8_t mask_reset_reg;
25077f6828SYann Gautier 	uint8_t mask_reset;
26*ea552bf5SPascal Paillet 	uint8_t icc_reg;
27*ea552bf5SPascal Paillet 	uint8_t icc_mask;
2823684d0eSYann Gautier };
2923684d0eSYann Gautier 
3023684d0eSYann Gautier static struct i2c_handle_s *pmic_i2c_handle;
3123684d0eSYann Gautier static uint16_t pmic_i2c_addr;
32*ea552bf5SPascal Paillet /*
33*ea552bf5SPascal Paillet  * Special mode corresponds to LDO3 in sink source mode or in bypass mode.
34*ea552bf5SPascal Paillet  * LDO3 doesn't switch back from special to normal mode.
35*ea552bf5SPascal Paillet  */
36*ea552bf5SPascal Paillet static bool ldo3_special_mode;
3723684d0eSYann Gautier 
3823684d0eSYann Gautier /* Voltage tables in mV */
3923684d0eSYann Gautier static const uint16_t buck1_voltage_table[] = {
40077f6828SYann Gautier 	725,
41077f6828SYann Gautier 	725,
42077f6828SYann Gautier 	725,
43077f6828SYann Gautier 	725,
44077f6828SYann Gautier 	725,
4523684d0eSYann Gautier 	725,
4623684d0eSYann Gautier 	750,
4723684d0eSYann Gautier 	775,
4823684d0eSYann Gautier 	800,
4923684d0eSYann Gautier 	825,
5023684d0eSYann Gautier 	850,
5123684d0eSYann Gautier 	875,
5223684d0eSYann Gautier 	900,
5323684d0eSYann Gautier 	925,
5423684d0eSYann Gautier 	950,
5523684d0eSYann Gautier 	975,
5623684d0eSYann Gautier 	1000,
5723684d0eSYann Gautier 	1025,
5823684d0eSYann Gautier 	1050,
5923684d0eSYann Gautier 	1075,
6023684d0eSYann Gautier 	1100,
6123684d0eSYann Gautier 	1125,
6223684d0eSYann Gautier 	1150,
6323684d0eSYann Gautier 	1175,
6423684d0eSYann Gautier 	1200,
6523684d0eSYann Gautier 	1225,
6623684d0eSYann Gautier 	1250,
6723684d0eSYann Gautier 	1275,
6823684d0eSYann Gautier 	1300,
6923684d0eSYann Gautier 	1325,
7023684d0eSYann Gautier 	1350,
71077f6828SYann Gautier 	1375,
72077f6828SYann Gautier 	1400,
73077f6828SYann Gautier 	1425,
74077f6828SYann Gautier 	1450,
75077f6828SYann Gautier 	1475,
76077f6828SYann Gautier 	1500,
77077f6828SYann Gautier 	1500,
78077f6828SYann Gautier 	1500,
79077f6828SYann Gautier 	1500,
80077f6828SYann Gautier 	1500,
81077f6828SYann Gautier 	1500,
82077f6828SYann Gautier 	1500,
83077f6828SYann Gautier 	1500,
84077f6828SYann Gautier 	1500,
85077f6828SYann Gautier 	1500,
86077f6828SYann Gautier 	1500,
87077f6828SYann Gautier 	1500,
88077f6828SYann Gautier 	1500,
89077f6828SYann Gautier 	1500,
90077f6828SYann Gautier 	1500,
91077f6828SYann Gautier 	1500,
92077f6828SYann Gautier 	1500,
93077f6828SYann Gautier 	1500,
94077f6828SYann Gautier 	1500,
95077f6828SYann Gautier 	1500,
96077f6828SYann Gautier 	1500,
97077f6828SYann Gautier 	1500,
98077f6828SYann Gautier 	1500,
99077f6828SYann Gautier 	1500,
100077f6828SYann Gautier 	1500,
101077f6828SYann Gautier 	1500,
102077f6828SYann Gautier 	1500,
103077f6828SYann Gautier 	1500,
10423684d0eSYann Gautier };
10523684d0eSYann Gautier 
10623684d0eSYann Gautier static const uint16_t buck2_voltage_table[] = {
10723684d0eSYann Gautier 	1000,
10823684d0eSYann Gautier 	1000,
10923684d0eSYann Gautier 	1000,
11023684d0eSYann Gautier 	1000,
11123684d0eSYann Gautier 	1000,
11223684d0eSYann Gautier 	1000,
11323684d0eSYann Gautier 	1000,
11423684d0eSYann Gautier 	1000,
11523684d0eSYann Gautier 	1000,
11623684d0eSYann Gautier 	1000,
11723684d0eSYann Gautier 	1000,
11823684d0eSYann Gautier 	1000,
11923684d0eSYann Gautier 	1000,
12023684d0eSYann Gautier 	1000,
12123684d0eSYann Gautier 	1000,
12223684d0eSYann Gautier 	1000,
12323684d0eSYann Gautier 	1000,
12423684d0eSYann Gautier 	1000,
12523684d0eSYann Gautier 	1050,
12623684d0eSYann Gautier 	1050,
12723684d0eSYann Gautier 	1100,
12823684d0eSYann Gautier 	1100,
12923684d0eSYann Gautier 	1150,
13023684d0eSYann Gautier 	1150,
13123684d0eSYann Gautier 	1200,
13223684d0eSYann Gautier 	1200,
13323684d0eSYann Gautier 	1250,
13423684d0eSYann Gautier 	1250,
13523684d0eSYann Gautier 	1300,
13623684d0eSYann Gautier 	1300,
13723684d0eSYann Gautier 	1350,
13823684d0eSYann Gautier 	1350,
13923684d0eSYann Gautier 	1400,
14023684d0eSYann Gautier 	1400,
14123684d0eSYann Gautier 	1450,
14223684d0eSYann Gautier 	1450,
14323684d0eSYann Gautier 	1500,
14423684d0eSYann Gautier };
14523684d0eSYann Gautier 
14623684d0eSYann Gautier static const uint16_t buck3_voltage_table[] = {
14723684d0eSYann Gautier 	1000,
14823684d0eSYann Gautier 	1000,
14923684d0eSYann Gautier 	1000,
15023684d0eSYann Gautier 	1000,
15123684d0eSYann Gautier 	1000,
15223684d0eSYann Gautier 	1000,
15323684d0eSYann Gautier 	1000,
15423684d0eSYann Gautier 	1000,
15523684d0eSYann Gautier 	1000,
15623684d0eSYann Gautier 	1000,
15723684d0eSYann Gautier 	1000,
15823684d0eSYann Gautier 	1000,
15923684d0eSYann Gautier 	1000,
16023684d0eSYann Gautier 	1000,
16123684d0eSYann Gautier 	1000,
16223684d0eSYann Gautier 	1000,
16323684d0eSYann Gautier 	1000,
16423684d0eSYann Gautier 	1000,
16523684d0eSYann Gautier 	1000,
16623684d0eSYann Gautier 	1000,
16723684d0eSYann Gautier 	1100,
16823684d0eSYann Gautier 	1100,
16923684d0eSYann Gautier 	1100,
17023684d0eSYann Gautier 	1100,
17123684d0eSYann Gautier 	1200,
17223684d0eSYann Gautier 	1200,
17323684d0eSYann Gautier 	1200,
17423684d0eSYann Gautier 	1200,
17523684d0eSYann Gautier 	1300,
17623684d0eSYann Gautier 	1300,
17723684d0eSYann Gautier 	1300,
17823684d0eSYann Gautier 	1300,
17923684d0eSYann Gautier 	1400,
18023684d0eSYann Gautier 	1400,
18123684d0eSYann Gautier 	1400,
18223684d0eSYann Gautier 	1400,
18323684d0eSYann Gautier 	1500,
18423684d0eSYann Gautier 	1600,
18523684d0eSYann Gautier 	1700,
18623684d0eSYann Gautier 	1800,
18723684d0eSYann Gautier 	1900,
18823684d0eSYann Gautier 	2000,
18923684d0eSYann Gautier 	2100,
19023684d0eSYann Gautier 	2200,
19123684d0eSYann Gautier 	2300,
19223684d0eSYann Gautier 	2400,
19323684d0eSYann Gautier 	2500,
19423684d0eSYann Gautier 	2600,
19523684d0eSYann Gautier 	2700,
19623684d0eSYann Gautier 	2800,
19723684d0eSYann Gautier 	2900,
19823684d0eSYann Gautier 	3000,
19923684d0eSYann Gautier 	3100,
20023684d0eSYann Gautier 	3200,
20123684d0eSYann Gautier 	3300,
20223684d0eSYann Gautier 	3400,
20323684d0eSYann Gautier };
20423684d0eSYann Gautier 
20523684d0eSYann Gautier static const uint16_t buck4_voltage_table[] = {
20623684d0eSYann Gautier 	600,
20723684d0eSYann Gautier 	625,
20823684d0eSYann Gautier 	650,
20923684d0eSYann Gautier 	675,
21023684d0eSYann Gautier 	700,
21123684d0eSYann Gautier 	725,
21223684d0eSYann Gautier 	750,
21323684d0eSYann Gautier 	775,
21423684d0eSYann Gautier 	800,
21523684d0eSYann Gautier 	825,
21623684d0eSYann Gautier 	850,
21723684d0eSYann Gautier 	875,
21823684d0eSYann Gautier 	900,
21923684d0eSYann Gautier 	925,
22023684d0eSYann Gautier 	950,
22123684d0eSYann Gautier 	975,
22223684d0eSYann Gautier 	1000,
22323684d0eSYann Gautier 	1025,
22423684d0eSYann Gautier 	1050,
22523684d0eSYann Gautier 	1075,
22623684d0eSYann Gautier 	1100,
22723684d0eSYann Gautier 	1125,
22823684d0eSYann Gautier 	1150,
22923684d0eSYann Gautier 	1175,
23023684d0eSYann Gautier 	1200,
23123684d0eSYann Gautier 	1225,
23223684d0eSYann Gautier 	1250,
23323684d0eSYann Gautier 	1275,
23423684d0eSYann Gautier 	1300,
23523684d0eSYann Gautier 	1300,
23623684d0eSYann Gautier 	1350,
23723684d0eSYann Gautier 	1350,
23823684d0eSYann Gautier 	1400,
23923684d0eSYann Gautier 	1400,
24023684d0eSYann Gautier 	1450,
24123684d0eSYann Gautier 	1450,
24223684d0eSYann Gautier 	1500,
24323684d0eSYann Gautier 	1600,
24423684d0eSYann Gautier 	1700,
24523684d0eSYann Gautier 	1800,
24623684d0eSYann Gautier 	1900,
24723684d0eSYann Gautier 	2000,
24823684d0eSYann Gautier 	2100,
24923684d0eSYann Gautier 	2200,
25023684d0eSYann Gautier 	2300,
25123684d0eSYann Gautier 	2400,
25223684d0eSYann Gautier 	2500,
25323684d0eSYann Gautier 	2600,
25423684d0eSYann Gautier 	2700,
25523684d0eSYann Gautier 	2800,
25623684d0eSYann Gautier 	2900,
25723684d0eSYann Gautier 	3000,
25823684d0eSYann Gautier 	3100,
25923684d0eSYann Gautier 	3200,
26023684d0eSYann Gautier 	3300,
26123684d0eSYann Gautier 	3400,
26223684d0eSYann Gautier 	3500,
26323684d0eSYann Gautier 	3600,
26423684d0eSYann Gautier 	3700,
26523684d0eSYann Gautier 	3800,
26623684d0eSYann Gautier 	3900,
26723684d0eSYann Gautier };
26823684d0eSYann Gautier 
26923684d0eSYann Gautier static const uint16_t ldo1_voltage_table[] = {
27023684d0eSYann Gautier 	1700,
27123684d0eSYann Gautier 	1700,
27223684d0eSYann Gautier 	1700,
27323684d0eSYann Gautier 	1700,
27423684d0eSYann Gautier 	1700,
27523684d0eSYann Gautier 	1700,
27623684d0eSYann Gautier 	1700,
27723684d0eSYann Gautier 	1700,
27823684d0eSYann Gautier 	1700,
27923684d0eSYann Gautier 	1800,
28023684d0eSYann Gautier 	1900,
28123684d0eSYann Gautier 	2000,
28223684d0eSYann Gautier 	2100,
28323684d0eSYann Gautier 	2200,
28423684d0eSYann Gautier 	2300,
28523684d0eSYann Gautier 	2400,
28623684d0eSYann Gautier 	2500,
28723684d0eSYann Gautier 	2600,
28823684d0eSYann Gautier 	2700,
28923684d0eSYann Gautier 	2800,
29023684d0eSYann Gautier 	2900,
29123684d0eSYann Gautier 	3000,
29223684d0eSYann Gautier 	3100,
29323684d0eSYann Gautier 	3200,
29423684d0eSYann Gautier 	3300,
29523684d0eSYann Gautier };
29623684d0eSYann Gautier 
29723684d0eSYann Gautier static const uint16_t ldo2_voltage_table[] = {
29823684d0eSYann Gautier 	1700,
29923684d0eSYann Gautier 	1700,
30023684d0eSYann Gautier 	1700,
30123684d0eSYann Gautier 	1700,
30223684d0eSYann Gautier 	1700,
30323684d0eSYann Gautier 	1700,
30423684d0eSYann Gautier 	1700,
30523684d0eSYann Gautier 	1700,
30623684d0eSYann Gautier 	1700,
30723684d0eSYann Gautier 	1800,
30823684d0eSYann Gautier 	1900,
30923684d0eSYann Gautier 	2000,
31023684d0eSYann Gautier 	2100,
31123684d0eSYann Gautier 	2200,
31223684d0eSYann Gautier 	2300,
31323684d0eSYann Gautier 	2400,
31423684d0eSYann Gautier 	2500,
31523684d0eSYann Gautier 	2600,
31623684d0eSYann Gautier 	2700,
31723684d0eSYann Gautier 	2800,
31823684d0eSYann Gautier 	2900,
31923684d0eSYann Gautier 	3000,
32023684d0eSYann Gautier 	3100,
32123684d0eSYann Gautier 	3200,
32223684d0eSYann Gautier 	3300,
32323684d0eSYann Gautier };
32423684d0eSYann Gautier 
32523684d0eSYann Gautier static const uint16_t ldo3_voltage_table[] = {
32623684d0eSYann Gautier 	1700,
32723684d0eSYann Gautier 	1700,
32823684d0eSYann Gautier 	1700,
32923684d0eSYann Gautier 	1700,
33023684d0eSYann Gautier 	1700,
33123684d0eSYann Gautier 	1700,
33223684d0eSYann Gautier 	1700,
33323684d0eSYann Gautier 	1700,
33423684d0eSYann Gautier 	1700,
33523684d0eSYann Gautier 	1800,
33623684d0eSYann Gautier 	1900,
33723684d0eSYann Gautier 	2000,
33823684d0eSYann Gautier 	2100,
33923684d0eSYann Gautier 	2200,
34023684d0eSYann Gautier 	2300,
34123684d0eSYann Gautier 	2400,
34223684d0eSYann Gautier 	2500,
34323684d0eSYann Gautier 	2600,
34423684d0eSYann Gautier 	2700,
34523684d0eSYann Gautier 	2800,
34623684d0eSYann Gautier 	2900,
34723684d0eSYann Gautier 	3000,
34823684d0eSYann Gautier 	3100,
34923684d0eSYann Gautier 	3200,
35023684d0eSYann Gautier 	3300,
35123684d0eSYann Gautier 	3300,
35223684d0eSYann Gautier 	3300,
35323684d0eSYann Gautier 	3300,
35423684d0eSYann Gautier 	3300,
35523684d0eSYann Gautier 	3300,
35623684d0eSYann Gautier 	3300,
357*ea552bf5SPascal Paillet };
358*ea552bf5SPascal Paillet 
359*ea552bf5SPascal Paillet /* Special mode table is used for sink source OR bypass mode */
360*ea552bf5SPascal Paillet static const uint16_t ldo3_special_mode_table[] = {
361*ea552bf5SPascal Paillet 	0,
36223684d0eSYann Gautier };
36323684d0eSYann Gautier 
36423684d0eSYann Gautier static const uint16_t ldo5_voltage_table[] = {
36523684d0eSYann Gautier 	1700,
36623684d0eSYann Gautier 	1700,
36723684d0eSYann Gautier 	1700,
36823684d0eSYann Gautier 	1700,
36923684d0eSYann Gautier 	1700,
37023684d0eSYann Gautier 	1700,
37123684d0eSYann Gautier 	1700,
37223684d0eSYann Gautier 	1700,
37323684d0eSYann Gautier 	1700,
37423684d0eSYann Gautier 	1800,
37523684d0eSYann Gautier 	1900,
37623684d0eSYann Gautier 	2000,
37723684d0eSYann Gautier 	2100,
37823684d0eSYann Gautier 	2200,
37923684d0eSYann Gautier 	2300,
38023684d0eSYann Gautier 	2400,
38123684d0eSYann Gautier 	2500,
38223684d0eSYann Gautier 	2600,
38323684d0eSYann Gautier 	2700,
38423684d0eSYann Gautier 	2800,
38523684d0eSYann Gautier 	2900,
38623684d0eSYann Gautier 	3000,
38723684d0eSYann Gautier 	3100,
38823684d0eSYann Gautier 	3200,
38923684d0eSYann Gautier 	3300,
39023684d0eSYann Gautier 	3400,
39123684d0eSYann Gautier 	3500,
39223684d0eSYann Gautier 	3600,
39323684d0eSYann Gautier 	3700,
39423684d0eSYann Gautier 	3800,
39523684d0eSYann Gautier 	3900,
39623684d0eSYann Gautier };
39723684d0eSYann Gautier 
39823684d0eSYann Gautier static const uint16_t ldo6_voltage_table[] = {
39923684d0eSYann Gautier 	900,
40023684d0eSYann Gautier 	1000,
40123684d0eSYann Gautier 	1100,
40223684d0eSYann Gautier 	1200,
40323684d0eSYann Gautier 	1300,
40423684d0eSYann Gautier 	1400,
40523684d0eSYann Gautier 	1500,
40623684d0eSYann Gautier 	1600,
40723684d0eSYann Gautier 	1700,
40823684d0eSYann Gautier 	1800,
40923684d0eSYann Gautier 	1900,
41023684d0eSYann Gautier 	2000,
41123684d0eSYann Gautier 	2100,
41223684d0eSYann Gautier 	2200,
41323684d0eSYann Gautier 	2300,
41423684d0eSYann Gautier 	2400,
41523684d0eSYann Gautier 	2500,
41623684d0eSYann Gautier 	2600,
41723684d0eSYann Gautier 	2700,
41823684d0eSYann Gautier 	2800,
41923684d0eSYann Gautier 	2900,
42023684d0eSYann Gautier 	3000,
42123684d0eSYann Gautier 	3100,
42223684d0eSYann Gautier 	3200,
42323684d0eSYann Gautier 	3300,
42423684d0eSYann Gautier };
42523684d0eSYann Gautier 
42623684d0eSYann Gautier static const uint16_t ldo4_voltage_table[] = {
42723684d0eSYann Gautier 	3300,
42823684d0eSYann Gautier };
42923684d0eSYann Gautier 
43023684d0eSYann Gautier static const uint16_t vref_ddr_voltage_table[] = {
43123684d0eSYann Gautier 	3300,
43223684d0eSYann Gautier };
43323684d0eSYann Gautier 
43413fbfe04SEtienne Carriere static const uint16_t fixed_5v_voltage_table[] = {
43513fbfe04SEtienne Carriere 	5000,
43613fbfe04SEtienne Carriere };
43713fbfe04SEtienne Carriere 
43823684d0eSYann Gautier /* Table of Regulators in PMIC SoC */
43923684d0eSYann Gautier static const struct regul_struct regulators_table[] = {
44023684d0eSYann Gautier 	{
44123684d0eSYann Gautier 		.dt_node_name	= "buck1",
44223684d0eSYann Gautier 		.voltage_table	= buck1_voltage_table,
44323684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
44423684d0eSYann Gautier 		.control_reg	= BUCK1_CONTROL_REG,
44501619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
44623684d0eSYann Gautier 		.low_power_reg	= BUCK1_PWRCTRL_REG,
447077f6828SYann Gautier 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
448077f6828SYann Gautier 		.pull_down	= BUCK1_PULL_DOWN_SHIFT,
449077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
450077f6828SYann Gautier 		.mask_reset	= BUCK1_MASK_RESET,
451*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
452*ea552bf5SPascal Paillet 		.icc_mask	= BUCK1_ICC_SHIFT,
45323684d0eSYann Gautier 	},
45423684d0eSYann Gautier 	{
45523684d0eSYann Gautier 		.dt_node_name	= "buck2",
45623684d0eSYann Gautier 		.voltage_table	= buck2_voltage_table,
45723684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
45823684d0eSYann Gautier 		.control_reg	= BUCK2_CONTROL_REG,
45901619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
46023684d0eSYann Gautier 		.low_power_reg	= BUCK2_PWRCTRL_REG,
461077f6828SYann Gautier 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
462077f6828SYann Gautier 		.pull_down	= BUCK2_PULL_DOWN_SHIFT,
463077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
464077f6828SYann Gautier 		.mask_reset	= BUCK2_MASK_RESET,
465*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
466*ea552bf5SPascal Paillet 		.icc_mask	= BUCK2_ICC_SHIFT,
46723684d0eSYann Gautier 	},
46823684d0eSYann Gautier 	{
46923684d0eSYann Gautier 		.dt_node_name	= "buck3",
47023684d0eSYann Gautier 		.voltage_table	= buck3_voltage_table,
47123684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
47223684d0eSYann Gautier 		.control_reg	= BUCK3_CONTROL_REG,
47301619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
47423684d0eSYann Gautier 		.low_power_reg	= BUCK3_PWRCTRL_REG,
475077f6828SYann Gautier 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
476077f6828SYann Gautier 		.pull_down	= BUCK3_PULL_DOWN_SHIFT,
477077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
478077f6828SYann Gautier 		.mask_reset	= BUCK3_MASK_RESET,
479*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
480*ea552bf5SPascal Paillet 		.icc_mask	= BUCK3_ICC_SHIFT,
48123684d0eSYann Gautier 	},
48223684d0eSYann Gautier 	{
48323684d0eSYann Gautier 		.dt_node_name	= "buck4",
48423684d0eSYann Gautier 		.voltage_table	= buck4_voltage_table,
48523684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
48623684d0eSYann Gautier 		.control_reg	= BUCK4_CONTROL_REG,
48701619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
48823684d0eSYann Gautier 		.low_power_reg	= BUCK4_PWRCTRL_REG,
489077f6828SYann Gautier 		.pull_down_reg	= BUCK_PULL_DOWN_REG,
490077f6828SYann Gautier 		.pull_down	= BUCK4_PULL_DOWN_SHIFT,
491077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_BUCK_REG,
492077f6828SYann Gautier 		.mask_reset	= BUCK4_MASK_RESET,
493*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
494*ea552bf5SPascal Paillet 		.icc_mask	= BUCK4_ICC_SHIFT,
49523684d0eSYann Gautier 	},
49623684d0eSYann Gautier 	{
49723684d0eSYann Gautier 		.dt_node_name	= "ldo1",
49823684d0eSYann Gautier 		.voltage_table	= ldo1_voltage_table,
49923684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
50023684d0eSYann Gautier 		.control_reg	= LDO1_CONTROL_REG,
50101619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
50223684d0eSYann Gautier 		.low_power_reg	= LDO1_PWRCTRL_REG,
503077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
504077f6828SYann Gautier 		.mask_reset	= LDO1_MASK_RESET,
505*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
506*ea552bf5SPascal Paillet 		.icc_mask	= LDO1_ICC_SHIFT,
50723684d0eSYann Gautier 	},
50823684d0eSYann Gautier 	{
50923684d0eSYann Gautier 		.dt_node_name	= "ldo2",
51023684d0eSYann Gautier 		.voltage_table	= ldo2_voltage_table,
51123684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
51223684d0eSYann Gautier 		.control_reg	= LDO2_CONTROL_REG,
51301619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
51423684d0eSYann Gautier 		.low_power_reg	= LDO2_PWRCTRL_REG,
515077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
516077f6828SYann Gautier 		.mask_reset	= LDO2_MASK_RESET,
517*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
518*ea552bf5SPascal Paillet 		.icc_mask	= LDO2_ICC_SHIFT,
51923684d0eSYann Gautier 	},
52023684d0eSYann Gautier 	{
52123684d0eSYann Gautier 		.dt_node_name	= "ldo3",
52223684d0eSYann Gautier 		.voltage_table	= ldo3_voltage_table,
52323684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
52423684d0eSYann Gautier 		.control_reg	= LDO3_CONTROL_REG,
52501619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
52623684d0eSYann Gautier 		.low_power_reg	= LDO3_PWRCTRL_REG,
527077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
528077f6828SYann Gautier 		.mask_reset	= LDO3_MASK_RESET,
529*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
530*ea552bf5SPascal Paillet 		.icc_mask	= LDO3_ICC_SHIFT,
53123684d0eSYann Gautier 	},
53223684d0eSYann Gautier 	{
53323684d0eSYann Gautier 		.dt_node_name	= "ldo4",
53423684d0eSYann Gautier 		.voltage_table	= ldo4_voltage_table,
53523684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
53623684d0eSYann Gautier 		.control_reg	= LDO4_CONTROL_REG,
53701619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
53823684d0eSYann Gautier 		.low_power_reg	= LDO4_PWRCTRL_REG,
539077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
540077f6828SYann Gautier 		.mask_reset	= LDO4_MASK_RESET,
541*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
542*ea552bf5SPascal Paillet 		.icc_mask	= LDO4_ICC_SHIFT,
54323684d0eSYann Gautier 	},
54423684d0eSYann Gautier 	{
54523684d0eSYann Gautier 		.dt_node_name	= "ldo5",
54623684d0eSYann Gautier 		.voltage_table	= ldo5_voltage_table,
54723684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
54823684d0eSYann Gautier 		.control_reg	= LDO5_CONTROL_REG,
54901619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
55023684d0eSYann Gautier 		.low_power_reg	= LDO5_PWRCTRL_REG,
551077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
552077f6828SYann Gautier 		.mask_reset	= LDO5_MASK_RESET,
553*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
554*ea552bf5SPascal Paillet 		.icc_mask	= LDO5_ICC_SHIFT,
55523684d0eSYann Gautier 	},
55623684d0eSYann Gautier 	{
55723684d0eSYann Gautier 		.dt_node_name	= "ldo6",
55823684d0eSYann Gautier 		.voltage_table	= ldo6_voltage_table,
55923684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
56023684d0eSYann Gautier 		.control_reg	= LDO6_CONTROL_REG,
56101619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
56223684d0eSYann Gautier 		.low_power_reg	= LDO6_PWRCTRL_REG,
563077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
564077f6828SYann Gautier 		.mask_reset	= LDO6_MASK_RESET,
565*ea552bf5SPascal Paillet 		.icc_reg	= LDO_ICC_TURNOFF_REG,
566*ea552bf5SPascal Paillet 		.icc_mask	= LDO6_ICC_SHIFT,
56723684d0eSYann Gautier 	},
56823684d0eSYann Gautier 	{
56923684d0eSYann Gautier 		.dt_node_name	= "vref_ddr",
57023684d0eSYann Gautier 		.voltage_table	= vref_ddr_voltage_table,
57123684d0eSYann Gautier 		.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
57223684d0eSYann Gautier 		.control_reg	= VREF_DDR_CONTROL_REG,
57301619911SPascal Paillet 		.enable_mask	= LDO_BUCK_ENABLE_MASK,
57423684d0eSYann Gautier 		.low_power_reg	= VREF_DDR_PWRCTRL_REG,
575077f6828SYann Gautier 		.mask_reset_reg	= MASK_RESET_LDO_REG,
576077f6828SYann Gautier 		.mask_reset	= VREF_DDR_MASK_RESET,
57723684d0eSYann Gautier 	},
57813fbfe04SEtienne Carriere 	{
57913fbfe04SEtienne Carriere 		.dt_node_name	= "boost",
58013fbfe04SEtienne Carriere 		.voltage_table	= fixed_5v_voltage_table,
58113fbfe04SEtienne Carriere 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
58213fbfe04SEtienne Carriere 		.control_reg	= USB_CONTROL_REG,
58313fbfe04SEtienne Carriere 		.enable_mask	= BOOST_ENABLED,
584*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
585*ea552bf5SPascal Paillet 		.icc_mask	= BOOST_ICC_SHIFT,
58613fbfe04SEtienne Carriere 	},
58713fbfe04SEtienne Carriere 	{
58813fbfe04SEtienne Carriere 		.dt_node_name	= "pwr_sw1",
58913fbfe04SEtienne Carriere 		.voltage_table	= fixed_5v_voltage_table,
59013fbfe04SEtienne Carriere 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
59113fbfe04SEtienne Carriere 		.control_reg	= USB_CONTROL_REG,
59213fbfe04SEtienne Carriere 		.enable_mask	= USBSW_OTG_SWITCH_ENABLED,
593*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
594*ea552bf5SPascal Paillet 		.icc_mask	= PWR_SW1_ICC_SHIFT,
59513fbfe04SEtienne Carriere 	},
59613fbfe04SEtienne Carriere 	{
59713fbfe04SEtienne Carriere 		.dt_node_name	= "pwr_sw2",
59813fbfe04SEtienne Carriere 		.voltage_table	= fixed_5v_voltage_table,
59913fbfe04SEtienne Carriere 		.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
60013fbfe04SEtienne Carriere 		.control_reg	= USB_CONTROL_REG,
60113fbfe04SEtienne Carriere 		.enable_mask	= SWIN_SWOUT_ENABLED,
602*ea552bf5SPascal Paillet 		.icc_reg	= BUCK_ICC_TURNOFF_REG,
603*ea552bf5SPascal Paillet 		.icc_mask	= PWR_SW2_ICC_SHIFT,
60413fbfe04SEtienne Carriere 	},
60523684d0eSYann Gautier };
60623684d0eSYann Gautier 
60723684d0eSYann Gautier #define MAX_REGUL	ARRAY_SIZE(regulators_table)
60823684d0eSYann Gautier 
get_regulator_data(const char * name)60923684d0eSYann Gautier static const struct regul_struct *get_regulator_data(const char *name)
61023684d0eSYann Gautier {
61123684d0eSYann Gautier 	uint8_t i;
61223684d0eSYann Gautier 
61323684d0eSYann Gautier 	for (i = 0 ; i < MAX_REGUL ; i++) {
61423684d0eSYann Gautier 		if (strncmp(name, regulators_table[i].dt_node_name,
61523684d0eSYann Gautier 			    strlen(regulators_table[i].dt_node_name)) == 0) {
61623684d0eSYann Gautier 			return &regulators_table[i];
61723684d0eSYann Gautier 		}
61823684d0eSYann Gautier 	}
61923684d0eSYann Gautier 
62023684d0eSYann Gautier 	/* Regulator not found */
62123684d0eSYann Gautier 	panic();
62223684d0eSYann Gautier 	return NULL;
62323684d0eSYann Gautier }
62423684d0eSYann Gautier 
voltage_to_index(const char * name,uint16_t millivolts)62523684d0eSYann Gautier static uint8_t voltage_to_index(const char *name, uint16_t millivolts)
62623684d0eSYann Gautier {
62723684d0eSYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
62823684d0eSYann Gautier 	uint8_t i;
62923684d0eSYann Gautier 
63023684d0eSYann Gautier 	for (i = 0 ; i < regul->voltage_table_size ; i++) {
63123684d0eSYann Gautier 		if (regul->voltage_table[i] == millivolts) {
63223684d0eSYann Gautier 			return i;
63323684d0eSYann Gautier 		}
63423684d0eSYann Gautier 	}
63523684d0eSYann Gautier 
63623684d0eSYann Gautier 	/* Voltage not found */
63723684d0eSYann Gautier 	panic();
63823684d0eSYann Gautier 
63923684d0eSYann Gautier 	return 0;
64023684d0eSYann Gautier }
64123684d0eSYann Gautier 
stpmic1_powerctrl_on(void)642077f6828SYann Gautier int stpmic1_powerctrl_on(void)
643077f6828SYann Gautier {
644077f6828SYann Gautier 	return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID,
645077f6828SYann Gautier 				       PWRCTRL_PIN_VALID);
646077f6828SYann Gautier }
647077f6828SYann Gautier 
stpmic1_switch_off(void)64823684d0eSYann Gautier int stpmic1_switch_off(void)
64923684d0eSYann Gautier {
65023684d0eSYann Gautier 	return stpmic1_register_update(MAIN_CONTROL_REG, 1,
65123684d0eSYann Gautier 				       SOFTWARE_SWITCH_OFF_ENABLED);
65223684d0eSYann Gautier }
65323684d0eSYann Gautier 
stpmic1_regulator_enable(const char * name)65423684d0eSYann Gautier int stpmic1_regulator_enable(const char *name)
65523684d0eSYann Gautier {
65623684d0eSYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
65723684d0eSYann Gautier 
65801619911SPascal Paillet 	return stpmic1_register_update(regul->control_reg, regul->enable_mask,
65901619911SPascal Paillet 				       regul->enable_mask);
66023684d0eSYann Gautier }
66123684d0eSYann Gautier 
stpmic1_regulator_disable(const char * name)66223684d0eSYann Gautier int stpmic1_regulator_disable(const char *name)
66323684d0eSYann Gautier {
66423684d0eSYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
66523684d0eSYann Gautier 
66601619911SPascal Paillet 	return stpmic1_register_update(regul->control_reg, 0,
66701619911SPascal Paillet 				       regul->enable_mask);
66823684d0eSYann Gautier }
66923684d0eSYann Gautier 
stpmic1_is_regulator_enabled(const char * name)67016e56a75SNicolas Le Bayon bool stpmic1_is_regulator_enabled(const char *name)
67123684d0eSYann Gautier {
67223684d0eSYann Gautier 	uint8_t val;
67323684d0eSYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
67423684d0eSYann Gautier 
67523684d0eSYann Gautier 	if (stpmic1_register_read(regul->control_reg, &val) != 0) {
67623684d0eSYann Gautier 		panic();
67723684d0eSYann Gautier 	}
67823684d0eSYann Gautier 
67916e56a75SNicolas Le Bayon 	return (val & regul->enable_mask) == regul->enable_mask;
68023684d0eSYann Gautier }
68123684d0eSYann Gautier 
stpmic1_regulator_voltage_set(const char * name,uint16_t millivolts)68223684d0eSYann Gautier int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
68323684d0eSYann Gautier {
68423684d0eSYann Gautier 	uint8_t voltage_index = voltage_to_index(name, millivolts);
68523684d0eSYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
686077f6828SYann Gautier 	uint8_t mask;
68723684d0eSYann Gautier 
688*ea552bf5SPascal Paillet 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
689*ea552bf5SPascal Paillet 		/*
690*ea552bf5SPascal Paillet 		 * when the LDO3 is in special mode, we do not change voltage,
691*ea552bf5SPascal Paillet 		 * because by setting voltage, the LDO would leaves sink-source
692*ea552bf5SPascal Paillet 		 * mode. There is obviously no reason to leave sink-source mode
693*ea552bf5SPascal Paillet 		 * at runtime.
694*ea552bf5SPascal Paillet 		 */
695*ea552bf5SPascal Paillet 		return 0;
696*ea552bf5SPascal Paillet 	}
697*ea552bf5SPascal Paillet 
698077f6828SYann Gautier 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
699077f6828SYann Gautier 	if (strncmp(name, "buck", 4) == 0) {
700077f6828SYann Gautier 		mask = BUCK_VOLTAGE_MASK;
701077f6828SYann Gautier 	} else if ((strncmp(name, "ldo", 3) == 0) &&
702*ea552bf5SPascal Paillet 		   (strncmp(name, "ldo4", 5) != 0)) {
703077f6828SYann Gautier 		mask = LDO_VOLTAGE_MASK;
704077f6828SYann Gautier 	} else {
705077f6828SYann Gautier 		return 0;
706077f6828SYann Gautier 	}
707077f6828SYann Gautier 
708077f6828SYann Gautier 	return stpmic1_register_update(regul->control_reg,
709077f6828SYann Gautier 				       voltage_index << LDO_BUCK_VOLTAGE_SHIFT,
710077f6828SYann Gautier 				       mask);
711077f6828SYann Gautier }
712077f6828SYann Gautier 
stpmic1_regulator_pull_down_set(const char * name)713077f6828SYann Gautier int stpmic1_regulator_pull_down_set(const char *name)
714077f6828SYann Gautier {
715077f6828SYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
716077f6828SYann Gautier 
717077f6828SYann Gautier 	if (regul->pull_down_reg != 0) {
718077f6828SYann Gautier 		return stpmic1_register_update(regul->pull_down_reg,
719077f6828SYann Gautier 					       BIT(regul->pull_down),
720077f6828SYann Gautier 					       LDO_BUCK_PULL_DOWN_MASK <<
721077f6828SYann Gautier 					       regul->pull_down);
722077f6828SYann Gautier 	}
723077f6828SYann Gautier 
724077f6828SYann Gautier 	return 0;
725077f6828SYann Gautier }
726077f6828SYann Gautier 
stpmic1_regulator_mask_reset_set(const char * name)727077f6828SYann Gautier int stpmic1_regulator_mask_reset_set(const char *name)
728077f6828SYann Gautier {
729077f6828SYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
730077f6828SYann Gautier 
731*ea552bf5SPascal Paillet 	if (regul->mask_reset_reg == 0U) {
732*ea552bf5SPascal Paillet 		return -EPERM;
733*ea552bf5SPascal Paillet 	}
734*ea552bf5SPascal Paillet 
735077f6828SYann Gautier 	return stpmic1_register_update(regul->mask_reset_reg,
736077f6828SYann Gautier 				       BIT(regul->mask_reset),
737077f6828SYann Gautier 				       LDO_BUCK_RESET_MASK <<
738077f6828SYann Gautier 				       regul->mask_reset);
739077f6828SYann Gautier }
740077f6828SYann Gautier 
stpmic1_regulator_icc_set(const char * name)741*ea552bf5SPascal Paillet int stpmic1_regulator_icc_set(const char *name)
742*ea552bf5SPascal Paillet {
743*ea552bf5SPascal Paillet 	const struct regul_struct *regul = get_regulator_data(name);
744*ea552bf5SPascal Paillet 
745*ea552bf5SPascal Paillet 	if (regul->mask_reset_reg == 0U) {
746*ea552bf5SPascal Paillet 		return -EPERM;
747*ea552bf5SPascal Paillet 	}
748*ea552bf5SPascal Paillet 
749*ea552bf5SPascal Paillet 	return stpmic1_register_update(regul->icc_reg,
750*ea552bf5SPascal Paillet 				       BIT(regul->icc_mask),
751*ea552bf5SPascal Paillet 				       BIT(regul->icc_mask));
752*ea552bf5SPascal Paillet }
753*ea552bf5SPascal Paillet 
stpmic1_regulator_sink_mode_set(const char * name)754*ea552bf5SPascal Paillet int stpmic1_regulator_sink_mode_set(const char *name)
755*ea552bf5SPascal Paillet {
756*ea552bf5SPascal Paillet 	if (strncmp(name, "ldo3", 5) != 0) {
757*ea552bf5SPascal Paillet 		return -EPERM;
758*ea552bf5SPascal Paillet 	}
759*ea552bf5SPascal Paillet 
760*ea552bf5SPascal Paillet 	ldo3_special_mode = true;
761*ea552bf5SPascal Paillet 
762*ea552bf5SPascal Paillet 	/* disable bypass mode, enable sink mode */
763*ea552bf5SPascal Paillet 	return stpmic1_register_update(LDO3_CONTROL_REG,
764*ea552bf5SPascal Paillet 				       LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT,
765*ea552bf5SPascal Paillet 				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
766*ea552bf5SPascal Paillet }
767*ea552bf5SPascal Paillet 
stpmic1_regulator_bypass_mode_set(const char * name)768*ea552bf5SPascal Paillet int stpmic1_regulator_bypass_mode_set(const char *name)
769*ea552bf5SPascal Paillet {
770*ea552bf5SPascal Paillet 	if (strncmp(name, "ldo3", 5) != 0) {
771*ea552bf5SPascal Paillet 		return -EPERM;
772*ea552bf5SPascal Paillet 	}
773*ea552bf5SPascal Paillet 
774*ea552bf5SPascal Paillet 	ldo3_special_mode = true;
775*ea552bf5SPascal Paillet 
776*ea552bf5SPascal Paillet 	/* enable bypass mode, disable sink mode */
777*ea552bf5SPascal Paillet 	return stpmic1_register_update(LDO3_CONTROL_REG,
778*ea552bf5SPascal Paillet 				       LDO3_BYPASS,
779*ea552bf5SPascal Paillet 				       LDO3_BYPASS | LDO_VOLTAGE_MASK);
780*ea552bf5SPascal Paillet }
781*ea552bf5SPascal Paillet 
stpmic1_active_discharge_mode_set(const char * name)782*ea552bf5SPascal Paillet int stpmic1_active_discharge_mode_set(const char *name)
783*ea552bf5SPascal Paillet {
784*ea552bf5SPascal Paillet 	if (strncmp(name, "pwr_sw1", 8) == 0) {
785*ea552bf5SPascal Paillet 		return stpmic1_register_update(USB_CONTROL_REG,
786*ea552bf5SPascal Paillet 					       VBUS_OTG_DISCHARGE,
787*ea552bf5SPascal Paillet 					       VBUS_OTG_DISCHARGE);
788*ea552bf5SPascal Paillet 	}
789*ea552bf5SPascal Paillet 
790*ea552bf5SPascal Paillet 	if (strncmp(name, "pwr_sw2", 8) == 0) {
791*ea552bf5SPascal Paillet 		return stpmic1_register_update(USB_CONTROL_REG,
792*ea552bf5SPascal Paillet 					       SW_OUT_DISCHARGE,
793*ea552bf5SPascal Paillet 					       SW_OUT_DISCHARGE);
794*ea552bf5SPascal Paillet 	}
795*ea552bf5SPascal Paillet 
796*ea552bf5SPascal Paillet 	return -EPERM;
797*ea552bf5SPascal Paillet }
798*ea552bf5SPascal Paillet 
stpmic1_regulator_levels_mv(const char * name,const uint16_t ** levels,size_t * levels_count)799*ea552bf5SPascal Paillet int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels,
800*ea552bf5SPascal Paillet 				size_t *levels_count)
801*ea552bf5SPascal Paillet {
802*ea552bf5SPascal Paillet 	const struct regul_struct *regul = get_regulator_data(name);
803*ea552bf5SPascal Paillet 
804*ea552bf5SPascal Paillet 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
805*ea552bf5SPascal Paillet 		*levels_count = ARRAY_SIZE(ldo3_special_mode_table);
806*ea552bf5SPascal Paillet 		*levels = ldo3_special_mode_table;
807*ea552bf5SPascal Paillet 	} else {
808*ea552bf5SPascal Paillet 		*levels_count = regul->voltage_table_size;
809*ea552bf5SPascal Paillet 		*levels = regul->voltage_table;
810*ea552bf5SPascal Paillet 	}
811*ea552bf5SPascal Paillet 
812*ea552bf5SPascal Paillet 	return 0;
813*ea552bf5SPascal Paillet }
814*ea552bf5SPascal Paillet 
stpmic1_regulator_voltage_get(const char * name)815077f6828SYann Gautier int stpmic1_regulator_voltage_get(const char *name)
816077f6828SYann Gautier {
817077f6828SYann Gautier 	const struct regul_struct *regul = get_regulator_data(name);
818077f6828SYann Gautier 	uint8_t value;
819077f6828SYann Gautier 	uint8_t mask;
820ed6a8523SYann Gautier 	int status;
821077f6828SYann Gautier 
822*ea552bf5SPascal Paillet 	if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) {
823*ea552bf5SPascal Paillet 		return 0;
824*ea552bf5SPascal Paillet 	}
825*ea552bf5SPascal Paillet 
826077f6828SYann Gautier 	/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
827077f6828SYann Gautier 	if (strncmp(name, "buck", 4) == 0) {
828077f6828SYann Gautier 		mask = BUCK_VOLTAGE_MASK;
829077f6828SYann Gautier 	} else if ((strncmp(name, "ldo", 3) == 0) &&
830*ea552bf5SPascal Paillet 		   (strncmp(name, "ldo4", 5) != 0)) {
831077f6828SYann Gautier 		mask = LDO_VOLTAGE_MASK;
832077f6828SYann Gautier 	} else {
833077f6828SYann Gautier 		return 0;
834077f6828SYann Gautier 	}
835077f6828SYann Gautier 
836ed6a8523SYann Gautier 	status = stpmic1_register_read(regul->control_reg, &value);
837ed6a8523SYann Gautier 	if (status < 0) {
838ed6a8523SYann Gautier 		return status;
839ed6a8523SYann Gautier 	}
840077f6828SYann Gautier 
841077f6828SYann Gautier 	value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT;
842077f6828SYann Gautier 
843ed6a8523SYann Gautier 	if (value > regul->voltage_table_size) {
844ed6a8523SYann Gautier 		return -ERANGE;
845ed6a8523SYann Gautier 	}
846077f6828SYann Gautier 
847077f6828SYann Gautier 	return (int)regul->voltage_table[value];
84823684d0eSYann Gautier }
84923684d0eSYann Gautier 
stpmic1_register_read(uint8_t register_id,uint8_t * value)85023684d0eSYann Gautier int stpmic1_register_read(uint8_t register_id,  uint8_t *value)
85123684d0eSYann Gautier {
85223684d0eSYann Gautier 	return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr,
853d82d4ff0SYann Gautier 				  (uint16_t)register_id,
854d82d4ff0SYann Gautier 				  I2C_MEMADD_SIZE_8BIT, value,
855d82d4ff0SYann Gautier 				  1, I2C_TIMEOUT_MS);
85623684d0eSYann Gautier }
85723684d0eSYann Gautier 
stpmic1_register_write(uint8_t register_id,uint8_t value)85823684d0eSYann Gautier int stpmic1_register_write(uint8_t register_id, uint8_t value)
85923684d0eSYann Gautier {
86023684d0eSYann Gautier 	int status;
86123684d0eSYann Gautier 
86223684d0eSYann Gautier 	status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr,
86323684d0eSYann Gautier 				     (uint16_t)register_id,
864d82d4ff0SYann Gautier 				     I2C_MEMADD_SIZE_8BIT, &value,
865d82d4ff0SYann Gautier 				     1, I2C_TIMEOUT_MS);
86623684d0eSYann Gautier 
867077f6828SYann Gautier #if ENABLE_ASSERTIONS
86823684d0eSYann Gautier 	if (status != 0) {
86923684d0eSYann Gautier 		return status;
87023684d0eSYann Gautier 	}
87123684d0eSYann Gautier 
87223684d0eSYann Gautier 	if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
87323684d0eSYann Gautier 		uint8_t readval;
87423684d0eSYann Gautier 
87523684d0eSYann Gautier 		status = stpmic1_register_read(register_id, &readval);
87623684d0eSYann Gautier 		if (status != 0) {
87723684d0eSYann Gautier 			return status;
87823684d0eSYann Gautier 		}
87923684d0eSYann Gautier 
88023684d0eSYann Gautier 		if (readval != value) {
881ed6a8523SYann Gautier 			return -EIO;
88223684d0eSYann Gautier 		}
88323684d0eSYann Gautier 	}
884077f6828SYann Gautier #endif
88523684d0eSYann Gautier 
886077f6828SYann Gautier 	return status;
88723684d0eSYann Gautier }
88823684d0eSYann Gautier 
stpmic1_register_update(uint8_t register_id,uint8_t value,uint8_t mask)88923684d0eSYann Gautier int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
89023684d0eSYann Gautier {
89123684d0eSYann Gautier 	int status;
89223684d0eSYann Gautier 	uint8_t val;
89323684d0eSYann Gautier 
89423684d0eSYann Gautier 	status = stpmic1_register_read(register_id, &val);
89523684d0eSYann Gautier 	if (status != 0) {
89623684d0eSYann Gautier 		return status;
89723684d0eSYann Gautier 	}
89823684d0eSYann Gautier 
899077f6828SYann Gautier 	val = (val & ~mask) | (value & mask);
90023684d0eSYann Gautier 
90123684d0eSYann Gautier 	return stpmic1_register_write(register_id, val);
90223684d0eSYann Gautier }
90323684d0eSYann Gautier 
stpmic1_bind_i2c(struct i2c_handle_s * i2c_handle,uint16_t i2c_addr)90423684d0eSYann Gautier void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
90523684d0eSYann Gautier {
90623684d0eSYann Gautier 	pmic_i2c_handle = i2c_handle;
90723684d0eSYann Gautier 	pmic_i2c_addr = i2c_addr;
90823684d0eSYann Gautier }
909077f6828SYann Gautier 
stpmic1_dump_regulators(void)910077f6828SYann Gautier void stpmic1_dump_regulators(void)
911077f6828SYann Gautier {
912077f6828SYann Gautier 	uint32_t i;
913077f6828SYann Gautier 
914077f6828SYann Gautier 	for (i = 0U; i < MAX_REGUL; i++) {
915077f6828SYann Gautier 		const char *name __unused = regulators_table[i].dt_node_name;
916077f6828SYann Gautier 
917077f6828SYann Gautier 		VERBOSE("PMIC regul %s: %sable, %dmV",
918077f6828SYann Gautier 			name,
919077f6828SYann Gautier 			stpmic1_is_regulator_enabled(name) ? "en" : "dis",
920077f6828SYann Gautier 			stpmic1_regulator_voltage_get(name));
921077f6828SYann Gautier 	}
922077f6828SYann Gautier }
923077f6828SYann Gautier 
stpmic1_get_version(unsigned long * version)924077f6828SYann Gautier int stpmic1_get_version(unsigned long *version)
925077f6828SYann Gautier {
926077f6828SYann Gautier 	uint8_t read_val;
927ed6a8523SYann Gautier 	int status;
928077f6828SYann Gautier 
929ed6a8523SYann Gautier 	status = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
930ed6a8523SYann Gautier 	if (status < 0) {
931ed6a8523SYann Gautier 		return status;
932077f6828SYann Gautier 	}
933077f6828SYann Gautier 
934077f6828SYann Gautier 	*version = (unsigned long)read_val;
935077f6828SYann Gautier 
936077f6828SYann Gautier 	return 0;
937077f6828SYann Gautier }
938