2 * DA9150 Fuel-Gauge Driver
4 * Copyright (c) 2015 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/module.h>
16 #include <linux/platform_device.h>
18 #include <linux/of_platform.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
21 #include <linux/delay.h>
22 #include <linux/power_supply.h>
23 #include <linux/list.h>
24 #include <asm/div64.h>
25 #include <linux/mfd/da9150/core.h>
26 #include <linux/mfd/da9150/registers.h>
29 #define DA9150_QIF_READ (0x0 << 7)
30 #define DA9150_QIF_WRITE (0x1 << 7)
31 #define DA9150_QIF_CODE_MASK 0x7F
33 #define DA9150_QIF_BYTE_SIZE 8
34 #define DA9150_QIF_BYTE_MASK 0xFF
35 #define DA9150_QIF_SHORT_SIZE 2
36 #define DA9150_QIF_LONG_SIZE 4
39 #define DA9150_QIF_UAVG 6
40 #define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE
41 #define DA9150_QIF_IAVG 8
42 #define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE
43 #define DA9150_QIF_NTCAVG 12
44 #define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE
45 #define DA9150_QIF_SHUNT_VAL 36
46 #define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE
47 #define DA9150_QIF_SD_GAIN 38
48 #define DA9150_QIF_SD_GAIN_SIZE DA9150_QIF_LONG_SIZE
49 #define DA9150_QIF_FCC_MAH 40
50 #define DA9150_QIF_FCC_MAH_SIZE DA9150_QIF_SHORT_SIZE
51 #define DA9150_QIF_SOC_PCT 43
52 #define DA9150_QIF_SOC_PCT_SIZE DA9150_QIF_SHORT_SIZE
53 #define DA9150_QIF_CHARGE_LIMIT 44
54 #define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
55 #define DA9150_QIF_DISCHARGE_LIMIT 45
56 #define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
57 #define DA9150_QIF_FW_MAIN_VER 118
58 #define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE
59 #define DA9150_QIF_E_FG_STATUS 126
60 #define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE
61 #define DA9150_QIF_SYNC 127
62 #define DA9150_QIF_SYNC_SIZE DA9150_QIF_SHORT_SIZE
63 #define DA9150_QIF_MAX_CODES 128
65 /* QIF Sync Timeout */
66 #define DA9150_QIF_SYNC_TIMEOUT 1000
67 #define DA9150_QIF_SYNC_RETRIES 10
70 #define DA9150_FG_IRQ_LOW_SOC_MASK (1 << 0)
71 #define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1)
72 #define DA9150_FG_IRQ_SOC_MASK \
73 (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK)
77 struct da9150
*da9150
;
82 struct power_supply
*battery
;
83 struct delayed_work work
;
91 /* Battery Properties */
92 static u32
da9150_fg_read_attr(struct da9150_fg
*fg
, u8 code
, u8 size
)
100 /* Set QIF code (READ mode) */
101 read_addr
= (code
& DA9150_QIF_CODE_MASK
) | DA9150_QIF_READ
;
103 da9150_read_qif(fg
->da9150
, read_addr
, size
, buf
);
104 for (i
= 0; i
< size
; ++i
)
105 res
|= (buf
[i
] << (i
* DA9150_QIF_BYTE_SIZE
));
110 static void da9150_fg_write_attr(struct da9150_fg
*fg
, u8 code
, u8 size
,
118 /* Set QIF code (WRITE mode) */
119 write_addr
= (code
& DA9150_QIF_CODE_MASK
) | DA9150_QIF_WRITE
;
121 for (i
= 0; i
< size
; ++i
) {
122 buf
[i
] = (val
>> (i
* DA9150_QIF_BYTE_SIZE
)) &
123 DA9150_QIF_BYTE_MASK
;
125 da9150_write_qif(fg
->da9150
, write_addr
, size
, buf
);
128 /* Trigger QIF Sync to update QIF readable data */
129 static void da9150_fg_read_sync_start(struct da9150_fg
*fg
)
134 mutex_lock(&fg
->io_lock
);
136 /* Check if QIF sync already requested, and write to sync if not */
137 res
= da9150_fg_read_attr(fg
, DA9150_QIF_SYNC
,
138 DA9150_QIF_SYNC_SIZE
);
140 da9150_fg_write_attr(fg
, DA9150_QIF_SYNC
,
141 DA9150_QIF_SYNC_SIZE
, 0);
143 /* Wait for sync to complete */
145 while ((res
== 0) && (i
++ < DA9150_QIF_SYNC_RETRIES
)) {
146 usleep_range(DA9150_QIF_SYNC_TIMEOUT
,
147 DA9150_QIF_SYNC_TIMEOUT
* 2);
148 res
= da9150_fg_read_attr(fg
, DA9150_QIF_SYNC
,
149 DA9150_QIF_SYNC_SIZE
);
152 /* Check if sync completed */
154 dev_err(fg
->dev
, "Failed to perform QIF read sync!\n");
158 * Should always be called after QIF sync read has been performed, and all
159 * attributes required have been accessed.
161 static inline void da9150_fg_read_sync_end(struct da9150_fg
*fg
)
163 mutex_unlock(&fg
->io_lock
);
166 /* Sync read of single QIF attribute */
167 static u32
da9150_fg_read_attr_sync(struct da9150_fg
*fg
, u8 code
, u8 size
)
171 da9150_fg_read_sync_start(fg
);
172 val
= da9150_fg_read_attr(fg
, code
, size
);
173 da9150_fg_read_sync_end(fg
);
178 /* Wait for QIF Sync, write QIF data and wait for ack */
179 static void da9150_fg_write_attr_sync(struct da9150_fg
*fg
, u8 code
, u8 size
,
183 u32 res
= 0, sync_val
;
185 mutex_lock(&fg
->io_lock
);
187 /* Check if QIF sync already requested */
188 res
= da9150_fg_read_attr(fg
, DA9150_QIF_SYNC
,
189 DA9150_QIF_SYNC_SIZE
);
191 /* Wait for an existing sync to complete */
192 while ((res
== 0) && (i
++ < DA9150_QIF_SYNC_RETRIES
)) {
193 usleep_range(DA9150_QIF_SYNC_TIMEOUT
,
194 DA9150_QIF_SYNC_TIMEOUT
* 2);
195 res
= da9150_fg_read_attr(fg
, DA9150_QIF_SYNC
,
196 DA9150_QIF_SYNC_SIZE
);
200 dev_err(fg
->dev
, "Timeout waiting for existing QIF sync!\n");
201 mutex_unlock(&fg
->io_lock
);
205 /* Write value for QIF code */
206 da9150_fg_write_attr(fg
, code
, size
, val
);
208 /* Wait for write acknowledgment */
211 while ((res
== sync_val
) && (i
++ < DA9150_QIF_SYNC_RETRIES
)) {
212 usleep_range(DA9150_QIF_SYNC_TIMEOUT
,
213 DA9150_QIF_SYNC_TIMEOUT
* 2);
214 res
= da9150_fg_read_attr(fg
, DA9150_QIF_SYNC
,
215 DA9150_QIF_SYNC_SIZE
);
218 mutex_unlock(&fg
->io_lock
);
220 /* Check write was actually successful */
221 if (res
!= (sync_val
+ 1))
222 dev_err(fg
->dev
, "Error performing QIF sync write for code %d\n",
226 /* Power Supply attributes */
227 static int da9150_fg_capacity(struct da9150_fg
*fg
,
228 union power_supply_propval
*val
)
230 val
->intval
= da9150_fg_read_attr_sync(fg
, DA9150_QIF_SOC_PCT
,
231 DA9150_QIF_SOC_PCT_SIZE
);
233 if (val
->intval
> 100)
239 static int da9150_fg_current_avg(struct da9150_fg
*fg
,
240 union power_supply_propval
*val
)
242 u32 iavg
, sd_gain
, shunt_val
;
245 da9150_fg_read_sync_start(fg
);
246 iavg
= da9150_fg_read_attr(fg
, DA9150_QIF_IAVG
,
247 DA9150_QIF_IAVG_SIZE
);
248 shunt_val
= da9150_fg_read_attr(fg
, DA9150_QIF_SHUNT_VAL
,
249 DA9150_QIF_SHUNT_VAL_SIZE
);
250 sd_gain
= da9150_fg_read_attr(fg
, DA9150_QIF_SD_GAIN
,
251 DA9150_QIF_SD_GAIN_SIZE
);
252 da9150_fg_read_sync_end(fg
);
254 div
= (u64
) (sd_gain
* shunt_val
* 65536ULL);
255 do_div(div
, 1000000);
256 res
= (u64
) (iavg
* 1000000ULL);
259 val
->intval
= (int) res
;
264 static int da9150_fg_voltage_avg(struct da9150_fg
*fg
,
265 union power_supply_propval
*val
)
269 val
->intval
= da9150_fg_read_attr_sync(fg
, DA9150_QIF_UAVG
,
270 DA9150_QIF_UAVG_SIZE
);
272 res
= (u64
) (val
->intval
* 186ULL);
274 val
->intval
= (int) res
;
279 static int da9150_fg_charge_full(struct da9150_fg
*fg
,
280 union power_supply_propval
*val
)
282 val
->intval
= da9150_fg_read_attr_sync(fg
, DA9150_QIF_FCC_MAH
,
283 DA9150_QIF_FCC_MAH_SIZE
);
285 val
->intval
= val
->intval
* 1000;
291 * Temperature reading from device is only valid if battery/system provides
292 * valid NTC to associated pin of DA9150 chip.
294 static int da9150_fg_temp(struct da9150_fg
*fg
,
295 union power_supply_propval
*val
)
297 val
->intval
= da9150_fg_read_attr_sync(fg
, DA9150_QIF_NTCAVG
,
298 DA9150_QIF_NTCAVG_SIZE
);
300 val
->intval
= (val
->intval
* 10) / 1048576;
305 static enum power_supply_property da9150_fg_props
[] = {
306 POWER_SUPPLY_PROP_CAPACITY
,
307 POWER_SUPPLY_PROP_CURRENT_AVG
,
308 POWER_SUPPLY_PROP_VOLTAGE_AVG
,
309 POWER_SUPPLY_PROP_CHARGE_FULL
,
310 POWER_SUPPLY_PROP_TEMP
,
313 static int da9150_fg_get_prop(struct power_supply
*psy
,
314 enum power_supply_property psp
,
315 union power_supply_propval
*val
)
317 struct da9150_fg
*fg
= dev_get_drvdata(psy
->dev
.parent
);
321 case POWER_SUPPLY_PROP_CAPACITY
:
322 ret
= da9150_fg_capacity(fg
, val
);
324 case POWER_SUPPLY_PROP_CURRENT_AVG
:
325 ret
= da9150_fg_current_avg(fg
, val
);
327 case POWER_SUPPLY_PROP_VOLTAGE_AVG
:
328 ret
= da9150_fg_voltage_avg(fg
, val
);
330 case POWER_SUPPLY_PROP_CHARGE_FULL
:
331 ret
= da9150_fg_charge_full(fg
, val
);
333 case POWER_SUPPLY_PROP_TEMP
:
334 ret
= da9150_fg_temp(fg
, val
);
344 /* Repeated SOC check */
345 static bool da9150_fg_soc_changed(struct da9150_fg
*fg
)
347 union power_supply_propval val
;
349 da9150_fg_capacity(fg
, &val
);
350 if (val
.intval
!= fg
->soc
) {
351 fg
->soc
= val
.intval
;
358 static void da9150_fg_work(struct work_struct
*work
)
360 struct da9150_fg
*fg
= container_of(work
, struct da9150_fg
, work
.work
);
362 /* Report if SOC has changed */
363 if (da9150_fg_soc_changed(fg
))
364 power_supply_changed(fg
->battery
);
366 schedule_delayed_work(&fg
->work
, msecs_to_jiffies(fg
->interval
));
369 /* SOC level event configuration */
370 static void da9150_fg_soc_event_config(struct da9150_fg
*fg
)
374 soc
= da9150_fg_read_attr_sync(fg
, DA9150_QIF_SOC_PCT
,
375 DA9150_QIF_SOC_PCT_SIZE
);
377 if (soc
> fg
->warn_soc
) {
378 /* If SOC > warn level, set discharge warn level event */
379 da9150_fg_write_attr_sync(fg
, DA9150_QIF_DISCHARGE_LIMIT
,
380 DA9150_QIF_DISCHARGE_LIMIT_SIZE
,
382 } else if ((soc
<= fg
->warn_soc
) && (soc
> fg
->crit_soc
)) {
384 * If SOC <= warn level, set discharge crit level event,
385 * and set charge warn level event.
387 da9150_fg_write_attr_sync(fg
, DA9150_QIF_DISCHARGE_LIMIT
,
388 DA9150_QIF_DISCHARGE_LIMIT_SIZE
,
391 da9150_fg_write_attr_sync(fg
, DA9150_QIF_CHARGE_LIMIT
,
392 DA9150_QIF_CHARGE_LIMIT_SIZE
,
394 } else if (soc
<= fg
->crit_soc
) {
395 /* If SOC <= crit level, set charge crit level event */
396 da9150_fg_write_attr_sync(fg
, DA9150_QIF_CHARGE_LIMIT
,
397 DA9150_QIF_CHARGE_LIMIT_SIZE
,
402 static irqreturn_t
da9150_fg_irq(int irq
, void *data
)
404 struct da9150_fg
*fg
= data
;
407 /* Read FG IRQ status info */
408 e_fg_status
= da9150_fg_read_attr(fg
, DA9150_QIF_E_FG_STATUS
,
409 DA9150_QIF_E_FG_STATUS_SIZE
);
411 /* Handle warning/critical threhold events */
412 if (e_fg_status
& DA9150_FG_IRQ_SOC_MASK
)
413 da9150_fg_soc_event_config(fg
);
415 /* Clear any FG IRQs */
416 da9150_fg_write_attr(fg
, DA9150_QIF_E_FG_STATUS
,
417 DA9150_QIF_E_FG_STATUS_SIZE
, e_fg_status
);
422 static struct da9150_fg_pdata
*da9150_fg_dt_pdata(struct device
*dev
)
424 struct device_node
*fg_node
= dev
->of_node
;
425 struct da9150_fg_pdata
*pdata
;
427 pdata
= devm_kzalloc(dev
, sizeof(struct da9150_fg_pdata
), GFP_KERNEL
);
431 of_property_read_u32(fg_node
, "dlg,update-interval",
432 &pdata
->update_interval
);
433 of_property_read_u8(fg_node
, "dlg,warn-soc-level",
434 &pdata
->warn_soc_lvl
);
435 of_property_read_u8(fg_node
, "dlg,crit-soc-level",
436 &pdata
->crit_soc_lvl
);
441 static const struct power_supply_desc fg_desc
= {
443 .type
= POWER_SUPPLY_TYPE_BATTERY
,
444 .properties
= da9150_fg_props
,
445 .num_properties
= ARRAY_SIZE(da9150_fg_props
),
446 .get_property
= da9150_fg_get_prop
,
449 static int da9150_fg_probe(struct platform_device
*pdev
)
451 struct device
*dev
= &pdev
->dev
;
452 struct da9150
*da9150
= dev_get_drvdata(dev
->parent
);
453 struct da9150_fg_pdata
*fg_pdata
= dev_get_platdata(dev
);
454 struct da9150_fg
*fg
;
455 int ver
, irq
, ret
= 0;
457 fg
= devm_kzalloc(dev
, sizeof(*fg
), GFP_KERNEL
);
461 platform_set_drvdata(pdev
, fg
);
465 mutex_init(&fg
->io_lock
);
468 da9150_set_bits(da9150
, DA9150_CORE2WIRE_CTRL_A
, DA9150_FG_QIF_EN_MASK
,
469 DA9150_FG_QIF_EN_MASK
);
471 fg
->battery
= devm_power_supply_register(dev
, &fg_desc
, NULL
);
472 if (IS_ERR(fg
->battery
)) {
473 ret
= PTR_ERR(fg
->battery
);
477 ver
= da9150_fg_read_attr(fg
, DA9150_QIF_FW_MAIN_VER
,
478 DA9150_QIF_FW_MAIN_VER_SIZE
);
479 dev_info(dev
, "Version: 0x%x\n", ver
);
481 /* Handle DT data if provided */
483 fg_pdata
= da9150_fg_dt_pdata(dev
);
484 dev
->platform_data
= fg_pdata
;
487 /* Handle any pdata provided */
489 fg
->interval
= fg_pdata
->update_interval
;
491 if (fg_pdata
->warn_soc_lvl
> 100)
492 dev_warn(dev
, "Invalid SOC warning level provided, Ignoring");
494 fg
->warn_soc
= fg_pdata
->warn_soc_lvl
;
496 if ((fg_pdata
->crit_soc_lvl
> 100) ||
497 (fg_pdata
->crit_soc_lvl
>= fg_pdata
->warn_soc_lvl
))
498 dev_warn(dev
, "Invalid SOC critical level provided, Ignoring");
500 fg
->crit_soc
= fg_pdata
->crit_soc_lvl
;
505 /* Configure initial SOC level events */
506 da9150_fg_soc_event_config(fg
);
509 * If an interval period has been provided then setup repeating
510 * work for reporting data updates.
513 INIT_DELAYED_WORK(&fg
->work
, da9150_fg_work
);
514 schedule_delayed_work(&fg
->work
,
515 msecs_to_jiffies(fg
->interval
));
519 irq
= platform_get_irq_byname(pdev
, "FG");
521 dev_err(dev
, "Failed to get IRQ FG: %d\n", irq
);
526 ret
= devm_request_threaded_irq(dev
, irq
, NULL
, da9150_fg_irq
,
527 IRQF_ONESHOT
, "FG", fg
);
529 dev_err(dev
, "Failed to request IRQ %d: %d\n", irq
, ret
);
537 cancel_delayed_work(&fg
->work
);
542 static int da9150_fg_remove(struct platform_device
*pdev
)
544 struct da9150_fg
*fg
= platform_get_drvdata(pdev
);
547 cancel_delayed_work(&fg
->work
);
552 static int da9150_fg_resume(struct platform_device
*pdev
)
554 struct da9150_fg
*fg
= platform_get_drvdata(pdev
);
557 * Trigger SOC check to happen now so as to indicate any value change
558 * since last check before suspend.
561 flush_delayed_work(&fg
->work
);
566 static struct platform_driver da9150_fg_driver
= {
568 .name
= "da9150-fuel-gauge",
570 .probe
= da9150_fg_probe
,
571 .remove
= da9150_fg_remove
,
572 .resume
= da9150_fg_resume
,
575 module_platform_driver(da9150_fg_driver
);
577 MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150");
578 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
579 MODULE_LICENSE("GPL");