1 /*
2 * Copyright 2024 Arduino SA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_pf1550_charger
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/charger.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/sys/linear_range.h>
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(pf1550_charger, CONFIG_CHARGER_LOG_LEVEL);
19
20 #define INT_ENABLE_DELAY K_MSEC(500)
21
22 #define CHARGER_CHG_INT (0x80 + 0x00)
23 #define CHARGER_CHG_INT_MASK (0x80 + 0x02)
24 #define CHARGER_CHG_INT_OK (0x80 + 0x04)
25 #define CHARGER_VBUS_SNS (0x80 + 0x06)
26 #define CHARGER_CHG_SNS (0x80 + 0x07)
27 #define CHARGER_BATT_SNS (0x80 + 0x08)
28 #define CHARGER_CHG_OPER (0x80 + 0x09)
29 #define CHARGER_CHG_TMR (0x80 + 0x0A)
30 #define CHARGER_CHG_EOC_CNFG (0x80 + 0x0D)
31 #define CHARGER_CHG_CURR_CNFG (0x80 + 0x0E)
32 #define CHARGER_BATT_REG (0x80 + 0x0F)
33 #define CHARGER_BATFET_CNFG (0x80 + 0x11)
34 #define CHARGER_THM_REG_CNFG (0x80 + 0x12)
35 #define CHARGER_VBUS_INLIM_CNFG (0x80 + 0x14)
36 #define CHARGER_VBUS_LIN_DPM (0x80 + 0x15)
37 #define CHARGER_USB_PHY_LDO_CNFG (0x80 + 0x16)
38 #define CHARGER_DBNC_DELAY_TIME (0x80 + 0x18)
39 #define CHARGER_CHG_INT_CNFG (0x80 + 0x19)
40 #define CHARGER_THM_ADJ_SETTING (0x80 + 0x1A)
41 #define CHARGER_VBUS2SYS_CNFG (0x80 + 0x1B)
42 #define CHARGER_LED_PWM (0x80 + 0x1C)
43 #define CHARGER_FAULT_BATFET_CNFG (0x80 + 0x1D)
44 #define CHARGER_LED_CNFG (0x80 + 0x1E)
45 #define CHARGER_CHGR_KEY2 (0x80 + 0x1F)
46
47 #define PF1550_BAT_IRQ BIT(2)
48 #define PF1550_CHG_IRQ BIT(3)
49 #define PF1550_VBUS_IRQ BIT(5)
50 #define PF1550_VBUS_DPM_IRQ BIT(5)
51 #define CHG_INT_ENABLE_ALL (0xFF)
52
53 #define LED_PWM_LED_EN BIT(7)
54 #define LED_PWM_FULL_ON BIT(5)
55
56 #define LED_CNFG_LED_CFG BIT(4)
57 #define LED_CNFG_LEDOVRD BIT(5)
58
59 #define CHG_OPER_CHG_OPER_MASK GENMASK(1, 0)
60 #define CHG_CURR_CNFG_CHG_CC_MASK GENMASK(4, 0)
61 #define CHG_SNS_CHG_SNS_MASK GENMASK(3, 0)
62 #define VBUS_INLIM_CNFG_VBUS_INLIM_MASK GENMASK(7, 3)
63 #define BATT_REG_CHGCV_MASK GENMASK(5, 0)
64 #define BATT_REG_VSYSMIN_MASK GENMASK(7, 6)
65 #define THM_REG_CNFG_THM_CNFG_MASK GENMASK(1, 0)
66
67 #define CHG_OPER_CHARGER_OFF_LINEAR_OFF 0
68 #define CHG_OPER_CHARGER_OFF_LINEAR_ON 1
69 #define CHG_OPER_CHARGER_ON_LINEAR_ON 2
70
71 enum charger_pf1550_therm_mode {
72 PF1550_THERM_MODE_DISABLED,
73 PF1550_THERM_MODE_THERMISTOR,
74 PF1550_THERM_MODE_JEITA_1,
75 PF1550_THERM_MODE_JEITA_2,
76 PF1550_THERM_MODE_UNKNOWN,
77 };
78
79 /* synced with YAML binding */
80 enum charger_pf1550_led_behaviour {
81 PF1550_LED_ON_IN_CHARGING_FLASH_IN_FAULT,
82 PF1550_LED_FLASH_IN_CHARGING_ON_IN_FAULT,
83 PF1550_LED_MANUAL_OFF
84 };
85
86 struct charger_pf1550_led_config {
87 bool enabled;
88 bool manual;
89 enum charger_pf1550_led_behaviour behaviour;
90 };
91
92 struct charger_pf1550_config {
93 struct i2c_dt_spec bus;
94 struct gpio_dt_spec int_gpio;
95 char *therm_mon_mode;
96 uint32_t charge_current_ua;
97 uint32_t vbus_ilim_ua;
98 uint32_t charge_voltage_max_uv;
99 uint32_t vsys_min_uv;
100 };
101
102 struct charger_pf1550_data {
103 const struct device *dev;
104 struct gpio_callback gpio_cb;
105 struct k_work int_routine_work;
106 struct k_work_delayable int_enable_work;
107 enum charger_status charger_status;
108 enum charger_online charger_online;
109 charger_status_notifier_t charger_status_notifier;
110 charger_online_notifier_t charger_online_notifier;
111 bool charger_enabled;
112 uint32_t charge_current_ua;
113 uint32_t vbus_ilim_ua;
114 struct charger_pf1550_led_config *led_config;
115 };
116
117 static const struct linear_range charger_vbus_ilim_range[] = {
118 LINEAR_RANGE_INIT(10000, 5000, 0, 8),
119 LINEAR_RANGE_INIT(100000, 50000, 9, 10),
120 LINEAR_RANGE_INIT(200000, 100000, 11, 19),
121 LINEAR_RANGE_INIT(1500000, 0, 20, 20),
122 };
123
124 static const struct linear_range charger_fast_charge_ua_range[] = {
125 LINEAR_RANGE_INIT(100000, 50000, 0, 18),
126 };
127
128 static const struct linear_range charger_battery_termination_uv_range[] = {
129 LINEAR_RANGE_INIT(3500000, 20000, 8, 55),
130 };
131
132 static const struct linear_range charger_vsysmin_uv[] = {
133 LINEAR_RANGE_INIT(3500000, 0, 0, 0),
134 LINEAR_RANGE_INIT(3700000, 0, 1, 1),
135 LINEAR_RANGE_INIT(4300000, 0, 2, 2),
136 };
137
pf1550_get_charger_status(const struct device * dev,enum charger_status * status)138 static int pf1550_get_charger_status(const struct device *dev, enum charger_status *status)
139 {
140 enum chg_sns {
141 PF1550_CHARGER_PRECHARGE,
142 PF1550_FAST_CHARGE_CONSTANT_CURRENT,
143 PF1550_FAST_CHARGE_CONSTANT_VOLTAGE,
144 PF1550_END_OF_CHARGE,
145 PF1550_CHARGE_DONE,
146 PF1550_TIMER_FAULT = 6,
147 PF1550_THERMISTOR_SUSPEND,
148 PF1550_CHARGER_OFF_INVALID_INPUT,
149 PF1550_BATTERY_OVERVOLTAGE,
150 PF1550_BATTERY_OVERTEMPERATURE,
151 PF1550_CHARGER_OFF_LINEAR_MODE = 12,
152 };
153
154 const struct charger_pf1550_config *const config = dev->config;
155 uint8_t val;
156 int ret;
157
158 ret = i2c_reg_read_byte_dt(&config->bus, CHARGER_CHG_SNS, &val);
159 if (ret) {
160 return ret;
161 }
162
163 val = FIELD_GET(CHG_SNS_CHG_SNS_MASK, val);
164
165 if (val == PF1550_CHARGE_DONE) {
166 *status = CHARGER_STATUS_FULL;
167 } else if (val < PF1550_CHARGE_DONE) {
168 *status = CHARGER_STATUS_CHARGING;
169 } else {
170 *status = CHARGER_STATUS_NOT_CHARGING;
171 }
172
173 return 0;
174 }
175
pf1550_get_charger_online(const struct device * dev,enum charger_online * online)176 static int pf1550_get_charger_online(const struct device *dev, enum charger_online *online)
177 {
178 const struct charger_pf1550_config *const config = dev->config;
179 uint8_t val;
180 int ret;
181
182 ret = i2c_reg_read_byte_dt(&config->bus, CHARGER_CHG_OPER, &val);
183 if (ret) {
184 return ret;
185 }
186
187 val = FIELD_GET(CHG_OPER_CHG_OPER_MASK, val);
188
189 switch (val) {
190 case CHG_OPER_CHARGER_ON_LINEAR_ON:
191 *online = CHARGER_ONLINE_FIXED;
192 break;
193 default:
194 *online = CHARGER_ONLINE_OFFLINE;
195 break;
196 };
197
198 return 0;
199 }
200
pf1550_set_constant_charge_current(const struct device * dev,uint32_t current_ua)201 static int pf1550_set_constant_charge_current(const struct device *dev, uint32_t current_ua)
202 {
203 const struct charger_pf1550_config *const config = dev->config;
204 uint16_t idx;
205 uint8_t val;
206 int ret;
207
208 ret = linear_range_group_get_index(charger_fast_charge_ua_range,
209 ARRAY_SIZE(charger_fast_charge_ua_range), current_ua,
210 &idx);
211 if (ret < 0) {
212 return ret;
213 }
214
215 val = FIELD_PREP(CHG_CURR_CNFG_CHG_CC_MASK, idx);
216
217 return i2c_reg_update_byte_dt(&config->bus, CHARGER_CHG_CURR_CNFG,
218 CHG_CURR_CNFG_CHG_CC_MASK, val);
219 }
220
pf1550_set_vbus_ilim(const struct device * dev,uint32_t current_ua)221 static int pf1550_set_vbus_ilim(const struct device *dev, uint32_t current_ua)
222 {
223 const struct charger_pf1550_config *const config = dev->config;
224 uint16_t idx;
225 uint8_t val;
226 int ret;
227
228 ret = linear_range_group_get_index(charger_vbus_ilim_range,
229 ARRAY_SIZE(charger_vbus_ilim_range), current_ua, &idx);
230 if (ret < 0) {
231 return ret;
232 }
233
234 val = FIELD_PREP(VBUS_INLIM_CNFG_VBUS_INLIM_MASK, idx);
235
236 return i2c_reg_update_byte_dt(&config->bus, CHARGER_VBUS_INLIM_CNFG,
237 VBUS_INLIM_CNFG_VBUS_INLIM_MASK, val);
238 }
239
pf1550_set_vsys_min(const struct device * dev,uint32_t voltage_uv)240 static int pf1550_set_vsys_min(const struct device *dev, uint32_t voltage_uv)
241 {
242 const struct charger_pf1550_config *const config = dev->config;
243 uint16_t idx;
244 uint8_t val;
245 int ret;
246
247 ret = linear_range_group_get_index(charger_vsysmin_uv, ARRAY_SIZE(charger_vsysmin_uv),
248 voltage_uv, &idx);
249 if (ret < 0) {
250 return ret;
251 }
252
253 val = FIELD_PREP(BATT_REG_VSYSMIN_MASK, idx);
254
255 return i2c_reg_update_byte_dt(&config->bus, CHARGER_BATT_REG, BATT_REG_VSYSMIN_MASK, val);
256 }
257
pf1550_set_charge_termination_uv(const struct device * dev,uint32_t voltage_uv)258 static int pf1550_set_charge_termination_uv(const struct device *dev, uint32_t voltage_uv)
259 {
260 const struct charger_pf1550_config *const config = dev->config;
261 uint16_t idx;
262 uint8_t val;
263 int ret;
264
265 ret = linear_range_group_get_index(charger_battery_termination_uv_range,
266 ARRAY_SIZE(charger_battery_termination_uv_range),
267 voltage_uv, &idx);
268 if (ret < 0) {
269 return ret;
270 }
271
272 val = FIELD_PREP(BATT_REG_CHGCV_MASK, idx);
273
274 return i2c_reg_update_byte_dt(&config->bus, CHARGER_BATT_REG, BATT_REG_CHGCV_MASK, val);
275 }
276
pf1550_set_thermistor_mode(const struct device * dev,enum charger_pf1550_therm_mode mode)277 static int pf1550_set_thermistor_mode(const struct device *dev, enum charger_pf1550_therm_mode mode)
278 {
279 const struct charger_pf1550_config *const config = dev->config;
280 uint8_t val;
281
282 val = FIELD_PREP(THM_REG_CNFG_THM_CNFG_MASK, mode);
283
284 return i2c_reg_update_byte_dt(&config->bus, CHARGER_THM_REG_CNFG,
285 THM_REG_CNFG_THM_CNFG_MASK, val);
286 }
287
pf1550_set_enabled(const struct device * dev,bool enable)288 static int pf1550_set_enabled(const struct device *dev, bool enable)
289 {
290 struct charger_pf1550_data *data = dev->data;
291 const struct charger_pf1550_config *const config = dev->config;
292
293 int ret = i2c_reg_update_byte_dt(&config->bus, CHARGER_CHG_OPER, CHG_OPER_CHG_OPER_MASK,
294 enable ? 2 : 0);
295
296 if (ret == 0) {
297 data->charger_enabled = enable;
298 }
299
300 return ret;
301 }
302
pf1550_get_interrupt_source(const struct device * dev,uint8_t * int_a)303 static int pf1550_get_interrupt_source(const struct device *dev, uint8_t *int_a)
304 {
305 const struct charger_pf1550_config *config = dev->config;
306 uint8_t buf = 0;
307 int ret;
308
309 ret = i2c_reg_read_byte_dt(&config->bus, CHARGER_CHG_INT, &buf);
310
311 if (int_a) {
312 *int_a = buf;
313 }
314 return ret;
315 }
316
pf1550_enable_interrupts(const struct device * dev)317 static int pf1550_enable_interrupts(const struct device *dev)
318 {
319 const struct charger_pf1550_config *config = dev->config;
320 int ret;
321
322 ret = pf1550_get_interrupt_source(dev, NULL);
323 if (ret < 0) {
324 LOG_WRN("Failed to clear pending interrupts: %d", ret);
325 return ret;
326 }
327
328 return i2c_reg_write_byte_dt(&config->bus, CHARGER_CHG_INT_MASK, CHG_INT_ENABLE_ALL);
329 }
330
pf1550_led_config(const struct device * dev)331 static int pf1550_led_config(const struct device *dev)
332 {
333 struct charger_pf1550_data *data = dev->data;
334 const struct charger_pf1550_config *config = dev->config;
335 struct charger_pf1550_led_config *cfg = data->led_config;
336 int ret;
337 uint8_t val;
338
339 cfg->enabled = true;
340
341 if (cfg->behaviour == PF1550_LED_MANUAL_OFF) {
342 cfg->manual = true;
343 cfg->enabled = false;
344 }
345
346 val = (cfg->enabled ? LED_PWM_LED_EN : 0) | LED_PWM_FULL_ON;
347
348 ret = i2c_reg_write_byte_dt(&config->bus, CHARGER_LED_PWM, val);
349 if (ret < 0) {
350 return ret;
351 }
352
353 val = (cfg->manual ? LED_CNFG_LEDOVRD : 0) |
354 (cfg->behaviour == PF1550_LED_FLASH_IN_CHARGING_ON_IN_FAULT ?
355 LED_CNFG_LED_CFG : 0);
356
357 return i2c_reg_write_byte_dt(&config->bus, CHARGER_LED_CNFG, val);
358 }
359
pf1550_init_properties(const struct device * dev)360 static int pf1550_init_properties(const struct device *dev)
361 {
362 struct charger_pf1550_data *data = dev->data;
363 const struct charger_pf1550_config *config = dev->config;
364 int ret;
365
366 data->charger_enabled = true;
367 data->charge_current_ua = config->charge_current_ua;
368 data->vbus_ilim_ua = config->vbus_ilim_ua;
369
370 ret = pf1550_get_charger_status(dev, &data->charger_status);
371 if (ret < 0) {
372 LOG_ERR("Failed to read charger status: %d", ret);
373 return ret;
374 }
375
376 ret = pf1550_get_charger_online(dev, &data->charger_online);
377 if (ret < 0) {
378 LOG_ERR("Failed to read charger online: %d", ret);
379 return ret;
380 }
381
382 return 0;
383 }
384
pf1550_string_to_therm_mode(const char * mode_string)385 enum charger_pf1550_therm_mode pf1550_string_to_therm_mode(const char *mode_string)
386 {
387 static const char *const modes[] = {
388 [PF1550_THERM_MODE_DISABLED] = "disabled",
389 [PF1550_THERM_MODE_THERMISTOR] = "thermistor",
390 [PF1550_THERM_MODE_JEITA_1] = "JEITA-1",
391 [PF1550_THERM_MODE_JEITA_2] = "JEITA-2",
392 };
393 enum charger_pf1550_therm_mode i;
394
395 for (i = PF1550_THERM_MODE_DISABLED; i < ARRAY_SIZE(modes); i++) {
396 if (strncmp(mode_string, modes[i], strlen(modes[i])) == 0) {
397 return i;
398 }
399 }
400
401 return PF1550_THERM_MODE_UNKNOWN;
402 }
403
pf1550_update_properties(const struct device * dev)404 static int pf1550_update_properties(const struct device *dev)
405 {
406 struct charger_pf1550_data *data = dev->data;
407 const struct charger_pf1550_config *config = dev->config;
408 enum charger_pf1550_therm_mode therm_mode;
409 int ret;
410
411 ret = pf1550_set_vbus_ilim(dev, config->vbus_ilim_ua);
412 if (ret < 0) {
413 LOG_ERR("Failed to set vbus current limit: %d", ret);
414 return ret;
415 }
416
417 ret = pf1550_set_vsys_min(dev, config->vsys_min_uv);
418 if (ret < 0) {
419 LOG_ERR("Failed to set minimum system voltage threshold: %d", ret);
420 return ret;
421 }
422
423 ret = pf1550_set_charge_termination_uv(dev, config->charge_voltage_max_uv);
424 if (ret < 0) {
425 LOG_ERR("Failed to set recharge threshold: %d", ret);
426 return ret;
427 }
428
429 therm_mode = pf1550_string_to_therm_mode(config->therm_mon_mode);
430 ret = pf1550_set_thermistor_mode(dev, therm_mode);
431 if (ret < 0) {
432 LOG_ERR("Failed to set thermistor mode: %d", ret);
433 return ret;
434 }
435
436 ret = pf1550_set_constant_charge_current(dev, data->charge_current_ua);
437 if (ret < 0) {
438 LOG_ERR("Failed to set charge voltage: %d", ret);
439 return ret;
440 }
441
442 ret = pf1550_set_enabled(dev, data->charger_enabled);
443 if (ret < 0) {
444 LOG_ERR("Failed to set enabled: %d", ret);
445 return ret;
446 }
447
448 ret = pf1550_led_config(dev);
449 if (ret < 0) {
450 LOG_ERR("Failed to configure led: %d", ret);
451 return ret;
452 }
453
454 return 0;
455 }
456
pf1550_get_prop(const struct device * dev,charger_prop_t prop,union charger_propval * val)457 static int pf1550_get_prop(const struct device *dev, charger_prop_t prop,
458 union charger_propval *val)
459 {
460 struct charger_pf1550_data *data = dev->data;
461
462 switch (prop) {
463 case CHARGER_PROP_ONLINE:
464 val->online = data->charger_online;
465 return 0;
466 case CHARGER_PROP_STATUS:
467 val->status = data->charger_status;
468 return 0;
469 case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA:
470 val->const_charge_current_ua = data->charge_current_ua;
471 return 0;
472 default:
473 return -ENOTSUP;
474 }
475 }
476
pf1550_set_prop(const struct device * dev,charger_prop_t prop,const union charger_propval * val)477 static int pf1550_set_prop(const struct device *dev, charger_prop_t prop,
478 const union charger_propval *val)
479 {
480 struct charger_pf1550_data *data = dev->data;
481 int ret;
482
483 switch (prop) {
484 case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA:
485 ret = pf1550_set_constant_charge_current(dev, val->const_charge_current_ua);
486 if (ret == 0) {
487 data->charge_current_ua = val->const_charge_current_ua;
488 }
489 return ret;
490 case CHARGER_PROP_INPUT_REGULATION_CURRENT_UA:
491 ret = pf1550_set_vbus_ilim(dev, val->input_current_regulation_current_ua);
492 if (ret == 0) {
493 data->vbus_ilim_ua = val->input_current_regulation_current_ua;
494 }
495 return ret;
496 case CHARGER_PROP_STATUS_NOTIFICATION:
497 data->charger_status_notifier = val->status_notification;
498 return 0;
499 case CHARGER_PROP_ONLINE_NOTIFICATION:
500 data->charger_online_notifier = val->online_notification;
501 return 0;
502 default:
503 return -ENOTSUP;
504 }
505 }
506
pf1550_enable_interrupt_pin(const struct device * dev,bool enabled)507 static int pf1550_enable_interrupt_pin(const struct device *dev, bool enabled)
508 {
509 const struct charger_pf1550_config *const config = dev->config;
510 gpio_flags_t flags;
511 int ret;
512
513 flags = enabled ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE;
514
515 ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, flags);
516 if (ret < 0) {
517 LOG_ERR("Could not %s interrupt GPIO callback: %d", enabled ? "enable" : "disable",
518 ret);
519 }
520
521 return ret;
522 }
523
pf1550_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)524 static void pf1550_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
525 {
526 struct charger_pf1550_data *data = CONTAINER_OF(cb, struct charger_pf1550_data, gpio_cb);
527 int ret;
528
529 (void)pf1550_enable_interrupt_pin(data->dev, false);
530
531 ret = k_work_submit(&data->int_routine_work);
532 if (ret < 0) {
533 LOG_WRN("Could not submit int work: %d", ret);
534 }
535 }
536
pf1550_int_routine_work_handler(struct k_work * work)537 static void pf1550_int_routine_work_handler(struct k_work *work)
538 {
539 struct charger_pf1550_data *data =
540 CONTAINER_OF(work, struct charger_pf1550_data, int_routine_work);
541 uint8_t int_src;
542 int ret;
543
544 ret = pf1550_get_interrupt_source(data->dev, &int_src);
545 if (ret < 0) {
546 LOG_WRN("Failed to read interrupt source: %d", ret);
547 return;
548 }
549
550 LOG_DBG("Interrupt received: %x", int_src);
551
552 ret = pf1550_get_charger_status(data->dev, &data->charger_status);
553 if (ret < 0) {
554 LOG_WRN("Failed to read charger status: %d", ret);
555 return;
556 }
557
558 ret = pf1550_get_charger_online(data->dev, &data->charger_online);
559 if (ret < 0) {
560 LOG_WRN("Failed to read charger online %d", ret);
561 return;
562 }
563
564 if (data->charger_status_notifier != NULL) {
565 data->charger_status_notifier(data->charger_status);
566 }
567 if (data->charger_online_notifier != NULL) {
568 data->charger_online_notifier(data->charger_online);
569 }
570
571 if (data->charger_online != CHARGER_ONLINE_OFFLINE) {
572 (void)pf1550_update_properties(data->dev);
573 }
574
575 ret = k_work_reschedule(&data->int_enable_work, INT_ENABLE_DELAY);
576 if (ret < 0) {
577 LOG_WRN("Could not reschedule int_enable_work: %d", ret);
578 }
579 }
580
pf1550_int_enable_work_handler(struct k_work * work)581 static void pf1550_int_enable_work_handler(struct k_work *work)
582 {
583 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
584 struct charger_pf1550_data *data =
585 CONTAINER_OF(dwork, struct charger_pf1550_data, int_enable_work);
586
587 (void)pf1550_enable_interrupt_pin(data->dev, true);
588 }
589
pf1550_configure_interrupt_pin(const struct device * dev)590 static int pf1550_configure_interrupt_pin(const struct device *dev)
591 {
592 struct charger_pf1550_data *data = dev->data;
593 const struct charger_pf1550_config *config = dev->config;
594 int ret;
595
596 ret = gpio_is_ready_dt(&config->int_gpio) ? 0 : -ENODEV;
597 if (ret < 0) {
598 LOG_ERR("Interrupt GPIO device not ready: %d", ret);
599 return ret;
600 }
601
602 ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
603 if (ret < 0) {
604 LOG_ERR("Could not configure interrupt GPIO: %d", ret);
605 return ret;
606 }
607
608 gpio_init_callback(&data->gpio_cb, pf1550_gpio_callback, BIT(config->int_gpio.pin));
609 ret = gpio_add_callback_dt(&config->int_gpio, &data->gpio_cb);
610 if (ret < 0) {
611 LOG_ERR("Could not add interrupt GPIO callback: %d", ret);
612 return ret;
613 }
614
615 return 0;
616 }
617
pf1550_init(const struct device * dev)618 static int pf1550_init(const struct device *dev)
619 {
620 struct charger_pf1550_data *data = dev->data;
621 const struct charger_pf1550_config *config = dev->config;
622 int ret;
623
624 if (!i2c_is_ready_dt(&config->bus)) {
625 return -ENODEV;
626 }
627
628 data->dev = dev;
629
630 ret = pf1550_init_properties(dev);
631 if (ret < 0) {
632 return ret;
633 }
634
635 k_work_init(&data->int_routine_work, pf1550_int_routine_work_handler);
636 k_work_init_delayable(&data->int_enable_work, pf1550_int_enable_work_handler);
637
638 ret = pf1550_configure_interrupt_pin(dev);
639 if (ret < 0) {
640 return ret;
641 }
642
643 ret = pf1550_enable_interrupt_pin(dev, true);
644 if (ret < 0) {
645 return ret;
646 }
647
648 ret = pf1550_enable_interrupts(dev);
649 if (ret < 0) {
650 LOG_ERR("Failed to enable interrupts: %d", ret);
651 return ret;
652 }
653
654 ret = pf1550_update_properties(dev);
655 if (ret < 0) {
656 LOG_ERR("Failed to setup charger: %d", ret);
657 return ret;
658 }
659
660 return 0;
661 }
662
663 static DEVICE_API(charger, pf1550_driver_api) = {
664 .get_property = pf1550_get_prop,
665 .set_property = pf1550_set_prop,
666 .charge_enable = pf1550_set_enabled,
667 };
668
669 #define PF1550_DEFINE(inst) \
670 static struct charger_pf1550_led_config charger_pf1550_led_config_##inst = { \
671 .behaviour = DT_INST_ENUM_IDX(inst, pf1550_led_behaviour), \
672 }; \
673 static struct charger_pf1550_data charger_pf1550_data_##inst = { \
674 .led_config = &charger_pf1550_led_config_##inst, \
675 }; \
676 static const struct charger_pf1550_config charger_pf1550_config_##inst = { \
677 .bus = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
678 .int_gpio = GPIO_DT_SPEC_INST_GET(inst, pf1550_int_gpios), \
679 .charge_current_ua = DT_INST_PROP(inst, constant_charge_current_max_microamp), \
680 .vsys_min_uv = DT_INST_PROP(inst, pf1550_system_voltage_min_threshold_microvolt), \
681 .therm_mon_mode = DT_INST_PROP(inst, pf1550_thermistor_monitoring_mode), \
682 .vbus_ilim_ua = DT_INST_PROP(inst, pf1550_vbus_current_limit_microamp), \
683 .charge_voltage_max_uv = \
684 DT_INST_PROP(inst, constant_charge_voltage_max_microvolt), \
685 }; \
686 \
687 DEVICE_DT_INST_DEFINE(inst, &pf1550_init, NULL, &charger_pf1550_data_##inst, \
688 &charger_pf1550_config_##inst, POST_KERNEL, \
689 CONFIG_MFD_INIT_PRIORITY, &pf1550_driver_api);
690
691 DT_INST_FOREACH_STATUS_OKAY(PF1550_DEFINE)
692