2 * I2C client/driver for the Linear Technology LTC2941 and LTC2943
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_THRESH_HIGH_MSB
= 0x04,
38 LTC294X_REG_THRESH_HIGH_LSB
= 0x05,
39 LTC294X_REG_THRESH_LOW_MSB
= 0x06,
40 LTC294X_REG_THRESH_LOW_LSB
= 0x07,
41 LTC294X_REG_VOLTAGE_MSB
= 0x08,
42 LTC294X_REG_VOLTAGE_LSB
= 0x09,
43 LTC294X_REG_CURRENT_MSB
= 0x0E,
44 LTC294X_REG_CURRENT_LSB
= 0x0F,
45 LTC294X_REG_TEMPERATURE_MSB
= 0x14,
46 LTC294X_REG_TEMPERATURE_LSB
= 0x15,
49 #define LTC2943_REG_CONTROL_MODE_MASK (BIT(7) | BIT(6))
50 #define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
51 #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3))
52 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0))
53 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
54 ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
55 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
57 #define LTC2941_NUM_REGS 0x08
58 #define LTC2943_NUM_REGS 0x18
61 struct i2c_client
*client
; /* I2C Client pointer */
62 struct power_supply
*supply
; /* Supply pointer */
63 struct power_supply_desc supply_desc
; /* Supply description */
64 struct delayed_work work
; /* Work scheduler */
65 unsigned long num_regs
; /* Number of registers (chip type) */
66 int charge
; /* Last charge register content */
67 int r_sense
; /* mOhm */
71 static inline int convert_bin_to_uAh(
72 const struct ltc294x_info
*info
, int Q
)
74 return ((Q
* (info
->Qlsb
/ 10))) / 100;
77 static inline int convert_uAh_to_bin(
78 const struct ltc294x_info
*info
, int uAh
)
82 Q
= (uAh
* 100) / (info
->Qlsb
/10);
83 return (Q
< LTC294X_MAX_VALUE
) ? Q
: LTC294X_MAX_VALUE
;
86 static int ltc294x_read_regs(struct i2c_client
*client
,
87 enum ltc294x_reg reg
, u8
*buf
, int num_regs
)
90 struct i2c_msg msgs
[2] = { };
93 msgs
[0].addr
= client
->addr
;
95 msgs
[0].buf
= ®_start
;
97 msgs
[1].addr
= client
->addr
;
98 msgs
[1].len
= num_regs
;
100 msgs
[1].flags
= I2C_M_RD
;
102 ret
= i2c_transfer(client
->adapter
, &msgs
[0], 2);
104 dev_err(&client
->dev
, "ltc2941 read_reg failed!\n");
108 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
109 __func__
, reg
, num_regs
, *buf
);
114 static int ltc294x_write_regs(struct i2c_client
*client
,
115 enum ltc294x_reg reg
, const u8
*buf
, int num_regs
)
120 ret
= i2c_smbus_write_i2c_block_data(client
, reg_start
, num_regs
, buf
);
122 dev_err(&client
->dev
, "ltc2941 write_reg failed!\n");
126 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
127 __func__
, reg
, num_regs
, *buf
);
132 static int ltc294x_reset(const struct ltc294x_info
*info
, int prescaler_exp
)
138 /* Read status and control registers */
139 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
141 dev_err(&info
->client
->dev
,
142 "Could not read registers from device\n");
146 control
= LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp
) |
147 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED
;
148 /* Put the 2943 into "monitor" mode, so it measures every 10 sec */
149 if (info
->num_regs
== LTC2943_NUM_REGS
)
150 control
|= LTC2943_REG_CONTROL_MODE_SCAN
;
152 if (value
!= control
) {
153 ret
= ltc294x_write_regs(info
->client
,
154 LTC294X_REG_CONTROL
, &control
, 1);
156 dev_err(&info
->client
->dev
,
157 "Could not write register\n");
168 static int ltc294x_read_charge_register(const struct ltc294x_info
*info
)
173 ret
= ltc294x_read_regs(info
->client
,
174 LTC294X_REG_ACC_CHARGE_MSB
, &datar
[0], 2);
177 return (datar
[0] << 8) + datar
[1];
180 static int ltc294x_get_charge_now(const struct ltc294x_info
*info
, int *val
)
182 int value
= ltc294x_read_charge_register(info
);
186 /* When r_sense < 0, this counts up when the battery discharges */
189 *val
= convert_bin_to_uAh(info
, value
);
193 static int ltc294x_set_charge_now(const struct ltc294x_info
*info
, int val
)
200 value
= convert_uAh_to_bin(info
, val
);
201 /* Direction depends on how sense+/- were connected */
204 if ((value
< 0) || (value
> 0xFFFF)) /* input validation */
207 /* Read control register */
208 ret
= ltc294x_read_regs(info
->client
,
209 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
212 /* Disable analog section */
213 ctrl_reg
|= LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
214 ret
= ltc294x_write_regs(info
->client
,
215 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
218 /* Set new charge value */
219 dataw
[0] = I16_MSB(value
);
220 dataw
[1] = I16_LSB(value
);
221 ret
= ltc294x_write_regs(info
->client
,
222 LTC294X_REG_ACC_CHARGE_MSB
, &dataw
[0], 2);
225 /* Enable analog section */
227 ctrl_reg
&= ~LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
228 ret
= ltc294x_write_regs(info
->client
,
229 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
231 return ret
< 0 ? ret
: 0;
234 static int ltc294x_get_charge_counter(
235 const struct ltc294x_info
*info
, int *val
)
237 int value
= ltc294x_read_charge_register(info
);
241 value
-= LTC294X_MID_SUPPLY
;
242 *val
= convert_bin_to_uAh(info
, value
);
246 static int ltc294x_get_voltage(const struct ltc294x_info
*info
, int *val
)
252 ret
= ltc294x_read_regs(info
->client
,
253 LTC294X_REG_VOLTAGE_MSB
, &datar
[0], 2);
254 value
= (datar
[0] << 8) | datar
[1];
255 *val
= ((value
* 23600) / 0xFFFF) * 1000; /* in uV */
259 static int ltc294x_get_current(const struct ltc294x_info
*info
, int *val
)
265 ret
= ltc294x_read_regs(info
->client
,
266 LTC294X_REG_CURRENT_MSB
, &datar
[0], 2);
267 value
= (datar
[0] << 8) | datar
[1];
269 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
270 * the formula below keeps everything in s32 range while preserving
272 *val
= 1000 * ((60000 * value
) / (info
->r_sense
* 0x7FFF)); /* in uA */
276 static int ltc294x_get_temperature(const struct ltc294x_info
*info
, int *val
)
282 ret
= ltc294x_read_regs(info
->client
,
283 LTC294X_REG_TEMPERATURE_MSB
, &datar
[0], 2);
284 value
= (datar
[0] << 8) | datar
[1];
285 /* Full-scale is 510 Kelvin, convert to centidegrees */
286 *val
= (((51000 * value
) / 0xFFFF) - 27215);
290 static int ltc294x_get_property(struct power_supply
*psy
,
291 enum power_supply_property prop
,
292 union power_supply_propval
*val
)
294 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
297 case POWER_SUPPLY_PROP_CHARGE_NOW
:
298 return ltc294x_get_charge_now(info
, &val
->intval
);
299 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
300 return ltc294x_get_charge_counter(info
, &val
->intval
);
301 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
302 return ltc294x_get_voltage(info
, &val
->intval
);
303 case POWER_SUPPLY_PROP_CURRENT_NOW
:
304 return ltc294x_get_current(info
, &val
->intval
);
305 case POWER_SUPPLY_PROP_TEMP
:
306 return ltc294x_get_temperature(info
, &val
->intval
);
312 static int ltc294x_set_property(struct power_supply
*psy
,
313 enum power_supply_property psp
,
314 const union power_supply_propval
*val
)
316 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
319 case POWER_SUPPLY_PROP_CHARGE_NOW
:
320 return ltc294x_set_charge_now(info
, val
->intval
);
326 static int ltc294x_property_is_writeable(
327 struct power_supply
*psy
, enum power_supply_property psp
)
330 case POWER_SUPPLY_PROP_CHARGE_NOW
:
337 static void ltc294x_update(struct ltc294x_info
*info
)
339 int charge
= ltc294x_read_charge_register(info
);
341 if (charge
!= info
->charge
) {
342 info
->charge
= charge
;
343 power_supply_changed(info
->supply
);
347 static void ltc294x_work(struct work_struct
*work
)
349 struct ltc294x_info
*info
;
351 info
= container_of(work
, struct ltc294x_info
, work
.work
);
352 ltc294x_update(info
);
353 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
356 static enum power_supply_property ltc294x_properties
[] = {
357 POWER_SUPPLY_PROP_CHARGE_COUNTER
,
358 POWER_SUPPLY_PROP_CHARGE_NOW
,
359 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
360 POWER_SUPPLY_PROP_CURRENT_NOW
,
361 POWER_SUPPLY_PROP_TEMP
,
364 static int ltc294x_i2c_remove(struct i2c_client
*client
)
366 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
368 cancel_delayed_work(&info
->work
);
369 power_supply_unregister(info
->supply
);
373 static int ltc294x_i2c_probe(struct i2c_client
*client
,
374 const struct i2c_device_id
*id
)
376 struct power_supply_config psy_cfg
= {};
377 struct ltc294x_info
*info
;
381 struct device_node
*np
;
383 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
387 i2c_set_clientdata(client
, info
);
389 np
= of_node_get(client
->dev
.of_node
);
391 info
->num_regs
= (unsigned long)of_device_get_match_data(&client
->dev
);
392 info
->supply_desc
.name
= np
->name
;
394 /* r_sense can be negative, when sense+ is connected to the battery
395 * instead of the sense-. This results in reversed measurements. */
396 ret
= of_property_read_u32(np
, "lltc,resistor-sense", &r_sense
);
398 dev_err(&client
->dev
,
399 "Could not find lltc,resistor-sense in devicetree\n");
402 info
->r_sense
= r_sense
;
404 ret
= of_property_read_u32(np
, "lltc,prescaler-exponent",
407 dev_warn(&client
->dev
,
408 "lltc,prescaler-exponent not in devicetree\n");
409 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
412 if (info
->num_regs
== LTC2943_NUM_REGS
) {
413 if (prescaler_exp
> LTC2943_MAX_PRESCALER_EXP
)
414 prescaler_exp
= LTC2943_MAX_PRESCALER_EXP
;
415 info
->Qlsb
= ((340 * 50000) / r_sense
) /
416 (4096 / (1 << (2*prescaler_exp
)));
418 if (prescaler_exp
> LTC2941_MAX_PRESCALER_EXP
)
419 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
420 info
->Qlsb
= ((85 * 50000) / r_sense
) /
421 (128 / (1 << prescaler_exp
));
424 info
->client
= client
;
425 info
->supply_desc
.type
= POWER_SUPPLY_TYPE_BATTERY
;
426 info
->supply_desc
.properties
= ltc294x_properties
;
427 if (info
->num_regs
>= LTC294X_REG_TEMPERATURE_LSB
)
428 info
->supply_desc
.num_properties
=
429 ARRAY_SIZE(ltc294x_properties
);
430 else if (info
->num_regs
>= LTC294X_REG_CURRENT_LSB
)
431 info
->supply_desc
.num_properties
=
432 ARRAY_SIZE(ltc294x_properties
) - 1;
433 else if (info
->num_regs
>= LTC294X_REG_VOLTAGE_LSB
)
434 info
->supply_desc
.num_properties
=
435 ARRAY_SIZE(ltc294x_properties
) - 2;
437 info
->supply_desc
.num_properties
=
438 ARRAY_SIZE(ltc294x_properties
) - 3;
439 info
->supply_desc
.get_property
= ltc294x_get_property
;
440 info
->supply_desc
.set_property
= ltc294x_set_property
;
441 info
->supply_desc
.property_is_writeable
= ltc294x_property_is_writeable
;
442 info
->supply_desc
.external_power_changed
= NULL
;
444 psy_cfg
.drv_data
= info
;
446 INIT_DELAYED_WORK(&info
->work
, ltc294x_work
);
448 ret
= ltc294x_reset(info
, prescaler_exp
);
450 dev_err(&client
->dev
, "Communication with chip failed\n");
454 info
->supply
= power_supply_register(&client
->dev
, &info
->supply_desc
,
456 if (IS_ERR(info
->supply
)) {
457 dev_err(&client
->dev
, "failed to register ltc2941\n");
458 return PTR_ERR(info
->supply
);
460 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
466 #ifdef CONFIG_PM_SLEEP
468 static int ltc294x_suspend(struct device
*dev
)
470 struct i2c_client
*client
= to_i2c_client(dev
);
471 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
473 cancel_delayed_work(&info
->work
);
477 static int ltc294x_resume(struct device
*dev
)
479 struct i2c_client
*client
= to_i2c_client(dev
);
480 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
482 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
486 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops
, ltc294x_suspend
, ltc294x_resume
);
487 #define LTC294X_PM_OPS (<c294x_pm_ops)
490 #define LTC294X_PM_OPS NULL
491 #endif /* CONFIG_PM_SLEEP */
494 static const struct i2c_device_id ltc294x_i2c_id
[] = {
495 {"ltc2941", LTC2941_NUM_REGS
},
496 {"ltc2943", LTC2943_NUM_REGS
},
499 MODULE_DEVICE_TABLE(i2c
, ltc294x_i2c_id
);
501 static const struct of_device_id ltc294x_i2c_of_match
[] = {
503 .compatible
= "lltc,ltc2941",
504 .data
= (void *)LTC2941_NUM_REGS
507 .compatible
= "lltc,ltc2943",
508 .data
= (void *)LTC2943_NUM_REGS
512 MODULE_DEVICE_TABLE(of
, ltc294x_i2c_of_match
);
514 static struct i2c_driver ltc294x_driver
= {
517 .of_match_table
= ltc294x_i2c_of_match
,
518 .pm
= LTC294X_PM_OPS
,
520 .probe
= ltc294x_i2c_probe
,
521 .remove
= ltc294x_i2c_remove
,
522 .id_table
= ltc294x_i2c_id
,
524 module_i2c_driver(ltc294x_driver
);
526 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
527 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
528 MODULE_DESCRIPTION("LTC2941/LTC2943 Battery Gas Gauge IC driver");
529 MODULE_LICENSE("GPL");