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/idr.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 int num_regs
; /* Number of registers (chip type) */
66 int id
; /* Identifier of ltc294x chip */
67 int charge
; /* Last charge register content */
68 int r_sense
; /* mOhm */
72 static DEFINE_IDR(ltc294x_id
);
73 static DEFINE_MUTEX(ltc294x_lock
);
75 static inline int convert_bin_to_uAh(
76 const struct ltc294x_info
*info
, int Q
)
78 return ((Q
* (info
->Qlsb
/ 10))) / 100;
81 static inline int convert_uAh_to_bin(
82 const struct ltc294x_info
*info
, int uAh
)
86 Q
= (uAh
* 100) / (info
->Qlsb
/10);
87 return (Q
< LTC294X_MAX_VALUE
) ? Q
: LTC294X_MAX_VALUE
;
90 static int ltc294x_read_regs(struct i2c_client
*client
,
91 enum ltc294x_reg reg
, u8
*buf
, int num_regs
)
94 struct i2c_msg msgs
[2] = { };
97 msgs
[0].addr
= client
->addr
;
99 msgs
[0].buf
= ®_start
;
101 msgs
[1].addr
= client
->addr
;
102 msgs
[1].len
= num_regs
;
104 msgs
[1].flags
= I2C_M_RD
;
106 ret
= i2c_transfer(client
->adapter
, &msgs
[0], 2);
108 dev_err(&client
->dev
, "ltc2941 read_reg failed!\n");
112 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
113 __func__
, reg
, num_regs
, *buf
);
118 static int ltc294x_write_regs(struct i2c_client
*client
,
119 enum ltc294x_reg reg
, const u8
*buf
, int num_regs
)
124 ret
= i2c_smbus_write_i2c_block_data(client
, reg_start
, num_regs
, buf
);
126 dev_err(&client
->dev
, "ltc2941 write_reg failed!\n");
130 dev_dbg(&client
->dev
, "%s (%#x, %d) -> %#x\n",
131 __func__
, reg
, num_regs
, *buf
);
136 static int ltc294x_reset(const struct ltc294x_info
*info
, int prescaler_exp
)
142 /* Read status and control registers */
143 ret
= ltc294x_read_regs(info
->client
, LTC294X_REG_CONTROL
, &value
, 1);
145 dev_err(&info
->client
->dev
,
146 "Could not read registers from device\n");
150 control
= LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp
) |
151 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED
;
152 /* Put the 2943 into "monitor" mode, so it measures every 10 sec */
153 if (info
->num_regs
== LTC2943_NUM_REGS
)
154 control
|= LTC2943_REG_CONTROL_MODE_SCAN
;
156 if (value
!= control
) {
157 ret
= ltc294x_write_regs(info
->client
,
158 LTC294X_REG_CONTROL
, &control
, 1);
160 dev_err(&info
->client
->dev
,
161 "Could not write register\n");
172 static int ltc294x_read_charge_register(const struct ltc294x_info
*info
)
177 ret
= ltc294x_read_regs(info
->client
,
178 LTC294X_REG_ACC_CHARGE_MSB
, &datar
[0], 2);
181 return (datar
[0] << 8) + datar
[1];
184 static int ltc294x_get_charge_now(const struct ltc294x_info
*info
, int *val
)
186 int value
= ltc294x_read_charge_register(info
);
190 /* When r_sense < 0, this counts up when the battery discharges */
193 *val
= convert_bin_to_uAh(info
, value
);
197 static int ltc294x_set_charge_now(const struct ltc294x_info
*info
, int val
)
204 value
= convert_uAh_to_bin(info
, val
);
205 /* Direction depends on how sense+/- were connected */
208 if ((value
< 0) || (value
> 0xFFFF)) /* input validation */
211 /* Read control register */
212 ret
= ltc294x_read_regs(info
->client
,
213 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
216 /* Disable analog section */
217 ctrl_reg
|= LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
218 ret
= ltc294x_write_regs(info
->client
,
219 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
222 /* Set new charge value */
223 dataw
[0] = I16_MSB(value
);
224 dataw
[1] = I16_LSB(value
);
225 ret
= ltc294x_write_regs(info
->client
,
226 LTC294X_REG_ACC_CHARGE_MSB
, &dataw
[0], 2);
229 /* Enable analog section */
231 ctrl_reg
&= ~LTC294X_REG_CONTROL_SHUTDOWN_MASK
;
232 ret
= ltc294x_write_regs(info
->client
,
233 LTC294X_REG_CONTROL
, &ctrl_reg
, 1);
235 return ret
< 0 ? ret
: 0;
238 static int ltc294x_get_charge_counter(
239 const struct ltc294x_info
*info
, int *val
)
241 int value
= ltc294x_read_charge_register(info
);
245 value
-= LTC294X_MID_SUPPLY
;
246 *val
= convert_bin_to_uAh(info
, value
);
250 static int ltc294x_get_voltage(const struct ltc294x_info
*info
, int *val
)
256 ret
= ltc294x_read_regs(info
->client
,
257 LTC294X_REG_VOLTAGE_MSB
, &datar
[0], 2);
258 value
= (datar
[0] << 8) | datar
[1];
259 *val
= ((value
* 23600) / 0xFFFF) * 1000; /* in uV */
263 static int ltc294x_get_current(const struct ltc294x_info
*info
, int *val
)
269 ret
= ltc294x_read_regs(info
->client
,
270 LTC294X_REG_CURRENT_MSB
, &datar
[0], 2);
271 value
= (datar
[0] << 8) | datar
[1];
273 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
274 * the formula below keeps everything in s32 range while preserving
276 *val
= 1000 * ((60000 * value
) / (info
->r_sense
* 0x7FFF)); /* in uA */
280 static int ltc294x_get_temperature(const struct ltc294x_info
*info
, int *val
)
286 ret
= ltc294x_read_regs(info
->client
,
287 LTC294X_REG_TEMPERATURE_MSB
, &datar
[0], 2);
288 value
= (datar
[0] << 8) | datar
[1];
289 /* Full-scale is 510 Kelvin, convert to centidegrees */
290 *val
= (((51000 * value
) / 0xFFFF) - 27215);
294 static int ltc294x_get_property(struct power_supply
*psy
,
295 enum power_supply_property prop
,
296 union power_supply_propval
*val
)
298 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
301 case POWER_SUPPLY_PROP_CHARGE_NOW
:
302 return ltc294x_get_charge_now(info
, &val
->intval
);
303 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
304 return ltc294x_get_charge_counter(info
, &val
->intval
);
305 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
306 return ltc294x_get_voltage(info
, &val
->intval
);
307 case POWER_SUPPLY_PROP_CURRENT_NOW
:
308 return ltc294x_get_current(info
, &val
->intval
);
309 case POWER_SUPPLY_PROP_TEMP
:
310 return ltc294x_get_temperature(info
, &val
->intval
);
316 static int ltc294x_set_property(struct power_supply
*psy
,
317 enum power_supply_property psp
,
318 const union power_supply_propval
*val
)
320 struct ltc294x_info
*info
= power_supply_get_drvdata(psy
);
323 case POWER_SUPPLY_PROP_CHARGE_NOW
:
324 return ltc294x_set_charge_now(info
, val
->intval
);
330 static int ltc294x_property_is_writeable(
331 struct power_supply
*psy
, enum power_supply_property psp
)
334 case POWER_SUPPLY_PROP_CHARGE_NOW
:
341 static void ltc294x_update(struct ltc294x_info
*info
)
343 int charge
= ltc294x_read_charge_register(info
);
345 if (charge
!= info
->charge
) {
346 info
->charge
= charge
;
347 power_supply_changed(info
->supply
);
351 static void ltc294x_work(struct work_struct
*work
)
353 struct ltc294x_info
*info
;
355 info
= container_of(work
, struct ltc294x_info
, work
.work
);
356 ltc294x_update(info
);
357 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
360 static enum power_supply_property ltc294x_properties
[] = {
361 POWER_SUPPLY_PROP_CHARGE_COUNTER
,
362 POWER_SUPPLY_PROP_CHARGE_NOW
,
363 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
364 POWER_SUPPLY_PROP_CURRENT_NOW
,
365 POWER_SUPPLY_PROP_TEMP
,
368 static int ltc294x_i2c_remove(struct i2c_client
*client
)
370 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
372 cancel_delayed_work(&info
->work
);
373 power_supply_unregister(info
->supply
);
374 kfree(info
->supply_desc
.name
);
375 mutex_lock(<c294x_lock
);
376 idr_remove(<c294x_id
, info
->id
);
377 mutex_unlock(<c294x_lock
);
381 static int ltc294x_i2c_probe(struct i2c_client
*client
,
382 const struct i2c_device_id
*id
)
384 struct power_supply_config psy_cfg
= {};
385 struct ltc294x_info
*info
;
390 struct device_node
*np
;
392 mutex_lock(<c294x_lock
);
393 ret
= idr_alloc(<c294x_id
, client
, 0, 0, GFP_KERNEL
);
394 mutex_unlock(<c294x_lock
);
400 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
406 i2c_set_clientdata(client
, info
);
408 info
->num_regs
= id
->driver_data
;
409 info
->supply_desc
.name
= kasprintf(GFP_KERNEL
, "%s-%d", client
->name
,
411 if (!info
->supply_desc
.name
) {
416 np
= of_node_get(client
->dev
.of_node
);
418 /* r_sense can be negative, when sense+ is connected to the battery
419 * instead of the sense-. This results in reversed measurements. */
420 ret
= of_property_read_u32(np
, "lltc,resistor-sense", &r_sense
);
422 dev_err(&client
->dev
,
423 "Could not find lltc,resistor-sense in devicetree\n");
426 info
->r_sense
= r_sense
;
428 ret
= of_property_read_u32(np
, "lltc,prescaler-exponent",
431 dev_warn(&client
->dev
,
432 "lltc,prescaler-exponent not in devicetree\n");
433 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
436 if (info
->num_regs
== LTC2943_NUM_REGS
) {
437 if (prescaler_exp
> LTC2943_MAX_PRESCALER_EXP
)
438 prescaler_exp
= LTC2943_MAX_PRESCALER_EXP
;
439 info
->Qlsb
= ((340 * 50000) / r_sense
) /
440 (4096 / (1 << (2*prescaler_exp
)));
442 if (prescaler_exp
> LTC2941_MAX_PRESCALER_EXP
)
443 prescaler_exp
= LTC2941_MAX_PRESCALER_EXP
;
444 info
->Qlsb
= ((85 * 50000) / r_sense
) /
445 (128 / (1 << prescaler_exp
));
448 info
->client
= client
;
450 info
->supply_desc
.type
= POWER_SUPPLY_TYPE_BATTERY
;
451 info
->supply_desc
.properties
= ltc294x_properties
;
452 if (info
->num_regs
>= LTC294X_REG_TEMPERATURE_LSB
)
453 info
->supply_desc
.num_properties
=
454 ARRAY_SIZE(ltc294x_properties
);
455 else if (info
->num_regs
>= LTC294X_REG_CURRENT_LSB
)
456 info
->supply_desc
.num_properties
=
457 ARRAY_SIZE(ltc294x_properties
) - 1;
458 else if (info
->num_regs
>= LTC294X_REG_VOLTAGE_LSB
)
459 info
->supply_desc
.num_properties
=
460 ARRAY_SIZE(ltc294x_properties
) - 2;
462 info
->supply_desc
.num_properties
=
463 ARRAY_SIZE(ltc294x_properties
) - 3;
464 info
->supply_desc
.get_property
= ltc294x_get_property
;
465 info
->supply_desc
.set_property
= ltc294x_set_property
;
466 info
->supply_desc
.property_is_writeable
= ltc294x_property_is_writeable
;
467 info
->supply_desc
.external_power_changed
= NULL
;
469 psy_cfg
.drv_data
= info
;
471 INIT_DELAYED_WORK(&info
->work
, ltc294x_work
);
473 ret
= ltc294x_reset(info
, prescaler_exp
);
475 dev_err(&client
->dev
, "Communication with chip failed\n");
479 info
->supply
= power_supply_register(&client
->dev
, &info
->supply_desc
,
481 if (IS_ERR(info
->supply
)) {
482 dev_err(&client
->dev
, "failed to register ltc2941\n");
483 ret
= PTR_ERR(info
->supply
);
486 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
492 kfree(info
->supply_desc
.name
);
496 mutex_lock(<c294x_lock
);
497 idr_remove(<c294x_id
, num
);
498 mutex_unlock(<c294x_lock
);
503 #ifdef CONFIG_PM_SLEEP
505 static int ltc294x_suspend(struct device
*dev
)
507 struct i2c_client
*client
= to_i2c_client(dev
);
508 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
510 cancel_delayed_work(&info
->work
);
514 static int ltc294x_resume(struct device
*dev
)
516 struct i2c_client
*client
= to_i2c_client(dev
);
517 struct ltc294x_info
*info
= i2c_get_clientdata(client
);
519 schedule_delayed_work(&info
->work
, LTC294X_WORK_DELAY
* HZ
);
523 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops
, ltc294x_suspend
, ltc294x_resume
);
524 #define LTC294X_PM_OPS (<c294x_pm_ops)
527 #define LTC294X_PM_OPS NULL
528 #endif /* CONFIG_PM_SLEEP */
531 static const struct i2c_device_id ltc294x_i2c_id
[] = {
532 {"ltc2941", LTC2941_NUM_REGS
},
533 {"ltc2943", LTC2943_NUM_REGS
},
536 MODULE_DEVICE_TABLE(i2c
, ltc294x_i2c_id
);
538 static struct i2c_driver ltc294x_driver
= {
541 .pm
= LTC294X_PM_OPS
,
543 .probe
= ltc294x_i2c_probe
,
544 .remove
= ltc294x_i2c_remove
,
545 .id_table
= ltc294x_i2c_id
,
547 module_i2c_driver(ltc294x_driver
);
549 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
550 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
551 MODULE_DESCRIPTION("LTC2941/LTC2943 Battery Gas Gauge IC driver");
552 MODULE_LICENSE("GPL");