1 // SPDX-License-Identifier: GPL-2.0-only
3 * I2C client/driver for the Linear Technology LTC2941, LTC2942, LTC2943
4 * and LTC2944 Battery Gas Gauge IC
6 * Copyright (C) 2014 Topic Embedded Systems
8 * Author: Auryn Verwegen
9 * Author: Mike Looijmans
11 #include <linux/devm-helpers.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/errno.h>
17 #include <linux/swab.h>
18 #include <linux/i2c.h>
19 #include <linux/delay.h>
20 #include <linux/power_supply.h>
21 #include <linux/slab.h>
23 #define I16_MSB(x) ((x >> 8) & 0xFF)
24 #define I16_LSB(x) (x & 0xFF)
26 #define LTC294X_WORK_DELAY 10 /* Update delay in seconds */
28 #define LTC294X_MAX_VALUE 0xFFFF
29 #define LTC294X_MID_SUPPLY 0x7FFF
31 #define LTC2941_MAX_PRESCALER_EXP 7
32 #define LTC2943_MAX_PRESCALER_EXP 6
35 LTC294X_REG_STATUS
= 0x00,
36 LTC294X_REG_CONTROL
= 0x01,
37 LTC294X_REG_ACC_CHARGE_MSB
= 0x02,
38 LTC294X_REG_ACC_CHARGE_LSB
= 0x03,
39 LTC294X_REG_CHARGE_THR_HIGH_MSB
= 0x04,
40 LTC294X_REG_CHARGE_THR_HIGH_LSB
= 0x05,
41 LTC294X_REG_CHARGE_THR_LOW_MSB
= 0x06,
42 LTC294X_REG_CHARGE_THR_LOW_LSB
= 0x07,
43 LTC294X_REG_VOLTAGE_MSB
= 0x08,
44 LTC294X_REG_VOLTAGE_LSB
= 0x09,
45 LTC2942_REG_TEMPERATURE_MSB
= 0x0C,
46 LTC2942_REG_TEMPERATURE_LSB
= 0x0D,
47 LTC2943_REG_CURRENT_MSB
= 0x0E,
48 LTC2943_REG_CURRENT_LSB
= 0x0F,
49 LTC2943_REG_TEMPERATURE_MSB
= 0x14,
50 LTC2943_REG_TEMPERATURE_LSB
= 0x15,
60 #define LTC2941_REG_STATUS_CHIP_ID BIT(7)
62 #define LTC2942_REG_CONTROL_MODE_SCAN (BIT(7) | BIT(6))
63 #define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
64 #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3))
65 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0))
66 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
67 ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
68 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
69 #define LTC294X_REG_CONTROL_ADC_DISABLE(x) ((x) & ~(BIT(7) | BIT(6)))
72 struct i2c_client
*client
; /* I2C Client pointer */
73 struct power_supply
*supply
; /* Supply pointer */
74 struct power_supply_desc supply_desc
; /* Supply description */
75 struct delayed_work work
; /* Work scheduler */
76 enum ltc294x_id id
; /* Chip type */
77 int charge
; /* Last charge register content */
78 int r_sense
; /* mOhm */
82 static inline int convert_bin_to_uAh(
83 const struct ltc294x_info
*info
, int Q
)
85 return ((Q
* (info
->Qlsb
/ 10))) / 100;
88 static inline int convert_uAh_to_bin(
89 const struct ltc294x_info
*info
, int uAh
)
93 Q
= (uAh
* 100) / (info
->Qlsb
/10);
94 return (Q
< LTC294X_MAX_VALUE
) ? Q
: LTC294X_MAX_VALUE
;
97 static int ltc294x_read_regs(struct i2c_client
*client
,
98 enum ltc294x_reg reg
, u8
*buf
, int num_regs
)
101 struct i2c_msg msgs
[2] = { };
104 msgs
[0].addr
= client
->addr
;
106 msgs
[0].buf
= ®_start
;
108 msgs
[1].addr
= client
->addr
;
109 msgs
[1].len
= num_regs
;
111 msgs
[1].flags
= I2C_M_RD
;
113 ret
= i2c_transfer(client
->adapter
, &msgs
[0], 2);
115 dev_err(&client
->dev
, "ltc2941 read_reg(0x%x[%d]) failed: %pe\n",
116 reg
, num_regs
, ERR_PTR(ret
));
120 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
121 __func__
, reg
, num_regs
, *buf
);
126 static int ltc294x_write_regs(struct i2c_client
*client
,
127 enum ltc294x_reg reg
, const u8
*buf
, int num_regs
)
132 ret
= i2c_smbus_write_i2c_block_data(client
, reg_start
, num_regs
, buf
);
134 dev_err(&client
->dev
, "ltc2941 write_reg(0x%x[%d]) failed: %pe\n",
135 reg
, num_regs
, ERR_PTR(ret
));
139 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
140 __func__
, reg
, num_regs
, *buf
);
145 static int ltc294x_reset(const struct ltc294x_info
*info
, int prescaler_exp
)
151 /* Read status and control registers */
152 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
156 control
= LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp
) |
157 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED
;
158 /* Put device into "monitor" mode */
160 case LTC2942_ID
: /* 2942 measures every 2 sec */
161 control
|= LTC2942_REG_CONTROL_MODE_SCAN
;
164 case LTC2944_ID
: /* 2943 and 2944 measure every 10 sec */
165 control
|= LTC2943_REG_CONTROL_MODE_SCAN
;
171 if (value
!= control
) {
172 ret
= ltc294x_write_regs(info
->client
,
173 LTC294X_REG_CONTROL
, &control
, 1);
181 static int ltc294x_read_charge_register(const struct ltc294x_info
*info
,
182 enum ltc294x_reg reg
)
187 ret
= ltc294x_read_regs(info
->client
, reg
, &datar
[0], 2);
190 return (datar
[0] << 8) + datar
[1];
193 static int ltc294x_get_charge(const struct ltc294x_info
*info
,
194 enum ltc294x_reg reg
, int *val
)
196 int value
= ltc294x_read_charge_register(info
, reg
);
200 /* When r_sense < 0, this counts up when the battery discharges */
203 *val
= convert_bin_to_uAh(info
, value
);
207 static int ltc294x_set_charge_now(const struct ltc294x_info
*info
, int val
)
214 value
= convert_uAh_to_bin(info
, val
);
215 /* Direction depends on how sense+/- were connected */
218 if ((value
< 0) || (value
> 0xFFFF)) /* input validation */
221 /* Read control register */
222 ret
= ltc294x_read_regs(info
->client
,
223 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
226 /* Disable analog section */
227 ctrl_reg
|= LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
228 ret
= ltc294x_write_regs(info
->client
,
229 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
232 /* Set new charge value */
233 dataw
[0] = I16_MSB(value
);
234 dataw
[1] = I16_LSB(value
);
235 ret
= ltc294x_write_regs(info
->client
,
236 LTC294X_REG_ACC_CHARGE_MSB
, &dataw
[0], 2);
239 /* Enable analog section */
241 ctrl_reg
&= ~LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
242 ret
= ltc294x_write_regs(info
->client
,
243 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
245 return ret
< 0 ? ret
: 0;
248 static int ltc294x_set_charge_thr(const struct ltc294x_info
*info
,
249 enum ltc294x_reg reg
, int val
)
254 value
= convert_uAh_to_bin(info
, val
);
255 /* Direction depends on how sense+/- were connected */
258 if ((value
< 0) || (value
> 0xFFFF)) /* input validation */
261 /* Set new charge value */
262 dataw
[0] = I16_MSB(value
);
263 dataw
[1] = I16_LSB(value
);
264 return ltc294x_write_regs(info
->client
, reg
, &dataw
[0], 2);
267 static int ltc294x_get_charge_counter(
268 const struct ltc294x_info
*info
, int *val
)
270 int value
= ltc294x_read_charge_register(info
, LTC294X_REG_ACC_CHARGE_MSB
);
274 value
-= LTC294X_MID_SUPPLY
;
275 *val
= convert_bin_to_uAh(info
, value
);
279 static int ltc294x_get_voltage(const struct ltc294x_info
*info
, int *val
)
285 ret
= ltc294x_read_regs(info
->client
,
286 LTC294X_REG_VOLTAGE_MSB
, &datar
[0], 2);
287 value
= (datar
[0] << 8) | datar
[1];
295 value
*= 70800 / 5*4;
309 static int ltc294x_get_current(const struct ltc294x_info
*info
, int *val
)
315 ret
= ltc294x_read_regs(info
->client
,
316 LTC2943_REG_CURRENT_MSB
, &datar
[0], 2);
317 value
= (datar
[0] << 8) | datar
[1];
319 if (info
->id
== LTC2944_ID
)
323 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
324 * the formula below keeps everything in s32 range while preserving
326 *val
= 1000 * (value
/ (info
->r_sense
* 0x7FFF)); /* in uA */
330 static int ltc294x_get_temperature(const struct ltc294x_info
*info
, int *val
)
332 enum ltc294x_reg reg
;
337 if (info
->id
== LTC2942_ID
) {
338 reg
= LTC2942_REG_TEMPERATURE_MSB
;
339 value
= 6000; /* Full-scale is 600 Kelvin */
341 reg
= LTC2943_REG_TEMPERATURE_MSB
;
342 value
= 5100; /* Full-scale is 510 Kelvin */
344 ret
= ltc294x_read_regs(info
->client
, reg
, &datar
[0], 2);
345 value
*= (datar
[0] << 8) | datar
[1];
346 /* Convert to tenths of degree Celsius */
347 *val
= value
/ 0xFFFF - 2722;
351 static int ltc294x_get_property(struct power_supply
*psy
,
352 enum power_supply_property prop
,
353 union power_supply_propval
*val
)
355 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
358 case POWER_SUPPLY_PROP_CHARGE_FULL
:
359 return ltc294x_get_charge(info
, LTC294X_REG_CHARGE_THR_HIGH_MSB
,
361 case POWER_SUPPLY_PROP_CHARGE_EMPTY
:
362 return ltc294x_get_charge(info
, LTC294X_REG_CHARGE_THR_LOW_MSB
,
364 case POWER_SUPPLY_PROP_CHARGE_NOW
:
365 return ltc294x_get_charge(info
, LTC294X_REG_ACC_CHARGE_MSB
,
367 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
368 return ltc294x_get_charge_counter(info
, &val
->intval
);
369 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
370 return ltc294x_get_voltage(info
, &val
->intval
);
371 case POWER_SUPPLY_PROP_CURRENT_NOW
:
372 return ltc294x_get_current(info
, &val
->intval
);
373 case POWER_SUPPLY_PROP_TEMP
:
374 return ltc294x_get_temperature(info
, &val
->intval
);
380 static int ltc294x_set_property(struct power_supply
*psy
,
381 enum power_supply_property psp
,
382 const union power_supply_propval
*val
)
384 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
387 case POWER_SUPPLY_PROP_CHARGE_FULL
:
388 return ltc294x_set_charge_thr(info
,
389 LTC294X_REG_CHARGE_THR_HIGH_MSB
, val
->intval
);
390 case POWER_SUPPLY_PROP_CHARGE_EMPTY
:
391 return ltc294x_set_charge_thr(info
,
392 LTC294X_REG_CHARGE_THR_LOW_MSB
, val
->intval
);
393 case POWER_SUPPLY_PROP_CHARGE_NOW
:
394 return ltc294x_set_charge_now(info
, val
->intval
);
400 static int ltc294x_property_is_writeable(
401 struct power_supply
*psy
, enum power_supply_property psp
)
404 case POWER_SUPPLY_PROP_CHARGE_FULL
:
405 case POWER_SUPPLY_PROP_CHARGE_EMPTY
:
406 case POWER_SUPPLY_PROP_CHARGE_NOW
:
413 static void ltc294x_update(struct ltc294x_info
*info
)
415 int charge
= ltc294x_read_charge_register(info
, LTC294X_REG_ACC_CHARGE_MSB
);
417 if (charge
!= info
->charge
) {
418 info
->charge
= charge
;
419 power_supply_changed(info
->supply
);
423 static void ltc294x_work(struct work_struct
*work
)
425 struct ltc294x_info
*info
;
427 info
= container_of(work
, struct ltc294x_info
, work
.work
);
428 ltc294x_update(info
);
429 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
432 static enum power_supply_property ltc294x_properties
[] = {
433 POWER_SUPPLY_PROP_CHARGE_COUNTER
,
434 POWER_SUPPLY_PROP_CHARGE_FULL
,
435 POWER_SUPPLY_PROP_CHARGE_EMPTY
,
436 POWER_SUPPLY_PROP_CHARGE_NOW
,
437 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
438 POWER_SUPPLY_PROP_TEMP
,
439 POWER_SUPPLY_PROP_CURRENT_NOW
,
442 static int ltc294x_i2c_probe(struct i2c_client
*client
)
444 struct power_supply_config psy_cfg
= {};
445 struct ltc294x_info
*info
;
446 struct device_node
*np
;
452 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
456 i2c_set_clientdata(client
, info
);
458 np
= of_node_get(client
->dev
.of_node
);
460 info
->id
= (enum ltc294x_id
) (uintptr_t) of_device_get_match_data(
462 info
->supply_desc
.name
= np
->name
;
464 /* r_sense can be negative, when sense+ is connected to the battery
465 * instead of the sense-. This results in reversed measurements. */
466 ret
= of_property_read_u32(np
, "lltc,resistor-sense", &r_sense
);
468 return dev_err_probe(&client
->dev
, ret
,
469 "Could not find lltc,resistor-sense in devicetree\n");
470 info
->r_sense
= r_sense
;
472 ret
= of_property_read_u32(np
, "lltc,prescaler-exponent",
475 dev_warn(&client
->dev
,
476 "lltc,prescaler-exponent not in devicetree\n");
477 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
480 if (info
->id
== LTC2943_ID
) {
481 if (prescaler_exp
> LTC2943_MAX_PRESCALER_EXP
)
482 prescaler_exp
= LTC2943_MAX_PRESCALER_EXP
;
483 info
->Qlsb
= ((340 * 50000) / r_sense
) >>
484 (12 - 2*prescaler_exp
);
486 if (prescaler_exp
> LTC2941_MAX_PRESCALER_EXP
)
487 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
488 info
->Qlsb
= ((85 * 50000) / r_sense
) >>
492 /* Read status register to check for LTC2942 */
493 if (info
->id
== LTC2941_ID
|| info
->id
== LTC2942_ID
) {
494 ret
= ltc294x_read_regs(client
, LTC294X_REG_STATUS
, &status
, 1);
496 return dev_err_probe(&client
->dev
, ret
,
497 "Could not read status register\n");
498 if (status
& LTC2941_REG_STATUS_CHIP_ID
)
499 info
->id
= LTC2941_ID
;
501 info
->id
= LTC2942_ID
;
504 info
->client
= client
;
505 info
->supply_desc
.type
= POWER_SUPPLY_TYPE_BATTERY
;
506 info
->supply_desc
.properties
= ltc294x_properties
;
510 info
->supply_desc
.num_properties
=
511 ARRAY_SIZE(ltc294x_properties
);
514 info
->supply_desc
.num_properties
=
515 ARRAY_SIZE(ltc294x_properties
) - 1;
519 info
->supply_desc
.num_properties
=
520 ARRAY_SIZE(ltc294x_properties
) - 3;
523 info
->supply_desc
.get_property
= ltc294x_get_property
;
524 info
->supply_desc
.set_property
= ltc294x_set_property
;
525 info
->supply_desc
.property_is_writeable
= ltc294x_property_is_writeable
;
526 info
->supply_desc
.external_power_changed
= NULL
;
528 psy_cfg
.drv_data
= info
;
530 ret
= devm_delayed_work_autocancel(&client
->dev
, &info
->work
,
535 ret
= ltc294x_reset(info
, prescaler_exp
);
537 return dev_err_probe(&client
->dev
, ret
,
538 "Communication with chip failed\n");
540 info
->supply
= devm_power_supply_register(&client
->dev
,
541 &info
->supply_desc
, &psy_cfg
);
542 if (IS_ERR(info
->supply
))
543 return dev_err_probe(&client
->dev
, PTR_ERR(info
->supply
),
544 "failed to register ltc2941\n");
546 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
551 static void ltc294x_i2c_shutdown(struct i2c_client
*client
)
553 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
558 /* The LTC2941 does not need any special handling */
559 if (info
->id
== LTC2941_ID
)
562 /* Read control register */
563 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
567 /* Disable continuous ADC conversion as this drains the battery */
568 control
= LTC294X_REG_CONTROL_ADC_DISABLE(value
);
569 if (control
!= value
)
570 ltc294x_write_regs(info
->client
, LTC294X_REG_CONTROL
,
574 #ifdef CONFIG_PM_SLEEP
576 static int ltc294x_suspend(struct device
*dev
)
578 struct i2c_client
*client
= to_i2c_client(dev
);
579 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
581 cancel_delayed_work(&info
->work
);
585 static int ltc294x_resume(struct device
*dev
)
587 struct i2c_client
*client
= to_i2c_client(dev
);
588 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
590 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
594 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops
, ltc294x_suspend
, ltc294x_resume
);
595 #define LTC294X_PM_OPS (<c294x_pm_ops)
598 #define LTC294X_PM_OPS NULL
599 #endif /* CONFIG_PM_SLEEP */
602 static const struct i2c_device_id ltc294x_i2c_id
[] = {
603 { "ltc2941", LTC2941_ID
, },
604 { "ltc2942", LTC2942_ID
, },
605 { "ltc2943", LTC2943_ID
, },
606 { "ltc2944", LTC2944_ID
, },
609 MODULE_DEVICE_TABLE(i2c
, ltc294x_i2c_id
);
611 static const struct of_device_id ltc294x_i2c_of_match
[] = {
613 .compatible
= "lltc,ltc2941",
614 .data
= (void *)LTC2941_ID
,
617 .compatible
= "lltc,ltc2942",
618 .data
= (void *)LTC2942_ID
,
621 .compatible
= "lltc,ltc2943",
622 .data
= (void *)LTC2943_ID
,
625 .compatible
= "lltc,ltc2944",
626 .data
= (void *)LTC2944_ID
,
630 MODULE_DEVICE_TABLE(of
, ltc294x_i2c_of_match
);
632 static struct i2c_driver ltc294x_driver
= {
635 .of_match_table
= ltc294x_i2c_of_match
,
636 .pm
= LTC294X_PM_OPS
,
638 .probe
= ltc294x_i2c_probe
,
639 .shutdown
= ltc294x_i2c_shutdown
,
640 .id_table
= ltc294x_i2c_id
,
642 module_i2c_driver(ltc294x_driver
);
644 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
645 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
646 MODULE_DESCRIPTION("LTC2941/LTC2942/LTC2943/LTC2944 Battery Gas Gauge IC driver");
647 MODULE_LICENSE("GPL");