xref: /rk3399_ARM-atf/drivers/st/pmic/stm32mp_pmic.c (revision be7195d06cb7731fe0d906c6eabe6cb6f39f29b1)
123684d0eSYann Gautier /*
247065ffeSYann Gautier  * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
323684d0eSYann Gautier  *
423684d0eSYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
523684d0eSYann Gautier  */
623684d0eSYann Gautier 
785fb175bSYann Gautier #include <assert.h>
823684d0eSYann Gautier #include <errno.h>
923684d0eSYann Gautier 
1023684d0eSYann Gautier #include <common/debug.h>
1123684d0eSYann Gautier #include <drivers/delay_timer.h>
1285fb175bSYann 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 
2423684d0eSYann Gautier static struct i2c_handle_s i2c_handle;
2523684d0eSYann Gautier static uint32_t pmic_i2c_addr;
2623684d0eSYann Gautier 
2785fb175bSYann Gautier static int register_pmic(void);
2885fb175bSYann Gautier 
2923684d0eSYann Gautier static int dt_get_pmic_node(void *fdt)
3023684d0eSYann Gautier {
31c77c7d9eSNicolas Le Bayon 	static int node = -FDT_ERR_BADOFFSET;
32c77c7d9eSNicolas Le Bayon 
33c77c7d9eSNicolas Le Bayon 	if (node == -FDT_ERR_BADOFFSET) {
34c77c7d9eSNicolas Le Bayon 		node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
35c77c7d9eSNicolas Le Bayon 	}
36c77c7d9eSNicolas Le Bayon 
37c77c7d9eSNicolas Le Bayon 	return node;
3823684d0eSYann Gautier }
3923684d0eSYann Gautier 
40d82d4ff0SYann Gautier int dt_pmic_status(void)
4123684d0eSYann Gautier {
42c77c7d9eSNicolas Le Bayon 	static int status = -FDT_ERR_BADVALUE;
4323684d0eSYann Gautier 	int node;
4423684d0eSYann Gautier 	void *fdt;
4523684d0eSYann Gautier 
46c77c7d9eSNicolas Le Bayon 	if (status != -FDT_ERR_BADVALUE) {
47c77c7d9eSNicolas Le Bayon 		return status;
48c77c7d9eSNicolas Le Bayon 	}
49c77c7d9eSNicolas Le Bayon 
5023684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
51d82d4ff0SYann Gautier 		return -ENOENT;
5223684d0eSYann Gautier 	}
5323684d0eSYann Gautier 
5423684d0eSYann Gautier 	node = dt_get_pmic_node(fdt);
55d82d4ff0SYann Gautier 	if (node <= 0) {
56c77c7d9eSNicolas Le Bayon 		status = -FDT_ERR_NOTFOUND;
57c77c7d9eSNicolas Le Bayon 
58c77c7d9eSNicolas Le Bayon 		return status;
5923684d0eSYann Gautier 	}
6023684d0eSYann Gautier 
61c77c7d9eSNicolas Le Bayon 	status = (int)fdt_get_status(node);
62c77c7d9eSNicolas Le Bayon 
63c77c7d9eSNicolas Le Bayon 	return status;
6423684d0eSYann Gautier }
6523684d0eSYann Gautier 
66f564d439SEtienne Carriere static bool dt_pmic_is_secure(void)
67f564d439SEtienne Carriere {
68f564d439SEtienne Carriere 	int status = dt_pmic_status();
69f564d439SEtienne Carriere 
70f564d439SEtienne Carriere 	return (status >= 0) &&
71f564d439SEtienne Carriere 	       (status == DT_SECURE) &&
72f564d439SEtienne Carriere 	       (i2c_handle.dt_status == DT_SECURE);
73f564d439SEtienne Carriere }
74f564d439SEtienne Carriere 
75d82d4ff0SYann Gautier /*
76d82d4ff0SYann Gautier  * Get PMIC and its I2C bus configuration from the device tree.
77c77c7d9eSNicolas Le Bayon  * Return 0 on success, negative on error, 1 if no PMIC node is defined.
78d82d4ff0SYann Gautier  */
79d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
80d82d4ff0SYann Gautier 			      struct stm32_i2c_init_s *init)
8123684d0eSYann Gautier {
82c77c7d9eSNicolas Le Bayon 	static int i2c_node = -FDT_ERR_NOTFOUND;
8323684d0eSYann Gautier 	void *fdt;
8423684d0eSYann Gautier 
8523684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
86c77c7d9eSNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
8723684d0eSYann Gautier 	}
8823684d0eSYann Gautier 
89c77c7d9eSNicolas Le Bayon 	if (i2c_node == -FDT_ERR_NOTFOUND) {
90c77c7d9eSNicolas Le Bayon 		int pmic_node;
91c77c7d9eSNicolas Le Bayon 		const fdt32_t *cuint;
92c77c7d9eSNicolas Le Bayon 
9323684d0eSYann Gautier 		pmic_node = dt_get_pmic_node(fdt);
9423684d0eSYann Gautier 		if (pmic_node < 0) {
95c77c7d9eSNicolas Le Bayon 			return PMIC_NODE_NOT_FOUND;
9623684d0eSYann Gautier 		}
9723684d0eSYann Gautier 
9823684d0eSYann Gautier 		cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
9923684d0eSYann Gautier 		if (cuint == NULL) {
10023684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
10123684d0eSYann Gautier 		}
10223684d0eSYann Gautier 
10323684d0eSYann Gautier 		pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
10423684d0eSYann Gautier 		if (pmic_i2c_addr > UINT16_MAX) {
105c77c7d9eSNicolas Le Bayon 			return -FDT_ERR_BADVALUE;
10623684d0eSYann Gautier 		}
10723684d0eSYann Gautier 
10823684d0eSYann Gautier 		i2c_node = fdt_parent_offset(fdt, pmic_node);
10923684d0eSYann Gautier 		if (i2c_node < 0) {
11023684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
11123684d0eSYann Gautier 		}
112c77c7d9eSNicolas Le Bayon 	}
11323684d0eSYann Gautier 
11423684d0eSYann Gautier 	dt_fill_device_info(i2c_info, i2c_node);
11523684d0eSYann Gautier 	if (i2c_info->base == 0U) {
11623684d0eSYann Gautier 		return -FDT_ERR_NOTFOUND;
11723684d0eSYann Gautier 	}
11823684d0eSYann Gautier 
119d82d4ff0SYann Gautier 	return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
12023684d0eSYann Gautier }
12123684d0eSYann Gautier 
122d82d4ff0SYann Gautier bool initialize_pmic_i2c(void)
12323684d0eSYann Gautier {
12423684d0eSYann Gautier 	int ret;
12523684d0eSYann Gautier 	struct dt_node_info i2c_info;
126d82d4ff0SYann Gautier 	struct i2c_handle_s *i2c = &i2c_handle;
127d82d4ff0SYann Gautier 	struct stm32_i2c_init_s i2c_init;
12823684d0eSYann Gautier 
129d82d4ff0SYann Gautier 	ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
130d82d4ff0SYann Gautier 	if (ret < 0) {
131d82d4ff0SYann Gautier 		ERROR("I2C configuration failed %d\n", ret);
13223684d0eSYann Gautier 		panic();
13323684d0eSYann Gautier 	}
13423684d0eSYann Gautier 
135d82d4ff0SYann Gautier 	if (ret != 0) {
136d82d4ff0SYann Gautier 		return false;
13723684d0eSYann Gautier 	}
13823684d0eSYann Gautier 
13923684d0eSYann Gautier 	/* Initialize PMIC I2C */
140d82d4ff0SYann Gautier 	i2c->i2c_base_addr		= i2c_info.base;
141d82d4ff0SYann Gautier 	i2c->dt_status			= i2c_info.status;
142d82d4ff0SYann Gautier 	i2c->clock			= i2c_info.clock;
14342822844SBenjamin Gaignard 	i2c->i2c_state			= I2C_STATE_RESET;
144d82d4ff0SYann Gautier 	i2c_init.own_address1		= pmic_i2c_addr;
145d82d4ff0SYann Gautier 	i2c_init.addressing_mode	= I2C_ADDRESSINGMODE_7BIT;
146d82d4ff0SYann Gautier 	i2c_init.dual_address_mode	= I2C_DUALADDRESS_DISABLE;
147d82d4ff0SYann Gautier 	i2c_init.own_address2		= 0;
148d82d4ff0SYann Gautier 	i2c_init.own_address2_masks	= I2C_OAR2_OA2NOMASK;
149d82d4ff0SYann Gautier 	i2c_init.general_call_mode	= I2C_GENERALCALL_DISABLE;
150d82d4ff0SYann Gautier 	i2c_init.no_stretch_mode	= I2C_NOSTRETCH_DISABLE;
151d82d4ff0SYann Gautier 	i2c_init.analog_filter		= 1;
152d82d4ff0SYann Gautier 	i2c_init.digital_filter_coef	= 0;
15323684d0eSYann Gautier 
154d82d4ff0SYann Gautier 	ret = stm32_i2c_init(i2c, &i2c_init);
15523684d0eSYann Gautier 	if (ret != 0) {
15623684d0eSYann Gautier 		ERROR("Cannot initialize I2C %x (%d)\n",
157d82d4ff0SYann Gautier 		      i2c->i2c_base_addr, ret);
15823684d0eSYann Gautier 		panic();
15923684d0eSYann Gautier 	}
16023684d0eSYann Gautier 
161d82d4ff0SYann Gautier 	if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
162d82d4ff0SYann Gautier 				       I2C_TIMEOUT_BUSY_MS)) {
163d82d4ff0SYann Gautier 		ERROR("I2C device not ready\n");
16423684d0eSYann Gautier 		panic();
16523684d0eSYann Gautier 	}
16623684d0eSYann Gautier 
167d82d4ff0SYann Gautier 	stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
16823684d0eSYann Gautier 
169d82d4ff0SYann Gautier 	return true;
17023684d0eSYann Gautier }
17123684d0eSYann Gautier 
172f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void)
173f564d439SEtienne Carriere {
174f564d439SEtienne Carriere 	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
175f564d439SEtienne Carriere 
176f564d439SEtienne Carriere 	if (dt_pmic_is_secure()) {
177f564d439SEtienne Carriere 		stm32mp_register_secure_periph_iomem(i2c_base);
178f564d439SEtienne Carriere 	} else {
179f564d439SEtienne Carriere 		if (i2c_base != 0U) {
180f564d439SEtienne Carriere 			stm32mp_register_non_secure_periph_iomem(i2c_base);
181f564d439SEtienne Carriere 		}
182f564d439SEtienne Carriere 	}
183f564d439SEtienne Carriere }
184f564d439SEtienne Carriere 
18523684d0eSYann Gautier void initialize_pmic(void)
18623684d0eSYann Gautier {
187d82d4ff0SYann Gautier 	if (!initialize_pmic_i2c()) {
188d82d4ff0SYann Gautier 		VERBOSE("No PMIC\n");
189d82d4ff0SYann Gautier 		return;
190d82d4ff0SYann Gautier 	}
19123684d0eSYann Gautier 
192f564d439SEtienne Carriere 	register_pmic_shared_peripherals();
193f564d439SEtienne Carriere 
19485fb175bSYann Gautier 	if (register_pmic() < 0) {
195ae7792e0SNicolas Le Bayon 		panic();
19685fb175bSYann Gautier 	}
19785fb175bSYann Gautier 
19885fb175bSYann Gautier 	if (stpmic1_powerctrl_on() < 0) {
19985fb175bSYann Gautier 		panic();
20085fb175bSYann Gautier 	}
20185fb175bSYann Gautier 
202ae7792e0SNicolas Le Bayon }
203ae7792e0SNicolas Le Bayon 
204ae7792e0SNicolas Le Bayon #if DEBUG
205ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void)
206ae7792e0SNicolas Le Bayon {
207ae7792e0SNicolas Le Bayon 	unsigned long pmic_version;
208ae7792e0SNicolas Le Bayon 
209d82d4ff0SYann Gautier 	if (stpmic1_get_version(&pmic_version) != 0) {
210d82d4ff0SYann Gautier 		ERROR("Failed to access PMIC\n");
21123684d0eSYann Gautier 		panic();
21223684d0eSYann Gautier 	}
21323684d0eSYann Gautier 
214d82d4ff0SYann Gautier 	INFO("PMIC version = 0x%02lx\n", pmic_version);
21523684d0eSYann Gautier }
216ae7792e0SNicolas Le Bayon #endif
21723684d0eSYann Gautier 
21823684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type)
21923684d0eSYann Gautier {
22023684d0eSYann Gautier 	int status;
2210ba71ac9SPascal Paillet 	uint16_t buck3_min_mv;
222111a384cSYann Gautier 	struct rdev *buck2, *buck3, *vref;
223111a384cSYann Gautier 	struct rdev *ldo3 __unused;
2240ba71ac9SPascal Paillet 
2250ba71ac9SPascal Paillet 	buck2 = regulator_get_by_name("buck2");
2260ba71ac9SPascal Paillet 	if (buck2 == NULL) {
2270ba71ac9SPascal Paillet 		return -ENOENT;
2280ba71ac9SPascal Paillet 	}
2290ba71ac9SPascal Paillet 
230111a384cSYann Gautier #if STM32MP15
2310ba71ac9SPascal Paillet 	ldo3 = regulator_get_by_name("ldo3");
2320ba71ac9SPascal Paillet 	if (ldo3 == NULL) {
2330ba71ac9SPascal Paillet 		return -ENOENT;
2340ba71ac9SPascal Paillet 	}
235111a384cSYann Gautier #endif
2360ba71ac9SPascal Paillet 
2370ba71ac9SPascal Paillet 	vref = regulator_get_by_name("vref_ddr");
2380ba71ac9SPascal Paillet 	if (vref == NULL) {
2390ba71ac9SPascal Paillet 		return -ENOENT;
2400ba71ac9SPascal Paillet 	}
24123684d0eSYann Gautier 
24223684d0eSYann Gautier 	switch (ddr_type) {
24323684d0eSYann Gautier 	case STM32MP_DDR3:
244111a384cSYann Gautier #if STM32MP15
2450ba71ac9SPascal Paillet 		status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE);
24623684d0eSYann Gautier 		if (status != 0) {
24723684d0eSYann Gautier 			return status;
24823684d0eSYann Gautier 		}
249111a384cSYann Gautier #endif
25023684d0eSYann Gautier 
2510ba71ac9SPascal Paillet 		status = regulator_set_min_voltage(buck2);
25223684d0eSYann Gautier 		if (status != 0) {
25323684d0eSYann Gautier 			return status;
25423684d0eSYann Gautier 		}
25523684d0eSYann Gautier 
2560ba71ac9SPascal Paillet 		status = regulator_enable(buck2);
25723684d0eSYann Gautier 		if (status != 0) {
25823684d0eSYann Gautier 			return status;
25923684d0eSYann Gautier 		}
26023684d0eSYann Gautier 
2610ba71ac9SPascal Paillet 		status = regulator_enable(vref);
26223684d0eSYann Gautier 		if (status != 0) {
26323684d0eSYann Gautier 			return status;
26423684d0eSYann Gautier 		}
26523684d0eSYann Gautier 
266111a384cSYann Gautier #if STM32MP15
2670ba71ac9SPascal Paillet 		status = regulator_enable(ldo3);
26823684d0eSYann Gautier 		if (status != 0) {
26923684d0eSYann Gautier 			return status;
27023684d0eSYann Gautier 		}
271111a384cSYann Gautier #endif
27223684d0eSYann Gautier 		break;
27323684d0eSYann Gautier 
27423684d0eSYann Gautier 	case STM32MP_LPDDR2:
2754b549b21SYann Gautier 	case STM32MP_LPDDR3:
27623684d0eSYann Gautier 		/*
27723684d0eSYann Gautier 		 * Set LDO3 to 1.8V
27823684d0eSYann Gautier 		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
27923684d0eSYann Gautier 		 * Set LDO3 to normal mode if BUCK3 != 1.8V
28023684d0eSYann Gautier 		 */
2810ba71ac9SPascal Paillet 		buck3 = regulator_get_by_name("buck3");
2820ba71ac9SPascal Paillet 		if (buck3 == NULL) {
2830ba71ac9SPascal Paillet 			return -ENOENT;
2840ba71ac9SPascal Paillet 		}
2850ba71ac9SPascal Paillet 
2860ba71ac9SPascal Paillet 		regulator_get_range(buck3, &buck3_min_mv, NULL);
2870ba71ac9SPascal Paillet 
288111a384cSYann Gautier #if STM32MP15
2890ba71ac9SPascal Paillet 		if (buck3_min_mv != 1800) {
2900ba71ac9SPascal Paillet 			status = regulator_set_min_voltage(ldo3);
2910ba71ac9SPascal Paillet 			if (status != 0) {
2920ba71ac9SPascal Paillet 				return status;
2930ba71ac9SPascal Paillet 			}
2940ba71ac9SPascal Paillet 		} else {
2950ba71ac9SPascal Paillet 			status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS);
2960ba71ac9SPascal Paillet 			if (status != 0) {
2970ba71ac9SPascal Paillet 				return status;
2980ba71ac9SPascal Paillet 			}
2990ba71ac9SPascal Paillet 		}
300111a384cSYann Gautier #endif
3010ba71ac9SPascal Paillet 
3020ba71ac9SPascal Paillet 		status = regulator_set_min_voltage(buck2);
30323684d0eSYann Gautier 		if (status != 0) {
30423684d0eSYann Gautier 			return status;
30523684d0eSYann Gautier 		}
30623684d0eSYann Gautier 
307111a384cSYann Gautier #if STM32MP15
3080ba71ac9SPascal Paillet 		status = regulator_enable(ldo3);
30923684d0eSYann Gautier 		if (status != 0) {
31023684d0eSYann Gautier 			return status;
31123684d0eSYann Gautier 		}
312111a384cSYann Gautier #endif
31323684d0eSYann Gautier 
3140ba71ac9SPascal Paillet 		status = regulator_enable(buck2);
31523684d0eSYann Gautier 		if (status != 0) {
31623684d0eSYann Gautier 			return status;
31723684d0eSYann Gautier 		}
31823684d0eSYann Gautier 
3190ba71ac9SPascal Paillet 		status = regulator_enable(vref);
32023684d0eSYann Gautier 		if (status != 0) {
32123684d0eSYann Gautier 			return status;
32223684d0eSYann Gautier 		}
32323684d0eSYann Gautier 		break;
32423684d0eSYann Gautier 
32523684d0eSYann Gautier 	default:
32623684d0eSYann Gautier 		break;
32723684d0eSYann Gautier 	};
32823684d0eSYann Gautier 
32923684d0eSYann Gautier 	return 0;
33023684d0eSYann Gautier }
33185fb175bSYann Gautier 
3325278ec3fSYann Gautier int pmic_voltages_init(void)
3335278ec3fSYann Gautier {
3345278ec3fSYann Gautier #if STM32MP13
3355278ec3fSYann Gautier 	struct rdev *buck1, *buck4;
3365278ec3fSYann Gautier 	int status;
3375278ec3fSYann Gautier 
3385278ec3fSYann Gautier 	buck1 = regulator_get_by_name("buck1");
3395278ec3fSYann Gautier 	if (buck1 == NULL) {
3405278ec3fSYann Gautier 		return -ENOENT;
3415278ec3fSYann Gautier 	}
3425278ec3fSYann Gautier 
3435278ec3fSYann Gautier 	buck4 = regulator_get_by_name("buck4");
3445278ec3fSYann Gautier 	if (buck4 == NULL) {
3455278ec3fSYann Gautier 		return -ENOENT;
3465278ec3fSYann Gautier 	}
3475278ec3fSYann Gautier 
3485278ec3fSYann Gautier 	status = regulator_set_min_voltage(buck1);
3495278ec3fSYann Gautier 	if (status != 0) {
3505278ec3fSYann Gautier 		return status;
3515278ec3fSYann Gautier 	}
3525278ec3fSYann Gautier 
3535278ec3fSYann Gautier 	status = regulator_set_min_voltage(buck4);
3545278ec3fSYann Gautier 	if (status != 0) {
3555278ec3fSYann Gautier 		return status;
3565278ec3fSYann Gautier 	}
3575278ec3fSYann Gautier #endif
3585278ec3fSYann Gautier 
3595278ec3fSYann Gautier 	return 0;
3605278ec3fSYann Gautier }
3615278ec3fSYann Gautier 
36285fb175bSYann Gautier enum {
36385fb175bSYann Gautier 	STPMIC1_BUCK1 = 0,
36485fb175bSYann Gautier 	STPMIC1_BUCK2,
36585fb175bSYann Gautier 	STPMIC1_BUCK3,
36685fb175bSYann Gautier 	STPMIC1_BUCK4,
36785fb175bSYann Gautier 	STPMIC1_LDO1,
36885fb175bSYann Gautier 	STPMIC1_LDO2,
36985fb175bSYann Gautier 	STPMIC1_LDO3,
37085fb175bSYann Gautier 	STPMIC1_LDO4,
37185fb175bSYann Gautier 	STPMIC1_LDO5,
37285fb175bSYann Gautier 	STPMIC1_LDO6,
37385fb175bSYann Gautier 	STPMIC1_VREF_DDR,
37485fb175bSYann Gautier 	STPMIC1_BOOST,
37585fb175bSYann Gautier 	STPMIC1_VBUS_OTG,
37685fb175bSYann Gautier 	STPMIC1_SW_OUT,
37785fb175bSYann Gautier };
37885fb175bSYann Gautier 
37985fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable)
38085fb175bSYann Gautier {
38147065ffeSYann Gautier 	VERBOSE("%s: set state to %d\n", desc->node_name, enable);
38285fb175bSYann Gautier 
38385fb175bSYann Gautier 	if (enable == STATE_ENABLE) {
38485fb175bSYann Gautier 		return stpmic1_regulator_enable(desc->node_name);
38585fb175bSYann Gautier 	} else {
38685fb175bSYann Gautier 		return stpmic1_regulator_disable(desc->node_name);
38785fb175bSYann Gautier 	}
38885fb175bSYann Gautier }
38985fb175bSYann Gautier 
39085fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc)
39185fb175bSYann Gautier {
39285fb175bSYann Gautier 	VERBOSE("%s: get state\n", desc->node_name);
39385fb175bSYann Gautier 
39485fb175bSYann Gautier 	return stpmic1_is_regulator_enabled(desc->node_name);
39585fb175bSYann Gautier }
39685fb175bSYann Gautier 
39785fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc)
39885fb175bSYann Gautier {
39985fb175bSYann Gautier 	VERBOSE("%s: get volt\n", desc->node_name);
40085fb175bSYann Gautier 
40185fb175bSYann Gautier 	return stpmic1_regulator_voltage_get(desc->node_name);
40285fb175bSYann Gautier }
40385fb175bSYann Gautier 
40485fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
40585fb175bSYann Gautier {
40685fb175bSYann Gautier 	VERBOSE("%s: get volt\n", desc->node_name);
40785fb175bSYann Gautier 
40885fb175bSYann Gautier 	return stpmic1_regulator_voltage_set(desc->node_name, mv);
40985fb175bSYann Gautier }
41085fb175bSYann Gautier 
41185fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc,
41285fb175bSYann Gautier 			      const uint16_t **levels, size_t *count)
41385fb175bSYann Gautier {
41485fb175bSYann Gautier 	VERBOSE("%s: list volt\n", desc->node_name);
41585fb175bSYann Gautier 
41685fb175bSYann Gautier 	return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
41785fb175bSYann Gautier }
41885fb175bSYann Gautier 
41985fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
42085fb175bSYann Gautier {
42185fb175bSYann Gautier 	VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
42285fb175bSYann Gautier 
42385fb175bSYann Gautier 	switch (flag) {
42485fb175bSYann Gautier 	case REGUL_OCP:
42585fb175bSYann Gautier 		return stpmic1_regulator_icc_set(desc->node_name);
42685fb175bSYann Gautier 
42785fb175bSYann Gautier 	case REGUL_ACTIVE_DISCHARGE:
42885fb175bSYann Gautier 		return stpmic1_active_discharge_mode_set(desc->node_name);
42985fb175bSYann Gautier 
43085fb175bSYann Gautier 	case REGUL_PULL_DOWN:
43185fb175bSYann Gautier 		return stpmic1_regulator_pull_down_set(desc->node_name);
43285fb175bSYann Gautier 
43385fb175bSYann Gautier 	case REGUL_MASK_RESET:
43485fb175bSYann Gautier 		return stpmic1_regulator_mask_reset_set(desc->node_name);
43585fb175bSYann Gautier 
43685fb175bSYann Gautier 	case REGUL_SINK_SOURCE:
43785fb175bSYann Gautier 		return stpmic1_regulator_sink_mode_set(desc->node_name);
43885fb175bSYann Gautier 
43985fb175bSYann Gautier 	case REGUL_ENABLE_BYPASS:
44085fb175bSYann Gautier 		return stpmic1_regulator_bypass_mode_set(desc->node_name);
44185fb175bSYann Gautier 
44285fb175bSYann Gautier 	default:
44385fb175bSYann Gautier 		return -EINVAL;
44485fb175bSYann Gautier 	}
44585fb175bSYann Gautier }
44685fb175bSYann Gautier 
44757e60183SYann Gautier static const struct regul_ops pmic_ops = {
44885fb175bSYann Gautier 	.set_state = pmic_set_state,
44985fb175bSYann Gautier 	.get_state = pmic_get_state,
45085fb175bSYann Gautier 	.set_voltage = pmic_set_voltage,
45185fb175bSYann Gautier 	.get_voltage = pmic_get_voltage,
45285fb175bSYann Gautier 	.list_voltages = pmic_list_voltages,
45385fb175bSYann Gautier 	.set_flag = pmic_set_flag,
45485fb175bSYann Gautier };
45585fb175bSYann Gautier 
45685fb175bSYann Gautier #define DEFINE_REGU(name) { \
457*be7195d0SYann Gautier 	.node_name = (name), \
45885fb175bSYann Gautier 	.ops = &pmic_ops, \
45985fb175bSYann Gautier 	.driver_data = NULL, \
46085fb175bSYann Gautier 	.enable_ramp_delay = 1000, \
46185fb175bSYann Gautier }
46285fb175bSYann Gautier 
46385fb175bSYann Gautier static const struct regul_description pmic_regs[] = {
46485fb175bSYann Gautier 	[STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
46585fb175bSYann Gautier 	[STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
46685fb175bSYann Gautier 	[STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
46785fb175bSYann Gautier 	[STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
46885fb175bSYann Gautier 	[STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
46985fb175bSYann Gautier 	[STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
47085fb175bSYann Gautier 	[STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
47185fb175bSYann Gautier 	[STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
47285fb175bSYann Gautier 	[STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
47385fb175bSYann Gautier 	[STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
47485fb175bSYann Gautier 	[STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
47585fb175bSYann Gautier 	[STPMIC1_BOOST] = DEFINE_REGU("boost"),
47685fb175bSYann Gautier 	[STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
47785fb175bSYann Gautier 	[STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
47885fb175bSYann Gautier };
47985fb175bSYann Gautier 
48085fb175bSYann Gautier #define NB_REG ARRAY_SIZE(pmic_regs)
48185fb175bSYann Gautier 
48285fb175bSYann Gautier static int register_pmic(void)
48385fb175bSYann Gautier {
48485fb175bSYann Gautier 	void *fdt;
48585fb175bSYann Gautier 	int pmic_node, regulators_node, subnode;
48685fb175bSYann Gautier 
48785fb175bSYann Gautier 	VERBOSE("Register pmic\n");
48885fb175bSYann Gautier 
48985fb175bSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
49085fb175bSYann Gautier 		return -FDT_ERR_NOTFOUND;
49185fb175bSYann Gautier 	}
49285fb175bSYann Gautier 
49385fb175bSYann Gautier 	pmic_node = dt_get_pmic_node(fdt);
49485fb175bSYann Gautier 	if (pmic_node < 0) {
49585fb175bSYann Gautier 		return pmic_node;
49685fb175bSYann Gautier 	}
49785fb175bSYann Gautier 
49885fb175bSYann Gautier 	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
49985fb175bSYann Gautier 	if (regulators_node < 0) {
50085fb175bSYann Gautier 		return -ENOENT;
50185fb175bSYann Gautier 	}
50285fb175bSYann Gautier 
50385fb175bSYann Gautier 	fdt_for_each_subnode(subnode, fdt, regulators_node) {
50485fb175bSYann Gautier 		const char *reg_name = fdt_get_name(fdt, subnode, NULL);
50585fb175bSYann Gautier 		const struct regul_description *desc;
50685fb175bSYann Gautier 		unsigned int i;
50785fb175bSYann Gautier 		int ret;
50885fb175bSYann Gautier 
50985fb175bSYann Gautier 		for (i = 0; i < NB_REG; i++) {
51085fb175bSYann Gautier 			desc = &pmic_regs[i];
51185fb175bSYann Gautier 			if (strcmp(desc->node_name, reg_name) == 0) {
51285fb175bSYann Gautier 				break;
51385fb175bSYann Gautier 			}
51485fb175bSYann Gautier 		}
51585fb175bSYann Gautier 		assert(i < NB_REG);
51685fb175bSYann Gautier 
51785fb175bSYann Gautier 		ret = regulator_register(desc, subnode);
51885fb175bSYann Gautier 		if (ret != 0) {
51985fb175bSYann Gautier 			WARN("%s:%d failed to register %s\n", __func__,
52085fb175bSYann Gautier 			     __LINE__, reg_name);
52185fb175bSYann Gautier 			return ret;
52285fb175bSYann Gautier 		}
52385fb175bSYann Gautier 	}
52485fb175bSYann Gautier 
52585fb175bSYann Gautier 	return 0;
52685fb175bSYann Gautier }
527