diff options
author | Grazvydas Ignotas <notasas@gmail.com> | 2010-02-27 10:06:09 -0500 |
---|---|---|
committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2010-02-27 10:09:23 -0500 |
commit | 4e924a814ac78e325653840190e9e4762e6f4b7c (patch) | |
tree | 228d81e5ada34293912a457d511c946eb22bb3c4 /drivers/power | |
parent | e20908d95e89d04b9537aefecc0734d2e4f7faed (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/power')
-rw-r--r-- | drivers/power/bq27x00_battery.c | 81 |
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 | ||
64 | static enum power_supply_property bq27x00_battery_props[] = { | 70 | static 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 | ||
187 | static 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 | */ | ||
222 | static 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 | ||
209 | static void bq27x00_powersupply_init(struct bq27x00_device_info *di) | 286 | static void bq27x00_powersupply_init(struct bq27x00_device_info *di) |