1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DA9150 Charger Driver
5 * Copyright (c) 2014 Dialog Semiconductor
7 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
15 #include <linux/of_platform.h>
16 #include <linux/interrupt.h>
17 #include <linux/power_supply.h>
18 #include <linux/notifier.h>
19 #include <linux/usb/phy.h>
20 #include <linux/iio/consumer.h>
21 #include <linux/mfd/da9150/core.h>
22 #include <linux/mfd/da9150/registers.h>
25 struct da9150_charger
{
26 struct da9150
*da9150
;
29 struct power_supply
*usb
;
30 struct power_supply
*battery
;
31 struct power_supply
*supply_online
;
33 struct usb_phy
*usb_phy
;
34 struct notifier_block otg_nb
;
35 struct work_struct otg_work
;
36 unsigned long usb_event
;
38 struct iio_channel
*ibus_chan
;
39 struct iio_channel
*vbus_chan
;
40 struct iio_channel
*tjunc_chan
;
41 struct iio_channel
*vbat_chan
;
44 static inline int da9150_charger_supply_online(struct da9150_charger
*charger
,
45 struct power_supply
*psy
,
46 union power_supply_propval
*val
)
48 val
->intval
= (psy
== charger
->supply_online
) ? 1 : 0;
53 /* Charger Properties */
54 static int da9150_charger_vbus_voltage_now(struct da9150_charger
*charger
,
55 union power_supply_propval
*val
)
59 /* Read processed value - mV units */
60 ret
= iio_read_channel_processed(charger
->vbus_chan
, &v_val
);
64 /* Convert voltage to expected uV units */
65 val
->intval
= v_val
* 1000;
70 static int da9150_charger_ibus_current_avg(struct da9150_charger
*charger
,
71 union power_supply_propval
*val
)
75 /* Read processed value - mA units */
76 ret
= iio_read_channel_processed(charger
->ibus_chan
, &i_val
);
80 /* Convert current to expected uA units */
81 val
->intval
= i_val
* 1000;
86 static int da9150_charger_tjunc_temp(struct da9150_charger
*charger
,
87 union power_supply_propval
*val
)
91 /* Read processed value - 0.001 degrees C units */
92 ret
= iio_read_channel_processed(charger
->tjunc_chan
, &t_val
);
96 /* Convert temp to expect 0.1 degrees C units */
97 val
->intval
= t_val
/ 100;
102 static enum power_supply_property da9150_charger_props
[] = {
103 POWER_SUPPLY_PROP_ONLINE
,
104 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
105 POWER_SUPPLY_PROP_CURRENT_AVG
,
106 POWER_SUPPLY_PROP_TEMP
,
109 static int da9150_charger_get_prop(struct power_supply
*psy
,
110 enum power_supply_property psp
,
111 union power_supply_propval
*val
)
113 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
117 case POWER_SUPPLY_PROP_ONLINE
:
118 ret
= da9150_charger_supply_online(charger
, psy
, val
);
120 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
121 ret
= da9150_charger_vbus_voltage_now(charger
, val
);
123 case POWER_SUPPLY_PROP_CURRENT_AVG
:
124 ret
= da9150_charger_ibus_current_avg(charger
, val
);
126 case POWER_SUPPLY_PROP_TEMP
:
127 ret
= da9150_charger_tjunc_temp(charger
, val
);
137 /* Battery Properties */
138 static int da9150_charger_battery_status(struct da9150_charger
*charger
,
139 union power_supply_propval
*val
)
143 /* Check to see if battery is discharging */
144 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
146 if (((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_OFF
) ||
147 ((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_WAIT
)) {
148 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
153 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
155 /* Now check for other states */
156 switch (reg
& DA9150_CHG_STAT_MASK
) {
157 case DA9150_CHG_STAT_ACT
:
158 case DA9150_CHG_STAT_PRE
:
159 case DA9150_CHG_STAT_CC
:
160 case DA9150_CHG_STAT_CV
:
161 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
163 case DA9150_CHG_STAT_OFF
:
164 case DA9150_CHG_STAT_SUSP
:
165 case DA9150_CHG_STAT_TEMP
:
166 case DA9150_CHG_STAT_TIME
:
167 case DA9150_CHG_STAT_BAT
:
168 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
170 case DA9150_CHG_STAT_FULL
:
171 val
->intval
= POWER_SUPPLY_STATUS_FULL
;
174 val
->intval
= POWER_SUPPLY_STATUS_UNKNOWN
;
181 static int da9150_charger_battery_health(struct da9150_charger
*charger
,
182 union power_supply_propval
*val
)
186 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
188 /* Check if temperature limit reached */
189 switch (reg
& DA9150_CHG_TEMP_MASK
) {
190 case DA9150_CHG_TEMP_UNDER
:
191 val
->intval
= POWER_SUPPLY_HEALTH_COLD
;
193 case DA9150_CHG_TEMP_OVER
:
194 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
200 /* Check for other health states */
201 switch (reg
& DA9150_CHG_STAT_MASK
) {
202 case DA9150_CHG_STAT_ACT
:
203 case DA9150_CHG_STAT_PRE
:
204 val
->intval
= POWER_SUPPLY_HEALTH_DEAD
;
206 case DA9150_CHG_STAT_TIME
:
207 val
->intval
= POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
;
210 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
217 static int da9150_charger_battery_present(struct da9150_charger
*charger
,
218 union power_supply_propval
*val
)
222 /* Check if battery present or removed */
223 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
224 if ((reg
& DA9150_CHG_STAT_MASK
) == DA9150_CHG_STAT_BAT
)
232 static int da9150_charger_battery_charge_type(struct da9150_charger
*charger
,
233 union power_supply_propval
*val
)
237 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
239 switch (reg
& DA9150_CHG_STAT_MASK
) {
240 case DA9150_CHG_STAT_CC
:
241 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
243 case DA9150_CHG_STAT_ACT
:
244 case DA9150_CHG_STAT_PRE
:
245 case DA9150_CHG_STAT_CV
:
246 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
249 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_NONE
;
256 static int da9150_charger_battery_voltage_min(struct da9150_charger
*charger
,
257 union power_supply_propval
*val
)
261 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_C
);
263 /* Value starts at 2500 mV, 50 mV increments, presented in uV */
264 val
->intval
= ((reg
& DA9150_CHG_VFAULT_MASK
) * 50000) + 2500000;
269 static int da9150_charger_battery_voltage_now(struct da9150_charger
*charger
,
270 union power_supply_propval
*val
)
274 /* Read processed value - mV units */
275 ret
= iio_read_channel_processed(charger
->vbat_chan
, &v_val
);
279 val
->intval
= v_val
* 1000;
284 static int da9150_charger_battery_current_max(struct da9150_charger
*charger
,
285 union power_supply_propval
*val
)
289 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_D
);
291 /* 25mA increments */
292 val
->intval
= reg
* 25000;
297 static int da9150_charger_battery_voltage_max(struct da9150_charger
*charger
,
298 union power_supply_propval
*val
)
302 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_B
);
304 /* Value starts at 3650 mV, 25 mV increments, presented in uV */
305 val
->intval
= ((reg
& DA9150_CHG_VBAT_MASK
) * 25000) + 3650000;
309 static enum power_supply_property da9150_charger_bat_props
[] = {
310 POWER_SUPPLY_PROP_STATUS
,
311 POWER_SUPPLY_PROP_ONLINE
,
312 POWER_SUPPLY_PROP_HEALTH
,
313 POWER_SUPPLY_PROP_PRESENT
,
314 POWER_SUPPLY_PROP_CHARGE_TYPE
,
315 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
316 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
317 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
318 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
,
321 static int da9150_charger_battery_get_prop(struct power_supply
*psy
,
322 enum power_supply_property psp
,
323 union power_supply_propval
*val
)
325 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
329 case POWER_SUPPLY_PROP_STATUS
:
330 ret
= da9150_charger_battery_status(charger
, val
);
332 case POWER_SUPPLY_PROP_ONLINE
:
333 ret
= da9150_charger_supply_online(charger
, psy
, val
);
335 case POWER_SUPPLY_PROP_HEALTH
:
336 ret
= da9150_charger_battery_health(charger
, val
);
338 case POWER_SUPPLY_PROP_PRESENT
:
339 ret
= da9150_charger_battery_present(charger
, val
);
341 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
342 ret
= da9150_charger_battery_charge_type(charger
, val
);
344 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
345 ret
= da9150_charger_battery_voltage_min(charger
, val
);
347 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
348 ret
= da9150_charger_battery_voltage_now(charger
, val
);
350 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
351 ret
= da9150_charger_battery_current_max(charger
, val
);
353 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
:
354 ret
= da9150_charger_battery_voltage_max(charger
, val
);
364 static irqreturn_t
da9150_charger_chg_irq(int irq
, void *data
)
366 struct da9150_charger
*charger
= data
;
368 power_supply_changed(charger
->battery
);
373 static irqreturn_t
da9150_charger_tjunc_irq(int irq
, void *data
)
375 struct da9150_charger
*charger
= data
;
377 /* Nothing we can really do except report this. */
378 dev_crit(charger
->dev
, "TJunc over temperature!!!\n");
379 power_supply_changed(charger
->usb
);
384 static irqreturn_t
da9150_charger_vfault_irq(int irq
, void *data
)
386 struct da9150_charger
*charger
= data
;
388 /* Nothing we can really do except report this. */
389 dev_crit(charger
->dev
, "VSYS under voltage!!!\n");
390 power_supply_changed(charger
->usb
);
391 power_supply_changed(charger
->battery
);
396 static irqreturn_t
da9150_charger_vbus_irq(int irq
, void *data
)
398 struct da9150_charger
*charger
= data
;
401 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
403 /* Charger plugged in or battery only */
404 switch (reg
& DA9150_VBUS_STAT_MASK
) {
405 case DA9150_VBUS_STAT_OFF
:
406 case DA9150_VBUS_STAT_WAIT
:
407 charger
->supply_online
= charger
->battery
;
409 case DA9150_VBUS_STAT_CHG
:
410 charger
->supply_online
= charger
->usb
;
413 dev_warn(charger
->dev
, "Unknown VBUS state - reg = 0x%x\n",
415 charger
->supply_online
= NULL
;
419 power_supply_changed(charger
->usb
);
420 power_supply_changed(charger
->battery
);
425 static void da9150_charger_otg_work(struct work_struct
*data
)
427 struct da9150_charger
*charger
=
428 container_of(data
, struct da9150_charger
, otg_work
);
430 switch (charger
->usb_event
) {
432 /* Enable OTG Boost */
433 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
434 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_OTG
);
437 /* Revert to charge mode */
438 power_supply_changed(charger
->usb
);
439 power_supply_changed(charger
->battery
);
440 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
441 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_CHG
);
446 static int da9150_charger_otg_ncb(struct notifier_block
*nb
, unsigned long val
,
449 struct da9150_charger
*charger
=
450 container_of(nb
, struct da9150_charger
, otg_nb
);
452 dev_dbg(charger
->dev
, "DA9150 OTG notify %lu\n", val
);
454 charger
->usb_event
= val
;
455 schedule_work(&charger
->otg_work
);
460 static int da9150_charger_register_irq(struct platform_device
*pdev
,
461 irq_handler_t handler
,
462 const char *irq_name
)
464 struct device
*dev
= &pdev
->dev
;
465 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
468 irq
= platform_get_irq_byname(pdev
, irq_name
);
470 dev_err(dev
, "Failed to get IRQ CHG_STATUS: %d\n", irq
);
474 ret
= request_threaded_irq(irq
, NULL
, handler
, IRQF_ONESHOT
, irq_name
,
477 dev_err(dev
, "Failed to request IRQ %d: %d\n", irq
, ret
);
482 static void da9150_charger_unregister_irq(struct platform_device
*pdev
,
483 const char *irq_name
)
485 struct device
*dev
= &pdev
->dev
;
486 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
489 irq
= platform_get_irq_byname(pdev
, irq_name
);
491 dev_err(dev
, "Failed to get IRQ CHG_STATUS: %d\n", irq
);
495 free_irq(irq
, charger
);
498 static const struct power_supply_desc usb_desc
= {
499 .name
= "da9150-usb",
500 .type
= POWER_SUPPLY_TYPE_USB
,
501 .properties
= da9150_charger_props
,
502 .num_properties
= ARRAY_SIZE(da9150_charger_props
),
503 .get_property
= da9150_charger_get_prop
,
506 static const struct power_supply_desc battery_desc
= {
507 .name
= "da9150-battery",
508 .type
= POWER_SUPPLY_TYPE_BATTERY
,
509 .properties
= da9150_charger_bat_props
,
510 .num_properties
= ARRAY_SIZE(da9150_charger_bat_props
),
511 .get_property
= da9150_charger_battery_get_prop
,
514 static int da9150_charger_probe(struct platform_device
*pdev
)
516 struct device
*dev
= &pdev
->dev
;
517 struct da9150
*da9150
= dev_get_drvdata(dev
->parent
);
518 struct da9150_charger
*charger
;
522 charger
= devm_kzalloc(dev
, sizeof(struct da9150_charger
), GFP_KERNEL
);
526 platform_set_drvdata(pdev
, charger
);
527 charger
->da9150
= da9150
;
530 /* Acquire ADC channels */
531 charger
->ibus_chan
= iio_channel_get(dev
, "CHAN_IBUS");
532 if (IS_ERR(charger
->ibus_chan
)) {
533 ret
= PTR_ERR(charger
->ibus_chan
);
537 charger
->vbus_chan
= iio_channel_get(dev
, "CHAN_VBUS");
538 if (IS_ERR(charger
->vbus_chan
)) {
539 ret
= PTR_ERR(charger
->vbus_chan
);
543 charger
->tjunc_chan
= iio_channel_get(dev
, "CHAN_TJUNC");
544 if (IS_ERR(charger
->tjunc_chan
)) {
545 ret
= PTR_ERR(charger
->tjunc_chan
);
546 goto tjunc_chan_fail
;
549 charger
->vbat_chan
= iio_channel_get(dev
, "CHAN_VBAT");
550 if (IS_ERR(charger
->vbat_chan
)) {
551 ret
= PTR_ERR(charger
->vbat_chan
);
555 /* Register power supplies */
556 charger
->usb
= power_supply_register(dev
, &usb_desc
, NULL
);
557 if (IS_ERR(charger
->usb
)) {
558 ret
= PTR_ERR(charger
->usb
);
562 charger
->battery
= power_supply_register(dev
, &battery_desc
, NULL
);
563 if (IS_ERR(charger
->battery
)) {
564 ret
= PTR_ERR(charger
->battery
);
568 /* Get initial online supply */
569 reg
= da9150_reg_read(da9150
, DA9150_STATUS_H
);
571 switch (reg
& DA9150_VBUS_STAT_MASK
) {
572 case DA9150_VBUS_STAT_OFF
:
573 case DA9150_VBUS_STAT_WAIT
:
574 charger
->supply_online
= charger
->battery
;
576 case DA9150_VBUS_STAT_CHG
:
577 charger
->supply_online
= charger
->usb
;
580 dev_warn(dev
, "Unknown VBUS state - reg = 0x%x\n", reg
);
581 charger
->supply_online
= NULL
;
585 /* Setup OTG reporting & configuration */
586 charger
->usb_phy
= devm_usb_get_phy(dev
, USB_PHY_TYPE_USB2
);
587 if (!IS_ERR_OR_NULL(charger
->usb_phy
)) {
588 INIT_WORK(&charger
->otg_work
, da9150_charger_otg_work
);
589 charger
->otg_nb
.notifier_call
= da9150_charger_otg_ncb
;
590 usb_register_notifier(charger
->usb_phy
, &charger
->otg_nb
);
594 ret
= da9150_charger_register_irq(pdev
, da9150_charger_chg_irq
,
599 ret
= da9150_charger_register_irq(pdev
, da9150_charger_tjunc_irq
,
604 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vfault_irq
,
607 goto vfault_irq_fail
;
609 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vbus_irq
,
618 da9150_charger_unregister_irq(pdev
, "CHG_VFAULT");
620 da9150_charger_unregister_irq(pdev
, "CHG_TJUNC");
622 da9150_charger_unregister_irq(pdev
, "CHG_STATUS");
624 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
625 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
627 power_supply_unregister(charger
->usb
);
630 iio_channel_release(charger
->vbat_chan
);
633 iio_channel_release(charger
->tjunc_chan
);
636 iio_channel_release(charger
->vbus_chan
);
639 iio_channel_release(charger
->ibus_chan
);
645 static int da9150_charger_remove(struct platform_device
*pdev
)
647 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
650 /* Make sure IRQs are released before unregistering power supplies */
651 irq
= platform_get_irq_byname(pdev
, "CHG_VBUS");
652 free_irq(irq
, charger
);
654 irq
= platform_get_irq_byname(pdev
, "CHG_VFAULT");
655 free_irq(irq
, charger
);
657 irq
= platform_get_irq_byname(pdev
, "CHG_TJUNC");
658 free_irq(irq
, charger
);
660 irq
= platform_get_irq_byname(pdev
, "CHG_STATUS");
661 free_irq(irq
, charger
);
663 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
664 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
666 power_supply_unregister(charger
->battery
);
667 power_supply_unregister(charger
->usb
);
669 /* Release ADC channels */
670 iio_channel_release(charger
->ibus_chan
);
671 iio_channel_release(charger
->vbus_chan
);
672 iio_channel_release(charger
->tjunc_chan
);
673 iio_channel_release(charger
->vbat_chan
);
678 static struct platform_driver da9150_charger_driver
= {
680 .name
= "da9150-charger",
682 .probe
= da9150_charger_probe
,
683 .remove
= da9150_charger_remove
,
686 module_platform_driver(da9150_charger_driver
);
688 MODULE_DESCRIPTION("Charger Driver for DA9150");
689 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
690 MODULE_LICENSE("GPL");