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/types.h>
13 #include <linux/errno.h>
14 #include <linux/swab.h>
15 #include <linux/i2c.h>
16 #include <linux/delay.h>
17 #include <linux/power_supply.h>
18 #include <linux/slab.h>
20 #define I16_MSB(x) ((x >> 8) & 0xFF)
21 #define I16_LSB(x) (x & 0xFF)
23 #define LTC294X_WORK_DELAY 10 /* Update delay in seconds */
25 #define LTC294X_MAX_VALUE 0xFFFF
26 #define LTC294X_MID_SUPPLY 0x7FFF
28 #define LTC2941_MAX_PRESCALER_EXP 7
29 #define LTC2943_MAX_PRESCALER_EXP 6
32 LTC294X_REG_STATUS
= 0x00,
33 LTC294X_REG_CONTROL
= 0x01,
34 LTC294X_REG_ACC_CHARGE_MSB
= 0x02,
35 LTC294X_REG_ACC_CHARGE_LSB
= 0x03,
36 LTC294X_REG_THRESH_HIGH_MSB
= 0x04,
37 LTC294X_REG_THRESH_HIGH_LSB
= 0x05,
38 LTC294X_REG_THRESH_LOW_MSB
= 0x06,
39 LTC294X_REG_THRESH_LOW_LSB
= 0x07,
40 LTC294X_REG_VOLTAGE_MSB
= 0x08,
41 LTC294X_REG_VOLTAGE_LSB
= 0x09,
42 LTC294X_REG_CURRENT_MSB
= 0x0E,
43 LTC294X_REG_CURRENT_LSB
= 0x0F,
44 LTC294X_REG_TEMPERATURE_MSB
= 0x14,
45 LTC294X_REG_TEMPERATURE_LSB
= 0x15,
48 #define LTC2943_REG_CONTROL_MODE_MASK (BIT(7) | BIT(6))
49 #define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
50 #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3))
51 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0))
52 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
53 ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
54 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
56 #define LTC2941_NUM_REGS 0x08
57 #define LTC2943_NUM_REGS 0x18
60 struct i2c_client
*client
; /* I2C Client pointer */
61 struct power_supply
*supply
; /* Supply pointer */
62 struct power_supply_desc supply_desc
; /* Supply description */
63 struct delayed_work work
; /* Work scheduler */
64 int num_regs
; /* Number of registers (chip type) */
65 int charge
; /* Last charge register content */
66 int r_sense
; /* mOhm */
70 static inline int convert_bin_to_uAh(
71 const struct ltc294x_info
*info
, int Q
)
73 return ((Q
* (info
->Qlsb
/ 10))) / 100;
76 static inline int convert_uAh_to_bin(
77 const struct ltc294x_info
*info
, int uAh
)
81 Q
= (uAh
* 100) / (info
->Qlsb
/10);
82 return (Q
< LTC294X_MAX_VALUE
) ? Q
: LTC294X_MAX_VALUE
;
85 static int ltc294x_read_regs(struct i2c_client
*client
,
86 enum ltc294x_reg reg
, u8
*buf
, int num_regs
)
89 struct i2c_msg msgs
[2] = { };
92 msgs
[0].addr
= client
->addr
;
94 msgs
[0].buf
= ®_start
;
96 msgs
[1].addr
= client
->addr
;
97 msgs
[1].len
= num_regs
;
99 msgs
[1].flags
= I2C_M_RD
;
101 ret
= i2c_transfer(client
->adapter
, &msgs
[0], 2);
103 dev_err(&client
->dev
, "ltc2941 read_reg failed!\n");
107 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
108 __func__
, reg
, num_regs
, *buf
);
113 static int ltc294x_write_regs(struct i2c_client
*client
,
114 enum ltc294x_reg reg
, const u8
*buf
, int num_regs
)
119 ret
= i2c_smbus_write_i2c_block_data(client
, reg_start
, num_regs
, buf
);
121 dev_err(&client
->dev
, "ltc2941 write_reg failed!\n");
125 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
126 __func__
, reg
, num_regs
, *buf
);
131 static int ltc294x_reset(const struct ltc294x_info
*info
, int prescaler_exp
)
137 /* Read status and control registers */
138 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
140 dev_err(&info
->client
->dev
,
141 "Could not read registers from device\n");
145 control
= LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp
) |
146 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED
;
147 /* Put the 2943 into "monitor" mode, so it measures every 10 sec */
148 if (info
->num_regs
== LTC2943_NUM_REGS
)
149 control
|= LTC2943_REG_CONTROL_MODE_SCAN
;
151 if (value
!= control
) {
152 ret
= ltc294x_write_regs(info
->client
,
153 LTC294X_REG_CONTROL
, &control
, 1);
155 dev_err(&info
->client
->dev
,
156 "Could not write register\n");
167 static int ltc294x_read_charge_register(const struct ltc294x_info
*info
)
172 ret
= ltc294x_read_regs(info
->client
,
173 LTC294X_REG_ACC_CHARGE_MSB
, &datar
[0], 2);
176 return (datar
[0] << 8) + datar
[1];
179 static int ltc294x_get_charge_now(const struct ltc294x_info
*info
, int *val
)
181 int value
= ltc294x_read_charge_register(info
);
185 /* When r_sense < 0, this counts up when the battery discharges */
188 *val
= convert_bin_to_uAh(info
, value
);
192 static int ltc294x_set_charge_now(const struct ltc294x_info
*info
, int val
)
199 value
= convert_uAh_to_bin(info
, val
);
200 /* Direction depends on how sense+/- were connected */
203 if ((value
< 0) || (value
> 0xFFFF)) /* input validation */
206 /* Read control register */
207 ret
= ltc294x_read_regs(info
->client
,
208 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
211 /* Disable analog section */
212 ctrl_reg
|= LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
213 ret
= ltc294x_write_regs(info
->client
,
214 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
217 /* Set new charge value */
218 dataw
[0] = I16_MSB(value
);
219 dataw
[1] = I16_LSB(value
);
220 ret
= ltc294x_write_regs(info
->client
,
221 LTC294X_REG_ACC_CHARGE_MSB
, &dataw
[0], 2);
224 /* Enable analog section */
226 ctrl_reg
&= ~LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
227 ret
= ltc294x_write_regs(info
->client
,
228 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
230 return ret
< 0 ? ret
: 0;
233 static int ltc294x_get_charge_counter(
234 const struct ltc294x_info
*info
, int *val
)
236 int value
= ltc294x_read_charge_register(info
);
240 value
-= LTC294X_MID_SUPPLY
;
241 *val
= convert_bin_to_uAh(info
, value
);
245 static int ltc294x_get_voltage(const struct ltc294x_info
*info
, int *val
)
251 ret
= ltc294x_read_regs(info
->client
,
252 LTC294X_REG_VOLTAGE_MSB
, &datar
[0], 2);
253 value
= (datar
[0] << 8) | datar
[1];
254 *val
= ((value
* 23600) / 0xFFFF) * 1000; /* in uV */
258 static int ltc294x_get_current(const struct ltc294x_info
*info
, int *val
)
264 ret
= ltc294x_read_regs(info
->client
,
265 LTC294X_REG_CURRENT_MSB
, &datar
[0], 2);
266 value
= (datar
[0] << 8) | datar
[1];
268 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
269 * the formula below keeps everything in s32 range while preserving
271 *val
= 1000 * ((60000 * value
) / (info
->r_sense
* 0x7FFF)); /* in uA */
275 static int ltc294x_get_temperature(const struct ltc294x_info
*info
, int *val
)
281 ret
= ltc294x_read_regs(info
->client
,
282 LTC294X_REG_TEMPERATURE_MSB
, &datar
[0], 2);
283 value
= (datar
[0] << 8) | datar
[1];
284 /* Full-scale is 510 Kelvin, convert to centidegrees */
285 *val
= (((51000 * value
) / 0xFFFF) - 27215);
289 static int ltc294x_get_property(struct power_supply
*psy
,
290 enum power_supply_property prop
,
291 union power_supply_propval
*val
)
293 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
296 case POWER_SUPPLY_PROP_CHARGE_NOW
:
297 return ltc294x_get_charge_now(info
, &val
->intval
);
298 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
299 return ltc294x_get_charge_counter(info
, &val
->intval
);
300 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
301 return ltc294x_get_voltage(info
, &val
->intval
);
302 case POWER_SUPPLY_PROP_CURRENT_NOW
:
303 return ltc294x_get_current(info
, &val
->intval
);
304 case POWER_SUPPLY_PROP_TEMP
:
305 return ltc294x_get_temperature(info
, &val
->intval
);
311 static int ltc294x_set_property(struct power_supply
*psy
,
312 enum power_supply_property psp
,
313 const union power_supply_propval
*val
)
315 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
318 case POWER_SUPPLY_PROP_CHARGE_NOW
:
319 return ltc294x_set_charge_now(info
, val
->intval
);
325 static int ltc294x_property_is_writeable(
326 struct power_supply
*psy
, enum power_supply_property psp
)
329 case POWER_SUPPLY_PROP_CHARGE_NOW
:
336 static void ltc294x_update(struct ltc294x_info
*info
)
338 int charge
= ltc294x_read_charge_register(info
);
340 if (charge
!= info
->charge
) {
341 info
->charge
= charge
;
342 power_supply_changed(info
->supply
);
346 static void ltc294x_work(struct work_struct
*work
)
348 struct ltc294x_info
*info
;
350 info
= container_of(work
, struct ltc294x_info
, work
.work
);
351 ltc294x_update(info
);
352 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
355 static enum power_supply_property ltc294x_properties
[] = {
356 POWER_SUPPLY_PROP_CHARGE_COUNTER
,
357 POWER_SUPPLY_PROP_CHARGE_NOW
,
358 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
359 POWER_SUPPLY_PROP_CURRENT_NOW
,
360 POWER_SUPPLY_PROP_TEMP
,
363 static int ltc294x_i2c_remove(struct i2c_client
*client
)
365 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
367 cancel_delayed_work(&info
->work
);
368 power_supply_unregister(info
->supply
);
372 static int ltc294x_i2c_probe(struct i2c_client
*client
,
373 const struct i2c_device_id
*id
)
375 struct power_supply_config psy_cfg
= {};
376 struct ltc294x_info
*info
;
380 struct device_node
*np
;
382 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
386 i2c_set_clientdata(client
, info
);
388 np
= of_node_get(client
->dev
.of_node
);
390 info
->num_regs
= id
->driver_data
;
391 info
->supply_desc
.name
= np
->name
;
393 /* r_sense can be negative, when sense+ is connected to the battery
394 * instead of the sense-. This results in reversed measurements. */
395 ret
= of_property_read_u32(np
, "lltc,resistor-sense", &r_sense
);
397 dev_err(&client
->dev
,
398 "Could not find lltc,resistor-sense in devicetree\n");
401 info
->r_sense
= r_sense
;
403 ret
= of_property_read_u32(np
, "lltc,prescaler-exponent",
406 dev_warn(&client
->dev
,
407 "lltc,prescaler-exponent not in devicetree\n");
408 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
411 if (info
->num_regs
== LTC2943_NUM_REGS
) {
412 if (prescaler_exp
> LTC2943_MAX_PRESCALER_EXP
)
413 prescaler_exp
= LTC2943_MAX_PRESCALER_EXP
;
414 info
->Qlsb
= ((340 * 50000) / r_sense
) /
415 (4096 / (1 << (2*prescaler_exp
)));
417 if (prescaler_exp
> LTC2941_MAX_PRESCALER_EXP
)
418 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
419 info
->Qlsb
= ((85 * 50000) / r_sense
) /
420 (128 / (1 << prescaler_exp
));
423 info
->client
= client
;
424 info
->supply_desc
.type
= POWER_SUPPLY_TYPE_BATTERY
;
425 info
->supply_desc
.properties
= ltc294x_properties
;
426 if (info
->num_regs
>= LTC294X_REG_TEMPERATURE_LSB
)
427 info
->supply_desc
.num_properties
=
428 ARRAY_SIZE(ltc294x_properties
);
429 else if (info
->num_regs
>= LTC294X_REG_CURRENT_LSB
)
430 info
->supply_desc
.num_properties
=
431 ARRAY_SIZE(ltc294x_properties
) - 1;
432 else if (info
->num_regs
>= LTC294X_REG_VOLTAGE_LSB
)
433 info
->supply_desc
.num_properties
=
434 ARRAY_SIZE(ltc294x_properties
) - 2;
436 info
->supply_desc
.num_properties
=
437 ARRAY_SIZE(ltc294x_properties
) - 3;
438 info
->supply_desc
.get_property
= ltc294x_get_property
;
439 info
->supply_desc
.set_property
= ltc294x_set_property
;
440 info
->supply_desc
.property_is_writeable
= ltc294x_property_is_writeable
;
441 info
->supply_desc
.external_power_changed
= NULL
;
443 psy_cfg
.drv_data
= info
;
445 INIT_DELAYED_WORK(&info
->work
, ltc294x_work
);
447 ret
= ltc294x_reset(info
, prescaler_exp
);
449 dev_err(&client
->dev
, "Communication with chip failed\n");
453 info
->supply
= power_supply_register(&client
->dev
, &info
->supply_desc
,
455 if (IS_ERR(info
->supply
)) {
456 dev_err(&client
->dev
, "failed to register ltc2941\n");
457 return PTR_ERR(info
->supply
);
459 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
465 #ifdef CONFIG_PM_SLEEP
467 static int ltc294x_suspend(struct device
*dev
)
469 struct i2c_client
*client
= to_i2c_client(dev
);
470 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
472 cancel_delayed_work(&info
->work
);
476 static int ltc294x_resume(struct device
*dev
)
478 struct i2c_client
*client
= to_i2c_client(dev
);
479 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
481 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
485 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops
, ltc294x_suspend
, ltc294x_resume
);
486 #define LTC294X_PM_OPS (<c294x_pm_ops)
489 #define LTC294X_PM_OPS NULL
490 #endif /* CONFIG_PM_SLEEP */
493 static const struct i2c_device_id ltc294x_i2c_id
[] = {
494 {"ltc2941", LTC2941_NUM_REGS
},
495 {"ltc2943", LTC2943_NUM_REGS
},
498 MODULE_DEVICE_TABLE(i2c
, ltc294x_i2c_id
);
500 static struct i2c_driver ltc294x_driver
= {
503 .pm
= LTC294X_PM_OPS
,
505 .probe
= ltc294x_i2c_probe
,
506 .remove
= ltc294x_i2c_remove
,
507 .id_table
= ltc294x_i2c_id
,
509 module_i2c_driver(ltc294x_driver
);
511 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
512 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
513 MODULE_DESCRIPTION("LTC2941/LTC2943 Battery Gas Gauge IC driver");
514 MODULE_LICENSE("GPL");