aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGrazvydas Ignotas <notasas@gmail.com>2010-02-27 10:06:09 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2010-02-27 10:09:23 -0500
commit4e924a814ac78e325653840190e9e4762e6f4b7c (patch)
tree228d81e5ada34293912a457d511c946eb22bb3c4 /drivers
parente20908d95e89d04b9537aefecc0734d2e4f7faed (diff)
power_supply: bq27x00: add status and time properties
The BQ27x00 series of chips can report time-to-empty and time-to-full, so let's add corresponding properties. Also report charge status based on status flag register. Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/bq27x00_battery.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 1526d020cbc6..5d940fad8d43 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -32,10 +32,16 @@
32#define BQ27x00_REG_VOLT 0x08 32#define BQ27x00_REG_VOLT 0x08
33#define BQ27x00_REG_AI 0x14 33#define BQ27x00_REG_AI 0x14
34#define BQ27x00_REG_FLAGS 0x0A 34#define BQ27x00_REG_FLAGS 0x0A
35#define BQ27x00_REG_TTE 0x16
36#define BQ27x00_REG_TTF 0x18
37#define BQ27x00_REG_TTECP 0x26
35 38
36#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ 39#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
40#define BQ27000_FLAG_CHGS BIT(7)
37 41
38#define BQ27500_REG_SOC 0x2c 42#define BQ27500_REG_SOC 0x2c
43#define BQ27500_FLAG_DSC BIT(0)
44#define BQ27500_FLAG_FC BIT(9)
39 45
40/* If the system has several batteries we need a different name for each 46/* If the system has several batteries we need a different name for each
41 * of them... 47 * of them...
@@ -62,11 +68,15 @@ struct bq27x00_device_info {
62}; 68};
63 69
64static enum power_supply_property bq27x00_battery_props[] = { 70static enum power_supply_property bq27x00_battery_props[] = {
71 POWER_SUPPLY_PROP_STATUS,
65 POWER_SUPPLY_PROP_PRESENT, 72 POWER_SUPPLY_PROP_PRESENT,
66 POWER_SUPPLY_PROP_VOLTAGE_NOW, 73 POWER_SUPPLY_PROP_VOLTAGE_NOW,
67 POWER_SUPPLY_PROP_CURRENT_NOW, 74 POWER_SUPPLY_PROP_CURRENT_NOW,
68 POWER_SUPPLY_PROP_CAPACITY, 75 POWER_SUPPLY_PROP_CAPACITY,
69 POWER_SUPPLY_PROP_TEMP, 76 POWER_SUPPLY_PROP_TEMP,
77 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
78 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
79 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
70}; 80};
71 81
72/* 82/*
@@ -144,7 +154,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
144 dev_err(di->dev, "error reading flags\n"); 154 dev_err(di->dev, "error reading flags\n");
145 return 0; 155 return 0;
146 } 156 }
147 if ((flags & (1 << 7)) != 0) { 157 if (flags & BQ27000_FLAG_CHGS) {
148 dev_dbg(di->dev, "negative current!\n"); 158 dev_dbg(di->dev, "negative current!\n");
149 return -curr; 159 return -curr;
150 } 160 }
@@ -174,6 +184,60 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
174 return rsoc; 184 return rsoc;
175} 185}
176 186
187static int bq27x00_battery_status(struct bq27x00_device_info *di,
188 union power_supply_propval *val)
189{
190 int flags = 0;
191 int status;
192 int ret;
193
194 ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
195 if (ret < 0) {
196 dev_err(di->dev, "error reading flags\n");
197 return ret;
198 }
199
200 if (di->chip == BQ27500) {
201 if (flags & BQ27500_FLAG_FC)
202 status = POWER_SUPPLY_STATUS_FULL;
203 else if (flags & BQ27500_FLAG_DSC)
204 status = POWER_SUPPLY_STATUS_DISCHARGING;
205 else
206 status = POWER_SUPPLY_STATUS_CHARGING;
207 } else {
208 if (flags & BQ27000_FLAG_CHGS)
209 status = POWER_SUPPLY_STATUS_CHARGING;
210 else
211 status = POWER_SUPPLY_STATUS_DISCHARGING;
212 }
213
214 val->intval = status;
215 return 0;
216}
217
218/*
219 * Read a time register.
220 * Return < 0 if something fails.
221 */
222static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,
223 union power_supply_propval *val)
224{
225 int tval = 0;
226 int ret;
227
228 ret = bq27x00_read(reg, &tval, 0, di);
229 if (ret) {
230 dev_err(di->dev, "error reading register %02x\n", reg);
231 return ret;
232 }
233
234 if (tval == 65535)
235 return -ENODATA;
236
237 val->intval = tval * 60;
238 return 0;
239}
240
177#define to_bq27x00_device_info(x) container_of((x), \ 241#define to_bq27x00_device_info(x) container_of((x), \
178 struct bq27x00_device_info, bat); 242 struct bq27x00_device_info, bat);
179 243
@@ -181,9 +245,13 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
181 enum power_supply_property psp, 245 enum power_supply_property psp,
182 union power_supply_propval *val) 246 union power_supply_propval *val)
183{ 247{
248 int ret = 0;
184 struct bq27x00_device_info *di = to_bq27x00_device_info(psy); 249 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
185 250
186 switch (psp) { 251 switch (psp) {
252 case POWER_SUPPLY_PROP_STATUS:
253 ret = bq27x00_battery_status(di, val);
254 break;
187 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 255 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
188 case POWER_SUPPLY_PROP_PRESENT: 256 case POWER_SUPPLY_PROP_PRESENT:
189 val->intval = bq27x00_battery_voltage(di); 257 val->intval = bq27x00_battery_voltage(di);
@@ -199,11 +267,20 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
199 case POWER_SUPPLY_PROP_TEMP: 267 case POWER_SUPPLY_PROP_TEMP:
200 val->intval = bq27x00_battery_temperature(di); 268 val->intval = bq27x00_battery_temperature(di);
201 break; 269 break;
270 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
271 ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);
272 break;
273 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
274 ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);
275 break;
276 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
277 ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);
278 break;
202 default: 279 default:
203 return -EINVAL; 280 return -EINVAL;
204 } 281 }
205 282
206 return 0; 283 return ret;
207} 284}
208 285
209static void bq27x00_powersupply_init(struct bq27x00_device_info *di) 286static void bq27x00_powersupply_init(struct bq27x00_device_info *di)