aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/ds2760_battery.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index f4a9258aa9d0..1bb8498f14be 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -56,6 +56,7 @@ struct ds2760_device_info {
56 struct device *w1_dev; 56 struct device *w1_dev;
57 struct workqueue_struct *monitor_wqueue; 57 struct workqueue_struct *monitor_wqueue;
58 struct delayed_work monitor_work; 58 struct delayed_work monitor_work;
59 struct delayed_work set_charged_work;
59}; 60};
60 61
61static unsigned int cache_time = 1000; 62static unsigned int cache_time = 1000;
@@ -327,6 +328,52 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy)
327 queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10); 328 queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
328} 329}
329 330
331
332static void ds2760_battery_set_charged_work(struct work_struct *work)
333{
334 char bias;
335 struct ds2760_device_info *di = container_of(work,
336 struct ds2760_device_info, set_charged_work.work);
337
338 dev_dbg(di->dev, "%s\n", __func__);
339
340 ds2760_battery_read_status(di);
341
342 /* When we get notified by external circuitry that the battery is
343 * considered fully charged now, we know that there is no current
344 * flow any more. However, the ds2760's internal current meter is
345 * too inaccurate to rely on - spec say something ~15% failure.
346 * Hence, we use the current offset bias register to compensate
347 * that error.
348 */
349
350 if (!power_supply_am_i_supplied(&di->bat))
351 return;
352
353 bias = (signed char) di->current_raw +
354 (signed char) di->raw[DS2760_CURRENT_OFFSET_BIAS];
355
356 dev_dbg(di->dev, "%s: bias = %d\n", __func__, bias);
357
358 w1_ds2760_write(di->w1_dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
359 w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
360 w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
361
362 /* Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS
363 * value won't be read back by ds2760_battery_read_status() */
364 di->raw[DS2760_CURRENT_OFFSET_BIAS] = bias;
365}
366
367static void ds2760_battery_set_charged(struct power_supply *psy)
368{
369 struct ds2760_device_info *di = to_ds2760_device_info(psy);
370
371 /* postpone the actual work by 20 secs. This is for debouncing GPIO
372 * signals and to let the current value settle. See AN4188. */
373 cancel_delayed_work(&di->set_charged_work);
374 queue_delayed_work(di->monitor_wqueue, &di->set_charged_work, HZ * 20);
375}
376
330static int ds2760_battery_get_property(struct power_supply *psy, 377static int ds2760_battery_get_property(struct power_supply *psy,
331 enum power_supply_property psp, 378 enum power_supply_property psp,
332 union power_supply_propval *val) 379 union power_supply_propval *val)
@@ -412,6 +459,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
412 di->bat.properties = ds2760_battery_props; 459 di->bat.properties = ds2760_battery_props;
413 di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props); 460 di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
414 di->bat.get_property = ds2760_battery_get_property; 461 di->bat.get_property = ds2760_battery_get_property;
462 di->bat.set_charged = ds2760_battery_set_charged;
415 di->bat.external_power_changed = 463 di->bat.external_power_changed =
416 ds2760_battery_external_power_changed; 464 ds2760_battery_external_power_changed;
417 465
@@ -443,6 +491,8 @@ static int ds2760_battery_probe(struct platform_device *pdev)
443 } 491 }
444 492
445 INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work); 493 INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
494 INIT_DELAYED_WORK(&di->set_charged_work,
495 ds2760_battery_set_charged_work);
446 di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); 496 di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
447 if (!di->monitor_wqueue) { 497 if (!di->monitor_wqueue) {
448 retval = -ESRCH; 498 retval = -ESRCH;
@@ -467,6 +517,8 @@ static int ds2760_battery_remove(struct platform_device *pdev)
467 517
468 cancel_rearming_delayed_workqueue(di->monitor_wqueue, 518 cancel_rearming_delayed_workqueue(di->monitor_wqueue,
469 &di->monitor_work); 519 &di->monitor_work);
520 cancel_rearming_delayed_workqueue(di->monitor_wqueue,
521 &di->set_charged_work);
470 destroy_workqueue(di->monitor_wqueue); 522 destroy_workqueue(di->monitor_wqueue);
471 power_supply_unregister(&di->bat); 523 power_supply_unregister(&di->bat);
472 524