blob: 1e1628770be5c1cc8fb610fd6a7f538b125c4b3d [file] [log] [blame]
Yann Gautierbb836ee2018-07-16 17:55:07 +02001/*
Yann Gautierf0a74762022-01-06 09:35:35 +01002 * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
Yann Gautierbb836ee2018-07-16 17:55:07 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautiere6f10322021-09-27 14:31:40 +02007#include <assert.h>
Yann Gautierbb836ee2018-07-16 17:55:07 +02008#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <common/debug.h>
11#include <drivers/delay_timer.h>
Yann Gautiere6f10322021-09-27 14:31:40 +020012#include <drivers/st/regulator.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010013#include <drivers/st/stm32_i2c.h>
Yann Gautiera45433b2019-01-16 18:31:00 +010014#include <drivers/st/stm32mp_pmic.h>
Yann Gautiera45433b2019-01-16 18:31:00 +010015#include <drivers/st/stpmic1.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <lib/mmio.h>
17#include <lib/utils_def.h>
Nicolas Le Bayonf5188ee2019-09-19 11:24:50 +020018#include <libfdt.h>
19
20#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000021
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010022#define PMIC_NODE_NOT_FOUND 1
Yann Gautierf64eae02022-11-24 18:17:02 +010023#define NB_REG 14U
Yann Gautierbb836ee2018-07-16 17:55:07 +020024
25static struct i2c_handle_s i2c_handle;
26static uint32_t pmic_i2c_addr;
27
Yann Gautiere6f10322021-09-27 14:31:40 +020028static int register_pmic(void);
29
Yann Gautierbb836ee2018-07-16 17:55:07 +020030static int dt_get_pmic_node(void *fdt)
31{
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010032 static int node = -FDT_ERR_BADOFFSET;
33
34 if (node == -FDT_ERR_BADOFFSET) {
35 node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
36 }
37
38 return node;
Yann Gautierbb836ee2018-07-16 17:55:07 +020039}
40
Yann Gautierf3928f62019-02-14 11:15:03 +010041int dt_pmic_status(void)
Yann Gautierbb836ee2018-07-16 17:55:07 +020042{
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010043 static int status = -FDT_ERR_BADVALUE;
Yann Gautierbb836ee2018-07-16 17:55:07 +020044 int node;
45 void *fdt;
46
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010047 if (status != -FDT_ERR_BADVALUE) {
48 return status;
49 }
50
Yann Gautierbb836ee2018-07-16 17:55:07 +020051 if (fdt_get_address(&fdt) == 0) {
Yann Gautierf3928f62019-02-14 11:15:03 +010052 return -ENOENT;
Yann Gautierbb836ee2018-07-16 17:55:07 +020053 }
54
55 node = dt_get_pmic_node(fdt);
Yann Gautierf3928f62019-02-14 11:15:03 +010056 if (node <= 0) {
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010057 status = -FDT_ERR_NOTFOUND;
58
59 return status;
Yann Gautierbb836ee2018-07-16 17:55:07 +020060 }
61
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010062 status = (int)fdt_get_status(node);
63
64 return status;
Yann Gautierbb836ee2018-07-16 17:55:07 +020065}
66
Etienne Carriere67b106a2019-12-02 10:10:08 +010067static bool dt_pmic_is_secure(void)
68{
69 int status = dt_pmic_status();
70
71 return (status >= 0) &&
72 (status == DT_SECURE) &&
73 (i2c_handle.dt_status == DT_SECURE);
74}
75
Yann Gautierf3928f62019-02-14 11:15:03 +010076/*
77 * Get PMIC and its I2C bus configuration from the device tree.
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010078 * Return 0 on success, negative on error, 1 if no PMIC node is defined.
Yann Gautierf3928f62019-02-14 11:15:03 +010079 */
80static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
81 struct stm32_i2c_init_s *init)
Yann Gautierbb836ee2018-07-16 17:55:07 +020082{
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010083 static int i2c_node = -FDT_ERR_NOTFOUND;
Yann Gautierbb836ee2018-07-16 17:55:07 +020084 void *fdt;
Yann Gautierbb836ee2018-07-16 17:55:07 +020085
86 if (fdt_get_address(&fdt) == 0) {
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010087 return -FDT_ERR_NOTFOUND;
Yann Gautierbb836ee2018-07-16 17:55:07 +020088 }
89
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010090 if (i2c_node == -FDT_ERR_NOTFOUND) {
91 int pmic_node;
92 const fdt32_t *cuint;
Yann Gautierbb836ee2018-07-16 17:55:07 +020093
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010094 pmic_node = dt_get_pmic_node(fdt);
95 if (pmic_node < 0) {
96 return PMIC_NODE_NOT_FOUND;
97 }
Yann Gautierbb836ee2018-07-16 17:55:07 +020098
Nicolas Le Bayon342865a2019-11-15 15:56:06 +010099 cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
100 if (cuint == NULL) {
101 return -FDT_ERR_NOTFOUND;
102 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200103
Nicolas Le Bayon342865a2019-11-15 15:56:06 +0100104 pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
105 if (pmic_i2c_addr > UINT16_MAX) {
106 return -FDT_ERR_BADVALUE;
107 }
108
109 i2c_node = fdt_parent_offset(fdt, pmic_node);
110 if (i2c_node < 0) {
111 return -FDT_ERR_NOTFOUND;
112 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200113 }
114
115 dt_fill_device_info(i2c_info, i2c_node);
116 if (i2c_info->base == 0U) {
117 return -FDT_ERR_NOTFOUND;
118 }
119
Yann Gautierf3928f62019-02-14 11:15:03 +0100120 return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200121}
122
Yann Gautierf3928f62019-02-14 11:15:03 +0100123bool initialize_pmic_i2c(void)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200124{
125 int ret;
126 struct dt_node_info i2c_info;
Yann Gautierf3928f62019-02-14 11:15:03 +0100127 struct i2c_handle_s *i2c = &i2c_handle;
128 struct stm32_i2c_init_s i2c_init;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200129
Yann Gautierf3928f62019-02-14 11:15:03 +0100130 ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
131 if (ret < 0) {
132 ERROR("I2C configuration failed %d\n", ret);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200133 panic();
134 }
135
Yann Gautierf3928f62019-02-14 11:15:03 +0100136 if (ret != 0) {
137 return false;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200138 }
139
140 /* Initialize PMIC I2C */
Yann Gautierf3928f62019-02-14 11:15:03 +0100141 i2c->i2c_base_addr = i2c_info.base;
142 i2c->dt_status = i2c_info.status;
143 i2c->clock = i2c_info.clock;
Benjamin Gaignard53ee7d32020-02-24 13:57:40 +0100144 i2c->i2c_state = I2C_STATE_RESET;
Yann Gautierf3928f62019-02-14 11:15:03 +0100145 i2c_init.own_address1 = pmic_i2c_addr;
146 i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
147 i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
148 i2c_init.own_address2 = 0;
149 i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
150 i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
151 i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
152 i2c_init.analog_filter = 1;
153 i2c_init.digital_filter_coef = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200154
Yann Gautierf3928f62019-02-14 11:15:03 +0100155 ret = stm32_i2c_init(i2c, &i2c_init);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200156 if (ret != 0) {
157 ERROR("Cannot initialize I2C %x (%d)\n",
Yann Gautierf3928f62019-02-14 11:15:03 +0100158 i2c->i2c_base_addr, ret);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200159 panic();
160 }
161
Yann Gautierf3928f62019-02-14 11:15:03 +0100162 if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
163 I2C_TIMEOUT_BUSY_MS)) {
164 ERROR("I2C device not ready\n");
Yann Gautierbb836ee2018-07-16 17:55:07 +0200165 panic();
166 }
167
Yann Gautierf3928f62019-02-14 11:15:03 +0100168 stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200169
Yann Gautierf3928f62019-02-14 11:15:03 +0100170 return true;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200171}
172
Etienne Carriere67b106a2019-12-02 10:10:08 +0100173static void register_pmic_shared_peripherals(void)
174{
175 uintptr_t i2c_base = i2c_handle.i2c_base_addr;
176
177 if (dt_pmic_is_secure()) {
178 stm32mp_register_secure_periph_iomem(i2c_base);
179 } else {
180 if (i2c_base != 0U) {
181 stm32mp_register_non_secure_periph_iomem(i2c_base);
182 }
183 }
184}
185
Yann Gautierbb836ee2018-07-16 17:55:07 +0200186void initialize_pmic(void)
187{
Yann Gautierf3928f62019-02-14 11:15:03 +0100188 if (!initialize_pmic_i2c()) {
189 VERBOSE("No PMIC\n");
190 return;
191 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200192
Etienne Carriere67b106a2019-12-02 10:10:08 +0100193 register_pmic_shared_peripherals();
194
Yann Gautiere6f10322021-09-27 14:31:40 +0200195 if (register_pmic() < 0) {
Nicolas Le Bayon0b10b652019-11-18 13:13:36 +0100196 panic();
Yann Gautiere6f10322021-09-27 14:31:40 +0200197 }
198
199 if (stpmic1_powerctrl_on() < 0) {
200 panic();
201 }
202
Nicolas Le Bayon0b10b652019-11-18 13:13:36 +0100203}
204
205#if DEBUG
206void print_pmic_info_and_debug(void)
207{
208 unsigned long pmic_version;
209
Yann Gautierf3928f62019-02-14 11:15:03 +0100210 if (stpmic1_get_version(&pmic_version) != 0) {
211 ERROR("Failed to access PMIC\n");
Yann Gautierbb836ee2018-07-16 17:55:07 +0200212 panic();
213 }
214
Yann Gautierf3928f62019-02-14 11:15:03 +0100215 INFO("PMIC version = 0x%02lx\n", pmic_version);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200216}
Nicolas Le Bayon0b10b652019-11-18 13:13:36 +0100217#endif
Yann Gautierbb836ee2018-07-16 17:55:07 +0200218
219int pmic_ddr_power_init(enum ddr_type ddr_type)
220{
Yann Gautierbb836ee2018-07-16 17:55:07 +0200221 int status;
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100222 uint16_t buck3_min_mv;
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100223 struct rdev *buck2, *buck3, *vref;
224 struct rdev *ldo3 __unused;
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100225
226 buck2 = regulator_get_by_name("buck2");
227 if (buck2 == NULL) {
228 return -ENOENT;
229 }
230
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100231#if STM32MP15
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100232 ldo3 = regulator_get_by_name("ldo3");
233 if (ldo3 == NULL) {
234 return -ENOENT;
235 }
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100236#endif
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100237
238 vref = regulator_get_by_name("vref_ddr");
239 if (vref == NULL) {
240 return -ENOENT;
241 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200242
243 switch (ddr_type) {
244 case STM32MP_DDR3:
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100245#if STM32MP15
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100246 status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200247 if (status != 0) {
248 return status;
249 }
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100250#endif
Yann Gautierbb836ee2018-07-16 17:55:07 +0200251
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100252 status = regulator_set_min_voltage(buck2);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200253 if (status != 0) {
254 return status;
255 }
256
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100257 status = regulator_enable(buck2);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200258 if (status != 0) {
259 return status;
260 }
261
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100262 status = regulator_enable(vref);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200263 if (status != 0) {
264 return status;
265 }
266
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100267#if STM32MP15
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100268 status = regulator_enable(ldo3);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200269 if (status != 0) {
270 return status;
271 }
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100272#endif
Yann Gautierbb836ee2018-07-16 17:55:07 +0200273 break;
274
275 case STM32MP_LPDDR2:
Yann Gautier917a00c2019-04-16 16:20:58 +0200276 case STM32MP_LPDDR3:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200277 /*
278 * Set LDO3 to 1.8V
279 * Set LDO3 to bypass mode if BUCK3 = 1.8V
280 * Set LDO3 to normal mode if BUCK3 != 1.8V
281 */
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100282 buck3 = regulator_get_by_name("buck3");
283 if (buck3 == NULL) {
284 return -ENOENT;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200285 }
286
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100287 regulator_get_range(buck3, &buck3_min_mv, NULL);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200288
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100289#if STM32MP15
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100290 if (buck3_min_mv != 1800) {
291 status = regulator_set_min_voltage(ldo3);
292 if (status != 0) {
293 return status;
294 }
295 } else {
296 status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS);
297 if (status != 0) {
298 return status;
299 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200300 }
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100301#endif
Yann Gautierbb836ee2018-07-16 17:55:07 +0200302
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100303 status = regulator_set_min_voltage(buck2);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200304 if (status != 0) {
305 return status;
306 }
307
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100308#if STM32MP15
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100309 status = regulator_enable(ldo3);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200310 if (status != 0) {
311 return status;
312 }
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100313#endif
Yann Gautierbb836ee2018-07-16 17:55:07 +0200314
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100315 status = regulator_enable(buck2);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200316 if (status != 0) {
317 return status;
318 }
319
Pascal Paillet5e36dbb2020-12-15 19:05:09 +0100320 status = regulator_enable(vref);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200321 if (status != 0) {
322 return status;
323 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200324 break;
325
326 default:
327 break;
328 };
329
330 return 0;
331}
Yann Gautiere6f10322021-09-27 14:31:40 +0200332
Yann Gautiere05e8cf2022-01-18 15:49:42 +0100333int pmic_voltages_init(void)
334{
335#if STM32MP13
336 struct rdev *buck1, *buck4;
337 int status;
338
339 buck1 = regulator_get_by_name("buck1");
340 if (buck1 == NULL) {
341 return -ENOENT;
342 }
343
344 buck4 = regulator_get_by_name("buck4");
345 if (buck4 == NULL) {
346 return -ENOENT;
347 }
348
349 status = regulator_set_min_voltage(buck1);
350 if (status != 0) {
351 return status;
352 }
353
354 status = regulator_set_min_voltage(buck4);
355 if (status != 0) {
356 return status;
357 }
358#endif
359
360 return 0;
361}
362
Yann Gautiere6f10322021-09-27 14:31:40 +0200363enum {
364 STPMIC1_BUCK1 = 0,
365 STPMIC1_BUCK2,
366 STPMIC1_BUCK3,
367 STPMIC1_BUCK4,
368 STPMIC1_LDO1,
369 STPMIC1_LDO2,
370 STPMIC1_LDO3,
371 STPMIC1_LDO4,
372 STPMIC1_LDO5,
373 STPMIC1_LDO6,
374 STPMIC1_VREF_DDR,
375 STPMIC1_BOOST,
376 STPMIC1_VBUS_OTG,
377 STPMIC1_SW_OUT,
378};
379
380static int pmic_set_state(const struct regul_description *desc, bool enable)
381{
Yann Gautierf0a74762022-01-06 09:35:35 +0100382 VERBOSE("%s: set state to %d\n", desc->node_name, enable);
Yann Gautiere6f10322021-09-27 14:31:40 +0200383
384 if (enable == STATE_ENABLE) {
385 return stpmic1_regulator_enable(desc->node_name);
386 } else {
387 return stpmic1_regulator_disable(desc->node_name);
388 }
389}
390
391static int pmic_get_state(const struct regul_description *desc)
392{
393 VERBOSE("%s: get state\n", desc->node_name);
394
395 return stpmic1_is_regulator_enabled(desc->node_name);
396}
397
398static int pmic_get_voltage(const struct regul_description *desc)
399{
400 VERBOSE("%s: get volt\n", desc->node_name);
401
402 return stpmic1_regulator_voltage_get(desc->node_name);
403}
404
405static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
406{
407 VERBOSE("%s: get volt\n", desc->node_name);
408
409 return stpmic1_regulator_voltage_set(desc->node_name, mv);
410}
411
412static int pmic_list_voltages(const struct regul_description *desc,
413 const uint16_t **levels, size_t *count)
414{
415 VERBOSE("%s: list volt\n", desc->node_name);
416
417 return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
418}
419
420static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
421{
422 VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
423
424 switch (flag) {
425 case REGUL_OCP:
426 return stpmic1_regulator_icc_set(desc->node_name);
427
428 case REGUL_ACTIVE_DISCHARGE:
429 return stpmic1_active_discharge_mode_set(desc->node_name);
430
431 case REGUL_PULL_DOWN:
432 return stpmic1_regulator_pull_down_set(desc->node_name);
433
434 case REGUL_MASK_RESET:
435 return stpmic1_regulator_mask_reset_set(desc->node_name);
436
437 case REGUL_SINK_SOURCE:
438 return stpmic1_regulator_sink_mode_set(desc->node_name);
439
440 case REGUL_ENABLE_BYPASS:
441 return stpmic1_regulator_bypass_mode_set(desc->node_name);
442
443 default:
444 return -EINVAL;
445 }
446}
447
Yann Gautierb62e1172022-02-09 17:35:45 +0100448static const struct regul_ops pmic_ops = {
Yann Gautiere6f10322021-09-27 14:31:40 +0200449 .set_state = pmic_set_state,
450 .get_state = pmic_get_state,
451 .set_voltage = pmic_set_voltage,
452 .get_voltage = pmic_get_voltage,
453 .list_voltages = pmic_list_voltages,
454 .set_flag = pmic_set_flag,
455};
456
457#define DEFINE_REGU(name) { \
Yann Gautier4737ed62022-11-24 18:14:26 +0100458 .node_name = (name), \
Yann Gautiere6f10322021-09-27 14:31:40 +0200459 .ops = &pmic_ops, \
460 .driver_data = NULL, \
461 .enable_ramp_delay = 1000, \
462}
463
Yann Gautierf64eae02022-11-24 18:17:02 +0100464static const struct regul_description pmic_regs[NB_REG] = {
Yann Gautiere6f10322021-09-27 14:31:40 +0200465 [STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
466 [STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
467 [STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
468 [STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
469 [STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
470 [STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
471 [STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
472 [STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
473 [STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
474 [STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
475 [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
476 [STPMIC1_BOOST] = DEFINE_REGU("boost"),
477 [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
478 [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
479};
480
Yann Gautiere6f10322021-09-27 14:31:40 +0200481static int register_pmic(void)
482{
483 void *fdt;
484 int pmic_node, regulators_node, subnode;
485
486 VERBOSE("Register pmic\n");
487
488 if (fdt_get_address(&fdt) == 0) {
489 return -FDT_ERR_NOTFOUND;
490 }
491
492 pmic_node = dt_get_pmic_node(fdt);
493 if (pmic_node < 0) {
494 return pmic_node;
495 }
496
497 regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
498 if (regulators_node < 0) {
499 return -ENOENT;
500 }
501
502 fdt_for_each_subnode(subnode, fdt, regulators_node) {
503 const char *reg_name = fdt_get_name(fdt, subnode, NULL);
504 const struct regul_description *desc;
505 unsigned int i;
506 int ret;
507
Yann Gautierf64eae02022-11-24 18:17:02 +0100508 for (i = 0U; i < NB_REG; i++) {
Yann Gautiere6f10322021-09-27 14:31:40 +0200509 desc = &pmic_regs[i];
510 if (strcmp(desc->node_name, reg_name) == 0) {
511 break;
512 }
513 }
514 assert(i < NB_REG);
515
516 ret = regulator_register(desc, subnode);
517 if (ret != 0) {
518 WARN("%s:%d failed to register %s\n", __func__,
519 __LINE__, reg_name);
520 return ret;
521 }
522 }
523
524 return 0;
525}