diff options
author | Chanwoo Choi <cw00.choi@samsung.com> | 2012-09-21 00:20:05 -0400 |
---|---|---|
committer | Anton Vorontsov <anton.vorontsov@linaro.org> | 2012-09-21 01:08:00 -0400 |
commit | 8fcfe088e21aa0db9d62eaf565757def673efba6 (patch) | |
tree | 5394f0f8ac6ec50f1ab158927c858a621b074127 /drivers/power | |
parent | 2ed9e9b6530951b5b96185e6761119361a166d7a (diff) |
charger-manager: Support limit of maximum possible
This patch check maximum possible duration of charging/discharging.
If whole charging duration exceed 'desc->charging_max_duration_ms', cm
stop charging to prevent overcharge/overheat. And if discharging duration
exceed, charger cable is attached, after full-batt, cm start charging to
maintain fully charged state for battery.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/charger-manager.c | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index c701f5e6f327..e92ec55ced91 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -323,6 +323,14 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) | |||
323 | if (enable) { | 323 | if (enable) { |
324 | if (cm->emergency_stop) | 324 | if (cm->emergency_stop) |
325 | return -EAGAIN; | 325 | return -EAGAIN; |
326 | |||
327 | /* | ||
328 | * Save start time of charging to limit | ||
329 | * maximum possible charging time. | ||
330 | */ | ||
331 | cm->charging_start_time = ktime_to_ms(ktime_get()); | ||
332 | cm->charging_end_time = 0; | ||
333 | |||
326 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | 334 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { |
327 | err = regulator_enable(desc->charger_regulators[i].consumer); | 335 | err = regulator_enable(desc->charger_regulators[i].consumer); |
328 | if (err < 0) { | 336 | if (err < 0) { |
@@ -332,6 +340,13 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) | |||
332 | } | 340 | } |
333 | } | 341 | } |
334 | } else { | 342 | } else { |
343 | /* | ||
344 | * Save end time of charging to maintain fully charged state | ||
345 | * of battery after full-batt. | ||
346 | */ | ||
347 | cm->charging_start_time = 0; | ||
348 | cm->charging_end_time = ktime_to_ms(ktime_get()); | ||
349 | |||
335 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | 350 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { |
336 | err = regulator_disable(desc->charger_regulators[i].consumer); | 351 | err = regulator_disable(desc->charger_regulators[i].consumer); |
337 | if (err < 0) { | 352 | if (err < 0) { |
@@ -474,8 +489,55 @@ static void fullbatt_vchk(struct work_struct *work) | |||
474 | 489 | ||
475 | if (diff > desc->fullbatt_vchkdrop_uV) { | 490 | if (diff > desc->fullbatt_vchkdrop_uV) { |
476 | try_charger_restart(cm); | 491 | try_charger_restart(cm); |
477 | uevent_notify(cm, "Recharge"); | 492 | uevent_notify(cm, "Recharging"); |
493 | } | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * check_charging_duration - Monitor charging/discharging duration | ||
498 | * @cm: the Charger Manager representing the battery. | ||
499 | * | ||
500 | * If whole charging duration exceed 'charging_max_duration_ms', | ||
501 | * cm stop charging to prevent overcharge/overheat. If discharging | ||
502 | * duration exceed 'discharging _max_duration_ms', charger cable is | ||
503 | * attached, after full-batt, cm start charging to maintain fully | ||
504 | * charged state for battery. | ||
505 | */ | ||
506 | static int check_charging_duration(struct charger_manager *cm) | ||
507 | { | ||
508 | struct charger_desc *desc = cm->desc; | ||
509 | u64 curr = ktime_to_ms(ktime_get()); | ||
510 | u64 duration; | ||
511 | int ret = false; | ||
512 | |||
513 | if (!desc->charging_max_duration_ms && | ||
514 | !desc->discharging_max_duration_ms) | ||
515 | return ret; | ||
516 | |||
517 | if (cm->charger_enabled) { | ||
518 | duration = curr - cm->charging_start_time; | ||
519 | |||
520 | if (duration > desc->charging_max_duration_ms) { | ||
521 | dev_info(cm->dev, "Charging duration exceed %lldms", | ||
522 | desc->charging_max_duration_ms); | ||
523 | uevent_notify(cm, "Discharging"); | ||
524 | try_charger_enable(cm, false); | ||
525 | ret = true; | ||
526 | } | ||
527 | } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) { | ||
528 | duration = curr - cm->charging_end_time; | ||
529 | |||
530 | if (duration > desc->charging_max_duration_ms && | ||
531 | is_ext_pwr_online(cm)) { | ||
532 | dev_info(cm->dev, "DisCharging duration exceed %lldms", | ||
533 | desc->discharging_max_duration_ms); | ||
534 | uevent_notify(cm, "Recharing"); | ||
535 | try_charger_enable(cm, true); | ||
536 | ret = true; | ||
537 | } | ||
478 | } | 538 | } |
539 | |||
540 | return ret; | ||
479 | } | 541 | } |
480 | 542 | ||
481 | /** | 543 | /** |
@@ -511,6 +573,13 @@ static bool _cm_monitor(struct charger_manager *cm) | |||
511 | } | 573 | } |
512 | 574 | ||
513 | /* | 575 | /* |
576 | * Check whole charging duration and discharing duration | ||
577 | * after full-batt. | ||
578 | */ | ||
579 | } else if (!cm->emergency_stop && check_charging_duration(cm)) { | ||
580 | dev_dbg(cm->dev, | ||
581 | "Charging/Discharging duration is out of range"); | ||
582 | /* | ||
514 | * Check dropped voltage of battery. If battery voltage is more | 583 | * Check dropped voltage of battery. If battery voltage is more |
515 | * dropped than fullbatt_vchkdrop_uV after fully charged state, | 584 | * dropped than fullbatt_vchkdrop_uV after fully charged state, |
516 | * charger-manager have to recharge battery. | 585 | * charger-manager have to recharge battery. |
@@ -1271,6 +1340,15 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1271 | goto err_chg_stat; | 1340 | goto err_chg_stat; |
1272 | } | 1341 | } |
1273 | 1342 | ||
1343 | if (!desc->charging_max_duration_ms || | ||
1344 | !desc->discharging_max_duration_ms) { | ||
1345 | dev_info(&pdev->dev, "Cannot limit charging duration " | ||
1346 | "checking mechanism to prevent overcharge/overheat " | ||
1347 | "and control discharging duration"); | ||
1348 | desc->charging_max_duration_ms = 0; | ||
1349 | desc->discharging_max_duration_ms = 0; | ||
1350 | } | ||
1351 | |||
1274 | platform_set_drvdata(pdev, cm); | 1352 | platform_set_drvdata(pdev, cm); |
1275 | 1353 | ||
1276 | memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); | 1354 | memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); |