123684d0eSYann Gautier /*
2*47e62314SPatrick Delaunay * Copyright (c) 2017-2024, 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
233cebeec2SYann Gautier #define NB_REG 14U
2423684d0eSYann Gautier
2523684d0eSYann Gautier static struct i2c_handle_s i2c_handle;
2623684d0eSYann Gautier static uint32_t pmic_i2c_addr;
2723684d0eSYann Gautier
2885fb175bSYann Gautier static int register_pmic(void);
2985fb175bSYann Gautier
dt_get_pmic_node(void * fdt)3023684d0eSYann Gautier static int dt_get_pmic_node(void *fdt)
3123684d0eSYann Gautier {
32c77c7d9eSNicolas Le Bayon static int node = -FDT_ERR_BADOFFSET;
33c77c7d9eSNicolas Le Bayon
34c77c7d9eSNicolas Le Bayon if (node == -FDT_ERR_BADOFFSET) {
35c77c7d9eSNicolas Le Bayon node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
36c77c7d9eSNicolas Le Bayon }
37c77c7d9eSNicolas Le Bayon
38c77c7d9eSNicolas Le Bayon return node;
3923684d0eSYann Gautier }
4023684d0eSYann Gautier
dt_pmic_status(void)41d82d4ff0SYann Gautier int dt_pmic_status(void)
4223684d0eSYann Gautier {
43c77c7d9eSNicolas Le Bayon static int status = -FDT_ERR_BADVALUE;
4423684d0eSYann Gautier int node;
4523684d0eSYann Gautier void *fdt;
4623684d0eSYann Gautier
47c77c7d9eSNicolas Le Bayon if (status != -FDT_ERR_BADVALUE) {
48c77c7d9eSNicolas Le Bayon return status;
49c77c7d9eSNicolas Le Bayon }
50c77c7d9eSNicolas Le Bayon
5123684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) {
52d82d4ff0SYann Gautier return -ENOENT;
5323684d0eSYann Gautier }
5423684d0eSYann Gautier
5523684d0eSYann Gautier node = dt_get_pmic_node(fdt);
56d82d4ff0SYann Gautier if (node <= 0) {
57c77c7d9eSNicolas Le Bayon status = -FDT_ERR_NOTFOUND;
58c77c7d9eSNicolas Le Bayon
59c77c7d9eSNicolas Le Bayon return status;
6023684d0eSYann Gautier }
6123684d0eSYann Gautier
62c77c7d9eSNicolas Le Bayon status = (int)fdt_get_status(node);
63c77c7d9eSNicolas Le Bayon
64c77c7d9eSNicolas Le Bayon return status;
6523684d0eSYann Gautier }
6623684d0eSYann Gautier
dt_pmic_is_secure(void)67f564d439SEtienne Carriere static bool dt_pmic_is_secure(void)
68f564d439SEtienne Carriere {
69f564d439SEtienne Carriere int status = dt_pmic_status();
70f564d439SEtienne Carriere
71f564d439SEtienne Carriere return (status >= 0) &&
72f564d439SEtienne Carriere (status == DT_SECURE) &&
73f564d439SEtienne Carriere (i2c_handle.dt_status == DT_SECURE);
74f564d439SEtienne Carriere }
75f564d439SEtienne Carriere
76d82d4ff0SYann Gautier /*
77d82d4ff0SYann Gautier * Get PMIC and its I2C bus configuration from the device tree.
78c77c7d9eSNicolas Le Bayon * Return 0 on success, negative on error, 1 if no PMIC node is defined.
79d82d4ff0SYann Gautier */
dt_pmic_i2c_config(struct dt_node_info * i2c_info,struct stm32_i2c_init_s * init)80d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
81d82d4ff0SYann Gautier struct stm32_i2c_init_s *init)
8223684d0eSYann Gautier {
83c77c7d9eSNicolas Le Bayon static int i2c_node = -FDT_ERR_NOTFOUND;
8423684d0eSYann Gautier void *fdt;
8523684d0eSYann Gautier
8623684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) {
87c77c7d9eSNicolas Le Bayon return -FDT_ERR_NOTFOUND;
8823684d0eSYann Gautier }
8923684d0eSYann Gautier
90c77c7d9eSNicolas Le Bayon if (i2c_node == -FDT_ERR_NOTFOUND) {
91c77c7d9eSNicolas Le Bayon int pmic_node;
92c77c7d9eSNicolas Le Bayon const fdt32_t *cuint;
93c77c7d9eSNicolas Le Bayon
9423684d0eSYann Gautier pmic_node = dt_get_pmic_node(fdt);
9523684d0eSYann Gautier if (pmic_node < 0) {
96c77c7d9eSNicolas Le Bayon return PMIC_NODE_NOT_FOUND;
9723684d0eSYann Gautier }
9823684d0eSYann Gautier
9923684d0eSYann Gautier cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
10023684d0eSYann Gautier if (cuint == NULL) {
10123684d0eSYann Gautier return -FDT_ERR_NOTFOUND;
10223684d0eSYann Gautier }
10323684d0eSYann Gautier
10423684d0eSYann Gautier pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
10523684d0eSYann Gautier if (pmic_i2c_addr > UINT16_MAX) {
106c77c7d9eSNicolas Le Bayon return -FDT_ERR_BADVALUE;
10723684d0eSYann Gautier }
10823684d0eSYann Gautier
10923684d0eSYann Gautier i2c_node = fdt_parent_offset(fdt, pmic_node);
11023684d0eSYann Gautier if (i2c_node < 0) {
11123684d0eSYann Gautier return -FDT_ERR_NOTFOUND;
11223684d0eSYann Gautier }
113c77c7d9eSNicolas Le Bayon }
11423684d0eSYann Gautier
11523684d0eSYann Gautier dt_fill_device_info(i2c_info, i2c_node);
11623684d0eSYann Gautier if (i2c_info->base == 0U) {
11723684d0eSYann Gautier return -FDT_ERR_NOTFOUND;
11823684d0eSYann Gautier }
11923684d0eSYann Gautier
120d82d4ff0SYann Gautier return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
12123684d0eSYann Gautier }
12223684d0eSYann Gautier
initialize_pmic_i2c(void)123d82d4ff0SYann Gautier bool initialize_pmic_i2c(void)
12423684d0eSYann Gautier {
12523684d0eSYann Gautier int ret;
12623684d0eSYann Gautier struct dt_node_info i2c_info;
127d82d4ff0SYann Gautier struct i2c_handle_s *i2c = &i2c_handle;
128d82d4ff0SYann Gautier struct stm32_i2c_init_s i2c_init;
12923684d0eSYann Gautier
130d82d4ff0SYann Gautier ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
131d82d4ff0SYann Gautier if (ret < 0) {
132d82d4ff0SYann Gautier ERROR("I2C configuration failed %d\n", ret);
13323684d0eSYann Gautier panic();
13423684d0eSYann Gautier }
13523684d0eSYann Gautier
136d82d4ff0SYann Gautier if (ret != 0) {
137d82d4ff0SYann Gautier return false;
13823684d0eSYann Gautier }
13923684d0eSYann Gautier
14023684d0eSYann Gautier /* Initialize PMIC I2C */
141d82d4ff0SYann Gautier i2c->i2c_base_addr = i2c_info.base;
142d82d4ff0SYann Gautier i2c->dt_status = i2c_info.status;
143d82d4ff0SYann Gautier i2c->clock = i2c_info.clock;
14442822844SBenjamin Gaignard i2c->i2c_state = I2C_STATE_RESET;
145d82d4ff0SYann Gautier i2c_init.own_address1 = pmic_i2c_addr;
146d82d4ff0SYann Gautier i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
147d82d4ff0SYann Gautier i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
148d82d4ff0SYann Gautier i2c_init.own_address2 = 0;
149d82d4ff0SYann Gautier i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
150d82d4ff0SYann Gautier i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
151d82d4ff0SYann Gautier i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
152d82d4ff0SYann Gautier i2c_init.analog_filter = 1;
153d82d4ff0SYann Gautier i2c_init.digital_filter_coef = 0;
15423684d0eSYann Gautier
155d82d4ff0SYann Gautier ret = stm32_i2c_init(i2c, &i2c_init);
15623684d0eSYann Gautier if (ret != 0) {
15723684d0eSYann Gautier ERROR("Cannot initialize I2C %x (%d)\n",
158d82d4ff0SYann Gautier i2c->i2c_base_addr, ret);
15923684d0eSYann Gautier panic();
16023684d0eSYann Gautier }
16123684d0eSYann Gautier
162d82d4ff0SYann Gautier if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
163d82d4ff0SYann Gautier I2C_TIMEOUT_BUSY_MS)) {
164d82d4ff0SYann Gautier ERROR("I2C device not ready\n");
16523684d0eSYann Gautier panic();
16623684d0eSYann Gautier }
16723684d0eSYann Gautier
168d82d4ff0SYann Gautier stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
16923684d0eSYann Gautier
170d82d4ff0SYann Gautier return true;
17123684d0eSYann Gautier }
17223684d0eSYann Gautier
register_pmic_shared_peripherals(void)173f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void)
174f564d439SEtienne Carriere {
175f564d439SEtienne Carriere uintptr_t i2c_base = i2c_handle.i2c_base_addr;
176f564d439SEtienne Carriere
177f564d439SEtienne Carriere if (dt_pmic_is_secure()) {
178f564d439SEtienne Carriere stm32mp_register_secure_periph_iomem(i2c_base);
179f564d439SEtienne Carriere } else {
180f564d439SEtienne Carriere if (i2c_base != 0U) {
181f564d439SEtienne Carriere stm32mp_register_non_secure_periph_iomem(i2c_base);
182f564d439SEtienne Carriere }
183f564d439SEtienne Carriere }
184f564d439SEtienne Carriere }
185f564d439SEtienne Carriere
initialize_pmic(void)18623684d0eSYann Gautier void initialize_pmic(void)
18723684d0eSYann Gautier {
188d82d4ff0SYann Gautier if (!initialize_pmic_i2c()) {
189d82d4ff0SYann Gautier VERBOSE("No PMIC\n");
190d82d4ff0SYann Gautier return;
191d82d4ff0SYann Gautier }
19223684d0eSYann Gautier
193f564d439SEtienne Carriere register_pmic_shared_peripherals();
194f564d439SEtienne Carriere
19585fb175bSYann Gautier if (register_pmic() < 0) {
196ae7792e0SNicolas Le Bayon panic();
19785fb175bSYann Gautier }
19885fb175bSYann Gautier
19985fb175bSYann Gautier if (stpmic1_powerctrl_on() < 0) {
20085fb175bSYann Gautier panic();
20185fb175bSYann Gautier }
20285fb175bSYann Gautier
203ae7792e0SNicolas Le Bayon }
204ae7792e0SNicolas Le Bayon
205ae7792e0SNicolas Le Bayon #if DEBUG
print_pmic_info_and_debug(void)206ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void)
207ae7792e0SNicolas Le Bayon {
208ae7792e0SNicolas Le Bayon unsigned long pmic_version;
209ae7792e0SNicolas Le Bayon
210d82d4ff0SYann Gautier if (stpmic1_get_version(&pmic_version) != 0) {
211d82d4ff0SYann Gautier ERROR("Failed to access PMIC\n");
21223684d0eSYann Gautier panic();
21323684d0eSYann Gautier }
21423684d0eSYann Gautier
215d82d4ff0SYann Gautier INFO("PMIC version = 0x%02lx\n", pmic_version);
21623684d0eSYann Gautier }
217ae7792e0SNicolas Le Bayon #endif
21823684d0eSYann Gautier
pmic_voltages_init(void)2195278ec3fSYann Gautier int pmic_voltages_init(void)
2205278ec3fSYann Gautier {
2215278ec3fSYann Gautier #if STM32MP13
2225278ec3fSYann Gautier struct rdev *buck1, *buck4;
2235278ec3fSYann Gautier int status;
2245278ec3fSYann Gautier
2255278ec3fSYann Gautier buck1 = regulator_get_by_name("buck1");
2265278ec3fSYann Gautier if (buck1 == NULL) {
2275278ec3fSYann Gautier return -ENOENT;
2285278ec3fSYann Gautier }
2295278ec3fSYann Gautier
2305278ec3fSYann Gautier buck4 = regulator_get_by_name("buck4");
2315278ec3fSYann Gautier if (buck4 == NULL) {
2325278ec3fSYann Gautier return -ENOENT;
2335278ec3fSYann Gautier }
2345278ec3fSYann Gautier
2355278ec3fSYann Gautier status = regulator_set_min_voltage(buck1);
2365278ec3fSYann Gautier if (status != 0) {
2375278ec3fSYann Gautier return status;
2385278ec3fSYann Gautier }
2395278ec3fSYann Gautier
2405278ec3fSYann Gautier status = regulator_set_min_voltage(buck4);
2415278ec3fSYann Gautier if (status != 0) {
2425278ec3fSYann Gautier return status;
2435278ec3fSYann Gautier }
2445278ec3fSYann Gautier #endif
2455278ec3fSYann Gautier
2465278ec3fSYann Gautier return 0;
2475278ec3fSYann Gautier }
2485278ec3fSYann Gautier
24985fb175bSYann Gautier enum {
25085fb175bSYann Gautier STPMIC1_BUCK1 = 0,
25185fb175bSYann Gautier STPMIC1_BUCK2,
25285fb175bSYann Gautier STPMIC1_BUCK3,
25385fb175bSYann Gautier STPMIC1_BUCK4,
25485fb175bSYann Gautier STPMIC1_LDO1,
25585fb175bSYann Gautier STPMIC1_LDO2,
25685fb175bSYann Gautier STPMIC1_LDO3,
25785fb175bSYann Gautier STPMIC1_LDO4,
25885fb175bSYann Gautier STPMIC1_LDO5,
25985fb175bSYann Gautier STPMIC1_LDO6,
26085fb175bSYann Gautier STPMIC1_VREF_DDR,
26185fb175bSYann Gautier STPMIC1_BOOST,
26285fb175bSYann Gautier STPMIC1_VBUS_OTG,
26385fb175bSYann Gautier STPMIC1_SW_OUT,
26485fb175bSYann Gautier };
26585fb175bSYann Gautier
pmic_set_state(const struct regul_description * desc,bool enable)26685fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable)
26785fb175bSYann Gautier {
26847065ffeSYann Gautier VERBOSE("%s: set state to %d\n", desc->node_name, enable);
26985fb175bSYann Gautier
27085fb175bSYann Gautier if (enable == STATE_ENABLE) {
27185fb175bSYann Gautier return stpmic1_regulator_enable(desc->node_name);
27285fb175bSYann Gautier } else {
27385fb175bSYann Gautier return stpmic1_regulator_disable(desc->node_name);
27485fb175bSYann Gautier }
27585fb175bSYann Gautier }
27685fb175bSYann Gautier
pmic_get_state(const struct regul_description * desc)27785fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc)
27885fb175bSYann Gautier {
27985fb175bSYann Gautier VERBOSE("%s: get state\n", desc->node_name);
28085fb175bSYann Gautier
28185fb175bSYann Gautier return stpmic1_is_regulator_enabled(desc->node_name);
28285fb175bSYann Gautier }
28385fb175bSYann Gautier
pmic_get_voltage(const struct regul_description * desc)28485fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc)
28585fb175bSYann Gautier {
28685fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name);
28785fb175bSYann Gautier
28885fb175bSYann Gautier return stpmic1_regulator_voltage_get(desc->node_name);
28985fb175bSYann Gautier }
29085fb175bSYann Gautier
pmic_set_voltage(const struct regul_description * desc,uint16_t mv)29185fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
29285fb175bSYann Gautier {
29385fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name);
29485fb175bSYann Gautier
29585fb175bSYann Gautier return stpmic1_regulator_voltage_set(desc->node_name, mv);
29685fb175bSYann Gautier }
29785fb175bSYann Gautier
pmic_list_voltages(const struct regul_description * desc,const uint16_t ** levels,size_t * count)29885fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc,
29985fb175bSYann Gautier const uint16_t **levels, size_t *count)
30085fb175bSYann Gautier {
30185fb175bSYann Gautier VERBOSE("%s: list volt\n", desc->node_name);
30285fb175bSYann Gautier
30385fb175bSYann Gautier return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
30485fb175bSYann Gautier }
30585fb175bSYann Gautier
pmic_set_flag(const struct regul_description * desc,uint16_t flag)30685fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
30785fb175bSYann Gautier {
30885fb175bSYann Gautier VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
30985fb175bSYann Gautier
31085fb175bSYann Gautier switch (flag) {
31185fb175bSYann Gautier case REGUL_OCP:
31285fb175bSYann Gautier return stpmic1_regulator_icc_set(desc->node_name);
31385fb175bSYann Gautier
31485fb175bSYann Gautier case REGUL_ACTIVE_DISCHARGE:
31585fb175bSYann Gautier return stpmic1_active_discharge_mode_set(desc->node_name);
31685fb175bSYann Gautier
31785fb175bSYann Gautier case REGUL_PULL_DOWN:
31885fb175bSYann Gautier return stpmic1_regulator_pull_down_set(desc->node_name);
31985fb175bSYann Gautier
32085fb175bSYann Gautier case REGUL_MASK_RESET:
32185fb175bSYann Gautier return stpmic1_regulator_mask_reset_set(desc->node_name);
32285fb175bSYann Gautier
32385fb175bSYann Gautier case REGUL_SINK_SOURCE:
32485fb175bSYann Gautier return stpmic1_regulator_sink_mode_set(desc->node_name);
32585fb175bSYann Gautier
32685fb175bSYann Gautier case REGUL_ENABLE_BYPASS:
32785fb175bSYann Gautier return stpmic1_regulator_bypass_mode_set(desc->node_name);
32885fb175bSYann Gautier
32985fb175bSYann Gautier default:
33085fb175bSYann Gautier return -EINVAL;
33185fb175bSYann Gautier }
33285fb175bSYann Gautier }
33385fb175bSYann Gautier
33457e60183SYann Gautier static const struct regul_ops pmic_ops = {
33585fb175bSYann Gautier .set_state = pmic_set_state,
33685fb175bSYann Gautier .get_state = pmic_get_state,
33785fb175bSYann Gautier .set_voltage = pmic_set_voltage,
33885fb175bSYann Gautier .get_voltage = pmic_get_voltage,
33985fb175bSYann Gautier .list_voltages = pmic_list_voltages,
34085fb175bSYann Gautier .set_flag = pmic_set_flag,
34185fb175bSYann Gautier };
34285fb175bSYann Gautier
34385fb175bSYann Gautier #define DEFINE_REGU(name) { \
344be7195d0SYann Gautier .node_name = (name), \
34585fb175bSYann Gautier .ops = &pmic_ops, \
34685fb175bSYann Gautier .driver_data = NULL, \
34785fb175bSYann Gautier .enable_ramp_delay = 1000, \
34885fb175bSYann Gautier }
34985fb175bSYann Gautier
3503cebeec2SYann Gautier static const struct regul_description pmic_regs[NB_REG] = {
35185fb175bSYann Gautier [STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
35285fb175bSYann Gautier [STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
35385fb175bSYann Gautier [STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
35485fb175bSYann Gautier [STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
35585fb175bSYann Gautier [STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
35685fb175bSYann Gautier [STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
35785fb175bSYann Gautier [STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
35885fb175bSYann Gautier [STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
35985fb175bSYann Gautier [STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
36085fb175bSYann Gautier [STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
36185fb175bSYann Gautier [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
36285fb175bSYann Gautier [STPMIC1_BOOST] = DEFINE_REGU("boost"),
36385fb175bSYann Gautier [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
36485fb175bSYann Gautier [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
36585fb175bSYann Gautier };
36685fb175bSYann Gautier
register_pmic(void)36785fb175bSYann Gautier static int register_pmic(void)
36885fb175bSYann Gautier {
36985fb175bSYann Gautier void *fdt;
37085fb175bSYann Gautier int pmic_node, regulators_node, subnode;
37185fb175bSYann Gautier
37285fb175bSYann Gautier VERBOSE("Register pmic\n");
37385fb175bSYann Gautier
37485fb175bSYann Gautier if (fdt_get_address(&fdt) == 0) {
37585fb175bSYann Gautier return -FDT_ERR_NOTFOUND;
37685fb175bSYann Gautier }
37785fb175bSYann Gautier
37885fb175bSYann Gautier pmic_node = dt_get_pmic_node(fdt);
37985fb175bSYann Gautier if (pmic_node < 0) {
38085fb175bSYann Gautier return pmic_node;
38185fb175bSYann Gautier }
38285fb175bSYann Gautier
38385fb175bSYann Gautier regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
38485fb175bSYann Gautier if (regulators_node < 0) {
38585fb175bSYann Gautier return -ENOENT;
38685fb175bSYann Gautier }
38785fb175bSYann Gautier
38885fb175bSYann Gautier fdt_for_each_subnode(subnode, fdt, regulators_node) {
38985fb175bSYann Gautier const char *reg_name = fdt_get_name(fdt, subnode, NULL);
39085fb175bSYann Gautier const struct regul_description *desc;
39185fb175bSYann Gautier unsigned int i;
39285fb175bSYann Gautier int ret;
39385fb175bSYann Gautier
3943cebeec2SYann Gautier for (i = 0U; i < NB_REG; i++) {
39585fb175bSYann Gautier desc = &pmic_regs[i];
39685fb175bSYann Gautier if (strcmp(desc->node_name, reg_name) == 0) {
39785fb175bSYann Gautier break;
39885fb175bSYann Gautier }
39985fb175bSYann Gautier }
40085fb175bSYann Gautier assert(i < NB_REG);
40185fb175bSYann Gautier
40285fb175bSYann Gautier ret = regulator_register(desc, subnode);
40385fb175bSYann Gautier if (ret != 0) {
40485fb175bSYann Gautier WARN("%s:%d failed to register %s\n", __func__,
40585fb175bSYann Gautier __LINE__, reg_name);
40685fb175bSYann Gautier return ret;
40785fb175bSYann Gautier }
40885fb175bSYann Gautier }
40985fb175bSYann Gautier
41085fb175bSYann Gautier return 0;
41185fb175bSYann Gautier }
412