1 // SPDX-License-Identifier: GPL-2.0-only
3 * Battery charger driver for Dialog Semiconductor DA9030
5 * Copyright (C) 2008 Compulab, Ltd.
6 * Mike Rapoport <mike@compulab.co.il>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/init.h>
12 #include <linux/types.h>
13 #include <linux/device.h>
14 #include <linux/workqueue.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/power_supply.h>
18 #include <linux/mfd/da903x.h>
20 #include <linux/debugfs.h>
21 #include <linux/seq_file.h>
22 #include <linux/notifier.h>
24 #define DA9030_FAULT_LOG 0x0a
25 #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
26 #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
28 #define DA9030_CHARGE_CONTROL 0x28
29 #define DA9030_CHRG_CHARGER_ENABLE (1 << 7)
31 #define DA9030_ADC_MAN_CONTROL 0x30
32 #define DA9030_ADC_TBATREF_ENABLE (1 << 5)
33 #define DA9030_ADC_LDO_INT_ENABLE (1 << 4)
35 #define DA9030_ADC_AUTO_CONTROL 0x31
36 #define DA9030_ADC_TBAT_ENABLE (1 << 5)
37 #define DA9030_ADC_VBAT_IN_TXON (1 << 4)
38 #define DA9030_ADC_VCH_ENABLE (1 << 3)
39 #define DA9030_ADC_ICH_ENABLE (1 << 2)
40 #define DA9030_ADC_VBAT_ENABLE (1 << 1)
41 #define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0)
43 #define DA9030_VBATMON 0x32
44 #define DA9030_VBATMONTXON 0x33
45 #define DA9030_TBATHIGHP 0x34
46 #define DA9030_TBATHIGHN 0x35
47 #define DA9030_TBATLOW 0x36
49 #define DA9030_VBAT_RES 0x41
50 #define DA9030_VBATMIN_RES 0x42
51 #define DA9030_VBATMINTXON_RES 0x43
52 #define DA9030_ICHMAX_RES 0x44
53 #define DA9030_ICHMIN_RES 0x45
54 #define DA9030_ICHAVERAGE_RES 0x46
55 #define DA9030_VCHMAX_RES 0x47
56 #define DA9030_VCHMIN_RES 0x48
57 #define DA9030_TBAT_RES 0x49
59 struct da9030_adc_res
{
65 uint8_t ichaverage_res
;
73 struct da9030_battery_thresholds
{
80 int vbat_charge_start
;
82 int vbat_charge_restart
;
88 struct da9030_charger
{
89 struct power_supply
*psy
;
90 struct power_supply_desc psy_desc
;
92 struct device
*master
;
94 struct da9030_adc_res adc
;
95 struct delayed_work work
;
96 unsigned int interval
;
98 struct power_supply_info
*battery_info
;
100 struct da9030_battery_thresholds thresholds
;
102 unsigned int charge_milliamp
;
103 unsigned int charge_millivolt
;
112 struct notifier_block nb
;
114 /* platform callbacks for battery low and critical events */
115 void (*battery_low
)(void);
116 void (*battery_critical
)(void);
118 struct dentry
*debug_file
;
121 static inline int da9030_reg_to_mV(int reg
)
123 return ((reg
* 2650) >> 8) + 2650;
126 static inline int da9030_millivolt_to_reg(int mV
)
128 return ((mV
- 2650) << 8) / 2650;
131 static inline int da9030_reg_to_mA(int reg
)
133 return ((reg
* 24000) >> 8) / 15;
136 #ifdef CONFIG_DEBUG_FS
137 static int bat_debug_show(struct seq_file
*s
, void *data
)
139 struct da9030_charger
*charger
= s
->private;
141 seq_printf(s
, "charger is %s\n", charger
->is_on
? "on" : "off");
142 if (charger
->chdet
) {
143 seq_printf(s
, "iset = %dmA, vset = %dmV\n",
144 charger
->mA
, charger
->mV
);
147 seq_printf(s
, "vbat_res = %d (%dmV)\n",
148 charger
->adc
.vbat_res
,
149 da9030_reg_to_mV(charger
->adc
.vbat_res
));
150 seq_printf(s
, "vbatmin_res = %d (%dmV)\n",
151 charger
->adc
.vbatmin_res
,
152 da9030_reg_to_mV(charger
->adc
.vbatmin_res
));
153 seq_printf(s
, "vbatmintxon = %d (%dmV)\n",
154 charger
->adc
.vbatmintxon
,
155 da9030_reg_to_mV(charger
->adc
.vbatmintxon
));
156 seq_printf(s
, "ichmax_res = %d (%dmA)\n",
157 charger
->adc
.ichmax_res
,
158 da9030_reg_to_mV(charger
->adc
.ichmax_res
));
159 seq_printf(s
, "ichmin_res = %d (%dmA)\n",
160 charger
->adc
.ichmin_res
,
161 da9030_reg_to_mA(charger
->adc
.ichmin_res
));
162 seq_printf(s
, "ichaverage_res = %d (%dmA)\n",
163 charger
->adc
.ichaverage_res
,
164 da9030_reg_to_mA(charger
->adc
.ichaverage_res
));
165 seq_printf(s
, "vchmax_res = %d (%dmV)\n",
166 charger
->adc
.vchmax_res
,
167 da9030_reg_to_mA(charger
->adc
.vchmax_res
));
168 seq_printf(s
, "vchmin_res = %d (%dmV)\n",
169 charger
->adc
.vchmin_res
,
170 da9030_reg_to_mV(charger
->adc
.vchmin_res
));
175 DEFINE_SHOW_ATTRIBUTE(bat_debug
);
177 static struct dentry
*da9030_bat_create_debugfs(struct da9030_charger
*charger
)
179 charger
->debug_file
= debugfs_create_file("charger", 0666, NULL
,
180 charger
, &bat_debug_fops
);
181 return charger
->debug_file
;
184 static void da9030_bat_remove_debugfs(struct da9030_charger
*charger
)
186 debugfs_remove(charger
->debug_file
);
189 static inline struct dentry
*da9030_bat_create_debugfs(struct da9030_charger
*charger
)
193 static inline void da9030_bat_remove_debugfs(struct da9030_charger
*charger
)
198 static inline void da9030_read_adc(struct da9030_charger
*charger
,
199 struct da9030_adc_res
*adc
)
201 da903x_reads(charger
->master
, DA9030_VBAT_RES
,
202 sizeof(*adc
), (uint8_t *)adc
);
205 static void da9030_charger_update_state(struct da9030_charger
*charger
)
209 da903x_read(charger
->master
, DA9030_CHARGE_CONTROL
, &val
);
210 charger
->is_on
= (val
& DA9030_CHRG_CHARGER_ENABLE
) ? 1 : 0;
211 charger
->mA
= ((val
>> 3) & 0xf) * 100;
212 charger
->mV
= (val
& 0x7) * 50 + 4000;
214 da9030_read_adc(charger
, &charger
->adc
);
215 da903x_read(charger
->master
, DA9030_FAULT_LOG
, &charger
->fault
);
216 charger
->chdet
= da903x_query_status(charger
->master
,
217 DA9030_STATUS_CHDET
);
220 static void da9030_set_charge(struct da9030_charger
*charger
, int on
)
225 val
= DA9030_CHRG_CHARGER_ENABLE
;
226 val
|= (charger
->charge_milliamp
/ 100) << 3;
227 val
|= (charger
->charge_millivolt
- 4000) / 50;
234 da903x_write(charger
->master
, DA9030_CHARGE_CONTROL
, val
);
236 power_supply_changed(charger
->psy
);
239 static void da9030_charger_check_state(struct da9030_charger
*charger
)
241 da9030_charger_update_state(charger
);
243 /* we wake or boot with external power on */
244 if (!charger
->is_on
) {
245 if ((charger
->chdet
) &&
246 (charger
->adc
.vbat_res
<
247 charger
->thresholds
.vbat_charge_start
)) {
248 da9030_set_charge(charger
, 1);
251 /* Charger has been pulled out */
252 if (!charger
->chdet
) {
253 da9030_set_charge(charger
, 0);
257 if (charger
->adc
.vbat_res
>=
258 charger
->thresholds
.vbat_charge_stop
) {
259 da9030_set_charge(charger
, 0);
260 da903x_write(charger
->master
, DA9030_VBATMON
,
261 charger
->thresholds
.vbat_charge_restart
);
262 } else if (charger
->adc
.vbat_res
>
263 charger
->thresholds
.vbat_low
) {
264 /* we are charging and passed LOW_THRESH,
265 so upate DA9030 VBAT threshold
267 da903x_write(charger
->master
, DA9030_VBATMON
,
268 charger
->thresholds
.vbat_low
);
270 if (charger
->adc
.vchmax_res
> charger
->thresholds
.vcharge_max
||
271 charger
->adc
.vchmin_res
< charger
->thresholds
.vcharge_min
||
272 /* Tempreture readings are negative */
273 charger
->adc
.tbat_res
< charger
->thresholds
.tbat_high
||
274 charger
->adc
.tbat_res
> charger
->thresholds
.tbat_low
) {
275 /* disable charger */
276 da9030_set_charge(charger
, 0);
281 static void da9030_charging_monitor(struct work_struct
*work
)
283 struct da9030_charger
*charger
;
285 charger
= container_of(work
, struct da9030_charger
, work
.work
);
287 da9030_charger_check_state(charger
);
289 /* reschedule for the next time */
290 schedule_delayed_work(&charger
->work
, charger
->interval
);
293 static enum power_supply_property da9030_battery_props
[] = {
294 POWER_SUPPLY_PROP_MODEL_NAME
,
295 POWER_SUPPLY_PROP_STATUS
,
296 POWER_SUPPLY_PROP_HEALTH
,
297 POWER_SUPPLY_PROP_TECHNOLOGY
,
298 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
,
299 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
300 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
301 POWER_SUPPLY_PROP_CURRENT_AVG
,
304 static void da9030_battery_check_status(struct da9030_charger
*charger
,
305 union power_supply_propval
*val
)
307 if (charger
->chdet
) {
309 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
311 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
313 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
317 static void da9030_battery_check_health(struct da9030_charger
*charger
,
318 union power_supply_propval
*val
)
320 if (charger
->fault
& DA9030_FAULT_LOG_OVER_TEMP
)
321 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
322 else if (charger
->fault
& DA9030_FAULT_LOG_VBAT_OVER
)
323 val
->intval
= POWER_SUPPLY_HEALTH_OVERVOLTAGE
;
325 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
328 static int da9030_battery_get_property(struct power_supply
*psy
,
329 enum power_supply_property psp
,
330 union power_supply_propval
*val
)
332 struct da9030_charger
*charger
= power_supply_get_drvdata(psy
);
335 case POWER_SUPPLY_PROP_STATUS
:
336 da9030_battery_check_status(charger
, val
);
338 case POWER_SUPPLY_PROP_HEALTH
:
339 da9030_battery_check_health(charger
, val
);
341 case POWER_SUPPLY_PROP_TECHNOLOGY
:
342 val
->intval
= charger
->battery_info
->technology
;
344 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
345 val
->intval
= charger
->battery_info
->voltage_max_design
;
347 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
348 val
->intval
= charger
->battery_info
->voltage_min_design
;
350 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
351 val
->intval
= da9030_reg_to_mV(charger
->adc
.vbat_res
) * 1000;
353 case POWER_SUPPLY_PROP_CURRENT_AVG
:
355 da9030_reg_to_mA(charger
->adc
.ichaverage_res
) * 1000;
357 case POWER_SUPPLY_PROP_MODEL_NAME
:
358 val
->strval
= charger
->battery_info
->name
;
367 static void da9030_battery_vbat_event(struct da9030_charger
*charger
)
369 da9030_read_adc(charger
, &charger
->adc
);
374 if (charger
->adc
.vbat_res
< charger
->thresholds
.vbat_low
) {
375 /* set VBAT threshold for critical */
376 da903x_write(charger
->master
, DA9030_VBATMON
,
377 charger
->thresholds
.vbat_crit
);
378 if (charger
->battery_low
)
379 charger
->battery_low();
380 } else if (charger
->adc
.vbat_res
<
381 charger
->thresholds
.vbat_crit
) {
382 /* notify the system of battery critical */
383 if (charger
->battery_critical
)
384 charger
->battery_critical();
388 static int da9030_battery_event(struct notifier_block
*nb
, unsigned long event
,
391 struct da9030_charger
*charger
=
392 container_of(nb
, struct da9030_charger
, nb
);
395 case DA9030_EVENT_CHDET
:
396 cancel_delayed_work_sync(&charger
->work
);
397 schedule_work(&charger
->work
.work
);
399 case DA9030_EVENT_VBATMON
:
400 da9030_battery_vbat_event(charger
);
402 case DA9030_EVENT_CHIOVER
:
403 case DA9030_EVENT_TBAT
:
404 da9030_set_charge(charger
, 0);
411 static void da9030_battery_convert_thresholds(struct da9030_charger
*charger
,
412 struct da9030_battery_info
*pdata
)
414 charger
->thresholds
.tbat_low
= pdata
->tbat_low
;
415 charger
->thresholds
.tbat_high
= pdata
->tbat_high
;
416 charger
->thresholds
.tbat_restart
= pdata
->tbat_restart
;
418 charger
->thresholds
.vbat_low
=
419 da9030_millivolt_to_reg(pdata
->vbat_low
);
420 charger
->thresholds
.vbat_crit
=
421 da9030_millivolt_to_reg(pdata
->vbat_crit
);
422 charger
->thresholds
.vbat_charge_start
=
423 da9030_millivolt_to_reg(pdata
->vbat_charge_start
);
424 charger
->thresholds
.vbat_charge_stop
=
425 da9030_millivolt_to_reg(pdata
->vbat_charge_stop
);
426 charger
->thresholds
.vbat_charge_restart
=
427 da9030_millivolt_to_reg(pdata
->vbat_charge_restart
);
429 charger
->thresholds
.vcharge_min
=
430 da9030_millivolt_to_reg(pdata
->vcharge_min
);
431 charger
->thresholds
.vcharge_max
=
432 da9030_millivolt_to_reg(pdata
->vcharge_max
);
435 static void da9030_battery_setup_psy(struct da9030_charger
*charger
)
437 struct power_supply_desc
*psy_desc
= &charger
->psy_desc
;
438 struct power_supply_info
*info
= charger
->battery_info
;
440 psy_desc
->name
= info
->name
;
441 psy_desc
->use_for_apm
= info
->use_for_apm
;
442 psy_desc
->type
= POWER_SUPPLY_TYPE_BATTERY
;
443 psy_desc
->get_property
= da9030_battery_get_property
;
445 psy_desc
->properties
= da9030_battery_props
;
446 psy_desc
->num_properties
= ARRAY_SIZE(da9030_battery_props
);
449 static int da9030_battery_charger_init(struct da9030_charger
*charger
)
454 v
[0] = v
[1] = charger
->thresholds
.vbat_low
;
455 v
[2] = charger
->thresholds
.tbat_high
;
456 v
[3] = charger
->thresholds
.tbat_restart
;
457 v
[4] = charger
->thresholds
.tbat_low
;
459 ret
= da903x_writes(charger
->master
, DA9030_VBATMON
, 5, v
);
464 * Enable reference voltage supply for ADC from the LDO_INTERNAL
465 * regulator. Must be set before ADC measurements can be made.
467 ret
= da903x_write(charger
->master
, DA9030_ADC_MAN_CONTROL
,
468 DA9030_ADC_LDO_INT_ENABLE
|
469 DA9030_ADC_TBATREF_ENABLE
);
473 /* enable auto ADC measuremnts */
474 return da903x_write(charger
->master
, DA9030_ADC_AUTO_CONTROL
,
475 DA9030_ADC_TBAT_ENABLE
| DA9030_ADC_VBAT_IN_TXON
|
476 DA9030_ADC_VCH_ENABLE
| DA9030_ADC_ICH_ENABLE
|
477 DA9030_ADC_VBAT_ENABLE
|
478 DA9030_ADC_AUTO_SLEEP_ENABLE
);
481 static int da9030_battery_probe(struct platform_device
*pdev
)
483 struct da9030_charger
*charger
;
484 struct power_supply_config psy_cfg
= {};
485 struct da9030_battery_info
*pdata
= pdev
->dev
.platform_data
;
491 if (pdata
->charge_milliamp
>= 1500 ||
492 pdata
->charge_millivolt
< 4000 ||
493 pdata
->charge_millivolt
> 4350)
496 charger
= devm_kzalloc(&pdev
->dev
, sizeof(*charger
), GFP_KERNEL
);
500 charger
->master
= pdev
->dev
.parent
;
502 /* 10 seconds between monitor runs unless platform defines other
504 charger
->interval
= msecs_to_jiffies(
505 (pdata
->batmon_interval
? : 10) * 1000);
507 charger
->charge_milliamp
= pdata
->charge_milliamp
;
508 charger
->charge_millivolt
= pdata
->charge_millivolt
;
509 charger
->battery_info
= pdata
->battery_info
;
510 charger
->battery_low
= pdata
->battery_low
;
511 charger
->battery_critical
= pdata
->battery_critical
;
513 da9030_battery_convert_thresholds(charger
, pdata
);
515 ret
= da9030_battery_charger_init(charger
);
517 goto err_charger_init
;
519 INIT_DELAYED_WORK(&charger
->work
, da9030_charging_monitor
);
520 schedule_delayed_work(&charger
->work
, charger
->interval
);
522 charger
->nb
.notifier_call
= da9030_battery_event
;
523 ret
= da903x_register_notifier(charger
->master
, &charger
->nb
,
525 DA9030_EVENT_VBATMON
|
526 DA9030_EVENT_CHIOVER
|
531 da9030_battery_setup_psy(charger
);
532 psy_cfg
.drv_data
= charger
;
533 charger
->psy
= power_supply_register(&pdev
->dev
, &charger
->psy_desc
,
535 if (IS_ERR(charger
->psy
)) {
536 ret
= PTR_ERR(charger
->psy
);
537 goto err_ps_register
;
540 charger
->debug_file
= da9030_bat_create_debugfs(charger
);
541 platform_set_drvdata(pdev
, charger
);
545 da903x_unregister_notifier(charger
->master
, &charger
->nb
,
546 DA9030_EVENT_CHDET
| DA9030_EVENT_VBATMON
|
547 DA9030_EVENT_CHIOVER
| DA9030_EVENT_TBAT
);
549 cancel_delayed_work(&charger
->work
);
555 static int da9030_battery_remove(struct platform_device
*dev
)
557 struct da9030_charger
*charger
= platform_get_drvdata(dev
);
559 da9030_bat_remove_debugfs(charger
);
561 da903x_unregister_notifier(charger
->master
, &charger
->nb
,
562 DA9030_EVENT_CHDET
| DA9030_EVENT_VBATMON
|
563 DA9030_EVENT_CHIOVER
| DA9030_EVENT_TBAT
);
564 cancel_delayed_work_sync(&charger
->work
);
565 da9030_set_charge(charger
, 0);
566 power_supply_unregister(charger
->psy
);
571 static struct platform_driver da903x_battery_driver
= {
573 .name
= "da903x-battery",
575 .probe
= da9030_battery_probe
,
576 .remove
= da9030_battery_remove
,
579 module_platform_driver(da903x_battery_driver
);
581 MODULE_DESCRIPTION("DA9030 battery charger driver");
582 MODULE_AUTHOR("Mike Rapoport, CompuLab");
583 MODULE_LICENSE("GPL");