2 * I2C client/driver for the Linear Technology LTC2941, LTC2942, LTC2943
3 * and LTC2944 Battery Gas Gauge IC
5 * Copyright (C) 2014 Topic Embedded Systems
7 * Author: Auryn Verwegen
8 * Author: Mike Looijmans
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/types.h>
14 #include <linux/errno.h>
15 #include <linux/swab.h>
16 #include <linux/i2c.h>
17 #include <linux/delay.h>
18 #include <linux/power_supply.h>
19 #include <linux/slab.h>
21 #define I16_MSB(x) ((x >> 8) & 0xFF)
22 #define I16_LSB(x) (x & 0xFF)
24 #define LTC294X_WORK_DELAY 10 /* Update delay in seconds */
26 #define LTC294X_MAX_VALUE 0xFFFF
27 #define LTC294X_MID_SUPPLY 0x7FFF
29 #define LTC2941_MAX_PRESCALER_EXP 7
30 #define LTC2943_MAX_PRESCALER_EXP 6
33 LTC294X_REG_STATUS
= 0x00,
34 LTC294X_REG_CONTROL
= 0x01,
35 LTC294X_REG_ACC_CHARGE_MSB
= 0x02,
36 LTC294X_REG_ACC_CHARGE_LSB
= 0x03,
37 LTC294X_REG_VOLTAGE_MSB
= 0x08,
38 LTC294X_REG_VOLTAGE_LSB
= 0x09,
39 LTC2942_REG_TEMPERATURE_MSB
= 0x0C,
40 LTC2942_REG_TEMPERATURE_LSB
= 0x0D,
41 LTC2943_REG_CURRENT_MSB
= 0x0E,
42 LTC2943_REG_CURRENT_LSB
= 0x0F,
43 LTC2943_REG_TEMPERATURE_MSB
= 0x14,
44 LTC2943_REG_TEMPERATURE_LSB
= 0x15,
54 #define LTC2941_REG_STATUS_CHIP_ID BIT(7)
56 #define LTC2942_REG_CONTROL_MODE_SCAN (BIT(7) | BIT(6))
57 #define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
58 #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3))
59 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0))
60 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
61 ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
62 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
63 #define LTC294X_REG_CONTROL_ADC_DISABLE(x) ((x) & ~(BIT(7) | BIT(6)))
66 struct i2c_client
*client
; /* I2C Client pointer */
67 struct power_supply
*supply
; /* Supply pointer */
68 struct power_supply_desc supply_desc
; /* Supply description */
69 struct delayed_work work
; /* Work scheduler */
70 enum ltc294x_id id
; /* Chip type */
71 int charge
; /* Last charge register content */
72 int r_sense
; /* mOhm */
76 static inline int convert_bin_to_uAh(
77 const struct ltc294x_info
*info
, int Q
)
79 return ((Q
* (info
->Qlsb
/ 10))) / 100;
82 static inline int convert_uAh_to_bin(
83 const struct ltc294x_info
*info
, int uAh
)
87 Q
= (uAh
* 100) / (info
->Qlsb
/10);
88 return (Q
< LTC294X_MAX_VALUE
) ? Q
: LTC294X_MAX_VALUE
;
91 static int ltc294x_read_regs(struct i2c_client
*client
,
92 enum ltc294x_reg reg
, u8
*buf
, int num_regs
)
95 struct i2c_msg msgs
[2] = { };
98 msgs
[0].addr
= client
->addr
;
100 msgs
[0].buf
= ®_start
;
102 msgs
[1].addr
= client
->addr
;
103 msgs
[1].len
= num_regs
;
105 msgs
[1].flags
= I2C_M_RD
;
107 ret
= i2c_transfer(client
->adapter
, &msgs
[0], 2);
109 dev_err(&client
->dev
, "ltc2941 read_reg failed!\n");
113 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
114 __func__
, reg
, num_regs
, *buf
);
119 static int ltc294x_write_regs(struct i2c_client
*client
,
120 enum ltc294x_reg reg
, const u8
*buf
, int num_regs
)
125 ret
= i2c_smbus_write_i2c_block_data(client
, reg_start
, num_regs
, buf
);
127 dev_err(&client
->dev
, "ltc2941 write_reg failed!\n");
131 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
132 __func__
, reg
, num_regs
, *buf
);
137 static int ltc294x_reset(const struct ltc294x_info
*info
, int prescaler_exp
)
143 /* Read status and control registers */
144 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
146 dev_err(&info
->client
->dev
,
147 "Could not read registers from device\n");
151 control
= LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp
) |
152 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED
;
153 /* Put device into "monitor" mode */
155 case LTC2942_ID
: /* 2942 measures every 2 sec */
156 control
|= LTC2942_REG_CONTROL_MODE_SCAN
;
159 case LTC2944_ID
: /* 2943 and 2944 measure every 10 sec */
160 control
|= LTC2943_REG_CONTROL_MODE_SCAN
;
166 if (value
!= control
) {
167 ret
= ltc294x_write_regs(info
->client
,
168 LTC294X_REG_CONTROL
, &control
, 1);
170 dev_err(&info
->client
->dev
,
171 "Could not write register\n");
182 static int ltc294x_read_charge_register(const struct ltc294x_info
*info
)
187 ret
= ltc294x_read_regs(info
->client
,
188 LTC294X_REG_ACC_CHARGE_MSB
, &datar
[0], 2);
191 return (datar
[0] << 8) + datar
[1];
194 static int ltc294x_get_charge_now(const struct ltc294x_info
*info
, int *val
)
196 int value
= ltc294x_read_charge_register(info
);
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_get_charge_counter(
249 const struct ltc294x_info
*info
, int *val
)
251 int value
= ltc294x_read_charge_register(info
);
255 value
-= LTC294X_MID_SUPPLY
;
256 *val
= convert_bin_to_uAh(info
, value
);
260 static int ltc294x_get_voltage(const struct ltc294x_info
*info
, int *val
)
266 ret
= ltc294x_read_regs(info
->client
,
267 LTC294X_REG_VOLTAGE_MSB
, &datar
[0], 2);
268 value
= (datar
[0] << 8) | datar
[1];
276 value
*= 70800 / 5*4;
290 static int ltc294x_get_current(const struct ltc294x_info
*info
, int *val
)
296 ret
= ltc294x_read_regs(info
->client
,
297 LTC2943_REG_CURRENT_MSB
, &datar
[0], 2);
298 value
= (datar
[0] << 8) | datar
[1];
300 if (info
->id
== LTC2944_ID
)
304 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
305 * the formula below keeps everything in s32 range while preserving
307 *val
= 1000 * (value
/ (info
->r_sense
* 0x7FFF)); /* in uA */
311 static int ltc294x_get_temperature(const struct ltc294x_info
*info
, int *val
)
313 enum ltc294x_reg reg
;
318 if (info
->id
== LTC2942_ID
) {
319 reg
= LTC2942_REG_TEMPERATURE_MSB
;
320 value
= 60000; /* Full-scale is 600 Kelvin */
322 reg
= LTC2943_REG_TEMPERATURE_MSB
;
323 value
= 51000; /* Full-scale is 510 Kelvin */
325 ret
= ltc294x_read_regs(info
->client
, reg
, &datar
[0], 2);
326 value
*= (datar
[0] << 8) | datar
[1];
327 /* Convert to centidegrees */
328 *val
= value
/ 0xFFFF - 27215;
332 static int ltc294x_get_property(struct power_supply
*psy
,
333 enum power_supply_property prop
,
334 union power_supply_propval
*val
)
336 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
339 case POWER_SUPPLY_PROP_CHARGE_NOW
:
340 return ltc294x_get_charge_now(info
, &val
->intval
);
341 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
342 return ltc294x_get_charge_counter(info
, &val
->intval
);
343 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
344 return ltc294x_get_voltage(info
, &val
->intval
);
345 case POWER_SUPPLY_PROP_CURRENT_NOW
:
346 return ltc294x_get_current(info
, &val
->intval
);
347 case POWER_SUPPLY_PROP_TEMP
:
348 return ltc294x_get_temperature(info
, &val
->intval
);
354 static int ltc294x_set_property(struct power_supply
*psy
,
355 enum power_supply_property psp
,
356 const union power_supply_propval
*val
)
358 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
361 case POWER_SUPPLY_PROP_CHARGE_NOW
:
362 return ltc294x_set_charge_now(info
, val
->intval
);
368 static int ltc294x_property_is_writeable(
369 struct power_supply
*psy
, enum power_supply_property psp
)
372 case POWER_SUPPLY_PROP_CHARGE_NOW
:
379 static void ltc294x_update(struct ltc294x_info
*info
)
381 int charge
= ltc294x_read_charge_register(info
);
383 if (charge
!= info
->charge
) {
384 info
->charge
= charge
;
385 power_supply_changed(info
->supply
);
389 static void ltc294x_work(struct work_struct
*work
)
391 struct ltc294x_info
*info
;
393 info
= container_of(work
, struct ltc294x_info
, work
.work
);
394 ltc294x_update(info
);
395 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
398 static enum power_supply_property ltc294x_properties
[] = {
399 POWER_SUPPLY_PROP_CHARGE_COUNTER
,
400 POWER_SUPPLY_PROP_CHARGE_NOW
,
401 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
402 POWER_SUPPLY_PROP_TEMP
,
403 POWER_SUPPLY_PROP_CURRENT_NOW
,
406 static int ltc294x_i2c_remove(struct i2c_client
*client
)
408 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
410 cancel_delayed_work(&info
->work
);
411 power_supply_unregister(info
->supply
);
415 static int ltc294x_i2c_probe(struct i2c_client
*client
,
416 const struct i2c_device_id
*id
)
418 struct power_supply_config psy_cfg
= {};
419 struct ltc294x_info
*info
;
420 struct device_node
*np
;
426 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
430 i2c_set_clientdata(client
, info
);
432 np
= of_node_get(client
->dev
.of_node
);
434 info
->id
= (enum ltc294x_id
)of_device_get_match_data(&client
->dev
);
435 info
->supply_desc
.name
= np
->name
;
437 /* r_sense can be negative, when sense+ is connected to the battery
438 * instead of the sense-. This results in reversed measurements. */
439 ret
= of_property_read_u32(np
, "lltc,resistor-sense", &r_sense
);
441 dev_err(&client
->dev
,
442 "Could not find lltc,resistor-sense in devicetree\n");
445 info
->r_sense
= r_sense
;
447 ret
= of_property_read_u32(np
, "lltc,prescaler-exponent",
450 dev_warn(&client
->dev
,
451 "lltc,prescaler-exponent not in devicetree\n");
452 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
455 if (info
->id
== LTC2943_ID
) {
456 if (prescaler_exp
> LTC2943_MAX_PRESCALER_EXP
)
457 prescaler_exp
= LTC2943_MAX_PRESCALER_EXP
;
458 info
->Qlsb
= ((340 * 50000) / r_sense
) /
459 (4096 / (1 << (2*prescaler_exp
)));
461 if (prescaler_exp
> LTC2941_MAX_PRESCALER_EXP
)
462 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
463 info
->Qlsb
= ((85 * 50000) / r_sense
) /
464 (128 / (1 << prescaler_exp
));
467 /* Read status register to check for LTC2942 */
468 if (info
->id
== LTC2941_ID
|| info
->id
== LTC2942_ID
) {
469 ret
= ltc294x_read_regs(client
, LTC294X_REG_STATUS
, &status
, 1);
471 dev_err(&client
->dev
,
472 "Could not read status register\n");
475 if (status
& LTC2941_REG_STATUS_CHIP_ID
)
476 info
->id
= LTC2941_ID
;
478 info
->id
= LTC2942_ID
;
481 info
->client
= client
;
482 info
->supply_desc
.type
= POWER_SUPPLY_TYPE_BATTERY
;
483 info
->supply_desc
.properties
= ltc294x_properties
;
487 info
->supply_desc
.num_properties
=
488 ARRAY_SIZE(ltc294x_properties
);
491 info
->supply_desc
.num_properties
=
492 ARRAY_SIZE(ltc294x_properties
) - 1;
496 info
->supply_desc
.num_properties
=
497 ARRAY_SIZE(ltc294x_properties
) - 3;
500 info
->supply_desc
.get_property
= ltc294x_get_property
;
501 info
->supply_desc
.set_property
= ltc294x_set_property
;
502 info
->supply_desc
.property_is_writeable
= ltc294x_property_is_writeable
;
503 info
->supply_desc
.external_power_changed
= NULL
;
505 psy_cfg
.drv_data
= info
;
507 INIT_DELAYED_WORK(&info
->work
, ltc294x_work
);
509 ret
= ltc294x_reset(info
, prescaler_exp
);
511 dev_err(&client
->dev
, "Communication with chip failed\n");
515 info
->supply
= power_supply_register(&client
->dev
, &info
->supply_desc
,
517 if (IS_ERR(info
->supply
)) {
518 dev_err(&client
->dev
, "failed to register ltc2941\n");
519 return PTR_ERR(info
->supply
);
521 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
527 static void ltc294x_i2c_shutdown(struct i2c_client
*client
)
529 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
534 /* The LTC2941 does not need any special handling */
535 if (info
->id
== LTC2941_ID
)
538 /* Read control register */
539 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
543 /* Disable continuous ADC conversion as this drains the battery */
544 control
= LTC294X_REG_CONTROL_ADC_DISABLE(value
);
545 if (control
!= value
)
546 ltc294x_write_regs(info
->client
, LTC294X_REG_CONTROL
,
550 #ifdef CONFIG_PM_SLEEP
552 static int ltc294x_suspend(struct device
*dev
)
554 struct i2c_client
*client
= to_i2c_client(dev
);
555 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
557 cancel_delayed_work(&info
->work
);
561 static int ltc294x_resume(struct device
*dev
)
563 struct i2c_client
*client
= to_i2c_client(dev
);
564 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
566 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
570 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops
, ltc294x_suspend
, ltc294x_resume
);
571 #define LTC294X_PM_OPS (<c294x_pm_ops)
574 #define LTC294X_PM_OPS NULL
575 #endif /* CONFIG_PM_SLEEP */
578 static const struct i2c_device_id ltc294x_i2c_id
[] = {
579 { "ltc2941", LTC2941_ID
, },
580 { "ltc2942", LTC2942_ID
, },
581 { "ltc2943", LTC2943_ID
, },
582 { "ltc2944", LTC2944_ID
, },
585 MODULE_DEVICE_TABLE(i2c
, ltc294x_i2c_id
);
587 static const struct of_device_id ltc294x_i2c_of_match
[] = {
589 .compatible
= "lltc,ltc2941",
590 .data
= (void *)LTC2941_ID
,
593 .compatible
= "lltc,ltc2942",
594 .data
= (void *)LTC2942_ID
,
597 .compatible
= "lltc,ltc2943",
598 .data
= (void *)LTC2943_ID
,
601 .compatible
= "lltc,ltc2944",
602 .data
= (void *)LTC2944_ID
,
606 MODULE_DEVICE_TABLE(of
, ltc294x_i2c_of_match
);
608 static struct i2c_driver ltc294x_driver
= {
611 .of_match_table
= ltc294x_i2c_of_match
,
612 .pm
= LTC294X_PM_OPS
,
614 .probe
= ltc294x_i2c_probe
,
615 .remove
= ltc294x_i2c_remove
,
616 .shutdown
= ltc294x_i2c_shutdown
,
617 .id_table
= ltc294x_i2c_id
,
619 module_i2c_driver(ltc294x_driver
);
621 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
622 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
623 MODULE_DESCRIPTION("LTC2941/LTC2942/LTC2943/LTC2944 Battery Gas Gauge IC driver");
624 MODULE_LICENSE("GPL");