1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_npm2100_regulator
7 
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/drivers/regulator.h>
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/dt-bindings/regulator/npm2100.h>
15 #include <zephyr/sys/linear_range.h>
16 #include <zephyr/sys/util.h>
17 
18 enum npm2100_sources {
19 	NPM2100_SOURCE_BOOST,
20 	NPM2100_SOURCE_LDOSW,
21 };
22 
23 #define BOOST_VOUT     0x22U
24 #define BOOST_VOUTSEL  0x23U
25 #define BOOST_OPER     0x24U
26 #define BOOST_LIMIT    0x26U
27 #define BOOST_GPIO     0x28U
28 #define BOOST_PIN      0x29U
29 #define BOOST_CTRLSET  0x2AU
30 #define BOOST_CTRLCLR  0x2BU
31 #define BOOST_IBATLIM  0x2DU
32 #define BOOST_VBATMINL 0x2FU
33 #define BOOST_VBATMINH 0x30U
34 #define BOOST_VOUTMIN  0x31U
35 #define BOOST_VOUTWRN  0x32U
36 #define BOOST_VOUTDPS  0x33U
37 #define BOOST_STATUS0  0x34U
38 #define BOOST_STATUS1  0x35U
39 #define BOOST_VSET0    0x36U
40 #define BOOST_VSET1    0x37U
41 
42 #define LDOSW_VOUT   0x68U
43 #define LDOSW_ENABLE 0x69U
44 #define LDOSW_SEL    0x6AU
45 #define LDOSW_GPIO   0x6BU
46 #define LDOSW_STATUS 0x6EU
47 #define LDOSW_PRGOCP 0x6FU
48 
49 #define SHIP_TASK_SHIP 0xC0U
50 
51 #define RESET_ALTCONFIG    0xD6U
52 #define RESET_WRITESTICKY  0xDBU
53 #define RESET_STROBESTICKY 0xDCU
54 
55 #define BOOST_OPER_MODE_MASK     0x07U
56 #define BOOST_OPER_MODE_AUTO     0x00U
57 #define BOOST_OPER_MODE_HP       0x01U
58 #define BOOST_OPER_MODE_LP       0x02U
59 #define BOOST_OPER_MODE_PASS     0x03U
60 #define BOOST_OPER_MODE_NOHP     0x04U
61 #define BOOST_OPER_DPS_MASK      0x18U
62 #define BOOST_OPER_DPS_DISABLE   0x00U
63 #define BOOST_OPER_DPS_ALLOW     0x01U
64 #define BOOST_OPER_DPS_ALLOWLP   0x02U
65 #define BOOST_OPER_DPSTIMER_MASK 0x60U
66 
67 #define BOOST_PIN_FORCE_HP   0x00U
68 #define BOOST_PIN_FORCE_LP   0x01U
69 #define BOOST_PIN_FORCE_PASS 0x02U
70 #define BOOST_PIN_FORCE_NOHP 0x03U
71 
72 #define BOOST_STATUS0_MODE_MASK 0x07U
73 #define BOOST_STATUS0_MODE_HP   0x00U
74 #define BOOST_STATUS0_MODE_LP   0x01U
75 #define BOOST_STATUS0_MODE_ULP  0x02U
76 #define BOOST_STATUS0_MODE_PT   0x03U
77 #define BOOST_STATUS0_MODE_DPS  0x04U
78 
79 #define BOOST_STATUS1_VSET_MASK 0x40U
80 
81 #define LDOSW_SEL_OPER_MASK 0x06U
82 #define LDOSW_SEL_OPER_AUTO 0x00U
83 #define LDOSW_SEL_OPER_ULP  0x02U
84 #define LDOSW_SEL_OPER_HP   0x04U
85 #define LDOSW_SEL_OPER_PIN  0x06U
86 
87 #define LDOSW_GPIO_PIN_MASK     0x07U
88 #define LDOSW_GPIO_PINACT_MASK  0x18U
89 #define LDOSW_GPIO_PINACT_HP    0x00U
90 #define LDOSW_GPIO_PINACT_ULP   0x08U
91 #define LDOSW_GPIO_PININACT_OFF 0x00U
92 #define LDOSW_GPIO_PININACT_ULP 0x10U
93 
94 #define LDOSW_STATUS_LDO 0x01U
95 #define LDOSW_STATUS_SW  0x02U
96 #define LDOSW_STATUS_HP  0x04U
97 #define LDOSW_STATUS_ULP 0x08U
98 #define LDOSW_STATUS_OCP 0x10U
99 
100 #define RESET_ALTCONFIG_LDOSW_OFF 0x01U
101 
102 struct regulator_npm2100_pconfig {
103 	struct i2c_dt_spec i2c;
104 	struct gpio_dt_spec dvs_state_pins[2];
105 };
106 
107 struct regulator_npm2100_config {
108 	struct regulator_common_config common;
109 	struct i2c_dt_spec i2c;
110 	uint8_t source;
111 	struct gpio_dt_spec mode_gpios;
112 	bool ldosw_wd_reset;
113 	uint8_t dps_timer;
114 	uint8_t dps_pulse_limit;
115 };
116 
117 struct regulator_npm2100_data {
118 	struct regulator_common_data data;
119 	bool ldsw_mode;
120 };
121 
122 static const struct linear_range boost_range = LINEAR_RANGE_INIT(1800000, 50000, 0U, 30U);
123 static const struct linear_range ldosw_range = LINEAR_RANGE_INIT(800000, 50000, 8U, 52U);
124 static const struct linear_range vset0_range = LINEAR_RANGE_INIT(1800000, 100000, 0U, 6U);
125 static const struct linear_range vset1_ranges[] = {LINEAR_RANGE_INIT(3000000, 0, 0U, 0U),
126 						   LINEAR_RANGE_INIT(2700000, 100000, 1U, 3U),
127 						   LINEAR_RANGE_INIT(3100000, 100000, 4U, 6U)};
128 static const struct linear_range boost_ocp_range = LINEAR_RANGE_INIT(0, 300000, 0U, 1U);
129 
130 static const struct linear_range ldsw_ocp_ranges[] = {LINEAR_RANGE_INIT(40000, 0, 0U, 0U),
131 						      LINEAR_RANGE_INIT(70000, 5000, 1U, 3U),
132 						      LINEAR_RANGE_INIT(110000, 0, 4U, 4U)};
133 static const uint8_t ldo_ocp_lookup[] = {13, 7, 6, 4, 1};
134 
135 static const struct linear_range ldo_ocp_ranges[] = {LINEAR_RANGE_INIT(25000, 13000, 0U, 1U),
136 						     LINEAR_RANGE_INIT(50000, 25000, 2U, 3U),
137 						     LINEAR_RANGE_INIT(150000, 0, 4U, 4U)};
138 static const uint8_t ldsw_ocp_lookup[] = {1, 7, 8, 9, 15};
139 
regulator_npm2100_count_voltages(const struct device * dev)140 static unsigned int regulator_npm2100_count_voltages(const struct device *dev)
141 {
142 	const struct regulator_npm2100_config *config = dev->config;
143 
144 	switch (config->source) {
145 	case NPM2100_SOURCE_BOOST:
146 		return linear_range_values_count(&boost_range);
147 	case NPM2100_SOURCE_LDOSW:
148 		return linear_range_values_count(&ldosw_range);
149 	default:
150 		return 0;
151 	}
152 }
153 
regulator_npm2100_list_voltage(const struct device * dev,unsigned int idx,int32_t * volt_uv)154 static int regulator_npm2100_list_voltage(const struct device *dev, unsigned int idx,
155 					  int32_t *volt_uv)
156 {
157 	const struct regulator_npm2100_config *config = dev->config;
158 
159 	switch (config->source) {
160 	case NPM2100_SOURCE_BOOST:
161 		return linear_range_get_value(&boost_range, idx, volt_uv);
162 	case NPM2100_SOURCE_LDOSW:
163 		return linear_range_get_value(&ldosw_range, idx, volt_uv);
164 	default:
165 		return -EINVAL;
166 	}
167 }
168 
regulator_npm2100_set_voltage(const struct device * dev,int32_t min_uv,int32_t max_uv)169 static int regulator_npm2100_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv)
170 {
171 	const struct regulator_npm2100_config *config = dev->config;
172 	uint16_t idx;
173 	int ret;
174 
175 	switch (config->source) {
176 	case NPM2100_SOURCE_BOOST:
177 		ret = linear_range_get_win_index(&boost_range, min_uv, max_uv, &idx);
178 		if (ret == -EINVAL) {
179 			return ret;
180 		}
181 
182 		ret = i2c_reg_write_byte_dt(&config->i2c, BOOST_VOUT, idx);
183 		if (ret < 0) {
184 			return ret;
185 		}
186 
187 		/* Enable SW control of boost voltage */
188 		return i2c_reg_write_byte_dt(&config->i2c, BOOST_VOUTSEL, 1U);
189 
190 	case NPM2100_SOURCE_LDOSW:
191 		ret = linear_range_get_win_index(&ldosw_range, min_uv, max_uv, &idx);
192 		if (ret == -EINVAL) {
193 			return ret;
194 		}
195 
196 		return i2c_reg_write_byte_dt(&config->i2c, LDOSW_VOUT, idx);
197 
198 	default:
199 		return -ENODEV;
200 	}
201 }
202 
regulator_npm2100_get_voltage(const struct device * dev,int32_t * volt_uv)203 static int regulator_npm2100_get_voltage(const struct device *dev, int32_t *volt_uv)
204 {
205 	const struct regulator_npm2100_config *config = dev->config;
206 	uint8_t idx;
207 	int ret;
208 
209 	switch (config->source) {
210 	case NPM2100_SOURCE_BOOST:
211 		ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_VOUTSEL, &idx);
212 		if (ret < 0) {
213 			return ret;
214 		}
215 
216 		if (idx == 1U) {
217 			/* Voltage is selected by register value */
218 			ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_VOUT, &idx);
219 			if (ret < 0) {
220 				return ret;
221 			}
222 
223 			return linear_range_get_value(&boost_range, idx, volt_uv);
224 		}
225 
226 		/* Voltage is selected by VSET pin */
227 		ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_STATUS1, &idx);
228 		if (ret < 0) {
229 			return ret;
230 		}
231 
232 		if ((idx & BOOST_STATUS1_VSET_MASK) == 0U) {
233 			/* VSET low, voltage is selected by VSET0 register */
234 			ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_VSET0, &idx);
235 			if (ret < 0) {
236 				return ret;
237 			}
238 
239 			return linear_range_get_value(&vset0_range, idx, volt_uv);
240 		}
241 
242 		/* VSET high, voltage is selected by VSET1 register */
243 		ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_VSET1, &idx);
244 		if (ret < 0) {
245 			return ret;
246 		}
247 
248 		return linear_range_group_get_value(vset1_ranges, ARRAY_SIZE(vset1_ranges), idx,
249 						    volt_uv);
250 
251 	case NPM2100_SOURCE_LDOSW:
252 		ret = i2c_reg_read_byte_dt(&config->i2c, LDOSW_VOUT, &idx);
253 		if (ret < 0) {
254 			return ret;
255 		}
256 
257 		return linear_range_get_value(&ldosw_range, idx, volt_uv);
258 
259 	default:
260 		return -ENODEV;
261 	}
262 }
263 
regulator_npm2100_count_currents(const struct device * dev)264 static unsigned int regulator_npm2100_count_currents(const struct device *dev)
265 {
266 	const struct regulator_npm2100_config *config = dev->config;
267 	const struct regulator_npm2100_data *data = dev->data;
268 
269 	switch (config->source) {
270 	case NPM2100_SOURCE_BOOST:
271 		return linear_range_values_count(&boost_ocp_range);
272 	case NPM2100_SOURCE_LDOSW:
273 		if (data->ldsw_mode) {
274 			return linear_range_group_values_count(ldsw_ocp_ranges,
275 							       ARRAY_SIZE(ldsw_ocp_ranges));
276 		}
277 		return linear_range_group_values_count(ldo_ocp_ranges, ARRAY_SIZE(ldo_ocp_ranges));
278 	default:
279 		return 0;
280 	}
281 }
282 
regulator_npm2100_list_currents(const struct device * dev,unsigned int idx,int32_t * current_ua)283 static int regulator_npm2100_list_currents(const struct device *dev, unsigned int idx,
284 					   int32_t *current_ua)
285 {
286 	const struct regulator_npm2100_config *config = dev->config;
287 	const struct regulator_npm2100_data *data = dev->data;
288 
289 	switch (config->source) {
290 	case NPM2100_SOURCE_BOOST:
291 		return linear_range_get_value(&boost_ocp_range, idx, current_ua);
292 	case NPM2100_SOURCE_LDOSW:
293 		if (data->ldsw_mode) {
294 			return linear_range_group_get_value(
295 				ldsw_ocp_ranges, ARRAY_SIZE(ldsw_ocp_ranges), idx, current_ua);
296 		}
297 		return linear_range_group_get_value(ldo_ocp_ranges, ARRAY_SIZE(ldo_ocp_ranges), idx,
298 						    current_ua);
299 	default:
300 		return -EINVAL;
301 	}
302 }
303 
regulator_npm2100_set_current(const struct device * dev,int32_t min_ua,int32_t max_ua)304 static int regulator_npm2100_set_current(const struct device *dev, int32_t min_ua, int32_t max_ua)
305 {
306 	const struct regulator_npm2100_config *config = dev->config;
307 	const struct regulator_npm2100_data *data = dev->data;
308 	uint16_t idx = 0;
309 	uint8_t shift = 0;
310 	int ret;
311 
312 	switch (config->source) {
313 	case NPM2100_SOURCE_BOOST:
314 		ret = linear_range_get_win_index(&boost_ocp_range, min_ua, max_ua, &idx);
315 		if (ret == -EINVAL) {
316 			return ret;
317 		}
318 
319 		if (idx == 1) {
320 			return i2c_reg_write_byte_dt(&config->i2c, BOOST_CTRLSET, BIT(3));
321 		}
322 		return i2c_reg_write_byte_dt(&config->i2c, BOOST_CTRLCLR, BIT(3));
323 
324 	case NPM2100_SOURCE_LDOSW:
325 		if (data->ldsw_mode) {
326 			ret = linear_range_group_get_win_index(
327 				ldsw_ocp_ranges, ARRAY_SIZE(ldsw_ocp_ranges), min_ua, max_ua, &idx);
328 			idx = ldsw_ocp_lookup[idx];
329 			shift = 4U;
330 		} else {
331 			ret = linear_range_group_get_win_index(
332 				ldo_ocp_ranges, ARRAY_SIZE(ldo_ocp_ranges), min_ua, max_ua, &idx);
333 			idx = ldo_ocp_lookup[idx];
334 		}
335 
336 		if (ret == -EINVAL) {
337 			return ret;
338 		}
339 
340 		return i2c_reg_update_byte_dt(&config->i2c, LDOSW_PRGOCP, BIT_MASK(3) << shift,
341 					      idx << shift);
342 
343 	default:
344 		return -ENODEV;
345 	}
346 }
347 
set_boost_mode(const struct device * dev,regulator_mode_t mode)348 static int set_boost_mode(const struct device *dev, regulator_mode_t mode)
349 {
350 	const struct regulator_npm2100_config *config = dev->config;
351 	uint8_t reg;
352 
353 	/* Normal mode */
354 	switch (mode & NPM2100_REG_OPER_MASK) {
355 	case NPM2100_REG_OPER_AUTO:
356 		reg = BOOST_OPER_MODE_AUTO;
357 		break;
358 	case NPM2100_REG_OPER_HP:
359 		reg = BOOST_OPER_MODE_HP;
360 		break;
361 	case NPM2100_REG_OPER_LP:
362 		reg = BOOST_OPER_MODE_LP;
363 		break;
364 	case NPM2100_REG_OPER_PASS:
365 		reg = BOOST_OPER_MODE_PASS;
366 		break;
367 	case NPM2100_REG_OPER_NOHP:
368 		reg = BOOST_OPER_MODE_NOHP;
369 		break;
370 	default:
371 		return -ENOTSUP;
372 	}
373 
374 	/* Configure DPS mode */
375 	if ((mode & NPM2100_REG_DPS_MASK) != 0) {
376 		uint8_t dps_val = (mode & NPM2100_REG_DPS_MASK) == NPM2100_REG_DPS_ALLOW
377 					  ? BOOST_OPER_DPS_ALLOW
378 					  : BOOST_OPER_DPS_ALLOWLP;
379 
380 		reg |= FIELD_PREP(BOOST_OPER_DPS_MASK, dps_val);
381 	}
382 
383 	/* Update mode and dps fields, but not dpstimer */
384 	int ret = i2c_reg_update_byte_dt(&config->i2c, BOOST_OPER,
385 					 BOOST_OPER_MODE_MASK | BOOST_OPER_DPS_MASK, reg);
386 	if (ret < 0) {
387 		return ret;
388 	}
389 
390 	/* Forced mode */
391 	switch (mode & NPM2100_REG_FORCE_MASK) {
392 	case 0U:
393 		return 0;
394 	case NPM2100_REG_FORCE_HP:
395 		reg = BOOST_PIN_FORCE_HP;
396 		break;
397 	case NPM2100_REG_FORCE_LP:
398 		reg = BOOST_PIN_FORCE_LP;
399 		break;
400 	case NPM2100_REG_FORCE_PASS:
401 		reg = BOOST_PIN_FORCE_PASS;
402 		break;
403 	case NPM2100_REG_FORCE_NOHP:
404 		reg = BOOST_PIN_FORCE_NOHP;
405 		break;
406 	default:
407 		return -ENOTSUP;
408 	}
409 
410 	/* Forced mode is only valid when gpio is configured */
411 	if (config->mode_gpios.port == NULL) {
412 		return -EINVAL;
413 	}
414 
415 	return i2c_reg_write_byte_dt(&config->i2c, BOOST_PIN, reg);
416 }
417 
get_boost_mode(const struct device * dev,regulator_mode_t * mode)418 static int get_boost_mode(const struct device *dev, regulator_mode_t *mode)
419 {
420 	const struct regulator_npm2100_config *config = dev->config;
421 	uint8_t reg;
422 	int ret;
423 
424 	ret = i2c_reg_read_byte_dt(&config->i2c, BOOST_STATUS0, &reg);
425 	if (ret < 0) {
426 		return ret;
427 	}
428 
429 	switch (reg & BOOST_STATUS0_MODE_MASK) {
430 	case BOOST_STATUS0_MODE_HP:
431 		*mode = NPM2100_REG_OPER_HP;
432 		break;
433 	case BOOST_STATUS0_MODE_LP:
434 		*mode = NPM2100_REG_OPER_LP;
435 		break;
436 	case BOOST_STATUS0_MODE_ULP:
437 		*mode = NPM2100_REG_OPER_ULP;
438 		break;
439 	case BOOST_STATUS0_MODE_PT:
440 		*mode = NPM2100_REG_OPER_PASS;
441 		break;
442 	case BOOST_STATUS0_MODE_DPS:
443 		/* STATUS0 indicates whether DPS is enabled, regardless of ALLOW/ALLOWLP setting.
444 		 * BOOST_OPER_DPS_ALLOW chosen instead of creating new enum value.
445 		 */
446 		*mode = BOOST_OPER_DPS_ALLOW;
447 		break;
448 	default:
449 		return -ENOTSUP;
450 	}
451 
452 	return 0;
453 }
454 
get_ldosw_mode(const struct device * dev,regulator_mode_t * mode)455 static int get_ldosw_mode(const struct device *dev, regulator_mode_t *mode)
456 {
457 	const struct regulator_npm2100_config *config = dev->config;
458 	uint8_t reg;
459 	int ret;
460 
461 	ret = i2c_reg_read_byte_dt(&config->i2c, LDOSW_STATUS, &reg);
462 	if (ret < 0) {
463 		return ret;
464 	}
465 
466 	*mode = 0U;
467 	if (reg & LDOSW_STATUS_SW) {
468 		*mode |= NPM2100_REG_LDSW_EN;
469 	}
470 
471 	if (reg & LDOSW_STATUS_HP) {
472 		*mode |= NPM2100_REG_OPER_HP;
473 	} else if (reg & LDOSW_STATUS_ULP) {
474 		*mode |= NPM2100_REG_OPER_ULP;
475 	}
476 
477 	return 0;
478 }
479 
set_ldosw_gpio_mode(const struct device * dev,uint8_t inact,uint8_t act,uint8_t ldsw)480 static int set_ldosw_gpio_mode(const struct device *dev, uint8_t inact, uint8_t act, uint8_t ldsw)
481 {
482 	const struct regulator_npm2100_config *config = dev->config;
483 	int ret;
484 
485 	ret = i2c_reg_update_byte_dt(&config->i2c, LDOSW_GPIO, LDOSW_GPIO_PINACT_MASK, inact | act);
486 	if (ret < 0) {
487 		return ret;
488 	}
489 
490 	/* Set operating mode to pin control */
491 	return i2c_reg_write_byte_dt(&config->i2c, LDOSW_SEL, LDOSW_SEL_OPER_PIN | ldsw);
492 }
493 
set_ldosw_mode(const struct device * dev,regulator_mode_t mode)494 static int set_ldosw_mode(const struct device *dev, regulator_mode_t mode)
495 {
496 	const struct regulator_npm2100_config *config = dev->config;
497 	struct regulator_npm2100_data *data = dev->data;
498 	uint8_t ldsw = mode & NPM2100_REG_LDSW_EN;
499 	uint8_t oper = mode & NPM2100_REG_OPER_MASK;
500 	uint8_t force = mode & NPM2100_REG_FORCE_MASK;
501 
502 	/* Save load switch state, needed for OCP configuration */
503 	data->ldsw_mode = ldsw != 0;
504 
505 	if (force == 0U) {
506 		/* SW control of mode */
507 		switch (oper) {
508 		case NPM2100_REG_OPER_AUTO:
509 			return i2c_reg_write_byte_dt(&config->i2c, LDOSW_SEL,
510 						     LDOSW_SEL_OPER_AUTO | ldsw);
511 		case NPM2100_REG_OPER_ULP:
512 			return i2c_reg_write_byte_dt(&config->i2c, LDOSW_SEL,
513 						     LDOSW_SEL_OPER_ULP | ldsw);
514 		case NPM2100_REG_OPER_HP:
515 			return i2c_reg_write_byte_dt(&config->i2c, LDOSW_SEL,
516 						     LDOSW_SEL_OPER_HP | ldsw);
517 		default:
518 			return -ENOTSUP;
519 		}
520 	}
521 
522 	/* Forced mode is only valid when gpio is configured */
523 	if (config->mode_gpios.port == NULL) {
524 		return -EINVAL;
525 	}
526 
527 	switch (oper | force) {
528 	case NPM2100_REG_OPER_OFF | NPM2100_REG_FORCE_ULP:
529 		return set_ldosw_gpio_mode(dev, LDOSW_GPIO_PININACT_OFF, LDOSW_GPIO_PINACT_ULP,
530 					   ldsw);
531 	case NPM2100_REG_OPER_OFF | NPM2100_REG_FORCE_HP:
532 		return set_ldosw_gpio_mode(dev, LDOSW_GPIO_PININACT_OFF, LDOSW_GPIO_PINACT_HP,
533 					   ldsw);
534 	case NPM2100_REG_OPER_ULP | NPM2100_REG_FORCE_HP:
535 		return set_ldosw_gpio_mode(dev, LDOSW_GPIO_PININACT_ULP, LDOSW_GPIO_PINACT_HP,
536 					   ldsw);
537 	default:
538 		return -ENOTSUP;
539 	}
540 }
541 
regulator_npm2100_set_mode(const struct device * dev,regulator_mode_t mode)542 static int regulator_npm2100_set_mode(const struct device *dev, regulator_mode_t mode)
543 {
544 	const struct regulator_npm2100_config *config = dev->config;
545 
546 	switch (config->source) {
547 	case NPM2100_SOURCE_BOOST:
548 		return set_boost_mode(dev, mode);
549 	case NPM2100_SOURCE_LDOSW:
550 		return set_ldosw_mode(dev, mode);
551 	default:
552 		return -ENOTSUP;
553 	}
554 }
555 
regulator_npm2100_get_mode(const struct device * dev,regulator_mode_t * mode)556 static int regulator_npm2100_get_mode(const struct device *dev, regulator_mode_t *mode)
557 {
558 	const struct regulator_npm2100_config *config = dev->config;
559 
560 	switch (config->source) {
561 	case NPM2100_SOURCE_BOOST:
562 		return get_boost_mode(dev, mode);
563 	case NPM2100_SOURCE_LDOSW:
564 		return get_ldosw_mode(dev, mode);
565 	default:
566 		return -ENOTSUP;
567 	}
568 }
569 
regulator_npm2100_enable(const struct device * dev)570 static int regulator_npm2100_enable(const struct device *dev)
571 {
572 	const struct regulator_npm2100_config *config = dev->config;
573 
574 	if (config->source != NPM2100_SOURCE_LDOSW) {
575 		return 0;
576 	}
577 
578 	return i2c_reg_write_byte_dt(&config->i2c, LDOSW_ENABLE, 1U);
579 }
580 
regulator_npm2100_disable(const struct device * dev)581 static int regulator_npm2100_disable(const struct device *dev)
582 {
583 	const struct regulator_npm2100_config *config = dev->config;
584 
585 	if (config->source != NPM2100_SOURCE_LDOSW) {
586 		return 0;
587 	}
588 
589 	return i2c_reg_write_byte_dt(&config->i2c, LDOSW_ENABLE, 0U);
590 }
591 
init_pin_ctrl(const struct device * dev,const struct gpio_dt_spec * spec)592 static int init_pin_ctrl(const struct device *dev, const struct gpio_dt_spec *spec)
593 {
594 	const struct regulator_npm2100_config *config = dev->config;
595 
596 	if (spec->port == NULL) {
597 		return 0;
598 	}
599 
600 	int ret = gpio_pin_configure_dt(spec, GPIO_INPUT);
601 
602 	if (ret != 0) {
603 		return ret;
604 	}
605 
606 	uint8_t pin = spec->pin << 1U;
607 	uint8_t offset = ((spec->dt_flags & GPIO_ACTIVE_LOW) != 0U) ? 0U : 1U;
608 
609 	switch (config->source) {
610 	case NPM2100_SOURCE_BOOST:
611 		return i2c_reg_write_byte_dt(&config->i2c, BOOST_GPIO, pin + offset + 1U);
612 	case NPM2100_SOURCE_LDOSW:
613 		return i2c_reg_update_byte_dt(&config->i2c, LDOSW_GPIO, LDOSW_GPIO_PIN_MASK,
614 					      pin + offset);
615 	default:
616 		return -ENODEV;
617 	}
618 }
619 
regulator_npm2100_dvs_state_set(const struct device * dev,regulator_dvs_state_t state)620 static int regulator_npm2100_dvs_state_set(const struct device *dev, regulator_dvs_state_t state)
621 {
622 	const struct regulator_npm2100_pconfig *pconfig = dev->config;
623 	const struct gpio_dt_spec *spec;
624 	int ret;
625 
626 	for (size_t idx = 0U; idx < 2U; idx++) {
627 		spec = &pconfig->dvs_state_pins[idx];
628 
629 		if (spec->port != NULL) {
630 			ret = gpio_pin_set_dt(spec, ((state >> idx) & 1U) != 0U);
631 
632 			if (ret != 0) {
633 				return ret;
634 			}
635 		}
636 	}
637 
638 	return 0;
639 }
640 
regulator_npm2100_ship_mode(const struct device * dev)641 static int regulator_npm2100_ship_mode(const struct device *dev)
642 {
643 	const struct regulator_npm2100_pconfig *pconfig = dev->config;
644 
645 	/* Ensure shiphold button is enabled so that wakeup will work */
646 	int ret = i2c_reg_write_byte_dt(&pconfig->i2c, RESET_WRITESTICKY, 0);
647 
648 	if (ret < 0) {
649 		return ret;
650 	}
651 
652 	ret = i2c_reg_write_byte_dt(&pconfig->i2c, RESET_STROBESTICKY, 1U);
653 	if (ret < 0) {
654 		return ret;
655 	}
656 
657 	return i2c_reg_write_byte_dt(&pconfig->i2c, SHIP_TASK_SHIP, 1U);
658 }
659 
660 
661 static DEVICE_API(regulator_parent, parent_api) = {
662 	.dvs_state_set = regulator_npm2100_dvs_state_set,
663 	.ship_mode = regulator_npm2100_ship_mode,
664 };
665 
regulator_npm2100_common_init(const struct device * dev)666 static int regulator_npm2100_common_init(const struct device *dev)
667 {
668 	const struct regulator_npm2100_pconfig *pconfig = dev->config;
669 	const struct gpio_dt_spec *spec;
670 	int ret;
671 
672 	for (size_t idx = 0U; idx < 2U; idx++) {
673 		spec = &pconfig->dvs_state_pins[idx];
674 
675 		if (spec->port != NULL) {
676 			if (!gpio_is_ready_dt(spec)) {
677 				return -ENODEV;
678 			}
679 
680 			ret = gpio_pin_configure_dt(spec, GPIO_OUTPUT);
681 			if (ret != 0) {
682 				return ret;
683 			}
684 		}
685 	}
686 
687 	return 0;
688 }
689 
regulator_npm2100_init(const struct device * dev)690 static int regulator_npm2100_init(const struct device *dev)
691 {
692 	const struct regulator_npm2100_config *config = dev->config;
693 	int ret;
694 
695 	if (!i2c_is_ready_dt(&config->i2c)) {
696 		return -ENODEV;
697 	}
698 
699 	/* Configure GPIO pin control */
700 	ret = init_pin_ctrl(dev, &config->mode_gpios);
701 	if (ret != 0) {
702 		return ret;
703 	}
704 
705 	/* BOOST is always enabled */
706 	if (config->source == NPM2100_SOURCE_BOOST) {
707 		ret = i2c_reg_write_byte_dt(
708 			&config->i2c, BOOST_OPER,
709 			FIELD_PREP(BOOST_OPER_DPSTIMER_MASK, config->dps_timer));
710 		if (ret < 0) {
711 			return ret;
712 		}
713 
714 		ret = i2c_reg_write_byte_dt(&config->i2c, BOOST_LIMIT, config->dps_pulse_limit);
715 		if (ret < 0) {
716 			return ret;
717 		}
718 
719 		return regulator_common_init(dev, true);
720 	}
721 
722 	/* Configure LDOSW behavior during watchdog reset */
723 	if (config->ldosw_wd_reset) {
724 		ret = i2c_reg_write_byte_dt(&config->i2c, RESET_ALTCONFIG,
725 					    RESET_ALTCONFIG_LDOSW_OFF);
726 		if (ret < 0) {
727 			return ret;
728 		}
729 	}
730 
731 	/* Get enable state for LDOSW */
732 	uint8_t enabled;
733 
734 	ret = i2c_reg_read_byte_dt(&config->i2c, LDOSW_ENABLE, &enabled);
735 	if (ret < 0) {
736 		return ret;
737 	}
738 
739 	return regulator_common_init(dev, enabled != 0U);
740 }
741 
742 static DEVICE_API(regulator, api) = {
743 	.enable = regulator_npm2100_enable,
744 	.disable = regulator_npm2100_disable,
745 	.count_voltages = regulator_npm2100_count_voltages,
746 	.list_voltage = regulator_npm2100_list_voltage,
747 	.set_voltage = regulator_npm2100_set_voltage,
748 	.get_voltage = regulator_npm2100_get_voltage,
749 	.count_current_limits = regulator_npm2100_count_currents,
750 	.list_current_limit = regulator_npm2100_list_currents,
751 	.set_current_limit = regulator_npm2100_set_current,
752 	.set_mode = regulator_npm2100_set_mode,
753 	.get_mode = regulator_npm2100_get_mode};
754 
755 #define REGULATOR_NPM2100_DEFINE(node_id, id, _source)                                             \
756 	static struct regulator_npm2100_data data_##id;                                            \
757                                                                                                    \
758 	static const struct regulator_npm2100_config config_##id = {                               \
759 		.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id),                                \
760 		.i2c = I2C_DT_SPEC_GET(DT_GPARENT(node_id)),                                       \
761 		.source = _source,                                                                 \
762 		.mode_gpios = GPIO_DT_SPEC_GET_OR(node_id, mode_gpios, {0}),                       \
763 		.ldosw_wd_reset = DT_PROP(node_id, ldosw_wd_reset),                                \
764 		.dps_timer = DT_ENUM_IDX_OR(node_id, dps_timer_us, 0),                             \
765 		.dps_pulse_limit = DT_PROP_OR(node_id, dps_pulse_limit, 0)};                       \
766 	BUILD_ASSERT(DT_PROP_OR(node_id, dps_pulse_limit, 0) >= 3 ||                               \
767 			     DT_PROP_OR(node_id, dps_pulse_limit, 0) == 0,                         \
768 		     "Invalid dps_pulse_limit value");                                             \
769                                                                                                    \
770 	DEVICE_DT_DEFINE(node_id, regulator_npm2100_init, NULL, &data_##id, &config_##id,          \
771 			 POST_KERNEL, CONFIG_REGULATOR_NPM2100_INIT_PRIORITY, &api);
772 
773 #define REGULATOR_NPM2100_DEFINE_COND(inst, child, source)                                         \
774 	COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)),                                    \
775 		    (REGULATOR_NPM2100_DEFINE(DT_INST_CHILD(inst, child), child##inst, source)),   \
776 		    ())
777 
778 #define REGULATOR_NPM2100_DEFINE_ALL(inst)                                                         \
779 	static const struct regulator_npm2100_pconfig config_##inst = {                            \
780 		.i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)),                                      \
781 		.dvs_state_pins = {GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 0, {0}),       \
782 				   GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 1, {0})}};     \
783                                                                                                    \
784 	DEVICE_DT_INST_DEFINE(inst, regulator_npm2100_common_init, NULL, NULL, &config_##inst,     \
785 			      POST_KERNEL, CONFIG_REGULATOR_NPM2100_COMMON_INIT_PRIORITY,          \
786 			      &parent_api);                                                        \
787                                                                                                    \
788 	REGULATOR_NPM2100_DEFINE_COND(inst, boost, NPM2100_SOURCE_BOOST)                           \
789 	REGULATOR_NPM2100_DEFINE_COND(inst, ldosw, NPM2100_SOURCE_LDOSW)
790 
791 DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM2100_DEFINE_ALL)
792