1 /*
2  * Copyright (c) 2021 NXP
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nxp_pca9420
7 
8 #include <errno.h>
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/regulator.h>
13 #include <zephyr/drivers/regulator/pca9420.h>
14 #include <zephyr/sys/linear_range.h>
15 #include <zephyr/sys/util.h>
16 
17 /** Register memory map. See datasheet for more details. */
18 /** General purpose registers */
19 /** @brief Top level system ctrl 0 */
20 #define PCA9420_TOP_CNTL0     0x09U
21 /** @brief Top level system ctrl 2 */
22 #define PCA9420_TOP_CNTL2     0x0BU
23 /** @brief Top level system ctrl 3 */
24 #define PCA9420_TOP_CNTL3     0x0CU
25 
26 /** Regulator status indication registers */
27 /** @brief Active Discharge configuration for mode 0_0 */
28 #define PCA9420_ACT_DISCHARGE_CNTL   0x21U
29 /** @brief Mode configuration for mode 0_0 */
30 #define PCA9420_MODECFG_0_0          0x22U
31 /** @brief Mode configuration for mode 0_1 */
32 #define PCA9420_MODECFG_0_1          0x23U
33 /** @brief Mode configuration for mode 0_2 */
34 #define PCA9420_MODECFG_0_2          0x24U
35 /** @brief Mode configuration for mode 0_3 */
36 #define PCA9420_MODECFG_0_3          0x25U
37 
38 /** @brief VIN input current limit selection */
39 #define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS 5U
40 #define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U
41 #define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED 0x7U
42 
43 /** @brief ASYS UVLO threshold selection */
44 #define PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_POS  6U
45 #define PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_MASK 0xC0U
46 
47 /** @brief I2C Mode control mask */
48 #define PCA9420_TOP_CNTL3_MODE_I2C_POS 3U
49 #define PCA9420_TOP_CNTL3_MODE_I2C_MASK 0x18U
50 
51 /*
52  * @brief Mode control selection mask. When this bit is set, the external
53  * PMIC pins MODESEL0 and MODESEL1 can be used to select the active mode
54  */
55 #define PCA9420_MODECFG_0_X_EN_MODE_SEL_BY_PIN 0x40U
56 
57 /*
58  * @brief Mode configuration upon falling edge applied to ON pin. If set,
59  * the device will switch to mode 0 when a valid falling edge is applied.
60  * to the ON pin
61  */
62 /** @brief Mode output voltage mask */
63 #define PCA9420_MODECFG_0_SW1_OUT_MASK       0x3FU
64 #define PCA9420_MODECFG_0_SW1_OUT_POS        0U
65 /** @brief SW2_OUT offset and voltage level mask */
66 #define PCA9420_MODECFG_1_SW2_OUT_MASK       0x3FU
67 #define PCA9420_MODECFG_1_SW2_OUT_POS        0U
68 /** @brief LDO1_OUT voltage level mask */
69 #define PCA9420_MODECFG_2_LDO1_OUT_MASK      0xF0U
70 #define PCA9420_MODECFG_2_LDO1_OUT_POS       4U
71 /** @brief SW1 Enable */
72 #define PCA9420_MODECFG_2_SW1_EN_MASK	     0x08U
73 #define PCA9420_MODECFG_2_SW1_EN_VAL	     0x08U
74 /** @brief SW2 Enable */
75 #define PCA9420_MODECFG_2_SW2_EN_MASK	     0x04U
76 #define PCA9420_MODECFG_2_SW2_EN_VAL	     0x04U
77 /** @brief LDO1 Enable */
78 #define PCA9420_MODECFG_2_LDO1_EN_MASK	     0x02U
79 #define PCA9420_MODECFG_2_LDO1_EN_VAL	     0x02U
80 /** @brief LDO2 Enable */
81 #define PCA9420_MODECFG_2_LDO2_EN_MASK	     0x01U
82 #define PCA9420_MODECFG_2_LDO2_EN_VAL	     0x01U
83 /** @brief LDO2_OUT offset and voltage level mask */
84 #define PCA9420_MODECFG_3_LDO2_OUT_MASK      0x3FU
85 #define PCA9420_MODECFG_3_LDO2_OUT_POS       0U
86 /** @brief SW1 active discharge control */
87 #define PCA9420_ACT_DISCHARGE_CNTL_SW1_MASK  0x08U
88 #define PCA9420_ACT_DISCHARGE_CNTL_SW1_POS   4U
89 /** @brief SW2 active discharge control */
90 #define PCA9420_ACT_DISCHARGE_CNTL_SW2_MASK  0x04U
91 #define PCA9420_ACT_DISCHARGE_CNTL_SW2_POS   3U
92 /** @brief LDO1 active discharge control */
93 #define PCA9420_ACT_DISCHARGE_CNTL_LDO1_MASK 0x02U
94 #define PCA9420_ACT_DISCHARGE_CNTL_LDO1_POS  2U
95 /** @brief LDO2 active discharge control */
96 #define PCA9420_ACT_DISCHARGE_CNTL_LDO2_MASK 0x01U
97 #define PCA9420_ACT_DISCHARGE_CNTL_LDO2_POS  1U
98 
99 /** VIN ILIM resolution, uA/LSB */
100 #define PCA9420_VIN_ILIM_UA_LSB 170000
101 /** VIN ILIM minimum value, uA */
102 #define PCA9420_VIN_ILIM_MIN_UA 85000
103 
104 /** Number of modes */
105 #define PCA9420_NUM_MODES 4U
106 /** Offset applied to MODECFG* registers for a given mode */
107 #define PCA9420_MODECFG_OFFSET(mode) ((mode) * 4U)
108 
109 struct regulator_pca9420_desc {
110 	uint8_t enable_reg;
111 	uint8_t enable_mask;
112 	uint8_t enable_val;
113 	uint8_t vsel_reg;
114 	uint8_t vsel_mask;
115 	uint8_t vsel_pos;
116 	uint8_t ad_mask;
117 	uint8_t ad_pos;
118 	int32_t max_ua;
119 	uint8_t num_ranges;
120 	const struct linear_range *ranges;
121 };
122 
123 struct regulator_pca9420_common_config {
124 	struct i2c_dt_spec i2c;
125 	int32_t vin_ilim_ua;
126 	bool enable_modesel_pins;
127 	uint8_t asys_uvlo_sel_mv;
128 };
129 
130 struct regulator_pca9420_common_data {
131 	regulator_dvs_state_t dvs_state;
132 };
133 
134 struct regulator_pca9420_config {
135 	struct regulator_common_config common;
136 	bool enable_inverted;
137 	int32_t modes_uv[4];
138 	const struct regulator_pca9420_desc *desc;
139 	const struct device *parent;
140 };
141 
142 struct regulator_pca9420_data {
143 	struct regulator_common_data data;
144 };
145 
146 static const struct linear_range buck1_ranges[] = {
147 	LINEAR_RANGE_INIT(500000, 25000U, 0x0U, 0x28U),
148 	LINEAR_RANGE_INIT(1500000, 0U, 0x29U, 0x3E),
149 	LINEAR_RANGE_INIT(1800000, 0U, 0x3FU, 0x3FU),
150 };
151 
152 static const struct linear_range buck2_ranges[] = {
153 	LINEAR_RANGE_INIT(1500000, 25000U, 0x0U, 0x18U),
154 	LINEAR_RANGE_INIT(2100000, 0U, 0x19U, 0x1F),
155 	LINEAR_RANGE_INIT(2700000, 25000U, 0x20U, 0x38U),
156 	LINEAR_RANGE_INIT(3300000, 0U, 0x39U, 0x3F),
157 };
158 
159 static const struct linear_range ldo1_ranges[] = {
160 	LINEAR_RANGE_INIT(1700000, 25000U, 0x0U, 0x9U),
161 	LINEAR_RANGE_INIT(1900000, 0U, 0x9U, 0xFU),
162 };
163 
164 static const struct linear_range ldo2_ranges[] = {
165 	LINEAR_RANGE_INIT(1500000, 25000U, 0x0U, 0x18U),
166 	LINEAR_RANGE_INIT(2100000, 0U, 0x19U, 0x1FU),
167 	LINEAR_RANGE_INIT(2700000, 25000U, 0x20U, 0x38U),
168 	LINEAR_RANGE_INIT(3300000, 0U, 0x39U, 0x3FU),
169 };
170 
171 static const struct regulator_pca9420_desc buck1_desc = {
172 	.enable_reg = PCA9420_MODECFG_0_2,
173 	.enable_mask = PCA9420_MODECFG_2_SW1_EN_MASK,
174 	.enable_val = PCA9420_MODECFG_2_SW1_EN_VAL,
175 	.vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK,
176 	.vsel_pos = PCA9420_MODECFG_0_SW1_OUT_POS,
177 	.vsel_reg = PCA9420_MODECFG_0_0,
178 	.ad_mask = PCA9420_ACT_DISCHARGE_CNTL_SW1_MASK,
179 	.ad_pos = PCA9420_ACT_DISCHARGE_CNTL_SW1_POS,
180 	.max_ua = 250000,
181 	.ranges = buck1_ranges,
182 	.num_ranges = ARRAY_SIZE(buck1_ranges),
183 };
184 
185 static const struct regulator_pca9420_desc buck2_desc = {
186 	.enable_reg = PCA9420_MODECFG_0_2,
187 	.enable_mask = PCA9420_MODECFG_2_SW2_EN_MASK,
188 	.enable_val = PCA9420_MODECFG_2_SW2_EN_VAL,
189 	.vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK,
190 	.vsel_pos = PCA9420_MODECFG_1_SW2_OUT_POS,
191 	.vsel_reg = PCA9420_MODECFG_0_1,
192 	.ad_mask = PCA9420_ACT_DISCHARGE_CNTL_SW2_MASK,
193 	.ad_pos = PCA9420_ACT_DISCHARGE_CNTL_SW2_POS,
194 	.max_ua = 500000,
195 	.ranges = buck2_ranges,
196 	.num_ranges = ARRAY_SIZE(buck2_ranges),
197 };
198 
199 static const struct regulator_pca9420_desc ldo1_desc = {
200 	.enable_reg = PCA9420_MODECFG_0_2,
201 	.enable_mask = PCA9420_MODECFG_2_LDO1_EN_MASK,
202 	.enable_val = PCA9420_MODECFG_2_LDO1_EN_VAL,
203 	.vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK,
204 	.vsel_pos = PCA9420_MODECFG_2_LDO1_OUT_POS,
205 	.vsel_reg = PCA9420_MODECFG_0_2,
206 	.ad_mask = PCA9420_ACT_DISCHARGE_CNTL_LDO1_MASK,
207 	.ad_pos = PCA9420_ACT_DISCHARGE_CNTL_LDO1_POS,
208 	.max_ua = 1000,
209 	.ranges = ldo1_ranges,
210 	.num_ranges = ARRAY_SIZE(ldo1_ranges),
211 };
212 
213 static const struct regulator_pca9420_desc ldo2_desc = {
214 	.enable_reg = PCA9420_MODECFG_0_2,
215 	.enable_mask = PCA9420_MODECFG_2_LDO2_EN_MASK,
216 	.enable_val = PCA9420_MODECFG_2_LDO2_EN_VAL,
217 	.vsel_reg = PCA9420_MODECFG_0_3,
218 	.vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK,
219 	.vsel_pos = PCA9420_MODECFG_3_LDO2_OUT_POS,
220 	.ad_mask = PCA9420_ACT_DISCHARGE_CNTL_LDO2_MASK,
221 	.ad_pos = PCA9420_ACT_DISCHARGE_CNTL_LDO2_POS,
222 	.max_ua = 250000,
223 	.ranges = ldo2_ranges,
224 	.num_ranges = ARRAY_SIZE(ldo2_ranges),
225 };
226 
regulator_pca9420_count_voltages(const struct device * dev)227 static unsigned int regulator_pca9420_count_voltages(const struct device *dev)
228 {
229 	const struct regulator_pca9420_config *config = dev->config;
230 
231 	return linear_range_group_values_count(config->desc->ranges,
232 					       config->desc->num_ranges);
233 }
234 
regulator_pca9420_list_voltage(const struct device * dev,unsigned int idx,int32_t * volt_uv)235 static int regulator_pca9420_list_voltage(const struct device *dev,
236 					  unsigned int idx, int32_t *volt_uv)
237 {
238 	const struct regulator_pca9420_config *config = dev->config;
239 
240 	return linear_range_group_get_value(config->desc->ranges,
241 					    config->desc->num_ranges, idx,
242 					    volt_uv);
243 }
244 
regulator_pca9420_set_voltage(const struct device * dev,int32_t min_uv,int32_t max_uv)245 static int regulator_pca9420_set_voltage(const struct device *dev,
246 					 int32_t min_uv, int32_t max_uv)
247 {
248 	const struct regulator_pca9420_config *config = dev->config;
249 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
250 	struct regulator_pca9420_common_data *cdata = config->parent->data;
251 	uint16_t idx;
252 	int ret;
253 
254 	ret = linear_range_group_get_win_index(config->desc->ranges,
255 					       config->desc->num_ranges, min_uv,
256 					       max_uv, &idx);
257 	if (ret == -EINVAL) {
258 		return ret;
259 	}
260 
261 	idx <<= config->desc->vsel_pos;
262 
263 	return i2c_reg_update_byte_dt(&cconfig->i2c, config->desc->vsel_reg +
264 				      PCA9420_MODECFG_OFFSET(cdata->dvs_state),
265 				      config->desc->vsel_mask, (uint8_t)idx);
266 }
267 
regulator_pca9420_get_voltage(const struct device * dev,int32_t * volt_uv)268 static int regulator_pca9420_get_voltage(const struct device *dev,
269 					 int32_t *volt_uv)
270 {
271 	const struct regulator_pca9420_config *config = dev->config;
272 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
273 	struct regulator_pca9420_common_data *cdata = config->parent->data;
274 	int ret;
275 	uint8_t raw_reg;
276 
277 	ret = i2c_reg_read_byte_dt(&cconfig->i2c, config->desc->vsel_reg +
278 				   PCA9420_MODECFG_OFFSET(cdata->dvs_state),
279 				   &raw_reg);
280 	if (ret < 0) {
281 		return ret;
282 	}
283 
284 	raw_reg = (raw_reg & config->desc->vsel_mask) >> config->desc->vsel_pos;
285 
286 	return linear_range_group_get_value(config->desc->ranges,
287 					    config->desc->num_ranges, raw_reg,
288 					    volt_uv);
289 }
290 
regulator_pca9420_get_current_limit(const struct device * dev,int32_t * curr_ua)291 static int regulator_pca9420_get_current_limit(const struct device *dev,
292 					       int32_t *curr_ua)
293 {
294 	const struct regulator_pca9420_config *config = dev->config;
295 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
296 
297 	if (cconfig->vin_ilim_ua == 0U) {
298 		*curr_ua = config->desc->max_ua;
299 	} else {
300 		*curr_ua = MIN(config->desc->max_ua, cconfig->vin_ilim_ua);
301 	}
302 
303 	return 0;
304 }
305 
regulator_pca9420_set_active_discharge(const struct device * dev,bool active_discharge)306 static int regulator_pca9420_set_active_discharge(const struct device *dev,
307 							bool active_discharge)
308 {
309 	const struct regulator_pca9420_config *config = dev->config;
310 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
311 	uint8_t dis_val;
312 
313 	dis_val = (!active_discharge) << config->desc->ad_pos;
314 	return i2c_reg_update_byte_dt(&cconfig->i2c, PCA9420_ACT_DISCHARGE_CNTL,
315 				      config->desc->ad_mask, dis_val);
316 }
317 
regulator_pca9420_get_active_discharge(const struct device * dev,bool * active_discharge)318 static int regulator_pca9420_get_active_discharge(const struct device *dev,
319 							bool *active_discharge)
320 {
321 	const struct regulator_pca9420_config *config = dev->config;
322 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
323 	uint8_t raw_reg;
324 	int ret;
325 
326 	ret = i2c_reg_read_byte_dt(&cconfig->i2c, PCA9420_ACT_DISCHARGE_CNTL, &raw_reg);
327 	if (ret < 0) {
328 		return ret;
329 	}
330 
331 	*active_discharge = !((raw_reg & config->desc->ad_mask) >> config->desc->ad_pos);
332 
333 	return 0;
334 }
335 
regulator_pca9420_enable(const struct device * dev)336 static int regulator_pca9420_enable(const struct device *dev)
337 {
338 	const struct regulator_pca9420_config *config = dev->config;
339 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
340 	struct regulator_pca9420_common_data *cdata = config->parent->data;
341 	uint8_t en_val;
342 
343 	en_val = config->enable_inverted ? 0 : config->desc->enable_val;
344 	return i2c_reg_update_byte_dt(&cconfig->i2c, config->desc->enable_reg
345 				      + PCA9420_MODECFG_OFFSET(cdata->dvs_state),
346 				      config->desc->enable_mask, en_val);
347 }
348 
regulator_pca9420_disable(const struct device * dev)349 static int regulator_pca9420_disable(const struct device *dev)
350 {
351 	const struct regulator_pca9420_config *config = dev->config;
352 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
353 	struct regulator_pca9420_common_data *cdata = config->parent->data;
354 	uint8_t dis_val;
355 
356 	dis_val = config->enable_inverted ? config->desc->enable_val : 0;
357 	return i2c_reg_update_byte_dt(&cconfig->i2c, config->desc->enable_reg
358 				      + PCA9420_MODECFG_OFFSET(cdata->dvs_state),
359 				      config->desc->enable_mask, dis_val);
360 }
361 
362 static const struct regulator_driver_api api = {
363 	.enable = regulator_pca9420_enable,
364 	.disable = regulator_pca9420_disable,
365 	.count_voltages = regulator_pca9420_count_voltages,
366 	.list_voltage = regulator_pca9420_list_voltage,
367 	.set_voltage = regulator_pca9420_set_voltage,
368 	.get_voltage = regulator_pca9420_get_voltage,
369 	.get_current_limit = regulator_pca9420_get_current_limit,
370 	.set_active_discharge = regulator_pca9420_set_active_discharge,
371 	.get_active_discharge = regulator_pca9420_get_active_discharge,
372 };
373 
regulator_pca9420_init(const struct device * dev)374 static int regulator_pca9420_init(const struct device *dev)
375 {
376 	const struct regulator_pca9420_config *config = dev->config;
377 	const struct regulator_pca9420_common_config *cconfig = config->parent->config;
378 
379 	regulator_common_data_init(dev);
380 
381 	if (!device_is_ready(config->parent)) {
382 		return -ENODEV;
383 	}
384 
385 	/* configure mode voltages */
386 	for (uint8_t i = 0U; i < ARRAY_SIZE(config->modes_uv); i++) {
387 		int ret;
388 
389 		if (config->modes_uv[i] == 0) {
390 			/* disable mode if voltage is 0 */
391 			ret = i2c_reg_update_byte_dt(
392 				&cconfig->i2c,
393 				config->desc->enable_reg + PCA9420_MODECFG_OFFSET(i),
394 				config->desc->enable_mask, 0U);
395 			if (ret < 0) {
396 				return ret;
397 			}
398 		} else if (config->modes_uv[i] > 0) {
399 			uint16_t idx;
400 
401 			/* program mode voltage */
402 			ret = linear_range_group_get_win_index(
403 				config->desc->ranges, config->desc->num_ranges,
404 				config->modes_uv[i], config->modes_uv[i], &idx);
405 			if (ret == -EINVAL) {
406 				return ret;
407 			}
408 
409 			idx <<= config->desc->vsel_pos;
410 
411 			ret = i2c_reg_update_byte_dt(
412 				&cconfig->i2c,
413 				config->desc->vsel_reg + PCA9420_MODECFG_OFFSET(i),
414 				config->desc->vsel_mask, (uint8_t)idx);
415 			if (ret < 0) {
416 				return ret;
417 			}
418 		}
419 	}
420 
421 	return regulator_common_init(dev, false);
422 }
423 
regulator_pca9420_dvs_state_set(const struct device * dev,regulator_dvs_state_t state)424 int regulator_pca9420_dvs_state_set(const struct device *dev,
425 				    regulator_dvs_state_t state)
426 {
427 	const struct regulator_pca9420_common_config *config = dev->config;
428 	struct regulator_pca9420_common_data *data = dev->data;
429 	int ret;
430 
431 	if (state >= PCA9420_NUM_MODES) {
432 		return -ENOTSUP;
433 	}
434 
435 	if (config->enable_modesel_pins) {
436 		/*
437 		 * The user cannot set DVS state via this API,
438 		 * but they may want to query/set voltages for another mode.
439 		 * Return -EPERM to indicate change failed, but change the
440 		 * dvs_state variable so the user can access the alternative
441 		 * dvs mode settings.
442 		 */
443 		data->dvs_state = state;
444 		return -EPERM;
445 	}
446 
447 	ret = i2c_reg_update_byte_dt(&config->i2c, PCA9420_TOP_CNTL3,
448 				      PCA9420_TOP_CNTL3_MODE_I2C_MASK,
449 				      state << PCA9420_TOP_CNTL3_MODE_I2C_POS);
450 	if (ret < 0) {
451 		return ret;
452 	}
453 	/* Record new DVS state */
454 	data->dvs_state = state;
455 	return 0;
456 }
457 
458 static const struct regulator_parent_driver_api parent_api = {
459 	.dvs_state_set = regulator_pca9420_dvs_state_set,
460 };
461 
regulator_pca9420_common_init(const struct device * dev)462 static int regulator_pca9420_common_init(const struct device *dev)
463 {
464 	const struct regulator_pca9420_common_config *config = dev->config;
465 	uint8_t reg_val = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED;
466 	int ret;
467 
468 	if (!device_is_ready(config->i2c.bus)) {
469 		return -ENODEV;
470 	}
471 
472 	if (config->enable_modesel_pins) {
473 		/* enable MODESEL0/1 pins for each mode */
474 		for (uint8_t i = 0U; i < PCA9420_NUM_MODES; i++) {
475 			ret = i2c_reg_update_byte_dt(
476 				&config->i2c,
477 				PCA9420_MODECFG_0_0 +
478 				PCA9420_MODECFG_OFFSET(i),
479 				PCA9420_MODECFG_0_X_EN_MODE_SEL_BY_PIN,
480 				PCA9420_MODECFG_0_X_EN_MODE_SEL_BY_PIN);
481 			if (ret < 0) {
482 				return ret;
483 			}
484 		}
485 	}
486 
487 	/* configure VIN current limit */
488 	if (config->vin_ilim_ua != 0U) {
489 		reg_val = (config->vin_ilim_ua - PCA9420_VIN_ILIM_MIN_UA) /
490 			  PCA9420_VIN_ILIM_UA_LSB;
491 	}
492 
493 	ret = i2c_reg_update_byte_dt(
494 		&config->i2c, PCA9420_TOP_CNTL0,
495 		PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
496 		reg_val << PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS);
497 
498 	if (ret != 0) {
499 		return ret;
500 	}
501 
502 	/* configure ASYS UVLO threshold */
503 	return i2c_reg_update_byte_dt(&config->i2c, PCA9420_TOP_CNTL2,
504 		PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_MASK,
505 		config->asys_uvlo_sel_mv <<
506 		PCA9420_TOP_CNTL2_ASYS_UVLO_SEL_POS);
507 }
508 
509 #define REGULATOR_PCA9420_DEFINE(node_id, id, name, _parent)                   \
510 	static struct regulator_pca9420_data data_##id;                        \
511                                                                                \
512 	static const struct regulator_pca9420_config config_##id = {           \
513 		.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id),            \
514 		.enable_inverted = DT_PROP(node_id, enable_inverted),          \
515 		.modes_uv = {                                                  \
516 			DT_PROP_OR(node_id, nxp_mode0_microvolt, -1),          \
517 			DT_PROP_OR(node_id, nxp_mode1_microvolt, -1),          \
518 			DT_PROP_OR(node_id, nxp_mode2_microvolt, -1),          \
519 			DT_PROP_OR(node_id, nxp_mode3_microvolt, -1),          \
520 		},                                                             \
521 		.desc = &name ## _desc,                                        \
522 		.parent = _parent,                                             \
523 	};                                                                     \
524                                                                                \
525 	DEVICE_DT_DEFINE(node_id, regulator_pca9420_init, NULL, &data_##id,    \
526 			 &config_##id, POST_KERNEL,                            \
527 			 CONFIG_REGULATOR_PCA9420_INIT_PRIORITY, &api);
528 
529 #define REGULATOR_PCA9420_DEFINE_COND(inst, child, parent)                     \
530 	COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)),                \
531 		    (REGULATOR_PCA9420_DEFINE(DT_INST_CHILD(inst, child),      \
532 					      child ## inst, child, parent)),  \
533 		    ())
534 
535 #define REGULATOR_PCA9420_DEFINE_ALL(inst)                                     \
536 	static const struct regulator_pca9420_common_config config_##inst = {  \
537 		.i2c = I2C_DT_SPEC_INST_GET(inst),                             \
538 		.vin_ilim_ua = DT_INST_PROP(inst, nxp_vin_ilim_microamp),      \
539 		.enable_modesel_pins =                                         \
540 			DT_INST_PROP(inst, nxp_enable_modesel_pins),           \
541 		.asys_uvlo_sel_mv =                                            \
542 			DT_INST_ENUM_IDX(inst, nxp_asys_uvlo_sel_millivolt),   \
543 	};                                                                     \
544                                                                                \
545 	static struct regulator_pca9420_common_data data_##inst;               \
546                                                                                \
547 	DEVICE_DT_INST_DEFINE(inst, regulator_pca9420_common_init, NULL,       \
548 			      &data_##inst,                                    \
549 			      &config_##inst, POST_KERNEL,                     \
550 			      CONFIG_REGULATOR_PCA9420_COMMON_INIT_PRIORITY,   \
551 			      &parent_api);                                    \
552                                                                                \
553 	REGULATOR_PCA9420_DEFINE_COND(inst, buck1, DEVICE_DT_INST_GET(inst))   \
554 	REGULATOR_PCA9420_DEFINE_COND(inst, buck2, DEVICE_DT_INST_GET(inst))   \
555 	REGULATOR_PCA9420_DEFINE_COND(inst, ldo1, DEVICE_DT_INST_GET(inst))    \
556 	REGULATOR_PCA9420_DEFINE_COND(inst, ldo2, DEVICE_DT_INST_GET(inst))
557 
558 DT_INST_FOREACH_STATUS_OKAY(REGULATOR_PCA9420_DEFINE_ALL)
559