xref: /rk3399_ARM-atf/drivers/st/pmic/stm32mp_pmic.c (revision 85fb175b5ef854bc4607db98a4cfb5f35d822cee)
123684d0eSYann Gautier /*
242822844SBenjamin Gaignard  * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
323684d0eSYann Gautier  *
423684d0eSYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
523684d0eSYann Gautier  */
623684d0eSYann Gautier 
7*85fb175bSYann Gautier #include <assert.h>
823684d0eSYann Gautier #include <errno.h>
923684d0eSYann Gautier 
1023684d0eSYann Gautier #include <common/debug.h>
1123684d0eSYann Gautier #include <drivers/delay_timer.h>
12*85fb175bSYann Gautier #include <drivers/st/regulator.h>
13d82d4ff0SYann Gautier #include <drivers/st/stm32_i2c.h>
1423684d0eSYann Gautier #include <drivers/st/stm32mp_pmic.h>
1523684d0eSYann Gautier #include <drivers/st/stpmic1.h>
1623684d0eSYann Gautier #include <lib/mmio.h>
1723684d0eSYann Gautier #include <lib/utils_def.h>
1816e56a75SNicolas Le Bayon #include <libfdt.h>
1916e56a75SNicolas Le Bayon 
2016e56a75SNicolas Le Bayon #include <platform_def.h>
2123684d0eSYann Gautier 
22c77c7d9eSNicolas Le Bayon #define PMIC_NODE_NOT_FOUND	1
2323684d0eSYann Gautier #define STPMIC1_LDO12356_OUTPUT_MASK	(uint8_t)(GENMASK(6, 2))
2423684d0eSYann Gautier #define STPMIC1_LDO12356_OUTPUT_SHIFT	2
2523684d0eSYann Gautier #define STPMIC1_LDO3_MODE		(uint8_t)(BIT(7))
2623684d0eSYann Gautier #define STPMIC1_LDO3_DDR_SEL		31U
2723684d0eSYann Gautier #define STPMIC1_LDO3_1800000		(9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
2823684d0eSYann Gautier 
2923684d0eSYann Gautier #define STPMIC1_BUCK_OUTPUT_SHIFT	2
3023684d0eSYann Gautier #define STPMIC1_BUCK3_1V8		(39U << STPMIC1_BUCK_OUTPUT_SHIFT)
3123684d0eSYann Gautier 
3223684d0eSYann Gautier #define STPMIC1_DEFAULT_START_UP_DELAY_MS	1
3323684d0eSYann Gautier 
3423684d0eSYann Gautier static struct i2c_handle_s i2c_handle;
3523684d0eSYann Gautier static uint32_t pmic_i2c_addr;
3623684d0eSYann Gautier 
37*85fb175bSYann Gautier static int register_pmic(void);
38*85fb175bSYann Gautier 
3923684d0eSYann Gautier static int dt_get_pmic_node(void *fdt)
4023684d0eSYann Gautier {
41c77c7d9eSNicolas Le Bayon 	static int node = -FDT_ERR_BADOFFSET;
42c77c7d9eSNicolas Le Bayon 
43c77c7d9eSNicolas Le Bayon 	if (node == -FDT_ERR_BADOFFSET) {
44c77c7d9eSNicolas Le Bayon 		node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
45c77c7d9eSNicolas Le Bayon 	}
46c77c7d9eSNicolas Le Bayon 
47c77c7d9eSNicolas Le Bayon 	return node;
4823684d0eSYann Gautier }
4923684d0eSYann Gautier 
50d82d4ff0SYann Gautier int dt_pmic_status(void)
5123684d0eSYann Gautier {
52c77c7d9eSNicolas Le Bayon 	static int status = -FDT_ERR_BADVALUE;
5323684d0eSYann Gautier 	int node;
5423684d0eSYann Gautier 	void *fdt;
5523684d0eSYann Gautier 
56c77c7d9eSNicolas Le Bayon 	if (status != -FDT_ERR_BADVALUE) {
57c77c7d9eSNicolas Le Bayon 		return status;
58c77c7d9eSNicolas Le Bayon 	}
59c77c7d9eSNicolas Le Bayon 
6023684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
61d82d4ff0SYann Gautier 		return -ENOENT;
6223684d0eSYann Gautier 	}
6323684d0eSYann Gautier 
6423684d0eSYann Gautier 	node = dt_get_pmic_node(fdt);
65d82d4ff0SYann Gautier 	if (node <= 0) {
66c77c7d9eSNicolas Le Bayon 		status = -FDT_ERR_NOTFOUND;
67c77c7d9eSNicolas Le Bayon 
68c77c7d9eSNicolas Le Bayon 		return status;
6923684d0eSYann Gautier 	}
7023684d0eSYann Gautier 
71c77c7d9eSNicolas Le Bayon 	status = (int)fdt_get_status(node);
72c77c7d9eSNicolas Le Bayon 
73c77c7d9eSNicolas Le Bayon 	return status;
7423684d0eSYann Gautier }
7523684d0eSYann Gautier 
76f564d439SEtienne Carriere static bool dt_pmic_is_secure(void)
77f564d439SEtienne Carriere {
78f564d439SEtienne Carriere 	int status = dt_pmic_status();
79f564d439SEtienne Carriere 
80f564d439SEtienne Carriere 	return (status >= 0) &&
81f564d439SEtienne Carriere 	       (status == DT_SECURE) &&
82f564d439SEtienne Carriere 	       (i2c_handle.dt_status == DT_SECURE);
83f564d439SEtienne Carriere }
84f564d439SEtienne Carriere 
85d82d4ff0SYann Gautier /*
86d82d4ff0SYann Gautier  * Get PMIC and its I2C bus configuration from the device tree.
87c77c7d9eSNicolas Le Bayon  * Return 0 on success, negative on error, 1 if no PMIC node is defined.
88d82d4ff0SYann Gautier  */
89d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
90d82d4ff0SYann Gautier 			      struct stm32_i2c_init_s *init)
9123684d0eSYann Gautier {
92c77c7d9eSNicolas Le Bayon 	static int i2c_node = -FDT_ERR_NOTFOUND;
9323684d0eSYann Gautier 	void *fdt;
9423684d0eSYann Gautier 
9523684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
96c77c7d9eSNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
9723684d0eSYann Gautier 	}
9823684d0eSYann Gautier 
99c77c7d9eSNicolas Le Bayon 	if (i2c_node == -FDT_ERR_NOTFOUND) {
100c77c7d9eSNicolas Le Bayon 		int pmic_node;
101c77c7d9eSNicolas Le Bayon 		const fdt32_t *cuint;
102c77c7d9eSNicolas Le Bayon 
10323684d0eSYann Gautier 		pmic_node = dt_get_pmic_node(fdt);
10423684d0eSYann Gautier 		if (pmic_node < 0) {
105c77c7d9eSNicolas Le Bayon 			return PMIC_NODE_NOT_FOUND;
10623684d0eSYann Gautier 		}
10723684d0eSYann Gautier 
10823684d0eSYann Gautier 		cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
10923684d0eSYann Gautier 		if (cuint == NULL) {
11023684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
11123684d0eSYann Gautier 		}
11223684d0eSYann Gautier 
11323684d0eSYann Gautier 		pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
11423684d0eSYann Gautier 		if (pmic_i2c_addr > UINT16_MAX) {
115c77c7d9eSNicolas Le Bayon 			return -FDT_ERR_BADVALUE;
11623684d0eSYann Gautier 		}
11723684d0eSYann Gautier 
11823684d0eSYann Gautier 		i2c_node = fdt_parent_offset(fdt, pmic_node);
11923684d0eSYann Gautier 		if (i2c_node < 0) {
12023684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
12123684d0eSYann Gautier 		}
122c77c7d9eSNicolas Le Bayon 	}
12323684d0eSYann Gautier 
12423684d0eSYann Gautier 	dt_fill_device_info(i2c_info, i2c_node);
12523684d0eSYann Gautier 	if (i2c_info->base == 0U) {
12623684d0eSYann Gautier 		return -FDT_ERR_NOTFOUND;
12723684d0eSYann Gautier 	}
12823684d0eSYann Gautier 
129d82d4ff0SYann Gautier 	return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
13023684d0eSYann Gautier }
13123684d0eSYann Gautier 
132d82d4ff0SYann Gautier bool initialize_pmic_i2c(void)
13323684d0eSYann Gautier {
13423684d0eSYann Gautier 	int ret;
13523684d0eSYann Gautier 	struct dt_node_info i2c_info;
136d82d4ff0SYann Gautier 	struct i2c_handle_s *i2c = &i2c_handle;
137d82d4ff0SYann Gautier 	struct stm32_i2c_init_s i2c_init;
13823684d0eSYann Gautier 
139d82d4ff0SYann Gautier 	ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
140d82d4ff0SYann Gautier 	if (ret < 0) {
141d82d4ff0SYann Gautier 		ERROR("I2C configuration failed %d\n", ret);
14223684d0eSYann Gautier 		panic();
14323684d0eSYann Gautier 	}
14423684d0eSYann Gautier 
145d82d4ff0SYann Gautier 	if (ret != 0) {
146d82d4ff0SYann Gautier 		return false;
14723684d0eSYann Gautier 	}
14823684d0eSYann Gautier 
14923684d0eSYann Gautier 	/* Initialize PMIC I2C */
150d82d4ff0SYann Gautier 	i2c->i2c_base_addr		= i2c_info.base;
151d82d4ff0SYann Gautier 	i2c->dt_status			= i2c_info.status;
152d82d4ff0SYann Gautier 	i2c->clock			= i2c_info.clock;
15342822844SBenjamin Gaignard 	i2c->i2c_state			= I2C_STATE_RESET;
154d82d4ff0SYann Gautier 	i2c_init.own_address1		= pmic_i2c_addr;
155d82d4ff0SYann Gautier 	i2c_init.addressing_mode	= I2C_ADDRESSINGMODE_7BIT;
156d82d4ff0SYann Gautier 	i2c_init.dual_address_mode	= I2C_DUALADDRESS_DISABLE;
157d82d4ff0SYann Gautier 	i2c_init.own_address2		= 0;
158d82d4ff0SYann Gautier 	i2c_init.own_address2_masks	= I2C_OAR2_OA2NOMASK;
159d82d4ff0SYann Gautier 	i2c_init.general_call_mode	= I2C_GENERALCALL_DISABLE;
160d82d4ff0SYann Gautier 	i2c_init.no_stretch_mode	= I2C_NOSTRETCH_DISABLE;
161d82d4ff0SYann Gautier 	i2c_init.analog_filter		= 1;
162d82d4ff0SYann Gautier 	i2c_init.digital_filter_coef	= 0;
16323684d0eSYann Gautier 
164d82d4ff0SYann Gautier 	ret = stm32_i2c_init(i2c, &i2c_init);
16523684d0eSYann Gautier 	if (ret != 0) {
16623684d0eSYann Gautier 		ERROR("Cannot initialize I2C %x (%d)\n",
167d82d4ff0SYann Gautier 		      i2c->i2c_base_addr, ret);
16823684d0eSYann Gautier 		panic();
16923684d0eSYann Gautier 	}
17023684d0eSYann Gautier 
171d82d4ff0SYann Gautier 	if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
172d82d4ff0SYann Gautier 				       I2C_TIMEOUT_BUSY_MS)) {
173d82d4ff0SYann Gautier 		ERROR("I2C device not ready\n");
17423684d0eSYann Gautier 		panic();
17523684d0eSYann Gautier 	}
17623684d0eSYann Gautier 
177d82d4ff0SYann Gautier 	stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
17823684d0eSYann Gautier 
179d82d4ff0SYann Gautier 	return true;
18023684d0eSYann Gautier }
18123684d0eSYann Gautier 
182f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void)
183f564d439SEtienne Carriere {
184f564d439SEtienne Carriere 	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
185f564d439SEtienne Carriere 
186f564d439SEtienne Carriere 	if (dt_pmic_is_secure()) {
187f564d439SEtienne Carriere 		stm32mp_register_secure_periph_iomem(i2c_base);
188f564d439SEtienne Carriere 	} else {
189f564d439SEtienne Carriere 		if (i2c_base != 0U) {
190f564d439SEtienne Carriere 			stm32mp_register_non_secure_periph_iomem(i2c_base);
191f564d439SEtienne Carriere 		}
192f564d439SEtienne Carriere 	}
193f564d439SEtienne Carriere }
194f564d439SEtienne Carriere 
19523684d0eSYann Gautier void initialize_pmic(void)
19623684d0eSYann Gautier {
197d82d4ff0SYann Gautier 	if (!initialize_pmic_i2c()) {
198d82d4ff0SYann Gautier 		VERBOSE("No PMIC\n");
199d82d4ff0SYann Gautier 		return;
200d82d4ff0SYann Gautier 	}
20123684d0eSYann Gautier 
202f564d439SEtienne Carriere 	register_pmic_shared_peripherals();
203f564d439SEtienne Carriere 
204*85fb175bSYann Gautier 	if (register_pmic() < 0) {
205ae7792e0SNicolas Le Bayon 		panic();
206*85fb175bSYann Gautier 	}
207*85fb175bSYann Gautier 
208*85fb175bSYann Gautier 	if (stpmic1_powerctrl_on() < 0) {
209*85fb175bSYann Gautier 		panic();
210*85fb175bSYann Gautier 	}
211*85fb175bSYann Gautier 
212ae7792e0SNicolas Le Bayon }
213ae7792e0SNicolas Le Bayon 
214ae7792e0SNicolas Le Bayon #if DEBUG
215ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void)
216ae7792e0SNicolas Le Bayon {
217ae7792e0SNicolas Le Bayon 	unsigned long pmic_version;
218ae7792e0SNicolas Le Bayon 
219d82d4ff0SYann Gautier 	if (stpmic1_get_version(&pmic_version) != 0) {
220d82d4ff0SYann Gautier 		ERROR("Failed to access PMIC\n");
22123684d0eSYann Gautier 		panic();
22223684d0eSYann Gautier 	}
22323684d0eSYann Gautier 
224d82d4ff0SYann Gautier 	INFO("PMIC version = 0x%02lx\n", pmic_version);
22523684d0eSYann Gautier }
226ae7792e0SNicolas Le Bayon #endif
22723684d0eSYann Gautier 
22823684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type)
22923684d0eSYann Gautier {
23023684d0eSYann Gautier 	bool buck3_at_1v8 = false;
23123684d0eSYann Gautier 	uint8_t read_val;
23223684d0eSYann Gautier 	int status;
23323684d0eSYann Gautier 
23423684d0eSYann Gautier 	switch (ddr_type) {
23523684d0eSYann Gautier 	case STM32MP_DDR3:
23623684d0eSYann Gautier 		/* Set LDO3 to sync mode */
23723684d0eSYann Gautier 		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
23823684d0eSYann Gautier 		if (status != 0) {
23923684d0eSYann Gautier 			return status;
24023684d0eSYann Gautier 		}
24123684d0eSYann Gautier 
24223684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO3_MODE;
24323684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
24423684d0eSYann Gautier 		read_val |= STPMIC1_LDO3_DDR_SEL <<
24523684d0eSYann Gautier 			    STPMIC1_LDO12356_OUTPUT_SHIFT;
24623684d0eSYann Gautier 
24723684d0eSYann Gautier 		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
24823684d0eSYann Gautier 		if (status != 0) {
24923684d0eSYann Gautier 			return status;
25023684d0eSYann Gautier 		}
25123684d0eSYann Gautier 
25223684d0eSYann Gautier 		status = stpmic1_regulator_voltage_set("buck2", 1350);
25323684d0eSYann Gautier 		if (status != 0) {
25423684d0eSYann Gautier 			return status;
25523684d0eSYann Gautier 		}
25623684d0eSYann Gautier 
25723684d0eSYann Gautier 		status = stpmic1_regulator_enable("buck2");
25823684d0eSYann Gautier 		if (status != 0) {
25923684d0eSYann Gautier 			return status;
26023684d0eSYann Gautier 		}
26123684d0eSYann Gautier 
26223684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
26323684d0eSYann Gautier 
26423684d0eSYann Gautier 		status = stpmic1_regulator_enable("vref_ddr");
26523684d0eSYann Gautier 		if (status != 0) {
26623684d0eSYann Gautier 			return status;
26723684d0eSYann Gautier 		}
26823684d0eSYann Gautier 
26923684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
27023684d0eSYann Gautier 
27123684d0eSYann Gautier 		status = stpmic1_regulator_enable("ldo3");
27223684d0eSYann Gautier 		if (status != 0) {
27323684d0eSYann Gautier 			return status;
27423684d0eSYann Gautier 		}
27523684d0eSYann Gautier 
27623684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
27723684d0eSYann Gautier 		break;
27823684d0eSYann Gautier 
27923684d0eSYann Gautier 	case STM32MP_LPDDR2:
2804b549b21SYann Gautier 	case STM32MP_LPDDR3:
28123684d0eSYann Gautier 		/*
28223684d0eSYann Gautier 		 * Set LDO3 to 1.8V
28323684d0eSYann Gautier 		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
28423684d0eSYann Gautier 		 * Set LDO3 to normal mode if BUCK3 != 1.8V
28523684d0eSYann Gautier 		 */
28623684d0eSYann Gautier 		status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
28723684d0eSYann Gautier 		if (status != 0) {
28823684d0eSYann Gautier 			return status;
28923684d0eSYann Gautier 		}
29023684d0eSYann Gautier 
29123684d0eSYann Gautier 		if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
29223684d0eSYann Gautier 			buck3_at_1v8 = true;
29323684d0eSYann Gautier 		}
29423684d0eSYann Gautier 
29523684d0eSYann Gautier 		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
29623684d0eSYann Gautier 		if (status != 0) {
29723684d0eSYann Gautier 			return status;
29823684d0eSYann Gautier 		}
29923684d0eSYann Gautier 
30023684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO3_MODE;
30123684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
30223684d0eSYann Gautier 		read_val |= STPMIC1_LDO3_1800000;
30323684d0eSYann Gautier 		if (buck3_at_1v8) {
30423684d0eSYann Gautier 			read_val |= STPMIC1_LDO3_MODE;
30523684d0eSYann Gautier 		}
30623684d0eSYann Gautier 
30723684d0eSYann Gautier 		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
30823684d0eSYann Gautier 		if (status != 0) {
30923684d0eSYann Gautier 			return status;
31023684d0eSYann Gautier 		}
31123684d0eSYann Gautier 
31223684d0eSYann Gautier 		status = stpmic1_regulator_voltage_set("buck2", 1200);
31323684d0eSYann Gautier 		if (status != 0) {
31423684d0eSYann Gautier 			return status;
31523684d0eSYann Gautier 		}
31623684d0eSYann Gautier 
31723684d0eSYann Gautier 		status = stpmic1_regulator_enable("ldo3");
31823684d0eSYann Gautier 		if (status != 0) {
31923684d0eSYann Gautier 			return status;
32023684d0eSYann Gautier 		}
32123684d0eSYann Gautier 
32223684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
32323684d0eSYann Gautier 
32423684d0eSYann Gautier 		status = stpmic1_regulator_enable("buck2");
32523684d0eSYann Gautier 		if (status != 0) {
32623684d0eSYann Gautier 			return status;
32723684d0eSYann Gautier 		}
32823684d0eSYann Gautier 
32923684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
33023684d0eSYann Gautier 
33123684d0eSYann Gautier 		status = stpmic1_regulator_enable("vref_ddr");
33223684d0eSYann Gautier 		if (status != 0) {
33323684d0eSYann Gautier 			return status;
33423684d0eSYann Gautier 		}
33523684d0eSYann Gautier 
33623684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
33723684d0eSYann Gautier 		break;
33823684d0eSYann Gautier 
33923684d0eSYann Gautier 	default:
34023684d0eSYann Gautier 		break;
34123684d0eSYann Gautier 	};
34223684d0eSYann Gautier 
34323684d0eSYann Gautier 	return 0;
34423684d0eSYann Gautier }
345*85fb175bSYann Gautier 
346*85fb175bSYann Gautier enum {
347*85fb175bSYann Gautier 	STPMIC1_BUCK1 = 0,
348*85fb175bSYann Gautier 	STPMIC1_BUCK2,
349*85fb175bSYann Gautier 	STPMIC1_BUCK3,
350*85fb175bSYann Gautier 	STPMIC1_BUCK4,
351*85fb175bSYann Gautier 	STPMIC1_LDO1,
352*85fb175bSYann Gautier 	STPMIC1_LDO2,
353*85fb175bSYann Gautier 	STPMIC1_LDO3,
354*85fb175bSYann Gautier 	STPMIC1_LDO4,
355*85fb175bSYann Gautier 	STPMIC1_LDO5,
356*85fb175bSYann Gautier 	STPMIC1_LDO6,
357*85fb175bSYann Gautier 	STPMIC1_VREF_DDR,
358*85fb175bSYann Gautier 	STPMIC1_BOOST,
359*85fb175bSYann Gautier 	STPMIC1_VBUS_OTG,
360*85fb175bSYann Gautier 	STPMIC1_SW_OUT,
361*85fb175bSYann Gautier };
362*85fb175bSYann Gautier 
363*85fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable)
364*85fb175bSYann Gautier {
365*85fb175bSYann Gautier 	VERBOSE("%s: set state to %u\n", desc->node_name, enable);
366*85fb175bSYann Gautier 
367*85fb175bSYann Gautier 	if (enable == STATE_ENABLE) {
368*85fb175bSYann Gautier 		return stpmic1_regulator_enable(desc->node_name);
369*85fb175bSYann Gautier 	} else {
370*85fb175bSYann Gautier 		return stpmic1_regulator_disable(desc->node_name);
371*85fb175bSYann Gautier 	}
372*85fb175bSYann Gautier }
373*85fb175bSYann Gautier 
374*85fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc)
375*85fb175bSYann Gautier {
376*85fb175bSYann Gautier 	VERBOSE("%s: get state\n", desc->node_name);
377*85fb175bSYann Gautier 
378*85fb175bSYann Gautier 	return stpmic1_is_regulator_enabled(desc->node_name);
379*85fb175bSYann Gautier }
380*85fb175bSYann Gautier 
381*85fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc)
382*85fb175bSYann Gautier {
383*85fb175bSYann Gautier 	VERBOSE("%s: get volt\n", desc->node_name);
384*85fb175bSYann Gautier 
385*85fb175bSYann Gautier 	return stpmic1_regulator_voltage_get(desc->node_name);
386*85fb175bSYann Gautier }
387*85fb175bSYann Gautier 
388*85fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
389*85fb175bSYann Gautier {
390*85fb175bSYann Gautier 	VERBOSE("%s: get volt\n", desc->node_name);
391*85fb175bSYann Gautier 
392*85fb175bSYann Gautier 	return stpmic1_regulator_voltage_set(desc->node_name, mv);
393*85fb175bSYann Gautier }
394*85fb175bSYann Gautier 
395*85fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc,
396*85fb175bSYann Gautier 			      const uint16_t **levels, size_t *count)
397*85fb175bSYann Gautier {
398*85fb175bSYann Gautier 	VERBOSE("%s: list volt\n", desc->node_name);
399*85fb175bSYann Gautier 
400*85fb175bSYann Gautier 	return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
401*85fb175bSYann Gautier }
402*85fb175bSYann Gautier 
403*85fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
404*85fb175bSYann Gautier {
405*85fb175bSYann Gautier 	VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
406*85fb175bSYann Gautier 
407*85fb175bSYann Gautier 	switch (flag) {
408*85fb175bSYann Gautier 	case REGUL_OCP:
409*85fb175bSYann Gautier 		return stpmic1_regulator_icc_set(desc->node_name);
410*85fb175bSYann Gautier 
411*85fb175bSYann Gautier 	case REGUL_ACTIVE_DISCHARGE:
412*85fb175bSYann Gautier 		return stpmic1_active_discharge_mode_set(desc->node_name);
413*85fb175bSYann Gautier 
414*85fb175bSYann Gautier 	case REGUL_PULL_DOWN:
415*85fb175bSYann Gautier 		return stpmic1_regulator_pull_down_set(desc->node_name);
416*85fb175bSYann Gautier 
417*85fb175bSYann Gautier 	case REGUL_MASK_RESET:
418*85fb175bSYann Gautier 		return stpmic1_regulator_mask_reset_set(desc->node_name);
419*85fb175bSYann Gautier 
420*85fb175bSYann Gautier 	case REGUL_SINK_SOURCE:
421*85fb175bSYann Gautier 		return stpmic1_regulator_sink_mode_set(desc->node_name);
422*85fb175bSYann Gautier 
423*85fb175bSYann Gautier 	case REGUL_ENABLE_BYPASS:
424*85fb175bSYann Gautier 		return stpmic1_regulator_bypass_mode_set(desc->node_name);
425*85fb175bSYann Gautier 
426*85fb175bSYann Gautier 	default:
427*85fb175bSYann Gautier 		return -EINVAL;
428*85fb175bSYann Gautier 	}
429*85fb175bSYann Gautier }
430*85fb175bSYann Gautier 
431*85fb175bSYann Gautier struct regul_ops pmic_ops = {
432*85fb175bSYann Gautier 	.set_state = pmic_set_state,
433*85fb175bSYann Gautier 	.get_state = pmic_get_state,
434*85fb175bSYann Gautier 	.set_voltage = pmic_set_voltage,
435*85fb175bSYann Gautier 	.get_voltage = pmic_get_voltage,
436*85fb175bSYann Gautier 	.list_voltages = pmic_list_voltages,
437*85fb175bSYann Gautier 	.set_flag = pmic_set_flag,
438*85fb175bSYann Gautier };
439*85fb175bSYann Gautier 
440*85fb175bSYann Gautier #define DEFINE_REGU(name) { \
441*85fb175bSYann Gautier 	.node_name = name, \
442*85fb175bSYann Gautier 	.ops = &pmic_ops, \
443*85fb175bSYann Gautier 	.driver_data = NULL, \
444*85fb175bSYann Gautier 	.enable_ramp_delay = 1000, \
445*85fb175bSYann Gautier }
446*85fb175bSYann Gautier 
447*85fb175bSYann Gautier static const struct regul_description pmic_regs[] = {
448*85fb175bSYann Gautier 	[STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
449*85fb175bSYann Gautier 	[STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
450*85fb175bSYann Gautier 	[STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
451*85fb175bSYann Gautier 	[STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
452*85fb175bSYann Gautier 	[STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
453*85fb175bSYann Gautier 	[STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
454*85fb175bSYann Gautier 	[STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
455*85fb175bSYann Gautier 	[STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
456*85fb175bSYann Gautier 	[STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
457*85fb175bSYann Gautier 	[STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
458*85fb175bSYann Gautier 	[STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
459*85fb175bSYann Gautier 	[STPMIC1_BOOST] = DEFINE_REGU("boost"),
460*85fb175bSYann Gautier 	[STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
461*85fb175bSYann Gautier 	[STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
462*85fb175bSYann Gautier };
463*85fb175bSYann Gautier 
464*85fb175bSYann Gautier #define NB_REG ARRAY_SIZE(pmic_regs)
465*85fb175bSYann Gautier 
466*85fb175bSYann Gautier static int register_pmic(void)
467*85fb175bSYann Gautier {
468*85fb175bSYann Gautier 	void *fdt;
469*85fb175bSYann Gautier 	int pmic_node, regulators_node, subnode;
470*85fb175bSYann Gautier 
471*85fb175bSYann Gautier 	VERBOSE("Register pmic\n");
472*85fb175bSYann Gautier 
473*85fb175bSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
474*85fb175bSYann Gautier 		return -FDT_ERR_NOTFOUND;
475*85fb175bSYann Gautier 	}
476*85fb175bSYann Gautier 
477*85fb175bSYann Gautier 	pmic_node = dt_get_pmic_node(fdt);
478*85fb175bSYann Gautier 	if (pmic_node < 0) {
479*85fb175bSYann Gautier 		return pmic_node;
480*85fb175bSYann Gautier 	}
481*85fb175bSYann Gautier 
482*85fb175bSYann Gautier 	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
483*85fb175bSYann Gautier 	if (regulators_node < 0) {
484*85fb175bSYann Gautier 		return -ENOENT;
485*85fb175bSYann Gautier 	}
486*85fb175bSYann Gautier 
487*85fb175bSYann Gautier 	fdt_for_each_subnode(subnode, fdt, regulators_node) {
488*85fb175bSYann Gautier 		const char *reg_name = fdt_get_name(fdt, subnode, NULL);
489*85fb175bSYann Gautier 		const struct regul_description *desc;
490*85fb175bSYann Gautier 		unsigned int i;
491*85fb175bSYann Gautier 		int ret;
492*85fb175bSYann Gautier 
493*85fb175bSYann Gautier 		for (i = 0; i < NB_REG; i++) {
494*85fb175bSYann Gautier 			desc = &pmic_regs[i];
495*85fb175bSYann Gautier 			if (strcmp(desc->node_name, reg_name) == 0) {
496*85fb175bSYann Gautier 				break;
497*85fb175bSYann Gautier 			}
498*85fb175bSYann Gautier 		}
499*85fb175bSYann Gautier 		assert(i < NB_REG);
500*85fb175bSYann Gautier 
501*85fb175bSYann Gautier 		ret = regulator_register(desc, subnode);
502*85fb175bSYann Gautier 		if (ret != 0) {
503*85fb175bSYann Gautier 			WARN("%s:%d failed to register %s\n", __func__,
504*85fb175bSYann Gautier 			     __LINE__, reg_name);
505*85fb175bSYann Gautier 			return ret;
506*85fb175bSYann Gautier 		}
507*85fb175bSYann Gautier 	}
508*85fb175bSYann Gautier 
509*85fb175bSYann Gautier 	return 0;
510*85fb175bSYann Gautier }
511