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>
14 #include <linux/interrupt.h>
15 #include <linux/power_supply.h>
16 #include <linux/notifier.h>
17 #include <linux/usb/phy.h>
18 #include <linux/iio/consumer.h>
19 #include <linux/mfd/da9150/core.h>
20 #include <linux/mfd/da9150/registers.h>
23 struct da9150_charger
{
24 struct da9150
*da9150
;
27 struct power_supply
*usb
;
28 struct power_supply
*battery
;
29 struct power_supply
*supply_online
;
31 struct usb_phy
*usb_phy
;
32 struct notifier_block otg_nb
;
33 struct work_struct otg_work
;
34 unsigned long usb_event
;
36 struct iio_channel
*ibus_chan
;
37 struct iio_channel
*vbus_chan
;
38 struct iio_channel
*tjunc_chan
;
39 struct iio_channel
*vbat_chan
;
42 static inline int da9150_charger_supply_online(struct da9150_charger
*charger
,
43 struct power_supply
*psy
,
44 union power_supply_propval
*val
)
46 val
->intval
= (psy
== charger
->supply_online
) ? 1 : 0;
51 /* Charger Properties */
52 static int da9150_charger_vbus_voltage_now(struct da9150_charger
*charger
,
53 union power_supply_propval
*val
)
57 /* Read processed value - mV units */
58 ret
= iio_read_channel_processed(charger
->vbus_chan
, &v_val
);
62 /* Convert voltage to expected uV units */
63 val
->intval
= v_val
* 1000;
68 static int da9150_charger_ibus_current_avg(struct da9150_charger
*charger
,
69 union power_supply_propval
*val
)
73 /* Read processed value - mA units */
74 ret
= iio_read_channel_processed(charger
->ibus_chan
, &i_val
);
78 /* Convert current to expected uA units */
79 val
->intval
= i_val
* 1000;
84 static int da9150_charger_tjunc_temp(struct da9150_charger
*charger
,
85 union power_supply_propval
*val
)
89 /* Read processed value - 0.001 degrees C units */
90 ret
= iio_read_channel_processed(charger
->tjunc_chan
, &t_val
);
94 /* Convert temp to expect 0.1 degrees C units */
95 val
->intval
= t_val
/ 100;
100 static enum power_supply_property da9150_charger_props
[] = {
101 POWER_SUPPLY_PROP_ONLINE
,
102 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
103 POWER_SUPPLY_PROP_CURRENT_AVG
,
104 POWER_SUPPLY_PROP_TEMP
,
107 static int da9150_charger_get_prop(struct power_supply
*psy
,
108 enum power_supply_property psp
,
109 union power_supply_propval
*val
)
111 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
115 case POWER_SUPPLY_PROP_ONLINE
:
116 ret
= da9150_charger_supply_online(charger
, psy
, val
);
118 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
119 ret
= da9150_charger_vbus_voltage_now(charger
, val
);
121 case POWER_SUPPLY_PROP_CURRENT_AVG
:
122 ret
= da9150_charger_ibus_current_avg(charger
, val
);
124 case POWER_SUPPLY_PROP_TEMP
:
125 ret
= da9150_charger_tjunc_temp(charger
, val
);
135 /* Battery Properties */
136 static int da9150_charger_battery_status(struct da9150_charger
*charger
,
137 union power_supply_propval
*val
)
141 /* Check to see if battery is discharging */
142 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
144 if (((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_OFF
) ||
145 ((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_WAIT
)) {
146 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
151 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
153 /* Now check for other states */
154 switch (reg
& DA9150_CHG_STAT_MASK
) {
155 case DA9150_CHG_STAT_ACT
:
156 case DA9150_CHG_STAT_PRE
:
157 case DA9150_CHG_STAT_CC
:
158 case DA9150_CHG_STAT_CV
:
159 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
161 case DA9150_CHG_STAT_OFF
:
162 case DA9150_CHG_STAT_SUSP
:
163 case DA9150_CHG_STAT_TEMP
:
164 case DA9150_CHG_STAT_TIME
:
165 case DA9150_CHG_STAT_BAT
:
166 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
168 case DA9150_CHG_STAT_FULL
:
169 val
->intval
= POWER_SUPPLY_STATUS_FULL
;
172 val
->intval
= POWER_SUPPLY_STATUS_UNKNOWN
;
179 static int da9150_charger_battery_health(struct da9150_charger
*charger
,
180 union power_supply_propval
*val
)
184 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
186 /* Check if temperature limit reached */
187 switch (reg
& DA9150_CHG_TEMP_MASK
) {
188 case DA9150_CHG_TEMP_UNDER
:
189 val
->intval
= POWER_SUPPLY_HEALTH_COLD
;
191 case DA9150_CHG_TEMP_OVER
:
192 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
198 /* Check for other health states */
199 switch (reg
& DA9150_CHG_STAT_MASK
) {
200 case DA9150_CHG_STAT_ACT
:
201 case DA9150_CHG_STAT_PRE
:
202 val
->intval
= POWER_SUPPLY_HEALTH_DEAD
;
204 case DA9150_CHG_STAT_TIME
:
205 val
->intval
= POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
;
208 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
215 static int da9150_charger_battery_present(struct da9150_charger
*charger
,
216 union power_supply_propval
*val
)
220 /* Check if battery present or removed */
221 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
222 if ((reg
& DA9150_CHG_STAT_MASK
) == DA9150_CHG_STAT_BAT
)
230 static int da9150_charger_battery_charge_type(struct da9150_charger
*charger
,
231 union power_supply_propval
*val
)
235 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
237 switch (reg
& DA9150_CHG_STAT_MASK
) {
238 case DA9150_CHG_STAT_CC
:
239 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
241 case DA9150_CHG_STAT_ACT
:
242 case DA9150_CHG_STAT_PRE
:
243 case DA9150_CHG_STAT_CV
:
244 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
247 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_NONE
;
254 static int da9150_charger_battery_voltage_min(struct da9150_charger
*charger
,
255 union power_supply_propval
*val
)
259 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_C
);
261 /* Value starts at 2500 mV, 50 mV increments, presented in uV */
262 val
->intval
= ((reg
& DA9150_CHG_VFAULT_MASK
) * 50000) + 2500000;
267 static int da9150_charger_battery_voltage_now(struct da9150_charger
*charger
,
268 union power_supply_propval
*val
)
272 /* Read processed value - mV units */
273 ret
= iio_read_channel_processed(charger
->vbat_chan
, &v_val
);
277 val
->intval
= v_val
* 1000;
282 static int da9150_charger_battery_current_max(struct da9150_charger
*charger
,
283 union power_supply_propval
*val
)
287 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_D
);
289 /* 25mA increments */
290 val
->intval
= reg
* 25000;
295 static int da9150_charger_battery_voltage_max(struct da9150_charger
*charger
,
296 union power_supply_propval
*val
)
300 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_B
);
302 /* Value starts at 3650 mV, 25 mV increments, presented in uV */
303 val
->intval
= ((reg
& DA9150_CHG_VBAT_MASK
) * 25000) + 3650000;
307 static enum power_supply_property da9150_charger_bat_props
[] = {
308 POWER_SUPPLY_PROP_STATUS
,
309 POWER_SUPPLY_PROP_ONLINE
,
310 POWER_SUPPLY_PROP_HEALTH
,
311 POWER_SUPPLY_PROP_PRESENT
,
312 POWER_SUPPLY_PROP_CHARGE_TYPE
,
313 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
314 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
315 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
316 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
,
319 static int da9150_charger_battery_get_prop(struct power_supply
*psy
,
320 enum power_supply_property psp
,
321 union power_supply_propval
*val
)
323 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
327 case POWER_SUPPLY_PROP_STATUS
:
328 ret
= da9150_charger_battery_status(charger
, val
);
330 case POWER_SUPPLY_PROP_ONLINE
:
331 ret
= da9150_charger_supply_online(charger
, psy
, val
);
333 case POWER_SUPPLY_PROP_HEALTH
:
334 ret
= da9150_charger_battery_health(charger
, val
);
336 case POWER_SUPPLY_PROP_PRESENT
:
337 ret
= da9150_charger_battery_present(charger
, val
);
339 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
340 ret
= da9150_charger_battery_charge_type(charger
, val
);
342 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
343 ret
= da9150_charger_battery_voltage_min(charger
, val
);
345 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
346 ret
= da9150_charger_battery_voltage_now(charger
, val
);
348 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
349 ret
= da9150_charger_battery_current_max(charger
, val
);
351 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
:
352 ret
= da9150_charger_battery_voltage_max(charger
, val
);
362 static irqreturn_t
da9150_charger_chg_irq(int irq
, void *data
)
364 struct da9150_charger
*charger
= data
;
366 power_supply_changed(charger
->battery
);
371 static irqreturn_t
da9150_charger_tjunc_irq(int irq
, void *data
)
373 struct da9150_charger
*charger
= data
;
375 /* Nothing we can really do except report this. */
376 dev_crit(charger
->dev
, "TJunc over temperature!!!\n");
377 power_supply_changed(charger
->usb
);
382 static irqreturn_t
da9150_charger_vfault_irq(int irq
, void *data
)
384 struct da9150_charger
*charger
= data
;
386 /* Nothing we can really do except report this. */
387 dev_crit(charger
->dev
, "VSYS under voltage!!!\n");
388 power_supply_changed(charger
->usb
);
389 power_supply_changed(charger
->battery
);
394 static irqreturn_t
da9150_charger_vbus_irq(int irq
, void *data
)
396 struct da9150_charger
*charger
= data
;
399 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
401 /* Charger plugged in or battery only */
402 switch (reg
& DA9150_VBUS_STAT_MASK
) {
403 case DA9150_VBUS_STAT_OFF
:
404 case DA9150_VBUS_STAT_WAIT
:
405 charger
->supply_online
= charger
->battery
;
407 case DA9150_VBUS_STAT_CHG
:
408 charger
->supply_online
= charger
->usb
;
411 dev_warn(charger
->dev
, "Unknown VBUS state - reg = 0x%x\n",
413 charger
->supply_online
= NULL
;
417 power_supply_changed(charger
->usb
);
418 power_supply_changed(charger
->battery
);
423 static void da9150_charger_otg_work(struct work_struct
*data
)
425 struct da9150_charger
*charger
=
426 container_of(data
, struct da9150_charger
, otg_work
);
428 switch (charger
->usb_event
) {
430 /* Enable OTG Boost */
431 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
432 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_OTG
);
435 /* Revert to charge mode */
436 power_supply_changed(charger
->usb
);
437 power_supply_changed(charger
->battery
);
438 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
439 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_CHG
);
444 static int da9150_charger_otg_ncb(struct notifier_block
*nb
, unsigned long val
,
447 struct da9150_charger
*charger
=
448 container_of(nb
, struct da9150_charger
, otg_nb
);
450 dev_dbg(charger
->dev
, "DA9150 OTG notify %lu\n", val
);
452 charger
->usb_event
= val
;
453 schedule_work(&charger
->otg_work
);
458 static int da9150_charger_register_irq(struct platform_device
*pdev
,
459 irq_handler_t handler
,
460 const char *irq_name
)
462 struct device
*dev
= &pdev
->dev
;
463 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
466 irq
= platform_get_irq_byname(pdev
, irq_name
);
470 ret
= request_threaded_irq(irq
, NULL
, handler
, IRQF_ONESHOT
, irq_name
,
473 dev_err(dev
, "Failed to request IRQ %d: %d\n", irq
, ret
);
478 static void da9150_charger_unregister_irq(struct platform_device
*pdev
,
479 const char *irq_name
)
481 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
484 irq
= platform_get_irq_byname(pdev
, irq_name
);
488 free_irq(irq
, charger
);
491 static const struct power_supply_desc usb_desc
= {
492 .name
= "da9150-usb",
493 .type
= POWER_SUPPLY_TYPE_USB
,
494 .properties
= da9150_charger_props
,
495 .num_properties
= ARRAY_SIZE(da9150_charger_props
),
496 .get_property
= da9150_charger_get_prop
,
499 static const struct power_supply_desc battery_desc
= {
500 .name
= "da9150-battery",
501 .type
= POWER_SUPPLY_TYPE_BATTERY
,
502 .properties
= da9150_charger_bat_props
,
503 .num_properties
= ARRAY_SIZE(da9150_charger_bat_props
),
504 .get_property
= da9150_charger_battery_get_prop
,
507 static int da9150_charger_probe(struct platform_device
*pdev
)
509 struct device
*dev
= &pdev
->dev
;
510 struct da9150
*da9150
= dev_get_drvdata(dev
->parent
);
511 struct da9150_charger
*charger
;
515 charger
= devm_kzalloc(dev
, sizeof(struct da9150_charger
), GFP_KERNEL
);
519 platform_set_drvdata(pdev
, charger
);
520 charger
->da9150
= da9150
;
523 /* Acquire ADC channels */
524 charger
->ibus_chan
= devm_iio_channel_get(dev
, "CHAN_IBUS");
525 if (IS_ERR(charger
->ibus_chan
))
526 return PTR_ERR(charger
->ibus_chan
);
528 charger
->vbus_chan
= devm_iio_channel_get(dev
, "CHAN_VBUS");
529 if (IS_ERR(charger
->vbus_chan
))
530 return PTR_ERR(charger
->vbus_chan
);
532 charger
->tjunc_chan
= devm_iio_channel_get(dev
, "CHAN_TJUNC");
533 if (IS_ERR(charger
->tjunc_chan
))
534 return PTR_ERR(charger
->tjunc_chan
);
536 charger
->vbat_chan
= devm_iio_channel_get(dev
, "CHAN_VBAT");
537 if (IS_ERR(charger
->vbat_chan
))
538 return PTR_ERR(charger
->vbat_chan
);
540 /* Register power supplies */
541 charger
->usb
= devm_power_supply_register(dev
, &usb_desc
, NULL
);
542 if (IS_ERR(charger
->usb
))
543 return PTR_ERR(charger
->usb
);
545 charger
->battery
= devm_power_supply_register(dev
, &battery_desc
, NULL
);
546 if (IS_ERR(charger
->battery
))
547 return PTR_ERR(charger
->battery
);
549 /* Get initial online supply */
550 reg
= da9150_reg_read(da9150
, DA9150_STATUS_H
);
552 switch (reg
& DA9150_VBUS_STAT_MASK
) {
553 case DA9150_VBUS_STAT_OFF
:
554 case DA9150_VBUS_STAT_WAIT
:
555 charger
->supply_online
= charger
->battery
;
557 case DA9150_VBUS_STAT_CHG
:
558 charger
->supply_online
= charger
->usb
;
561 dev_warn(dev
, "Unknown VBUS state - reg = 0x%x\n", reg
);
562 charger
->supply_online
= NULL
;
566 /* Setup OTG reporting & configuration */
567 charger
->usb_phy
= devm_usb_get_phy(dev
, USB_PHY_TYPE_USB2
);
568 if (!IS_ERR_OR_NULL(charger
->usb_phy
)) {
569 INIT_WORK(&charger
->otg_work
, da9150_charger_otg_work
);
570 charger
->otg_nb
.notifier_call
= da9150_charger_otg_ncb
;
571 usb_register_notifier(charger
->usb_phy
, &charger
->otg_nb
);
575 ret
= da9150_charger_register_irq(pdev
, da9150_charger_chg_irq
,
580 ret
= da9150_charger_register_irq(pdev
, da9150_charger_tjunc_irq
,
585 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vfault_irq
,
588 goto vfault_irq_fail
;
590 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vbus_irq
,
599 da9150_charger_unregister_irq(pdev
, "CHG_VFAULT");
601 da9150_charger_unregister_irq(pdev
, "CHG_TJUNC");
603 da9150_charger_unregister_irq(pdev
, "CHG_STATUS");
605 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
606 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
611 static void da9150_charger_remove(struct platform_device
*pdev
)
613 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
616 /* Make sure IRQs are released before unregistering power supplies */
617 irq
= platform_get_irq_byname(pdev
, "CHG_VBUS");
618 free_irq(irq
, charger
);
620 irq
= platform_get_irq_byname(pdev
, "CHG_VFAULT");
621 free_irq(irq
, charger
);
623 irq
= platform_get_irq_byname(pdev
, "CHG_TJUNC");
624 free_irq(irq
, charger
);
626 irq
= platform_get_irq_byname(pdev
, "CHG_STATUS");
627 free_irq(irq
, charger
);
629 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
630 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
631 cancel_work_sync(&charger
->otg_work
);
634 static struct platform_driver da9150_charger_driver
= {
636 .name
= "da9150-charger",
638 .probe
= da9150_charger_probe
,
639 .remove
= da9150_charger_remove
,
642 module_platform_driver(da9150_charger_driver
);
644 MODULE_DESCRIPTION("Charger Driver for DA9150");
645 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
646 MODULE_LICENSE("GPL");