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, ®);
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, ®);
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