xref: /rk3399_ARM-atf/drivers/st/pmic/stm32mp_pmic.c (revision ae7792e0583f83adc06eb3b14693539e95110490)
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 
723684d0eSYann Gautier #include <errno.h>
823684d0eSYann Gautier 
923684d0eSYann Gautier #include <common/debug.h>
1023684d0eSYann Gautier #include <drivers/delay_timer.h>
11d82d4ff0SYann Gautier #include <drivers/st/stm32_i2c.h>
1223684d0eSYann Gautier #include <drivers/st/stm32mp_pmic.h>
1323684d0eSYann Gautier #include <drivers/st/stpmic1.h>
1423684d0eSYann Gautier #include <lib/mmio.h>
1523684d0eSYann Gautier #include <lib/utils_def.h>
1616e56a75SNicolas Le Bayon #include <libfdt.h>
1716e56a75SNicolas Le Bayon 
1816e56a75SNicolas Le Bayon #include <platform_def.h>
1923684d0eSYann Gautier 
20c77c7d9eSNicolas Le Bayon #define PMIC_NODE_NOT_FOUND	1
2123684d0eSYann Gautier #define STPMIC1_LDO12356_OUTPUT_MASK	(uint8_t)(GENMASK(6, 2))
2223684d0eSYann Gautier #define STPMIC1_LDO12356_OUTPUT_SHIFT	2
2323684d0eSYann Gautier #define STPMIC1_LDO3_MODE		(uint8_t)(BIT(7))
2423684d0eSYann Gautier #define STPMIC1_LDO3_DDR_SEL		31U
2523684d0eSYann Gautier #define STPMIC1_LDO3_1800000		(9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
2623684d0eSYann Gautier 
2723684d0eSYann Gautier #define STPMIC1_BUCK_OUTPUT_SHIFT	2
2823684d0eSYann Gautier #define STPMIC1_BUCK3_1V8		(39U << STPMIC1_BUCK_OUTPUT_SHIFT)
2923684d0eSYann Gautier 
3023684d0eSYann Gautier #define STPMIC1_DEFAULT_START_UP_DELAY_MS	1
3123684d0eSYann Gautier 
3223684d0eSYann Gautier static struct i2c_handle_s i2c_handle;
3323684d0eSYann Gautier static uint32_t pmic_i2c_addr;
3423684d0eSYann Gautier 
3523684d0eSYann Gautier static int dt_get_pmic_node(void *fdt)
3623684d0eSYann Gautier {
37c77c7d9eSNicolas Le Bayon 	static int node = -FDT_ERR_BADOFFSET;
38c77c7d9eSNicolas Le Bayon 
39c77c7d9eSNicolas Le Bayon 	if (node == -FDT_ERR_BADOFFSET) {
40c77c7d9eSNicolas Le Bayon 		node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
41c77c7d9eSNicolas Le Bayon 	}
42c77c7d9eSNicolas Le Bayon 
43c77c7d9eSNicolas Le Bayon 	return node;
4423684d0eSYann Gautier }
4523684d0eSYann Gautier 
46d82d4ff0SYann Gautier int dt_pmic_status(void)
4723684d0eSYann Gautier {
48c77c7d9eSNicolas Le Bayon 	static int status = -FDT_ERR_BADVALUE;
4923684d0eSYann Gautier 	int node;
5023684d0eSYann Gautier 	void *fdt;
5123684d0eSYann Gautier 
52c77c7d9eSNicolas Le Bayon 	if (status != -FDT_ERR_BADVALUE) {
53c77c7d9eSNicolas Le Bayon 		return status;
54c77c7d9eSNicolas Le Bayon 	}
55c77c7d9eSNicolas Le Bayon 
5623684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
57d82d4ff0SYann Gautier 		return -ENOENT;
5823684d0eSYann Gautier 	}
5923684d0eSYann Gautier 
6023684d0eSYann Gautier 	node = dt_get_pmic_node(fdt);
61d82d4ff0SYann Gautier 	if (node <= 0) {
62c77c7d9eSNicolas Le Bayon 		status = -FDT_ERR_NOTFOUND;
63c77c7d9eSNicolas Le Bayon 
64c77c7d9eSNicolas Le Bayon 		return status;
6523684d0eSYann Gautier 	}
6623684d0eSYann Gautier 
67c77c7d9eSNicolas Le Bayon 	status = (int)fdt_get_status(node);
68c77c7d9eSNicolas Le Bayon 
69c77c7d9eSNicolas Le Bayon 	return status;
7023684d0eSYann Gautier }
7123684d0eSYann Gautier 
72f564d439SEtienne Carriere static bool dt_pmic_is_secure(void)
73f564d439SEtienne Carriere {
74f564d439SEtienne Carriere 	int status = dt_pmic_status();
75f564d439SEtienne Carriere 
76f564d439SEtienne Carriere 	return (status >= 0) &&
77f564d439SEtienne Carriere 	       (status == DT_SECURE) &&
78f564d439SEtienne Carriere 	       (i2c_handle.dt_status == DT_SECURE);
79f564d439SEtienne Carriere }
80f564d439SEtienne Carriere 
81d82d4ff0SYann Gautier /*
82d82d4ff0SYann Gautier  * Get PMIC and its I2C bus configuration from the device tree.
83c77c7d9eSNicolas Le Bayon  * Return 0 on success, negative on error, 1 if no PMIC node is defined.
84d82d4ff0SYann Gautier  */
85d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
86d82d4ff0SYann Gautier 			      struct stm32_i2c_init_s *init)
8723684d0eSYann Gautier {
88c77c7d9eSNicolas Le Bayon 	static int i2c_node = -FDT_ERR_NOTFOUND;
8923684d0eSYann Gautier 	void *fdt;
9023684d0eSYann Gautier 
9123684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
92c77c7d9eSNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
9323684d0eSYann Gautier 	}
9423684d0eSYann Gautier 
95c77c7d9eSNicolas Le Bayon 	if (i2c_node == -FDT_ERR_NOTFOUND) {
96c77c7d9eSNicolas Le Bayon 		int pmic_node;
97c77c7d9eSNicolas Le Bayon 		const fdt32_t *cuint;
98c77c7d9eSNicolas Le Bayon 
9923684d0eSYann Gautier 		pmic_node = dt_get_pmic_node(fdt);
10023684d0eSYann Gautier 		if (pmic_node < 0) {
101c77c7d9eSNicolas Le Bayon 			return PMIC_NODE_NOT_FOUND;
10223684d0eSYann Gautier 		}
10323684d0eSYann Gautier 
10423684d0eSYann Gautier 		cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
10523684d0eSYann Gautier 		if (cuint == NULL) {
10623684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
10723684d0eSYann Gautier 		}
10823684d0eSYann Gautier 
10923684d0eSYann Gautier 		pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
11023684d0eSYann Gautier 		if (pmic_i2c_addr > UINT16_MAX) {
111c77c7d9eSNicolas Le Bayon 			return -FDT_ERR_BADVALUE;
11223684d0eSYann Gautier 		}
11323684d0eSYann Gautier 
11423684d0eSYann Gautier 		i2c_node = fdt_parent_offset(fdt, pmic_node);
11523684d0eSYann Gautier 		if (i2c_node < 0) {
11623684d0eSYann Gautier 			return -FDT_ERR_NOTFOUND;
11723684d0eSYann Gautier 		}
118c77c7d9eSNicolas Le Bayon 	}
11923684d0eSYann Gautier 
12023684d0eSYann Gautier 	dt_fill_device_info(i2c_info, i2c_node);
12123684d0eSYann Gautier 	if (i2c_info->base == 0U) {
12223684d0eSYann Gautier 		return -FDT_ERR_NOTFOUND;
12323684d0eSYann Gautier 	}
12423684d0eSYann Gautier 
125d82d4ff0SYann Gautier 	return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
12623684d0eSYann Gautier }
12723684d0eSYann Gautier 
128d82d4ff0SYann Gautier int dt_pmic_configure_boot_on_regulators(void)
12923684d0eSYann Gautier {
13023684d0eSYann Gautier 	int pmic_node, regulators_node, regulator_node;
13123684d0eSYann Gautier 	void *fdt;
13223684d0eSYann Gautier 
13323684d0eSYann Gautier 	if (fdt_get_address(&fdt) == 0) {
13423684d0eSYann Gautier 		return -ENOENT;
13523684d0eSYann Gautier 	}
13623684d0eSYann Gautier 
13723684d0eSYann Gautier 	pmic_node = dt_get_pmic_node(fdt);
13823684d0eSYann Gautier 	if (pmic_node < 0) {
13923684d0eSYann Gautier 		return -FDT_ERR_NOTFOUND;
14023684d0eSYann Gautier 	}
14123684d0eSYann Gautier 
14223684d0eSYann Gautier 	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
143a4bcfe94SNicolas Le Bayon 	if (regulators_node < 0) {
144a4bcfe94SNicolas Le Bayon 		return -ENOENT;
145a4bcfe94SNicolas Le Bayon 	}
14623684d0eSYann Gautier 
14723684d0eSYann Gautier 	fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
14823684d0eSYann Gautier 		const fdt32_t *cuint;
149d82d4ff0SYann Gautier 		const char *node_name = fdt_get_name(fdt, regulator_node, NULL);
15023684d0eSYann Gautier 		uint16_t voltage;
151d82d4ff0SYann Gautier 		int status;
15223684d0eSYann Gautier 
153d82d4ff0SYann Gautier #if defined(IMAGE_BL2)
154d82d4ff0SYann Gautier 		if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on",
155d82d4ff0SYann Gautier 				 NULL) == NULL) &&
156d82d4ff0SYann Gautier 		    (fdt_getprop(fdt, regulator_node, "regulator-always-on",
157d82d4ff0SYann Gautier 				 NULL) == NULL)) {
158d82d4ff0SYann Gautier #else
15923684d0eSYann Gautier 		if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
16023684d0eSYann Gautier 				NULL) == NULL) {
161d82d4ff0SYann Gautier #endif
16223684d0eSYann Gautier 			continue;
16323684d0eSYann Gautier 		}
16423684d0eSYann Gautier 
165d82d4ff0SYann Gautier 		if (fdt_getprop(fdt, regulator_node, "regulator-pull-down",
166d82d4ff0SYann Gautier 				NULL) != NULL) {
167d82d4ff0SYann Gautier 
168d82d4ff0SYann Gautier 			status = stpmic1_regulator_pull_down_set(node_name);
169d82d4ff0SYann Gautier 			if (status != 0) {
170d82d4ff0SYann Gautier 				return status;
171d82d4ff0SYann Gautier 			}
172d82d4ff0SYann Gautier 		}
173d82d4ff0SYann Gautier 
174d82d4ff0SYann Gautier 		if (fdt_getprop(fdt, regulator_node, "st,mask-reset",
175d82d4ff0SYann Gautier 				NULL) != NULL) {
176d82d4ff0SYann Gautier 
177d82d4ff0SYann Gautier 			status = stpmic1_regulator_mask_reset_set(node_name);
178d82d4ff0SYann Gautier 			if (status != 0) {
179d82d4ff0SYann Gautier 				return status;
180d82d4ff0SYann Gautier 			}
181d82d4ff0SYann Gautier 		}
182d82d4ff0SYann Gautier 
18323684d0eSYann Gautier 		cuint = fdt_getprop(fdt, regulator_node,
18423684d0eSYann Gautier 				    "regulator-min-microvolt", NULL);
18523684d0eSYann Gautier 		if (cuint == NULL) {
18623684d0eSYann Gautier 			continue;
18723684d0eSYann Gautier 		}
18823684d0eSYann Gautier 
18923684d0eSYann Gautier 		/* DT uses microvolts, whereas driver awaits millivolts */
19023684d0eSYann Gautier 		voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
19123684d0eSYann Gautier 
192d82d4ff0SYann Gautier 		status = stpmic1_regulator_voltage_set(node_name, voltage);
19323684d0eSYann Gautier 		if (status != 0) {
19423684d0eSYann Gautier 			return status;
19523684d0eSYann Gautier 		}
19623684d0eSYann Gautier 
19716e56a75SNicolas Le Bayon 		if (!stpmic1_is_regulator_enabled(node_name)) {
19823684d0eSYann Gautier 			status = stpmic1_regulator_enable(node_name);
19923684d0eSYann Gautier 			if (status != 0) {
20023684d0eSYann Gautier 				return status;
20123684d0eSYann Gautier 			}
20223684d0eSYann Gautier 		}
20323684d0eSYann Gautier 	}
20423684d0eSYann Gautier 
20523684d0eSYann Gautier 	return 0;
20623684d0eSYann Gautier }
20723684d0eSYann Gautier 
208d82d4ff0SYann Gautier bool initialize_pmic_i2c(void)
20923684d0eSYann Gautier {
21023684d0eSYann Gautier 	int ret;
21123684d0eSYann Gautier 	struct dt_node_info i2c_info;
212d82d4ff0SYann Gautier 	struct i2c_handle_s *i2c = &i2c_handle;
213d82d4ff0SYann Gautier 	struct stm32_i2c_init_s i2c_init;
21423684d0eSYann Gautier 
215d82d4ff0SYann Gautier 	ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
216d82d4ff0SYann Gautier 	if (ret < 0) {
217d82d4ff0SYann Gautier 		ERROR("I2C configuration failed %d\n", ret);
21823684d0eSYann Gautier 		panic();
21923684d0eSYann Gautier 	}
22023684d0eSYann Gautier 
221d82d4ff0SYann Gautier 	if (ret != 0) {
222d82d4ff0SYann Gautier 		return false;
22323684d0eSYann Gautier 	}
22423684d0eSYann Gautier 
22523684d0eSYann Gautier 	/* Initialize PMIC I2C */
226d82d4ff0SYann Gautier 	i2c->i2c_base_addr		= i2c_info.base;
227d82d4ff0SYann Gautier 	i2c->dt_status			= i2c_info.status;
228d82d4ff0SYann Gautier 	i2c->clock			= i2c_info.clock;
22942822844SBenjamin Gaignard 	i2c->i2c_state			= I2C_STATE_RESET;
230d82d4ff0SYann Gautier 	i2c_init.own_address1		= pmic_i2c_addr;
231d82d4ff0SYann Gautier 	i2c_init.addressing_mode	= I2C_ADDRESSINGMODE_7BIT;
232d82d4ff0SYann Gautier 	i2c_init.dual_address_mode	= I2C_DUALADDRESS_DISABLE;
233d82d4ff0SYann Gautier 	i2c_init.own_address2		= 0;
234d82d4ff0SYann Gautier 	i2c_init.own_address2_masks	= I2C_OAR2_OA2NOMASK;
235d82d4ff0SYann Gautier 	i2c_init.general_call_mode	= I2C_GENERALCALL_DISABLE;
236d82d4ff0SYann Gautier 	i2c_init.no_stretch_mode	= I2C_NOSTRETCH_DISABLE;
237d82d4ff0SYann Gautier 	i2c_init.analog_filter		= 1;
238d82d4ff0SYann Gautier 	i2c_init.digital_filter_coef	= 0;
23923684d0eSYann Gautier 
240d82d4ff0SYann Gautier 	ret = stm32_i2c_init(i2c, &i2c_init);
24123684d0eSYann Gautier 	if (ret != 0) {
24223684d0eSYann Gautier 		ERROR("Cannot initialize I2C %x (%d)\n",
243d82d4ff0SYann Gautier 		      i2c->i2c_base_addr, ret);
24423684d0eSYann Gautier 		panic();
24523684d0eSYann Gautier 	}
24623684d0eSYann Gautier 
247d82d4ff0SYann Gautier 	if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
248d82d4ff0SYann Gautier 				       I2C_TIMEOUT_BUSY_MS)) {
249d82d4ff0SYann Gautier 		ERROR("I2C device not ready\n");
25023684d0eSYann Gautier 		panic();
25123684d0eSYann Gautier 	}
25223684d0eSYann Gautier 
253d82d4ff0SYann Gautier 	stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
25423684d0eSYann Gautier 
255d82d4ff0SYann Gautier 	return true;
25623684d0eSYann Gautier }
25723684d0eSYann Gautier 
258f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void)
259f564d439SEtienne Carriere {
260f564d439SEtienne Carriere 	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
261f564d439SEtienne Carriere 
262f564d439SEtienne Carriere 	if (dt_pmic_is_secure()) {
263f564d439SEtienne Carriere 		stm32mp_register_secure_periph_iomem(i2c_base);
264f564d439SEtienne Carriere 	} else {
265f564d439SEtienne Carriere 		if (i2c_base != 0U) {
266f564d439SEtienne Carriere 			stm32mp_register_non_secure_periph_iomem(i2c_base);
267f564d439SEtienne Carriere 		}
268f564d439SEtienne Carriere 	}
269f564d439SEtienne Carriere }
270f564d439SEtienne Carriere 
27123684d0eSYann Gautier void initialize_pmic(void)
27223684d0eSYann Gautier {
273d82d4ff0SYann Gautier 	if (!initialize_pmic_i2c()) {
274d82d4ff0SYann Gautier 		VERBOSE("No PMIC\n");
275d82d4ff0SYann Gautier 		return;
276d82d4ff0SYann Gautier 	}
27723684d0eSYann Gautier 
278f564d439SEtienne Carriere 	register_pmic_shared_peripherals();
279f564d439SEtienne Carriere 
280*ae7792e0SNicolas Le Bayon 	if (dt_pmic_configure_boot_on_regulators() < 0) {
281*ae7792e0SNicolas Le Bayon 		panic();
282*ae7792e0SNicolas Le Bayon 	};
283*ae7792e0SNicolas Le Bayon }
284*ae7792e0SNicolas Le Bayon 
285*ae7792e0SNicolas Le Bayon #if DEBUG
286*ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void)
287*ae7792e0SNicolas Le Bayon {
288*ae7792e0SNicolas Le Bayon 	unsigned long pmic_version;
289*ae7792e0SNicolas Le Bayon 
290d82d4ff0SYann Gautier 	if (stpmic1_get_version(&pmic_version) != 0) {
291d82d4ff0SYann Gautier 		ERROR("Failed to access PMIC\n");
29223684d0eSYann Gautier 		panic();
29323684d0eSYann Gautier 	}
29423684d0eSYann Gautier 
295d82d4ff0SYann Gautier 	INFO("PMIC version = 0x%02lx\n", pmic_version);
296d82d4ff0SYann Gautier 	stpmic1_dump_regulators();
29723684d0eSYann Gautier }
298*ae7792e0SNicolas Le Bayon #endif
29923684d0eSYann Gautier 
30023684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type)
30123684d0eSYann Gautier {
30223684d0eSYann Gautier 	bool buck3_at_1v8 = false;
30323684d0eSYann Gautier 	uint8_t read_val;
30423684d0eSYann Gautier 	int status;
30523684d0eSYann Gautier 
30623684d0eSYann Gautier 	switch (ddr_type) {
30723684d0eSYann Gautier 	case STM32MP_DDR3:
30823684d0eSYann Gautier 		/* Set LDO3 to sync mode */
30923684d0eSYann Gautier 		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
31023684d0eSYann Gautier 		if (status != 0) {
31123684d0eSYann Gautier 			return status;
31223684d0eSYann Gautier 		}
31323684d0eSYann Gautier 
31423684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO3_MODE;
31523684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
31623684d0eSYann Gautier 		read_val |= STPMIC1_LDO3_DDR_SEL <<
31723684d0eSYann Gautier 			    STPMIC1_LDO12356_OUTPUT_SHIFT;
31823684d0eSYann Gautier 
31923684d0eSYann Gautier 		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
32023684d0eSYann Gautier 		if (status != 0) {
32123684d0eSYann Gautier 			return status;
32223684d0eSYann Gautier 		}
32323684d0eSYann Gautier 
32423684d0eSYann Gautier 		status = stpmic1_regulator_voltage_set("buck2", 1350);
32523684d0eSYann Gautier 		if (status != 0) {
32623684d0eSYann Gautier 			return status;
32723684d0eSYann Gautier 		}
32823684d0eSYann Gautier 
32923684d0eSYann Gautier 		status = stpmic1_regulator_enable("buck2");
33023684d0eSYann Gautier 		if (status != 0) {
33123684d0eSYann Gautier 			return status;
33223684d0eSYann Gautier 		}
33323684d0eSYann Gautier 
33423684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
33523684d0eSYann Gautier 
33623684d0eSYann Gautier 		status = stpmic1_regulator_enable("vref_ddr");
33723684d0eSYann Gautier 		if (status != 0) {
33823684d0eSYann Gautier 			return status;
33923684d0eSYann Gautier 		}
34023684d0eSYann Gautier 
34123684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
34223684d0eSYann Gautier 
34323684d0eSYann Gautier 		status = stpmic1_regulator_enable("ldo3");
34423684d0eSYann Gautier 		if (status != 0) {
34523684d0eSYann Gautier 			return status;
34623684d0eSYann Gautier 		}
34723684d0eSYann Gautier 
34823684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
34923684d0eSYann Gautier 		break;
35023684d0eSYann Gautier 
35123684d0eSYann Gautier 	case STM32MP_LPDDR2:
3524b549b21SYann Gautier 	case STM32MP_LPDDR3:
35323684d0eSYann Gautier 		/*
35423684d0eSYann Gautier 		 * Set LDO3 to 1.8V
35523684d0eSYann Gautier 		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
35623684d0eSYann Gautier 		 * Set LDO3 to normal mode if BUCK3 != 1.8V
35723684d0eSYann Gautier 		 */
35823684d0eSYann Gautier 		status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
35923684d0eSYann Gautier 		if (status != 0) {
36023684d0eSYann Gautier 			return status;
36123684d0eSYann Gautier 		}
36223684d0eSYann Gautier 
36323684d0eSYann Gautier 		if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
36423684d0eSYann Gautier 			buck3_at_1v8 = true;
36523684d0eSYann Gautier 		}
36623684d0eSYann Gautier 
36723684d0eSYann Gautier 		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
36823684d0eSYann Gautier 		if (status != 0) {
36923684d0eSYann Gautier 			return status;
37023684d0eSYann Gautier 		}
37123684d0eSYann Gautier 
37223684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO3_MODE;
37323684d0eSYann Gautier 		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
37423684d0eSYann Gautier 		read_val |= STPMIC1_LDO3_1800000;
37523684d0eSYann Gautier 		if (buck3_at_1v8) {
37623684d0eSYann Gautier 			read_val |= STPMIC1_LDO3_MODE;
37723684d0eSYann Gautier 		}
37823684d0eSYann Gautier 
37923684d0eSYann Gautier 		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
38023684d0eSYann Gautier 		if (status != 0) {
38123684d0eSYann Gautier 			return status;
38223684d0eSYann Gautier 		}
38323684d0eSYann Gautier 
38423684d0eSYann Gautier 		status = stpmic1_regulator_voltage_set("buck2", 1200);
38523684d0eSYann Gautier 		if (status != 0) {
38623684d0eSYann Gautier 			return status;
38723684d0eSYann Gautier 		}
38823684d0eSYann Gautier 
38923684d0eSYann Gautier 		status = stpmic1_regulator_enable("ldo3");
39023684d0eSYann Gautier 		if (status != 0) {
39123684d0eSYann Gautier 			return status;
39223684d0eSYann Gautier 		}
39323684d0eSYann Gautier 
39423684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
39523684d0eSYann Gautier 
39623684d0eSYann Gautier 		status = stpmic1_regulator_enable("buck2");
39723684d0eSYann Gautier 		if (status != 0) {
39823684d0eSYann Gautier 			return status;
39923684d0eSYann Gautier 		}
40023684d0eSYann Gautier 
40123684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
40223684d0eSYann Gautier 
40323684d0eSYann Gautier 		status = stpmic1_regulator_enable("vref_ddr");
40423684d0eSYann Gautier 		if (status != 0) {
40523684d0eSYann Gautier 			return status;
40623684d0eSYann Gautier 		}
40723684d0eSYann Gautier 
40823684d0eSYann Gautier 		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
40923684d0eSYann Gautier 		break;
41023684d0eSYann Gautier 
41123684d0eSYann Gautier 	default:
41223684d0eSYann Gautier 		break;
41323684d0eSYann Gautier 	};
41423684d0eSYann Gautier 
41523684d0eSYann Gautier 	return 0;
41623684d0eSYann Gautier }
417