diff options
Diffstat (limited to 'drivers/power/olpc_battery.c')
-rw-r--r-- | drivers/power/olpc_battery.c | 114 |
1 files changed, 111 insertions, 3 deletions
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 5bc1dcf7785e..0b0ff3a936a6 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c | |||
@@ -201,6 +201,72 @@ static int olpc_bat_get_tech(union power_supply_propval *val) | |||
201 | return ret; | 201 | return ret; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int olpc_bat_get_charge_full_design(union power_supply_propval *val) | ||
205 | { | ||
206 | uint8_t ec_byte; | ||
207 | union power_supply_propval tech; | ||
208 | int ret, mfr; | ||
209 | |||
210 | ret = olpc_bat_get_tech(&tech); | ||
211 | if (ret) | ||
212 | return ret; | ||
213 | |||
214 | ec_byte = BAT_ADDR_MFR_TYPE; | ||
215 | ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); | ||
216 | if (ret) | ||
217 | return ret; | ||
218 | |||
219 | mfr = ec_byte >> 4; | ||
220 | |||
221 | switch (tech.intval) { | ||
222 | case POWER_SUPPLY_TECHNOLOGY_NiMH: | ||
223 | switch (mfr) { | ||
224 | case 1: /* Gold Peak */ | ||
225 | val->intval = 3000000*.8; | ||
226 | break; | ||
227 | default: | ||
228 | return -EIO; | ||
229 | } | ||
230 | break; | ||
231 | |||
232 | case POWER_SUPPLY_TECHNOLOGY_LiFe: | ||
233 | switch (mfr) { | ||
234 | case 1: /* Gold Peak */ | ||
235 | val->intval = 2800000; | ||
236 | break; | ||
237 | case 2: /* BYD */ | ||
238 | val->intval = 3100000; | ||
239 | break; | ||
240 | default: | ||
241 | return -EIO; | ||
242 | } | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | return -EIO; | ||
247 | } | ||
248 | |||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static int olpc_bat_get_charge_now(union power_supply_propval *val) | ||
253 | { | ||
254 | uint8_t soc; | ||
255 | union power_supply_propval full; | ||
256 | int ret; | ||
257 | |||
258 | ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &soc, 1); | ||
259 | if (ret) | ||
260 | return ret; | ||
261 | |||
262 | ret = olpc_bat_get_charge_full_design(&full); | ||
263 | if (ret) | ||
264 | return ret; | ||
265 | |||
266 | val->intval = soc * (full.intval / 100); | ||
267 | return 0; | ||
268 | } | ||
269 | |||
204 | /********************************************************************* | 270 | /********************************************************************* |
205 | * Battery properties | 271 | * Battery properties |
206 | *********************************************************************/ | 272 | *********************************************************************/ |
@@ -267,6 +333,7 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
267 | return ret; | 333 | return ret; |
268 | break; | 334 | break; |
269 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | 335 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
336 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
270 | ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2); | 337 | ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2); |
271 | if (ret) | 338 | if (ret) |
272 | return ret; | 339 | return ret; |
@@ -274,6 +341,7 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
274 | val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32; | 341 | val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32; |
275 | break; | 342 | break; |
276 | case POWER_SUPPLY_PROP_CURRENT_AVG: | 343 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
344 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
277 | ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); | 345 | ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); |
278 | if (ret) | 346 | if (ret) |
279 | return ret; | 347 | return ret; |
@@ -294,6 +362,16 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
294 | else | 362 | else |
295 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | 363 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; |
296 | break; | 364 | break; |
365 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
366 | ret = olpc_bat_get_charge_full_design(val); | ||
367 | if (ret) | ||
368 | return ret; | ||
369 | break; | ||
370 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
371 | ret = olpc_bat_get_charge_now(val); | ||
372 | if (ret) | ||
373 | return ret; | ||
374 | break; | ||
297 | case POWER_SUPPLY_PROP_TEMP: | 375 | case POWER_SUPPLY_PROP_TEMP: |
298 | ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); | 376 | ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); |
299 | if (ret) | 377 | if (ret) |
@@ -331,16 +409,20 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
331 | return ret; | 409 | return ret; |
332 | } | 410 | } |
333 | 411 | ||
334 | static enum power_supply_property olpc_bat_props[] = { | 412 | static enum power_supply_property olpc_xo1_bat_props[] = { |
335 | POWER_SUPPLY_PROP_STATUS, | 413 | POWER_SUPPLY_PROP_STATUS, |
336 | POWER_SUPPLY_PROP_CHARGE_TYPE, | 414 | POWER_SUPPLY_PROP_CHARGE_TYPE, |
337 | POWER_SUPPLY_PROP_PRESENT, | 415 | POWER_SUPPLY_PROP_PRESENT, |
338 | POWER_SUPPLY_PROP_HEALTH, | 416 | POWER_SUPPLY_PROP_HEALTH, |
339 | POWER_SUPPLY_PROP_TECHNOLOGY, | 417 | POWER_SUPPLY_PROP_TECHNOLOGY, |
340 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | 418 | POWER_SUPPLY_PROP_VOLTAGE_AVG, |
419 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
341 | POWER_SUPPLY_PROP_CURRENT_AVG, | 420 | POWER_SUPPLY_PROP_CURRENT_AVG, |
421 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
342 | POWER_SUPPLY_PROP_CAPACITY, | 422 | POWER_SUPPLY_PROP_CAPACITY, |
343 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | 423 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, |
424 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
425 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
344 | POWER_SUPPLY_PROP_TEMP, | 426 | POWER_SUPPLY_PROP_TEMP, |
345 | POWER_SUPPLY_PROP_TEMP_AMBIENT, | 427 | POWER_SUPPLY_PROP_TEMP_AMBIENT, |
346 | POWER_SUPPLY_PROP_MANUFACTURER, | 428 | POWER_SUPPLY_PROP_MANUFACTURER, |
@@ -348,6 +430,27 @@ static enum power_supply_property olpc_bat_props[] = { | |||
348 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 430 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
349 | }; | 431 | }; |
350 | 432 | ||
433 | /* XO-1.5 does not have ambient temperature property */ | ||
434 | static enum power_supply_property olpc_xo15_bat_props[] = { | ||
435 | POWER_SUPPLY_PROP_STATUS, | ||
436 | POWER_SUPPLY_PROP_CHARGE_TYPE, | ||
437 | POWER_SUPPLY_PROP_PRESENT, | ||
438 | POWER_SUPPLY_PROP_HEALTH, | ||
439 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
440 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
441 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
442 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
443 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
444 | POWER_SUPPLY_PROP_CAPACITY, | ||
445 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
446 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
447 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
448 | POWER_SUPPLY_PROP_TEMP, | ||
449 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
450 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
451 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | ||
452 | }; | ||
453 | |||
351 | /* EEPROM reading goes completely around the power_supply API, sadly */ | 454 | /* EEPROM reading goes completely around the power_supply API, sadly */ |
352 | 455 | ||
353 | #define EEPROM_START 0x20 | 456 | #define EEPROM_START 0x20 |
@@ -419,8 +522,6 @@ static struct device_attribute olpc_bat_error = { | |||
419 | static struct platform_device *bat_pdev; | 522 | static struct platform_device *bat_pdev; |
420 | 523 | ||
421 | static struct power_supply olpc_bat = { | 524 | static struct power_supply olpc_bat = { |
422 | .properties = olpc_bat_props, | ||
423 | .num_properties = ARRAY_SIZE(olpc_bat_props), | ||
424 | .get_property = olpc_bat_get_property, | 525 | .get_property = olpc_bat_get_property, |
425 | .use_for_apm = 1, | 526 | .use_for_apm = 1, |
426 | }; | 527 | }; |
@@ -466,6 +567,13 @@ static int __init olpc_bat_init(void) | |||
466 | goto ac_failed; | 567 | goto ac_failed; |
467 | 568 | ||
468 | olpc_bat.name = bat_pdev->name; | 569 | olpc_bat.name = bat_pdev->name; |
570 | if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ | ||
571 | olpc_bat.properties = olpc_xo15_bat_props; | ||
572 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); | ||
573 | } else { /* XO-1 */ | ||
574 | olpc_bat.properties = olpc_xo1_bat_props; | ||
575 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); | ||
576 | } | ||
469 | 577 | ||
470 | ret = power_supply_register(&bat_pdev->dev, &olpc_bat); | 578 | ret = power_supply_register(&bat_pdev->dev, &olpc_bat); |
471 | if (ret) | 579 | if (ret) |