aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2011-01-31 18:08:02 -0500
committerLars-Peter Clausen <lars@metafoo.de>2011-02-22 05:02:44 -0500
commit631c17ee5daf0ca73688cb5e5216fc0e3e340483 (patch)
tree5e61bbbd7e2b62a0aa75ddfa8eca087528de7e7a /drivers/power
parent740b755a3b3433f5ee5f9ef54de5d1b4c08223cc (diff)
bq27x00: Add new properties
This patch add support for reporting properties POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_ENERGY_NOW in module bq27x00_battery. Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Tested-by: Grazvydas Ignotas <notasas@gmail.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/bq27x00_battery.c152
1 files changed, 151 insertions, 1 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 25350fcbadb3..a1bd1ff753b3 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -16,6 +16,13 @@
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 * 17 *
18 */ 18 */
19
20/*
21 * Datasheets:
22 * http://focus.ti.com/docs/prod/folders/print/bq27000.html
23 * http://focus.ti.com/docs/prod/folders/print/bq27500.html
24 */
25
19#include <linux/module.h> 26#include <linux/module.h>
20#include <linux/param.h> 27#include <linux/param.h>
21#include <linux/jiffies.h> 28#include <linux/jiffies.h>
@@ -30,7 +37,7 @@
30 37
31#include <linux/power/bq27x00_battery.h> 38#include <linux/power/bq27x00_battery.h>
32 39
33#define DRIVER_VERSION "1.1.0" 40#define DRIVER_VERSION "1.2.0"
34 41
35#define BQ27x00_REG_TEMP 0x06 42#define BQ27x00_REG_TEMP 0x06
36#define BQ27x00_REG_VOLT 0x08 43#define BQ27x00_REG_VOLT 0x08
@@ -39,11 +46,17 @@
39#define BQ27x00_REG_TTE 0x16 46#define BQ27x00_REG_TTE 0x16
40#define BQ27x00_REG_TTF 0x18 47#define BQ27x00_REG_TTF 0x18
41#define BQ27x00_REG_TTECP 0x26 48#define BQ27x00_REG_TTECP 0x26
49#define BQ27x00_REG_NAC 0x0C /* Nominal available capaciy */
50#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */
51#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */
52#define BQ27x00_REG_AE 0x22 /* Available enery */
42 53
43#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ 54#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
55#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
44#define BQ27000_FLAG_CHGS BIT(7) 56#define BQ27000_FLAG_CHGS BIT(7)
45 57
46#define BQ27500_REG_SOC 0x2c 58#define BQ27500_REG_SOC 0x2c
59#define BQ27500_REG_DCAP 0x3C /* Design capacity */
47#define BQ27500_FLAG_DSC BIT(0) 60#define BQ27500_FLAG_DSC BIT(0)
48#define BQ27500_FLAG_FC BIT(9) 61#define BQ27500_FLAG_FC BIT(9)
49 62
@@ -61,6 +74,8 @@ struct bq27x00_reg_cache {
61 int time_to_empty; 74 int time_to_empty;
62 int time_to_empty_avg; 75 int time_to_empty_avg;
63 int time_to_full; 76 int time_to_full;
77 int charge_full;
78 int charge_counter;
64 int capacity; 79 int capacity;
65 int flags; 80 int flags;
66 81
@@ -73,6 +88,8 @@ struct bq27x00_device_info {
73 enum bq27x00_chip chip; 88 enum bq27x00_chip chip;
74 89
75 struct bq27x00_reg_cache cache; 90 struct bq27x00_reg_cache cache;
91 int charge_design_full;
92
76 unsigned long last_update; 93 unsigned long last_update;
77 struct delayed_work work; 94 struct delayed_work work;
78 95
@@ -94,6 +111,11 @@ static enum power_supply_property bq27x00_battery_props[] = {
94 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 111 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
95 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 112 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
96 POWER_SUPPLY_PROP_TECHNOLOGY, 113 POWER_SUPPLY_PROP_TECHNOLOGY,
114 POWER_SUPPLY_PROP_CHARGE_FULL,
115 POWER_SUPPLY_PROP_CHARGE_NOW,
116 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
117 POWER_SUPPLY_PROP_CHARGE_COUNTER,
118 POWER_SUPPLY_PROP_ENERGY_NOW,
97}; 119};
98 120
99static unsigned int poll_interval = 360; 121static unsigned int poll_interval = 360;
@@ -131,6 +153,87 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
131} 153}
132 154
133/* 155/*
156 * Return a battery charge value in µAh
157 * Or < 0 if something fails.
158 */
159static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
160{
161 int charge;
162
163 charge = bq27x00_read(di, reg, false);
164 if (charge < 0) {
165 dev_err(di->dev, "error reading nominal available capacity\n");
166 return charge;
167 }
168
169 if (di->chip == BQ27500)
170 charge *= 1000;
171 else
172 charge = charge * 3570 / BQ27000_RS;
173
174 return charge;
175}
176
177/*
178 * Return the battery Nominal available capaciy in µAh
179 * Or < 0 if something fails.
180 */
181static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
182{
183 return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
184}
185
186/*
187 * Return the battery Last measured discharge in µAh
188 * Or < 0 if something fails.
189 */
190static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)
191{
192 return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);
193}
194
195/*
196 * Return the battery Initial last measured discharge in µAh
197 * Or < 0 if something fails.
198 */
199static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
200{
201 int ilmd;
202
203 if (di->chip == BQ27500)
204 ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
205 else
206 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
207
208 if (ilmd < 0) {
209 dev_err(di->dev, "error reading initial last measured discharge\n");
210 return ilmd;
211 }
212
213 if (di->chip == BQ27500)
214 ilmd *= 1000;
215 else
216 ilmd = ilmd * 256 * 3570 / BQ27000_RS;
217
218 return ilmd;
219}
220
221/*
222 * Return the battery Cycle count total
223 * Or < 0 if something fails.
224 */
225static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
226{
227 int cyct;
228
229 cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
230 if (cyct < 0)
231 dev_err(di->dev, "error reading cycle count total\n");
232
233 return cyct;
234}
235
236/*
134 * Read a time register. 237 * Read a time register.
135 * Return < 0 if something fails. 238 * Return < 0 if something fails.
136 */ 239 */
@@ -162,9 +265,15 @@ static void bq27x00_update(struct bq27x00_device_info *di)
162 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); 265 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
163 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); 266 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
164 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); 267 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
268 cache.charge_full = bq27x00_battery_read_lmd(di);
269 cache.charge_counter = bq27x00_battery_read_cyct(di);
165 270
166 if (!is_bq27500) 271 if (!is_bq27500)
167 cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); 272 cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
273
274 /* We only have to read charge design full once */
275 if (di->charge_design_full <= 0)
276 di->charge_design_full = bq27x00_battery_read_ilmd(di);
168 } 277 }
169 278
170 /* Ignore current_now which is a snapshot of the current battery state 279 /* Ignore current_now which is a snapshot of the current battery state
@@ -285,6 +394,32 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
285 return 0; 394 return 0;
286} 395}
287 396
397/*
398 * Return the battery Available energy in µWh
399 * Or < 0 if something fails.
400 */
401static int bq27x00_battery_energy(struct bq27x00_device_info *di,
402 union power_supply_propval *val)
403{
404 int ae;
405
406 ae = bq27x00_read(di, BQ27x00_REG_AE, false);
407 if (ae < 0) {
408 dev_err(di->dev, "error reading available energy\n");
409 return ae;
410 }
411
412 if (di->chip == BQ27500)
413 ae *= 1000;
414 else
415 ae = ae * 29200 / BQ27000_RS;
416
417 val->intval = ae;
418
419 return 0;
420}
421
422
288static int bq27x00_simple_value(int value, 423static int bq27x00_simple_value(int value,
289 union power_supply_propval *val) 424 union power_supply_propval *val)
290{ 425{
@@ -347,6 +482,21 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
347 case POWER_SUPPLY_PROP_TECHNOLOGY: 482 case POWER_SUPPLY_PROP_TECHNOLOGY:
348 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 483 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
349 break; 484 break;
485 case POWER_SUPPLY_PROP_CHARGE_NOW:
486 ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);
487 break;
488 case POWER_SUPPLY_PROP_CHARGE_FULL:
489 ret = bq27x00_simple_value(di->cache.charge_full, val);
490 break;
491 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
492 ret = bq27x00_simple_value(di->charge_design_full, val);
493 break;
494 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
495 ret = bq27x00_simple_value(di->cache.charge_counter, val);
496 break;
497 case POWER_SUPPLY_PROP_ENERGY_NOW:
498 ret = bq27x00_battery_energy(di, val);
499 break;
350 default: 500 default:
351 return -EINVAL; 501 return -EINVAL;
352 } 502 }