2 * DA9150 Charger Driver
4 * Copyright (c) 2014 Dialog Semiconductor
6 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
19 #include <linux/of_platform.h>
20 #include <linux/interrupt.h>
21 #include <linux/power_supply.h>
22 #include <linux/notifier.h>
23 #include <linux/usb/phy.h>
24 #include <linux/iio/consumer.h>
25 #include <linux/mfd/da9150/core.h>
26 #include <linux/mfd/da9150/registers.h>
29 struct da9150_charger
{
30 struct da9150
*da9150
;
33 struct power_supply
*usb
;
34 struct power_supply
*battery
;
35 struct power_supply
*supply_online
;
37 struct usb_phy
*usb_phy
;
38 struct notifier_block otg_nb
;
39 struct work_struct otg_work
;
40 unsigned long usb_event
;
42 struct iio_channel
*ibus_chan
;
43 struct iio_channel
*vbus_chan
;
44 struct iio_channel
*tjunc_chan
;
45 struct iio_channel
*vbat_chan
;
48 static inline int da9150_charger_supply_online(struct da9150_charger
*charger
,
49 struct power_supply
*psy
,
50 union power_supply_propval
*val
)
52 val
->intval
= (psy
== charger
->supply_online
) ? 1 : 0;
57 /* Charger Properties */
58 static int da9150_charger_vbus_voltage_now(struct da9150_charger
*charger
,
59 union power_supply_propval
*val
)
63 /* Read processed value - mV units */
64 ret
= iio_read_channel_processed(charger
->vbus_chan
, &v_val
);
68 /* Convert voltage to expected uV units */
69 val
->intval
= v_val
* 1000;
74 static int da9150_charger_ibus_current_avg(struct da9150_charger
*charger
,
75 union power_supply_propval
*val
)
79 /* Read processed value - mA units */
80 ret
= iio_read_channel_processed(charger
->ibus_chan
, &i_val
);
84 /* Convert current to expected uA units */
85 val
->intval
= i_val
* 1000;
90 static int da9150_charger_tjunc_temp(struct da9150_charger
*charger
,
91 union power_supply_propval
*val
)
95 /* Read processed value - 0.001 degrees C units */
96 ret
= iio_read_channel_processed(charger
->tjunc_chan
, &t_val
);
100 /* Convert temp to expect 0.1 degrees C units */
101 val
->intval
= t_val
/ 100;
106 static enum power_supply_property da9150_charger_props
[] = {
107 POWER_SUPPLY_PROP_ONLINE
,
108 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
109 POWER_SUPPLY_PROP_CURRENT_AVG
,
110 POWER_SUPPLY_PROP_TEMP
,
113 static int da9150_charger_get_prop(struct power_supply
*psy
,
114 enum power_supply_property psp
,
115 union power_supply_propval
*val
)
117 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
121 case POWER_SUPPLY_PROP_ONLINE
:
122 ret
= da9150_charger_supply_online(charger
, psy
, val
);
124 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
125 ret
= da9150_charger_vbus_voltage_now(charger
, val
);
127 case POWER_SUPPLY_PROP_CURRENT_AVG
:
128 ret
= da9150_charger_ibus_current_avg(charger
, val
);
130 case POWER_SUPPLY_PROP_TEMP
:
131 ret
= da9150_charger_tjunc_temp(charger
, val
);
141 /* Battery Properties */
142 static int da9150_charger_battery_status(struct da9150_charger
*charger
,
143 union power_supply_propval
*val
)
147 /* Check to see if battery is discharging */
148 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
150 if (((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_OFF
) ||
151 ((reg
& DA9150_VBUS_STAT_MASK
) == DA9150_VBUS_STAT_WAIT
)) {
152 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
157 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
159 /* Now check for other states */
160 switch (reg
& DA9150_CHG_STAT_MASK
) {
161 case DA9150_CHG_STAT_ACT
:
162 case DA9150_CHG_STAT_PRE
:
163 case DA9150_CHG_STAT_CC
:
164 case DA9150_CHG_STAT_CV
:
165 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
167 case DA9150_CHG_STAT_OFF
:
168 case DA9150_CHG_STAT_SUSP
:
169 case DA9150_CHG_STAT_TEMP
:
170 case DA9150_CHG_STAT_TIME
:
171 case DA9150_CHG_STAT_BAT
:
172 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
174 case DA9150_CHG_STAT_FULL
:
175 val
->intval
= POWER_SUPPLY_STATUS_FULL
;
178 val
->intval
= POWER_SUPPLY_STATUS_UNKNOWN
;
185 static int da9150_charger_battery_health(struct da9150_charger
*charger
,
186 union power_supply_propval
*val
)
190 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
192 /* Check if temperature limit reached */
193 switch (reg
& DA9150_CHG_TEMP_MASK
) {
194 case DA9150_CHG_TEMP_UNDER
:
195 val
->intval
= POWER_SUPPLY_HEALTH_COLD
;
197 case DA9150_CHG_TEMP_OVER
:
198 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
204 /* Check for other health states */
205 switch (reg
& DA9150_CHG_STAT_MASK
) {
206 case DA9150_CHG_STAT_ACT
:
207 case DA9150_CHG_STAT_PRE
:
208 val
->intval
= POWER_SUPPLY_HEALTH_DEAD
;
210 case DA9150_CHG_STAT_TIME
:
211 val
->intval
= POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
;
214 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
221 static int da9150_charger_battery_present(struct da9150_charger
*charger
,
222 union power_supply_propval
*val
)
226 /* Check if battery present or removed */
227 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
228 if ((reg
& DA9150_CHG_STAT_MASK
) == DA9150_CHG_STAT_BAT
)
236 static int da9150_charger_battery_charge_type(struct da9150_charger
*charger
,
237 union power_supply_propval
*val
)
241 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_J
);
243 switch (reg
& DA9150_CHG_STAT_MASK
) {
244 case DA9150_CHG_STAT_CC
:
245 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
247 case DA9150_CHG_STAT_ACT
:
248 case DA9150_CHG_STAT_PRE
:
249 case DA9150_CHG_STAT_CV
:
250 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
253 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_NONE
;
260 static int da9150_charger_battery_voltage_min(struct da9150_charger
*charger
,
261 union power_supply_propval
*val
)
265 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_C
);
267 /* Value starts at 2500 mV, 50 mV increments, presented in uV */
268 val
->intval
= ((reg
& DA9150_CHG_VFAULT_MASK
) * 50000) + 2500000;
273 static int da9150_charger_battery_voltage_now(struct da9150_charger
*charger
,
274 union power_supply_propval
*val
)
278 /* Read processed value - mV units */
279 ret
= iio_read_channel_processed(charger
->vbat_chan
, &v_val
);
283 val
->intval
= v_val
* 1000;
288 static int da9150_charger_battery_current_max(struct da9150_charger
*charger
,
289 union power_supply_propval
*val
)
293 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_D
);
295 /* 25mA increments */
296 val
->intval
= reg
* 25000;
301 static int da9150_charger_battery_voltage_max(struct da9150_charger
*charger
,
302 union power_supply_propval
*val
)
306 reg
= da9150_reg_read(charger
->da9150
, DA9150_PPR_CHGCTRL_B
);
308 /* Value starts at 3650 mV, 25 mV increments, presented in uV */
309 val
->intval
= ((reg
& DA9150_CHG_VBAT_MASK
) * 25000) + 3650000;
313 static enum power_supply_property da9150_charger_bat_props
[] = {
314 POWER_SUPPLY_PROP_STATUS
,
315 POWER_SUPPLY_PROP_ONLINE
,
316 POWER_SUPPLY_PROP_HEALTH
,
317 POWER_SUPPLY_PROP_PRESENT
,
318 POWER_SUPPLY_PROP_CHARGE_TYPE
,
319 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
320 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
321 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
322 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
,
325 static int da9150_charger_battery_get_prop(struct power_supply
*psy
,
326 enum power_supply_property psp
,
327 union power_supply_propval
*val
)
329 struct da9150_charger
*charger
= dev_get_drvdata(psy
->dev
.parent
);
333 case POWER_SUPPLY_PROP_STATUS
:
334 ret
= da9150_charger_battery_status(charger
, val
);
336 case POWER_SUPPLY_PROP_ONLINE
:
337 ret
= da9150_charger_supply_online(charger
, psy
, val
);
339 case POWER_SUPPLY_PROP_HEALTH
:
340 ret
= da9150_charger_battery_health(charger
, val
);
342 case POWER_SUPPLY_PROP_PRESENT
:
343 ret
= da9150_charger_battery_present(charger
, val
);
345 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
346 ret
= da9150_charger_battery_charge_type(charger
, val
);
348 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
349 ret
= da9150_charger_battery_voltage_min(charger
, val
);
351 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
352 ret
= da9150_charger_battery_voltage_now(charger
, val
);
354 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
355 ret
= da9150_charger_battery_current_max(charger
, val
);
357 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
:
358 ret
= da9150_charger_battery_voltage_max(charger
, val
);
368 static irqreturn_t
da9150_charger_chg_irq(int irq
, void *data
)
370 struct da9150_charger
*charger
= data
;
372 power_supply_changed(charger
->battery
);
377 static irqreturn_t
da9150_charger_tjunc_irq(int irq
, void *data
)
379 struct da9150_charger
*charger
= data
;
381 /* Nothing we can really do except report this. */
382 dev_crit(charger
->dev
, "TJunc over temperature!!!\n");
383 power_supply_changed(charger
->usb
);
388 static irqreturn_t
da9150_charger_vfault_irq(int irq
, void *data
)
390 struct da9150_charger
*charger
= data
;
392 /* Nothing we can really do except report this. */
393 dev_crit(charger
->dev
, "VSYS under voltage!!!\n");
394 power_supply_changed(charger
->usb
);
395 power_supply_changed(charger
->battery
);
400 static irqreturn_t
da9150_charger_vbus_irq(int irq
, void *data
)
402 struct da9150_charger
*charger
= data
;
405 reg
= da9150_reg_read(charger
->da9150
, DA9150_STATUS_H
);
407 /* Charger plugged in or battery only */
408 switch (reg
& DA9150_VBUS_STAT_MASK
) {
409 case DA9150_VBUS_STAT_OFF
:
410 case DA9150_VBUS_STAT_WAIT
:
411 charger
->supply_online
= charger
->battery
;
413 case DA9150_VBUS_STAT_CHG
:
414 charger
->supply_online
= charger
->usb
;
417 dev_warn(charger
->dev
, "Unknown VBUS state - reg = 0x%x\n",
419 charger
->supply_online
= NULL
;
423 power_supply_changed(charger
->usb
);
424 power_supply_changed(charger
->battery
);
429 static void da9150_charger_otg_work(struct work_struct
*data
)
431 struct da9150_charger
*charger
=
432 container_of(data
, struct da9150_charger
, otg_work
);
434 switch (charger
->usb_event
) {
436 /* Enable OTG Boost */
437 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
438 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_OTG
);
441 /* Revert to charge mode */
442 power_supply_changed(charger
->usb
);
443 power_supply_changed(charger
->battery
);
444 da9150_set_bits(charger
->da9150
, DA9150_PPR_BKCTRL_A
,
445 DA9150_VBUS_MODE_MASK
, DA9150_VBUS_MODE_CHG
);
450 static int da9150_charger_otg_ncb(struct notifier_block
*nb
, unsigned long val
,
453 struct da9150_charger
*charger
=
454 container_of(nb
, struct da9150_charger
, otg_nb
);
456 dev_dbg(charger
->dev
, "DA9150 OTG notify %lu\n", val
);
458 charger
->usb_event
= val
;
459 schedule_work(&charger
->otg_work
);
464 static int da9150_charger_register_irq(struct platform_device
*pdev
,
465 irq_handler_t handler
,
466 const char *irq_name
)
468 struct device
*dev
= &pdev
->dev
;
469 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
472 irq
= platform_get_irq_byname(pdev
, irq_name
);
474 dev_err(dev
, "Failed to get IRQ CHG_STATUS: %d\n", irq
);
478 ret
= request_threaded_irq(irq
, NULL
, handler
, IRQF_ONESHOT
, irq_name
,
481 dev_err(dev
, "Failed to request IRQ %d: %d\n", irq
, ret
);
486 static void da9150_charger_unregister_irq(struct platform_device
*pdev
,
487 const char *irq_name
)
489 struct device
*dev
= &pdev
->dev
;
490 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
493 irq
= platform_get_irq_byname(pdev
, irq_name
);
495 dev_err(dev
, "Failed to get IRQ CHG_STATUS: %d\n", irq
);
499 free_irq(irq
, charger
);
502 static const struct power_supply_desc usb_desc
= {
503 .name
= "da9150-usb",
504 .type
= POWER_SUPPLY_TYPE_USB
,
505 .properties
= da9150_charger_props
,
506 .num_properties
= ARRAY_SIZE(da9150_charger_props
),
507 .get_property
= da9150_charger_get_prop
,
510 static const struct power_supply_desc battery_desc
= {
511 .name
= "da9150-battery",
512 .type
= POWER_SUPPLY_TYPE_BATTERY
,
513 .properties
= da9150_charger_bat_props
,
514 .num_properties
= ARRAY_SIZE(da9150_charger_bat_props
),
515 .get_property
= da9150_charger_battery_get_prop
,
518 static int da9150_charger_probe(struct platform_device
*pdev
)
520 struct device
*dev
= &pdev
->dev
;
521 struct da9150
*da9150
= dev_get_drvdata(dev
->parent
);
522 struct da9150_charger
*charger
;
526 charger
= devm_kzalloc(dev
, sizeof(struct da9150_charger
), GFP_KERNEL
);
530 platform_set_drvdata(pdev
, charger
);
531 charger
->da9150
= da9150
;
534 /* Acquire ADC channels */
535 charger
->ibus_chan
= iio_channel_get(dev
, "CHAN_IBUS");
536 if (IS_ERR(charger
->ibus_chan
)) {
537 ret
= PTR_ERR(charger
->ibus_chan
);
541 charger
->vbus_chan
= iio_channel_get(dev
, "CHAN_VBUS");
542 if (IS_ERR(charger
->vbus_chan
)) {
543 ret
= PTR_ERR(charger
->vbus_chan
);
547 charger
->tjunc_chan
= iio_channel_get(dev
, "CHAN_TJUNC");
548 if (IS_ERR(charger
->tjunc_chan
)) {
549 ret
= PTR_ERR(charger
->tjunc_chan
);
550 goto tjunc_chan_fail
;
553 charger
->vbat_chan
= iio_channel_get(dev
, "CHAN_VBAT");
554 if (IS_ERR(charger
->vbat_chan
)) {
555 ret
= PTR_ERR(charger
->vbat_chan
);
559 /* Register power supplies */
560 charger
->usb
= power_supply_register(dev
, &usb_desc
, NULL
);
561 if (IS_ERR(charger
->usb
)) {
562 ret
= PTR_ERR(charger
->usb
);
566 charger
->battery
= power_supply_register(dev
, &battery_desc
, NULL
);
567 if (IS_ERR(charger
->battery
)) {
568 ret
= PTR_ERR(charger
->battery
);
572 /* Get initial online supply */
573 reg
= da9150_reg_read(da9150
, DA9150_STATUS_H
);
575 switch (reg
& DA9150_VBUS_STAT_MASK
) {
576 case DA9150_VBUS_STAT_OFF
:
577 case DA9150_VBUS_STAT_WAIT
:
578 charger
->supply_online
= charger
->battery
;
580 case DA9150_VBUS_STAT_CHG
:
581 charger
->supply_online
= charger
->usb
;
584 dev_warn(dev
, "Unknown VBUS state - reg = 0x%x\n", reg
);
585 charger
->supply_online
= NULL
;
589 /* Setup OTG reporting & configuration */
590 charger
->usb_phy
= devm_usb_get_phy(dev
, USB_PHY_TYPE_USB2
);
591 if (!IS_ERR_OR_NULL(charger
->usb_phy
)) {
592 INIT_WORK(&charger
->otg_work
, da9150_charger_otg_work
);
593 charger
->otg_nb
.notifier_call
= da9150_charger_otg_ncb
;
594 usb_register_notifier(charger
->usb_phy
, &charger
->otg_nb
);
598 ret
= da9150_charger_register_irq(pdev
, da9150_charger_chg_irq
,
603 ret
= da9150_charger_register_irq(pdev
, da9150_charger_tjunc_irq
,
608 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vfault_irq
,
611 goto vfault_irq_fail
;
613 ret
= da9150_charger_register_irq(pdev
, da9150_charger_vbus_irq
,
622 da9150_charger_unregister_irq(pdev
, "CHG_VFAULT");
624 da9150_charger_unregister_irq(pdev
, "CHG_TJUNC");
626 da9150_charger_unregister_irq(pdev
, "CHG_STATUS");
628 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
629 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
631 power_supply_unregister(charger
->usb
);
634 iio_channel_release(charger
->vbat_chan
);
637 iio_channel_release(charger
->tjunc_chan
);
640 iio_channel_release(charger
->vbus_chan
);
643 iio_channel_release(charger
->ibus_chan
);
649 static int da9150_charger_remove(struct platform_device
*pdev
)
651 struct da9150_charger
*charger
= platform_get_drvdata(pdev
);
654 /* Make sure IRQs are released before unregistering power supplies */
655 irq
= platform_get_irq_byname(pdev
, "CHG_VBUS");
656 free_irq(irq
, charger
);
658 irq
= platform_get_irq_byname(pdev
, "CHG_VFAULT");
659 free_irq(irq
, charger
);
661 irq
= platform_get_irq_byname(pdev
, "CHG_TJUNC");
662 free_irq(irq
, charger
);
664 irq
= platform_get_irq_byname(pdev
, "CHG_STATUS");
665 free_irq(irq
, charger
);
667 if (!IS_ERR_OR_NULL(charger
->usb_phy
))
668 usb_unregister_notifier(charger
->usb_phy
, &charger
->otg_nb
);
670 power_supply_unregister(charger
->battery
);
671 power_supply_unregister(charger
->usb
);
673 /* Release ADC channels */
674 iio_channel_release(charger
->ibus_chan
);
675 iio_channel_release(charger
->vbus_chan
);
676 iio_channel_release(charger
->tjunc_chan
);
677 iio_channel_release(charger
->vbat_chan
);
682 static struct platform_driver da9150_charger_driver
= {
684 .name
= "da9150-charger",
686 .probe
= da9150_charger_probe
,
687 .remove
= da9150_charger_remove
,
690 module_platform_driver(da9150_charger_driver
);
692 MODULE_DESCRIPTION("Charger Driver for DA9150");
693 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
694 MODULE_LICENSE("GPL");