1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_npm1300_charger
7 
8 #include <math.h>
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/drivers/mfd/npm1300.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/linear_range.h>
13 #include <zephyr/drivers/sensor/npm1300_charger.h>
14 
15 struct npm1300_charger_config {
16 	const struct device *mfd;
17 	int32_t term_microvolt;
18 	int32_t term_warm_microvolt;
19 	int32_t current_microamp;
20 	int32_t dischg_limit_microamp;
21 	uint8_t dischg_limit_idx;
22 	int32_t vbus_limit_microamp;
23 	int32_t temp_thresholds[4U];
24 	int32_t dietemp_thresholds[2U];
25 	uint32_t thermistor_ohms;
26 	uint16_t thermistor_beta;
27 	uint8_t thermistor_idx;
28 	uint8_t trickle_sel;
29 	uint8_t iterm_sel;
30 	bool charging_enable;
31 	bool vbatlow_charge_enable;
32 	bool disable_recharge;
33 };
34 
35 struct npm1300_charger_data {
36 	uint16_t voltage;
37 	uint16_t current;
38 	uint16_t temp;
39 	uint16_t dietemp;
40 	uint8_t status;
41 	uint8_t error;
42 	uint8_t ibat_stat;
43 	uint8_t vbus_stat;
44 };
45 
46 /* nPM1300 base addresses */
47 #define CHGR_BASE 0x03U
48 #define ADC_BASE  0x05U
49 #define VBUS_BASE 0x02U
50 
51 /* nPM1300 charger register offsets */
52 #define CHGR_OFFSET_ERR_CLR     0x00U
53 #define CHGR_OFFSET_EN_SET      0x04U
54 #define CHGR_OFFSET_EN_CLR      0x05U
55 #define CHGR_OFFSET_DIS_SET     0x06U
56 #define CHGR_OFFSET_ISET        0x08U
57 #define CHGR_OFFSET_ISET_DISCHG 0x0AU
58 #define CHGR_OFFSET_VTERM       0x0CU
59 #define CHGR_OFFSET_VTERM_R     0x0DU
60 #define CHGR_OFFSET_TRICKLE_SEL 0x0EU
61 #define CHGR_OFFSET_ITERM_SEL   0x0FU
62 #define CHGR_OFFSET_NTC_TEMPS   0x10U
63 #define CHGR_OFFSET_DIE_TEMPS   0x18U
64 #define CHGR_OFFSET_CHG_STAT    0x34U
65 #define CHGR_OFFSET_ERR_REASON  0x36U
66 #define CHGR_OFFSET_VBATLOW_EN  0x50U
67 
68 /* nPM1300 ADC register offsets */
69 #define ADC_OFFSET_TASK_VBAT 0x00U
70 #define ADC_OFFSET_TASK_TEMP 0x01U
71 #define ADC_OFFSET_TASK_DIE  0x02U
72 #define ADC_OFFSET_CONFIG    0x09U
73 #define ADC_OFFSET_NTCR_SEL  0x0AU
74 #define ADC_OFFSET_TASK_AUTO 0x0CU
75 #define ADC_OFFSET_RESULTS   0x10U
76 #define ADC_OFFSET_IBAT_EN   0x24U
77 
78 /* nPM1300 VBUS register offsets */
79 #define VBUS_OFFSET_ILIMUPDATE  0x00U
80 #define VBUS_OFFSET_ILIM        0x01U
81 #define VBUS_OFFSET_ILIMSTARTUP 0x02U
82 #define VBUS_OFFSET_DETECT      0x05U
83 #define VBUS_OFFSET_STATUS      0x07U
84 
85 /* Ibat status */
86 #define IBAT_STAT_DISCHARGE      0x04U
87 #define IBAT_STAT_CHARGE_TRICKLE 0x0CU
88 #define IBAT_STAT_CHARGE_COOL    0x0DU
89 #define IBAT_STAT_CHARGE_NORMAL  0x0FU
90 
91 struct adc_results_t {
92 	uint8_t ibat_stat;
93 	uint8_t msb_vbat;
94 	uint8_t msb_ntc;
95 	uint8_t msb_die;
96 	uint8_t msb_vsys;
97 	uint8_t lsb_a;
98 	uint8_t reserved1;
99 	uint8_t reserved2;
100 	uint8_t msb_ibat;
101 	uint8_t msb_vbus;
102 	uint8_t lsb_b;
103 } __packed;
104 
105 /* ADC result masks */
106 #define ADC_MSB_SHIFT      2U
107 #define ADC_LSB_MASK       0x03U
108 #define ADC_LSB_VBAT_SHIFT 0U
109 #define ADC_LSB_NTC_SHIFT  2U
110 #define ADC_LSB_DIE_SHIFT  4U
111 #define ADC_LSB_IBAT_SHIFT 4U
112 
113 /* NTC temp masks */
114 #define NTCTEMP_MSB_SHIFT 2U
115 #define NTCTEMP_LSB_MASK  0x03U
116 
117 /* dietemp masks */
118 #define DIETEMP_MSB_SHIFT 2U
119 #define DIETEMP_LSB_MASK  0x03U
120 
121 /* VBUS detect masks */
122 #define DETECT_HI_MASK    0x0AU
123 #define DETECT_HI_CURRENT 1500000
124 #define DETECT_LO_CURRENT 500000
125 
126 /* VBUS status masks */
127 #define STATUS_PRESENT_MASK      0x01U
128 #define STATUS_CUR_LIMIT_MASK    0x02U
129 #define STATUS_OVERVLT_PROT_MASK 0x04U
130 #define STATUS_UNDERVLT_MASK     0x08U
131 #define STATUS_SUSPENDED_MASK    0x10U
132 #define STATUS_BUSOUT_MASK       0x20U
133 
134 /* Dietemp calculation constants */
135 #define DIETEMP_OFFSET_MDEGC 394670
136 #define DIETEMP_FACTOR_MUL   3963000
137 #define DIETEMP_FACTOR_DIV   5000
138 
139 /* Linear range for charger terminal voltage */
140 static const struct linear_range charger_volt_ranges[] = {
141 	LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)};
142 
143 /* Linear range for charger current */
144 static const struct linear_range charger_current_range = LINEAR_RANGE_INIT(32000, 2000, 16U, 400U);
145 
146 /* Allowed values for discharge limit */
147 static const uint16_t discharge_limits[] = {84U, 415U};
148 
149 /* Linear range for vbusin current limit */
150 static const struct linear_range vbus_current_ranges[] = {
151 	LINEAR_RANGE_INIT(100000, 0, 1U, 1U), LINEAR_RANGE_INIT(500000, 100000, 5U, 15U)};
152 
calc_temp(const struct npm1300_charger_config * const config,uint16_t code,struct sensor_value * valp)153 static void calc_temp(const struct npm1300_charger_config *const config, uint16_t code,
154 		      struct sensor_value *valp)
155 {
156 	/* Ref: Datasheet Figure 42: Battery temperature (Kelvin) */
157 	float log_result = log((1024.f / (float)code) - 1);
158 	float inv_temp_k = (1.f / 298.15f) - (log_result / (float)config->thermistor_beta);
159 
160 	float temp = (1.f / inv_temp_k) - 273.15f;
161 
162 	valp->val1 = (int32_t)temp;
163 	valp->val2 = (int32_t)(fmodf(temp, 1.f) * 1000000.f);
164 }
165 
calc_dietemp(const struct npm1300_charger_config * const config,uint16_t code,struct sensor_value * valp)166 static void calc_dietemp(const struct npm1300_charger_config *const config, uint16_t code,
167 			 struct sensor_value *valp)
168 {
169 	/* Ref: Datasheet Figure 36: Die temperature (Celcius) */
170 	int32_t temp =
171 		DIETEMP_OFFSET_MDEGC - (((int32_t)code * DIETEMP_FACTOR_MUL) / DIETEMP_FACTOR_DIV);
172 
173 	valp->val1 = temp / 1000;
174 	valp->val2 = (temp % 1000) * 1000;
175 }
176 
calc_ntc_res(const struct npm1300_charger_config * const config,int32_t temp_mdegc)177 static uint32_t calc_ntc_res(const struct npm1300_charger_config *const config, int32_t temp_mdegc)
178 {
179 	float inv_t0 = 1.f / 298.15f;
180 	float temp = (float)temp_mdegc / 1000.f;
181 
182 	float inv_temp_k = 1.f / (temp + 273.15f);
183 
184 	return config->thermistor_ohms *
185 	       exp((float)config->thermistor_beta * (inv_temp_k - inv_t0));
186 }
187 
adc_get_res(uint8_t msb,uint8_t lsb,uint16_t lsb_shift)188 static uint16_t adc_get_res(uint8_t msb, uint8_t lsb, uint16_t lsb_shift)
189 {
190 	return ((uint16_t)msb << ADC_MSB_SHIFT) | ((lsb >> lsb_shift) & ADC_LSB_MASK);
191 }
192 
calc_current(const struct npm1300_charger_config * const config,struct npm1300_charger_data * const data,struct sensor_value * valp)193 static void calc_current(const struct npm1300_charger_config *const config,
194 			 struct npm1300_charger_data *const data, struct sensor_value *valp)
195 {
196 	int32_t full_scale_ma;
197 	int32_t current;
198 
199 	switch (data->ibat_stat) {
200 	case IBAT_STAT_DISCHARGE:
201 		full_scale_ma = config->dischg_limit_microamp / 893;
202 		break;
203 	case IBAT_STAT_CHARGE_TRICKLE:
204 	/* Fallthrough */
205 	case IBAT_STAT_CHARGE_COOL:
206 	/* Fallthrough */
207 	case IBAT_STAT_CHARGE_NORMAL:
208 		full_scale_ma = -config->current_microamp / 800;
209 		break;
210 	default:
211 		full_scale_ma = 0;
212 		break;
213 	}
214 
215 	current = (data->current * full_scale_ma) / 1024;
216 
217 	valp->val1 = current / 1000;
218 	valp->val2 = (current % 1000) * 1000;
219 }
220 
npm1300_charger_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * valp)221 int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel chan,
222 				struct sensor_value *valp)
223 {
224 	const struct npm1300_charger_config *const config = dev->config;
225 	struct npm1300_charger_data *const data = dev->data;
226 	int32_t tmp;
227 
228 	switch ((uint32_t)chan) {
229 	case SENSOR_CHAN_GAUGE_VOLTAGE:
230 		tmp = data->voltage * 5000 / 1024;
231 		valp->val1 = tmp / 1000;
232 		valp->val2 = (tmp % 1000) * 1000;
233 		break;
234 	case SENSOR_CHAN_GAUGE_TEMP:
235 		if (config->thermistor_idx == 0) {
236 			return -ENOTSUP;
237 		}
238 		calc_temp(config, data->temp, valp);
239 		break;
240 	case SENSOR_CHAN_GAUGE_AVG_CURRENT:
241 		calc_current(config, data, valp);
242 		break;
243 	case SENSOR_CHAN_NPM1300_CHARGER_STATUS:
244 		valp->val1 = data->status;
245 		valp->val2 = 0;
246 		break;
247 	case SENSOR_CHAN_NPM1300_CHARGER_ERROR:
248 		valp->val1 = data->error;
249 		valp->val2 = 0;
250 		break;
251 	case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT:
252 		valp->val1 = config->current_microamp / 1000000;
253 		valp->val2 = config->current_microamp % 1000000;
254 		break;
255 	case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT:
256 		valp->val1 = config->dischg_limit_microamp / 1000000;
257 		valp->val2 = config->dischg_limit_microamp % 1000000;
258 		break;
259 	case SENSOR_CHAN_DIE_TEMP:
260 		calc_dietemp(config, data->dietemp, valp);
261 		break;
262 	case SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS:
263 		valp->val1 = data->vbus_stat;
264 		valp->val2 = 0;
265 		break;
266 	default:
267 		return -ENOTSUP;
268 	}
269 
270 	return 0;
271 }
272 
npm1300_charger_sample_fetch(const struct device * dev,enum sensor_channel chan)273 int npm1300_charger_sample_fetch(const struct device *dev, enum sensor_channel chan)
274 {
275 	const struct npm1300_charger_config *const config = dev->config;
276 	struct npm1300_charger_data *data = dev->data;
277 	struct adc_results_t results;
278 	int ret;
279 
280 	/* Read charge status and error reason */
281 	ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status);
282 	if (ret != 0) {
283 		return ret;
284 	}
285 
286 	ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_REASON, &data->error);
287 	if (ret != 0) {
288 		return ret;
289 	}
290 
291 	/* Read adc results */
292 	ret = mfd_npm1300_reg_read_burst(config->mfd, ADC_BASE, ADC_OFFSET_RESULTS, &results,
293 					 sizeof(results));
294 	if (ret != 0) {
295 		return ret;
296 	}
297 
298 	data->voltage = adc_get_res(results.msb_vbat, results.lsb_a, ADC_LSB_VBAT_SHIFT);
299 	data->temp = adc_get_res(results.msb_ntc, results.lsb_a, ADC_LSB_NTC_SHIFT);
300 	data->dietemp = adc_get_res(results.msb_die, results.lsb_a, ADC_LSB_DIE_SHIFT);
301 	data->current = adc_get_res(results.msb_ibat, results.lsb_b, ADC_LSB_IBAT_SHIFT);
302 	data->ibat_stat = results.ibat_stat;
303 
304 	/* Trigger ntc and die temperature measurements */
305 	ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U);
306 	if (ret != 0) {
307 		return ret;
308 	}
309 
310 	/* Trigger current and voltage measurement */
311 	ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U);
312 	if (ret != 0) {
313 		return ret;
314 	}
315 
316 	/* Read vbus status */
317 	ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat);
318 	if (ret != 0) {
319 		return ret;
320 	}
321 
322 	return ret;
323 }
324 
set_ntc_thresholds(const struct npm1300_charger_config * const config)325 static int set_ntc_thresholds(const struct npm1300_charger_config *const config)
326 {
327 	for (uint8_t idx = 0U; idx < 4U; idx++) {
328 		if (config->temp_thresholds[idx] < INT32_MAX) {
329 			uint32_t res = calc_ntc_res(config, config->temp_thresholds[idx]);
330 
331 			/* Ref: Datasheet Figure 14: Equation for battery temperature */
332 			uint16_t code = (1024 * res) / (res + config->thermistor_ohms);
333 
334 			int ret = mfd_npm1300_reg_write2(
335 				config->mfd, CHGR_BASE, CHGR_OFFSET_NTC_TEMPS + (idx * 2U),
336 				code >> NTCTEMP_MSB_SHIFT, code & NTCTEMP_LSB_MASK);
337 
338 			if (ret != 0) {
339 				return ret;
340 			}
341 		}
342 	}
343 
344 	return 0;
345 }
346 
set_dietemp_thresholds(const struct npm1300_charger_config * const config)347 static int set_dietemp_thresholds(const struct npm1300_charger_config *const config)
348 {
349 	for (uint8_t idx = 0U; idx < 2U; idx++) {
350 		if (config->dietemp_thresholds[idx] < INT32_MAX) {
351 			/* Ref: Datasheet section 6.2.6: Charger thermal regulation */
352 			int32_t numerator =
353 				(DIETEMP_OFFSET_MDEGC - config->dietemp_thresholds[idx]) *
354 				DIETEMP_FACTOR_DIV;
355 			uint16_t code = DIV_ROUND_CLOSEST(numerator, DIETEMP_FACTOR_MUL);
356 
357 			int ret = mfd_npm1300_reg_write2(
358 				config->mfd, CHGR_BASE, CHGR_OFFSET_DIE_TEMPS + (idx * 2U),
359 				code >> DIETEMP_MSB_SHIFT, code & DIETEMP_LSB_MASK);
360 
361 			if (ret != 0) {
362 				return ret;
363 			}
364 		}
365 	}
366 
367 	return 0;
368 }
369 
npm1300_charger_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)370 static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channel chan,
371 				    enum sensor_attribute attr, struct sensor_value *val)
372 {
373 	const struct npm1300_charger_config *const config = dev->config;
374 	uint8_t data;
375 	int ret;
376 
377 	switch ((uint32_t)chan) {
378 	case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT:
379 		if (attr != SENSOR_ATTR_CONFIGURATION) {
380 			return -ENOTSUP;
381 		}
382 
383 		ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, &data);
384 		if (ret == 0) {
385 			val->val1 = data;
386 			val->val2 = 0U;
387 		}
388 		return ret;
389 
390 	case SENSOR_CHAN_CURRENT:
391 		if (attr != SENSOR_ATTR_UPPER_THRESH) {
392 			return -ENOTSUP;
393 		}
394 
395 		ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_DETECT, &data);
396 		if (ret < 0) {
397 			return ret;
398 		}
399 
400 		if (data == 0U) {
401 			/* No charger connected */
402 			val->val1 = 0;
403 			val->val2 = 0;
404 		} else if ((data & DETECT_HI_MASK) != 0U) {
405 			/* CC1 or CC2 indicate 1.5A or 3A capability */
406 			val->val1 = DETECT_HI_CURRENT / 1000000;
407 			val->val2 = DETECT_HI_CURRENT % 1000000;
408 		} else {
409 			val->val1 = DETECT_LO_CURRENT / 1000000;
410 			val->val2 = DETECT_LO_CURRENT % 1000000;
411 		}
412 
413 		return 0;
414 
415 	case SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS:
416 		ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data);
417 		if (ret < 0) {
418 			return ret;
419 		}
420 
421 		switch ((enum sensor_attribute_npm1300_charger)attr) {
422 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_PRESENT:
423 			val->val1 = (data & STATUS_PRESENT_MASK) != 0;
424 			break;
425 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_CUR_LIMIT:
426 			val->val1 = (data & STATUS_CUR_LIMIT_MASK) != 0;
427 			break;
428 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_OVERVLT_PROT:
429 			val->val1 = (data & STATUS_OVERVLT_PROT_MASK) != 0;
430 			break;
431 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_UNDERVLT:
432 			val->val1 = (data & STATUS_UNDERVLT_MASK) != 0;
433 			break;
434 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_SUSPENDED:
435 			val->val1 = (data & STATUS_SUSPENDED_MASK) != 0;
436 			break;
437 		case SENSOR_ATTR_NPM1300_CHARGER_VBUS_BUSOUT:
438 			val->val1 = (data & STATUS_BUSOUT_MASK) != 0;
439 			break;
440 		default:
441 			return -ENOTSUP;
442 		}
443 		val->val2 = 0;
444 		return 0;
445 
446 	default:
447 		return -ENOTSUP;
448 	}
449 }
450 
npm1300_charger_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)451 static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channel chan,
452 				    enum sensor_attribute attr, const struct sensor_value *val)
453 {
454 	const struct npm1300_charger_config *const config = dev->config;
455 	int ret;
456 
457 	if (attr != SENSOR_ATTR_CONFIGURATION) {
458 		return -ENOTSUP;
459 	}
460 
461 	switch ((uint32_t)chan) {
462 	case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT:
463 		if (val->val1 == 0) {
464 			/* Disable charging */
465 			return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_CLR,
466 						     1U);
467 		}
468 
469 		/* Clear any errors and enable charging */
470 		ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_CLR, 1U);
471 		if (ret != 0) {
472 			return ret;
473 		}
474 		return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U);
475 
476 	case SENSOR_CHAN_CURRENT:
477 		/* Set vbus current limit */
478 		int32_t current = (val->val1 * 1000000) + val->val2;
479 		uint16_t idx;
480 
481 		ret = linear_range_group_get_win_index(vbus_current_ranges,
482 						       ARRAY_SIZE(vbus_current_ranges), current,
483 						       current, &idx);
484 
485 		if (ret == -EINVAL) {
486 			return ret;
487 		}
488 
489 		ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIM, idx);
490 		if (ret != 0) {
491 			return ret;
492 		}
493 
494 		/* Switch to new current limit, this will be reset automatically on USB removal */
495 		return mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMUPDATE, 1U);
496 
497 	default:
498 		return -ENOTSUP;
499 	}
500 }
501 
npm1300_charger_init(const struct device * dev)502 int npm1300_charger_init(const struct device *dev)
503 {
504 	const struct npm1300_charger_config *const config = dev->config;
505 	uint16_t idx;
506 	uint8_t byte = 0U;
507 	int ret;
508 
509 	if (!device_is_ready(config->mfd)) {
510 		return -ENODEV;
511 	}
512 
513 	/* Configure temperature thresholds */
514 	ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_NTCR_SEL,
515 				    config->thermistor_idx);
516 	if (ret != 0) {
517 		return ret;
518 	}
519 
520 	ret = set_ntc_thresholds(config);
521 	if (ret != 0) {
522 		return ret;
523 	}
524 
525 	ret = set_dietemp_thresholds(config);
526 	if (ret != 0) {
527 		return ret;
528 	}
529 
530 	/* Configure termination voltages */
531 	ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges),
532 					       config->term_microvolt, config->term_microvolt,
533 					       &idx);
534 	if (ret == -EINVAL) {
535 		return ret;
536 	}
537 	ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM, idx);
538 	if (ret != 0) {
539 		return ret;
540 	}
541 
542 	ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges),
543 					       config->term_warm_microvolt,
544 					       config->term_warm_microvolt, &idx);
545 	if (ret == -EINVAL) {
546 		return ret;
547 	}
548 
549 	ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM_R, idx);
550 	if (ret != 0) {
551 		return ret;
552 	}
553 
554 	/* Set current, allow rounding down to closest value */
555 	ret = linear_range_get_win_index(&charger_current_range,
556 					 config->current_microamp - charger_current_range.step,
557 					 config->current_microamp, &idx);
558 	if (ret == -EINVAL) {
559 		return ret;
560 	}
561 
562 	ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, idx & 1U);
563 	if (ret != 0) {
564 		return ret;
565 	}
566 
567 	/* Set discharge limit */
568 	ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG,
569 				     discharge_limits[config->dischg_limit_idx] / 2U,
570 				     discharge_limits[config->dischg_limit_idx] & 1U);
571 	if (ret != 0) {
572 		return ret;
573 	}
574 
575 	/* Configure vbus current limit */
576 	ret = linear_range_group_get_win_index(vbus_current_ranges, ARRAY_SIZE(vbus_current_ranges),
577 					       config->vbus_limit_microamp,
578 					       config->vbus_limit_microamp, &idx);
579 	if (ret == -EINVAL) {
580 		return ret;
581 	}
582 	ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMSTARTUP, idx);
583 	if (ret != 0) {
584 		return ret;
585 	}
586 
587 	/* Configure trickle voltage threshold */
588 	ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_TRICKLE_SEL,
589 				    config->trickle_sel);
590 	if (ret != 0) {
591 		return ret;
592 	}
593 
594 	/* Configure termination current */
595 	ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ITERM_SEL,
596 				    config->iterm_sel);
597 	if (ret != 0) {
598 		return ret;
599 	}
600 
601 	/* Enable current measurement */
602 	ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_IBAT_EN, 1U);
603 	if (ret != 0) {
604 		return ret;
605 	}
606 
607 	/* Trigger current and voltage measurement */
608 	ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U);
609 	if (ret != 0) {
610 		return ret;
611 	}
612 
613 	/* Trigger ntc and die temperature measurements */
614 	ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U);
615 	if (ret != 0) {
616 		return ret;
617 	}
618 
619 	/* Enable automatic temperature measurements during charging */
620 	ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_AUTO, 1U);
621 	if (ret != 0) {
622 		return ret;
623 	}
624 
625 	/* Enable charging at low battery if configured */
626 	if (config->vbatlow_charge_enable) {
627 		ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VBATLOW_EN, 1U);
628 		if (ret != 0) {
629 			return ret;
630 		}
631 	}
632 
633 	/* Disable automatic recharging if configured */
634 	if (config->disable_recharge) {
635 		WRITE_BIT(byte, 0U, true);
636 	}
637 
638 	/* Disable NTC if configured */
639 	if (config->thermistor_idx == 0U) {
640 		WRITE_BIT(byte, 1U, true);
641 	}
642 
643 	ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_DIS_SET, byte);
644 	if (ret != 0) {
645 		return ret;
646 	}
647 
648 	/* Enable charging if configured */
649 	if (config->charging_enable) {
650 		ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U);
651 		if (ret != 0) {
652 			return ret;
653 		}
654 	}
655 
656 	return 0;
657 }
658 
659 static DEVICE_API(sensor, npm1300_charger_battery_driver_api) = {
660 	.sample_fetch = npm1300_charger_sample_fetch,
661 	.channel_get = npm1300_charger_channel_get,
662 	.attr_set = npm1300_charger_attr_set,
663 	.attr_get = npm1300_charger_attr_get,
664 };
665 
666 #define NPM1300_CHARGER_INIT(n)                                                                    \
667 	BUILD_ASSERT(DT_INST_ENUM_IDX(n, dischg_limit_microamp) < ARRAY_SIZE(discharge_limits));   \
668                                                                                                    \
669 	static struct npm1300_charger_data npm1300_charger_data_##n;                               \
670                                                                                                    \
671 	static const struct npm1300_charger_config npm1300_charger_config_##n = {                  \
672 		.mfd = DEVICE_DT_GET(DT_INST_PARENT(n)),                                           \
673 		.term_microvolt = DT_INST_PROP(n, term_microvolt),                                 \
674 		.term_warm_microvolt =                                                             \
675 			DT_INST_PROP_OR(n, term_warm_microvolt, DT_INST_PROP(n, term_microvolt)),  \
676 		.current_microamp = DT_INST_PROP(n, current_microamp),                             \
677 		.dischg_limit_microamp = DT_INST_PROP(n, dischg_limit_microamp),                   \
678 		.dischg_limit_idx = DT_INST_ENUM_IDX(n, dischg_limit_microamp),                    \
679 		.vbus_limit_microamp = DT_INST_PROP(n, vbus_limit_microamp),                       \
680 		.thermistor_ohms = DT_INST_PROP(n, thermistor_ohms),                               \
681 		.thermistor_idx = DT_INST_ENUM_IDX(n, thermistor_ohms),                            \
682 		.thermistor_beta = DT_INST_PROP(n, thermistor_beta),                               \
683 		.charging_enable = DT_INST_PROP(n, charging_enable),                               \
684 		.trickle_sel = DT_INST_ENUM_IDX(n, trickle_microvolt),                             \
685 		.iterm_sel = DT_INST_ENUM_IDX(n, term_current_percent),                            \
686 		.vbatlow_charge_enable = DT_INST_PROP(n, vbatlow_charge_enable),                   \
687 		.disable_recharge = DT_INST_PROP(n, disable_recharge),                             \
688 		.dietemp_thresholds = {DT_INST_PROP_OR(n, dietemp_stop_millidegrees, INT32_MAX),   \
689 				       DT_INST_PROP_OR(n, dietemp_resume_millidegrees,             \
690 						       INT32_MAX)},                                \
691 		.temp_thresholds = {DT_INST_PROP_OR(n, thermistor_cold_millidegrees, INT32_MAX),   \
692 				    DT_INST_PROP_OR(n, thermistor_cool_millidegrees, INT32_MAX),   \
693 				    DT_INST_PROP_OR(n, thermistor_warm_millidegrees, INT32_MAX),   \
694 				    DT_INST_PROP_OR(n, thermistor_hot_millidegrees, INT32_MAX)}};  \
695                                                                                                    \
696 	SENSOR_DEVICE_DT_INST_DEFINE(n, &npm1300_charger_init, NULL, &npm1300_charger_data_##n,    \
697 				     &npm1300_charger_config_##n, POST_KERNEL,                     \
698 				     CONFIG_SENSOR_INIT_PRIORITY,                                  \
699 				     &npm1300_charger_battery_driver_api);
700 
701 DT_INST_FOREACH_STATUS_OKAY(NPM1300_CHARGER_INIT)
702