2 * Battery charger driver for Dialog Semiconductor DA9030
4 * Copyright (C) 2008 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
14 #include <linux/init.h>
15 #include <linux/types.h>
16 #include <linux/device.h>
17 #include <linux/workqueue.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/power_supply.h>
21 #include <linux/mfd/da903x.h>
23 #include <linux/debugfs.h>
24 #include <linux/seq_file.h>
26 #define DA9030_FAULT_LOG 0x0a
27 #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
28 #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
30 #define DA9030_CHARGE_CONTROL 0x28
31 #define DA9030_CHRG_CHARGER_ENABLE (1 << 7)
33 #define DA9030_ADC_MAN_CONTROL 0x30
34 #define DA9030_ADC_TBATREF_ENABLE (1 << 5)
35 #define DA9030_ADC_LDO_INT_ENABLE (1 << 4)
37 #define DA9030_ADC_AUTO_CONTROL 0x31
38 #define DA9030_ADC_TBAT_ENABLE (1 << 5)
39 #define DA9030_ADC_VBAT_IN_TXON (1 << 4)
40 #define DA9030_ADC_VCH_ENABLE (1 << 3)
41 #define DA9030_ADC_ICH_ENABLE (1 << 2)
42 #define DA9030_ADC_VBAT_ENABLE (1 << 1)
43 #define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0)
45 #define DA9030_VBATMON 0x32
46 #define DA9030_VBATMONTXON 0x33
47 #define DA9030_TBATHIGHP 0x34
48 #define DA9030_TBATHIGHN 0x35
49 #define DA9030_TBATLOW 0x36
51 #define DA9030_VBAT_RES 0x41
52 #define DA9030_VBATMIN_RES 0x42
53 #define DA9030_VBATMINTXON_RES 0x43
54 #define DA9030_ICHMAX_RES 0x44
55 #define DA9030_ICHMIN_RES 0x45
56 #define DA9030_ICHAVERAGE_RES 0x46
57 #define DA9030_VCHMAX_RES 0x47
58 #define DA9030_VCHMIN_RES 0x48
59 #define DA9030_TBAT_RES 0x49
61 struct da9030_adc_res
{
67 uint8_t ichaverage_res
;
75 struct da9030_battery_thresholds
{
82 int vbat_charge_start
;
84 int vbat_charge_restart
;
90 struct da9030_charger
{
91 struct power_supply psy
;
93 struct device
*master
;
95 struct da9030_adc_res adc
;
96 struct delayed_work work
;
97 unsigned int interval
;
99 struct power_supply_info
*battery_info
;
101 struct da9030_battery_thresholds thresholds
;
103 unsigned int charge_milliamp
;
104 unsigned int charge_millivolt
;
113 struct notifier_block nb
;
115 /* platform callbacks for battery low and critical events */
116 void (*battery_low
)(void);
117 void (*battery_critical
)(void);
119 struct dentry
*debug_file
;
122 static inline int da9030_reg_to_mV(int reg
)
124 return ((reg
* 2650) >> 8) + 2650;
127 static inline int da9030_millivolt_to_reg(int mV
)
129 return ((mV
- 2650) << 8) / 2650;
132 static inline int da9030_reg_to_mA(int reg
)
134 return ((reg
* 24000) >> 8) / 15;
137 #ifdef CONFIG_DEBUG_FS
138 static int bat_debug_show(struct seq_file
*s
, void *data
)
140 struct da9030_charger
*charger
= s
->private;
142 seq_printf(s
, "charger is %s\n", charger
->is_on
? "on" : "off");
143 if (charger
->chdet
) {
144 seq_printf(s
, "iset = %dmA, vset = %dmV\n",
145 charger
->mA
, charger
->mV
);
148 seq_printf(s
, "vbat_res = %d (%dmV)\n",
149 charger
->adc
.vbat_res
,
150 da9030_reg_to_mV(charger
->adc
.vbat_res
));
151 seq_printf(s
, "vbatmin_res = %d (%dmV)\n",
152 charger
->adc
.vbatmin_res
,
153 da9030_reg_to_mV(charger
->adc
.vbatmin_res
));
154 seq_printf(s
, "vbatmintxon = %d (%dmV)\n",
155 charger
->adc
.vbatmintxon
,
156 da9030_reg_to_mV(charger
->adc
.vbatmintxon
));
157 seq_printf(s
, "ichmax_res = %d (%dmA)\n",
158 charger
->adc
.ichmax_res
,
159 da9030_reg_to_mV(charger
->adc
.ichmax_res
));
160 seq_printf(s
, "ichmin_res = %d (%dmA)\n",
161 charger
->adc
.ichmin_res
,
162 da9030_reg_to_mA(charger
->adc
.ichmin_res
));
163 seq_printf(s
, "ichaverage_res = %d (%dmA)\n",
164 charger
->adc
.ichaverage_res
,
165 da9030_reg_to_mA(charger
->adc
.ichaverage_res
));
166 seq_printf(s
, "vchmax_res = %d (%dmV)\n",
167 charger
->adc
.vchmax_res
,
168 da9030_reg_to_mA(charger
->adc
.vchmax_res
));
169 seq_printf(s
, "vchmin_res = %d (%dmV)\n",
170 charger
->adc
.vchmin_res
,
171 da9030_reg_to_mV(charger
->adc
.vchmin_res
));
176 static int debug_open(struct inode
*inode
, struct file
*file
)
178 return single_open(file
, bat_debug_show
, inode
->i_private
);
181 static const struct file_operations bat_debug_fops
= {
185 .release
= single_release
,
188 static struct dentry
*da9030_bat_create_debugfs(struct da9030_charger
*charger
)
190 charger
->debug_file
= debugfs_create_file("charger", 0666, 0, charger
,
192 return charger
->debug_file
;
195 static void da9030_bat_remove_debugfs(struct da9030_charger
*charger
)
197 debugfs_remove(charger
->debug_file
);
200 static inline struct dentry
*da9030_bat_create_debugfs(struct da9030_charger
*charger
)
204 static inline void da9030_bat_remove_debugfs(struct da9030_charger
*charger
)
209 static inline void da9030_read_adc(struct da9030_charger
*charger
,
210 struct da9030_adc_res
*adc
)
212 da903x_reads(charger
->master
, DA9030_VBAT_RES
,
213 sizeof(*adc
), (uint8_t *)adc
);
216 static void da9030_charger_update_state(struct da9030_charger
*charger
)
220 da903x_read(charger
->master
, DA9030_CHARGE_CONTROL
, &val
);
221 charger
->is_on
= (val
& DA9030_CHRG_CHARGER_ENABLE
) ? 1 : 0;
222 charger
->mA
= ((val
>> 3) & 0xf) * 100;
223 charger
->mV
= (val
& 0x7) * 50 + 4000;
225 da9030_read_adc(charger
, &charger
->adc
);
226 da903x_read(charger
->master
, DA9030_FAULT_LOG
, &charger
->fault
);
227 charger
->chdet
= da903x_query_status(charger
->master
,
228 DA9030_STATUS_CHDET
);
231 static void da9030_set_charge(struct da9030_charger
*charger
, int on
)
236 val
= DA9030_CHRG_CHARGER_ENABLE
;
237 val
|= (charger
->charge_milliamp
/ 100) << 3;
238 val
|= (charger
->charge_millivolt
- 4000) / 50;
245 da903x_write(charger
->master
, DA9030_CHARGE_CONTROL
, val
);
247 power_supply_changed(&charger
->psy
);
250 static void da9030_charger_check_state(struct da9030_charger
*charger
)
252 da9030_charger_update_state(charger
);
254 /* we wake or boot with external power on */
255 if (!charger
->is_on
) {
256 if ((charger
->chdet
) &&
257 (charger
->adc
.vbat_res
<
258 charger
->thresholds
.vbat_charge_start
)) {
259 da9030_set_charge(charger
, 1);
262 /* Charger has been pulled out */
263 if (!charger
->chdet
) {
264 da9030_set_charge(charger
, 0);
268 if (charger
->adc
.vbat_res
>=
269 charger
->thresholds
.vbat_charge_stop
) {
270 da9030_set_charge(charger
, 0);
271 da903x_write(charger
->master
, DA9030_VBATMON
,
272 charger
->thresholds
.vbat_charge_restart
);
273 } else if (charger
->adc
.vbat_res
>
274 charger
->thresholds
.vbat_low
) {
275 /* we are charging and passed LOW_THRESH,
276 so upate DA9030 VBAT threshold
278 da903x_write(charger
->master
, DA9030_VBATMON
,
279 charger
->thresholds
.vbat_low
);
281 if (charger
->adc
.vchmax_res
> charger
->thresholds
.vcharge_max
||
282 charger
->adc
.vchmin_res
< charger
->thresholds
.vcharge_min
||
283 /* Tempreture readings are negative */
284 charger
->adc
.tbat_res
< charger
->thresholds
.tbat_high
||
285 charger
->adc
.tbat_res
> charger
->thresholds
.tbat_low
) {
286 /* disable charger */
287 da9030_set_charge(charger
, 0);
292 static void da9030_charging_monitor(struct work_struct
*work
)
294 struct da9030_charger
*charger
;
296 charger
= container_of(work
, struct da9030_charger
, work
.work
);
298 da9030_charger_check_state(charger
);
300 /* reschedule for the next time */
301 schedule_delayed_work(&charger
->work
, charger
->interval
);
304 static enum power_supply_property da9030_battery_props
[] = {
305 POWER_SUPPLY_PROP_MODEL_NAME
,
306 POWER_SUPPLY_PROP_STATUS
,
307 POWER_SUPPLY_PROP_HEALTH
,
308 POWER_SUPPLY_PROP_TECHNOLOGY
,
309 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
,
310 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
311 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
312 POWER_SUPPLY_PROP_CURRENT_AVG
,
315 static void da9030_battery_check_status(struct da9030_charger
*charger
,
316 union power_supply_propval
*val
)
318 if (charger
->chdet
) {
320 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
322 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
324 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
328 static void da9030_battery_check_health(struct da9030_charger
*charger
,
329 union power_supply_propval
*val
)
331 if (charger
->fault
& DA9030_FAULT_LOG_OVER_TEMP
)
332 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
333 else if (charger
->fault
& DA9030_FAULT_LOG_VBAT_OVER
)
334 val
->intval
= POWER_SUPPLY_HEALTH_OVERVOLTAGE
;
336 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
339 static int da9030_battery_get_property(struct power_supply
*psy
,
340 enum power_supply_property psp
,
341 union power_supply_propval
*val
)
343 struct da9030_charger
*charger
;
344 charger
= container_of(psy
, struct da9030_charger
, psy
);
347 case POWER_SUPPLY_PROP_STATUS
:
348 da9030_battery_check_status(charger
, val
);
350 case POWER_SUPPLY_PROP_HEALTH
:
351 da9030_battery_check_health(charger
, val
);
353 case POWER_SUPPLY_PROP_TECHNOLOGY
:
354 val
->intval
= charger
->battery_info
->technology
;
356 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
357 val
->intval
= charger
->battery_info
->voltage_max_design
;
359 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
360 val
->intval
= charger
->battery_info
->voltage_min_design
;
362 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
363 val
->intval
= da9030_reg_to_mV(charger
->adc
.vbat_res
) * 1000;
365 case POWER_SUPPLY_PROP_CURRENT_AVG
:
367 da9030_reg_to_mA(charger
->adc
.ichaverage_res
) * 1000;
369 case POWER_SUPPLY_PROP_MODEL_NAME
:
370 val
->strval
= charger
->battery_info
->name
;
379 static void da9030_battery_vbat_event(struct da9030_charger
*charger
)
381 da9030_read_adc(charger
, &charger
->adc
);
386 if (charger
->adc
.vbat_res
< charger
->thresholds
.vbat_low
) {
387 /* set VBAT threshold for critical */
388 da903x_write(charger
->master
, DA9030_VBATMON
,
389 charger
->thresholds
.vbat_crit
);
390 if (charger
->battery_low
)
391 charger
->battery_low();
392 } else if (charger
->adc
.vbat_res
<
393 charger
->thresholds
.vbat_crit
) {
394 /* notify the system of battery critical */
395 if (charger
->battery_critical
)
396 charger
->battery_critical();
400 static int da9030_battery_event(struct notifier_block
*nb
, unsigned long event
,
403 struct da9030_charger
*charger
=
404 container_of(nb
, struct da9030_charger
, nb
);
407 case DA9030_EVENT_CHDET
:
408 cancel_delayed_work_sync(&charger
->work
);
409 schedule_work(&charger
->work
.work
);
411 case DA9030_EVENT_VBATMON
:
412 da9030_battery_vbat_event(charger
);
414 case DA9030_EVENT_CHIOVER
:
415 case DA9030_EVENT_TBAT
:
416 da9030_set_charge(charger
, 0);
423 static void da9030_battery_convert_thresholds(struct da9030_charger
*charger
,
424 struct da9030_battery_info
*pdata
)
426 charger
->thresholds
.tbat_low
= pdata
->tbat_low
;
427 charger
->thresholds
.tbat_high
= pdata
->tbat_high
;
428 charger
->thresholds
.tbat_restart
= pdata
->tbat_restart
;
430 charger
->thresholds
.vbat_low
=
431 da9030_millivolt_to_reg(pdata
->vbat_low
);
432 charger
->thresholds
.vbat_crit
=
433 da9030_millivolt_to_reg(pdata
->vbat_crit
);
434 charger
->thresholds
.vbat_charge_start
=
435 da9030_millivolt_to_reg(pdata
->vbat_charge_start
);
436 charger
->thresholds
.vbat_charge_stop
=
437 da9030_millivolt_to_reg(pdata
->vbat_charge_stop
);
438 charger
->thresholds
.vbat_charge_restart
=
439 da9030_millivolt_to_reg(pdata
->vbat_charge_restart
);
441 charger
->thresholds
.vcharge_min
=
442 da9030_millivolt_to_reg(pdata
->vcharge_min
);
443 charger
->thresholds
.vcharge_max
=
444 da9030_millivolt_to_reg(pdata
->vcharge_max
);
447 static void da9030_battery_setup_psy(struct da9030_charger
*charger
)
449 struct power_supply
*psy
= &charger
->psy
;
450 struct power_supply_info
*info
= charger
->battery_info
;
452 psy
->name
= info
->name
;
453 psy
->use_for_apm
= info
->use_for_apm
;
454 psy
->type
= POWER_SUPPLY_TYPE_BATTERY
;
455 psy
->get_property
= da9030_battery_get_property
;
457 psy
->properties
= da9030_battery_props
;
458 psy
->num_properties
= ARRAY_SIZE(da9030_battery_props
);
461 static int da9030_battery_charger_init(struct da9030_charger
*charger
)
466 v
[0] = v
[1] = charger
->thresholds
.vbat_low
;
467 v
[2] = charger
->thresholds
.tbat_high
;
468 v
[3] = charger
->thresholds
.tbat_restart
;
469 v
[4] = charger
->thresholds
.tbat_low
;
471 ret
= da903x_writes(charger
->master
, DA9030_VBATMON
, 5, v
);
476 * Enable reference voltage supply for ADC from the LDO_INTERNAL
477 * regulator. Must be set before ADC measurements can be made.
479 ret
= da903x_write(charger
->master
, DA9030_ADC_MAN_CONTROL
,
480 DA9030_ADC_LDO_INT_ENABLE
|
481 DA9030_ADC_TBATREF_ENABLE
);
485 /* enable auto ADC measuremnts */
486 return da903x_write(charger
->master
, DA9030_ADC_AUTO_CONTROL
,
487 DA9030_ADC_TBAT_ENABLE
| DA9030_ADC_VBAT_IN_TXON
|
488 DA9030_ADC_VCH_ENABLE
| DA9030_ADC_ICH_ENABLE
|
489 DA9030_ADC_VBAT_ENABLE
|
490 DA9030_ADC_AUTO_SLEEP_ENABLE
);
493 static int da9030_battery_probe(struct platform_device
*pdev
)
495 struct da9030_charger
*charger
;
496 struct da9030_battery_info
*pdata
= pdev
->dev
.platform_data
;
502 if (pdata
->charge_milliamp
>= 1500 ||
503 pdata
->charge_millivolt
< 4000 ||
504 pdata
->charge_millivolt
> 4350)
507 charger
= kzalloc(sizeof(*charger
), GFP_KERNEL
);
511 charger
->master
= pdev
->dev
.parent
;
513 /* 10 seconds between monitor runs unless platform defines other
515 charger
->interval
= msecs_to_jiffies(
516 (pdata
->batmon_interval
? : 10) * 1000);
518 charger
->charge_milliamp
= pdata
->charge_milliamp
;
519 charger
->charge_millivolt
= pdata
->charge_millivolt
;
520 charger
->battery_info
= pdata
->battery_info
;
521 charger
->battery_low
= pdata
->battery_low
;
522 charger
->battery_critical
= pdata
->battery_critical
;
524 da9030_battery_convert_thresholds(charger
, pdata
);
526 ret
= da9030_battery_charger_init(charger
);
528 goto err_charger_init
;
530 INIT_DELAYED_WORK(&charger
->work
, da9030_charging_monitor
);
531 schedule_delayed_work(&charger
->work
, charger
->interval
);
533 charger
->nb
.notifier_call
= da9030_battery_event
;
534 ret
= da903x_register_notifier(charger
->master
, &charger
->nb
,
536 DA9030_EVENT_VBATMON
|
537 DA9030_EVENT_CHIOVER
|
542 da9030_battery_setup_psy(charger
);
543 ret
= power_supply_register(&pdev
->dev
, &charger
->psy
);
545 goto err_ps_register
;
547 charger
->debug_file
= da9030_bat_create_debugfs(charger
);
548 platform_set_drvdata(pdev
, charger
);
552 da903x_unregister_notifier(charger
->master
, &charger
->nb
,
553 DA9030_EVENT_CHDET
| DA9030_EVENT_VBATMON
|
554 DA9030_EVENT_CHIOVER
| DA9030_EVENT_TBAT
);
556 cancel_delayed_work(&charger
->work
);
564 static int da9030_battery_remove(struct platform_device
*dev
)
566 struct da9030_charger
*charger
= platform_get_drvdata(dev
);
568 da9030_bat_remove_debugfs(charger
);
570 da903x_unregister_notifier(charger
->master
, &charger
->nb
,
571 DA9030_EVENT_CHDET
| DA9030_EVENT_VBATMON
|
572 DA9030_EVENT_CHIOVER
| DA9030_EVENT_TBAT
);
573 cancel_delayed_work_sync(&charger
->work
);
574 da9030_set_charge(charger
, 0);
575 power_supply_unregister(&charger
->psy
);
582 static struct platform_driver da903x_battery_driver
= {
584 .name
= "da903x-battery",
585 .owner
= THIS_MODULE
,
587 .probe
= da9030_battery_probe
,
588 .remove
= da9030_battery_remove
,
591 static int da903x_battery_init(void)
593 return platform_driver_register(&da903x_battery_driver
);
596 static void da903x_battery_exit(void)
598 platform_driver_unregister(&da903x_battery_driver
);
601 module_init(da903x_battery_init
);
602 module_exit(da903x_battery_exit
);
604 MODULE_DESCRIPTION("DA9030 battery charger driver");
605 MODULE_AUTHOR("Mike Rapoport, CompuLab");
606 MODULE_LICENSE("GPL");