diff options
author | Jonghwa Lee <jonghwa3.lee@samsung.com> | 2014-10-22 11:32:10 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-11-18 12:01:02 +0900 |
commit | 59ec47bda4ba1c0df507b4c6dfd9969af6120373 (patch) | |
tree | 080d997ae3050ba8ec746e482d607dc397be4711 | |
parent | 361f1558dfc48cab51df9d2194fcb1301dcb65e9 (diff) | |
download | linux-3.10-59ec47bda4ba1c0df507b4c6dfd9969af6120373.tar.gz linux-3.10-59ec47bda4ba1c0df507b4c6dfd9969af6120373.tar.bz2 linux-3.10-59ec47bda4ba1c0df507b4c6dfd9969af6120373.zip |
power: charger-manager: Make chraging decision focused on battery status.
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascade if statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.
Both of problems mentioned above becomes clean if it manages battery charging
with focusing battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.
Change-Id: I1c8cfe57cea6fc8c02a4c0bf7bde6a0d8395b786
Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com>
-rw-r--r-- | drivers/power/charger-manager.c | 179 | ||||
-rw-r--r-- | include/linux/power/charger-manager.h | 2 |
2 files changed, 62 insertions, 119 deletions
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 572c0fb7450..5abc379ca24 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -226,12 +226,25 @@ static bool is_full_charged(struct charger_manager *cm) struct charger_desc *desc = cm->desc; union power_supply_propval val; int ret = 0; - int uV; + int uV = 0; /* If there is no battery, it cannot be charged */ if (!is_batt_present(cm)) return false; + /* Full, if it's over the fullbatt voltage */ + if (desc->fullbatt_uV > 0) { + ret = get_batt_uV(cm, &uV); + if (!ret) { + /* Battery is already full, checks voltage drop. */ + if (cm->battery_status == POWER_SUPPLY_STATUS_FULL + && desc->fullbatt_vchkdrop_uV) + uV += desc->fullbatt_vchkdrop_uV; + if (uV >= desc->fullbatt_uV) + return true; + } + } + if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { val.intval = 0; @@ -242,13 +255,6 @@ static bool is_full_charged(struct charger_manager *cm) return true; } - /* Full, if it's over the fullbatt voltage */ - if (desc->fullbatt_uV > 0) { - ret = get_batt_uV(cm, &uV); - if (!ret && uV >= desc->fullbatt_uV) - return true; - } - /* Full, if the capacity is more than fullbatt_soc */ if (cm->fuel_gauge && desc->fullbatt_soc > 0) { val.intval = 0; @@ -359,67 +365,13 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) } } - if (!err) { + if (!err) cm->charger_enabled = enable; - power_supply_changed(&cm->charger_psy); - } return err; } /** - * try_charger_restart - Restart charging. - * @cm: the Charger Manager representing the battery. - * - * Restart charging by turning off and on the charger. - */ -static int try_charger_restart(struct charger_manager *cm) -{ - int err; - - if (cm->emergency_stop) - return -EAGAIN; - - err = try_charger_enable(cm, false); - if (err) - return err; - - return try_charger_enable(cm, true); -} - -/** - * fullbatt_vchk - Check voltage drop some times after "FULL" event. - * - * If a user has designated "fullbatt_vchkdrop_uV" values with - * charger_desc, Charger Manager checks voltage drop after the battery - * "FULL" event. It checks whether the voltage has dropped more than - * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms. - */ -static void fullbatt_vchk(struct charger_manager *cm) -{ - struct charger_desc *desc = cm->desc; - int batt_uV, err, diff; - - if (!desc->fullbatt_vchkdrop_uV) - return; - - err = get_batt_uV(cm, &batt_uV); - if (err) { - dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err); - return; - } - - diff = desc->fullbatt_uV - batt_uV; - if (diff < 0) - return; - - dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff); - - if (diff > desc->fullbatt_vchkdrop_uV) - try_charger_restart(cm); -} - -/** * check_charging_duration - Monitor charging/discharging duration * @cm: the Charger Manager representing the battery. * @@ -446,17 +398,14 @@ static int check_charging_duration(struct charger_manager *cm) if (duration > desc->charging_max_duration_ms) { dev_info(cm->dev, "Charging duration exceed %ums\n", desc->charging_max_duration_ms); - try_charger_enable(cm, false); ret = true; } - } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) { + } else if (cm->battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { duration = curr - cm->charging_end_time; - if (duration > desc->charging_max_duration_ms && - is_ext_pwr_online(cm)) { + if (duration > desc->charging_max_duration_ms) { dev_info(cm->dev, "Discharging duration exceed %ums\n", desc->discharging_max_duration_ms); - try_charger_enable(cm, true); ret = true; } } @@ -507,10 +456,45 @@ static int cm_check_thermal_status(struct charger_manager *cm) else if (temp < lower_limit) ret = CM_EVENT_BATT_COLD; + cm->emergency_stop = ret; + return ret; } /** + * cm_get_target_status - Check current status and get next target status. + * @cm: the Charger Manager representing the battery. + */ +static int cm_get_target_status(struct charger_manager *cm) +{ + if (!is_ext_pwr_online(cm)) + return POWER_SUPPLY_STATUS_DISCHARGING; + + if (cm_check_thermal_status(cm)) { + /* Check if discharging duration exeeds limit. */ + if (check_charging_duration(cm)) + goto charging_ok; + return POWER_SUPPLY_STATUS_NOT_CHARGING; + } + + switch (cm->battery_status) { + case POWER_SUPPLY_STATUS_CHARGING: + /* Check if charging duration exeeds limit. */ + if (check_charging_duration(cm)) + return POWER_SUPPLY_STATUS_FULL; + case POWER_SUPPLY_STATUS_FULL: + if (is_full_charged(cm)) + return POWER_SUPPLY_STATUS_FULL; + default: + break; + } + +charging_ok: + /* Charging is allowed. */ + return POWER_SUPPLY_STATUS_CHARGING; +} + +/** * _cm_monitor - Monitor the temperature and return true for exceptions. * @cm: the Charger Manager representing the battery. * @@ -519,56 +503,18 @@ static int cm_check_thermal_status(struct charger_manager *cm) */ static bool _cm_monitor(struct charger_manager *cm) { - int temp_alrt; - - temp_alrt = cm_check_thermal_status(cm); + int target; - /* It has been stopped already */ - if (temp_alrt && cm->emergency_stop) - return false; - - /* - * Check temperature whether overheat or cold. - * If temperature is out of range normal state, stop charging. - */ - if (temp_alrt) { - cm->emergency_stop = temp_alrt; - try_charger_enable(cm, false); - - /* - * Check whole charging duration and discharing duration - * after full-batt. - */ - } else if (!cm->emergency_stop && check_charging_duration(cm)) { - dev_dbg(cm->dev, - "Charging/Discharging duration is out of range\n"); - /* - * Check dropped voltage of battery. If battery voltage is more - * dropped than fullbatt_vchkdrop_uV after fully charged state, - * charger-manager have to recharge battery. - */ - } else if (!cm->emergency_stop && is_ext_pwr_online(cm) && - !cm->charger_enabled) { - fullbatt_vchk(cm); + target = cm_get_target_status(cm); - /* - * Check whether fully charged state to protect overcharge - * if charger-manager is charging for battery. - */ - } else if (!cm->emergency_stop && is_full_charged(cm) && - cm->charger_enabled) { - dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n"); - try_charger_enable(cm, false); + try_charger_enable(cm, (target == POWER_SUPPLY_STATUS_CHARGING)); - fullbatt_vchk(cm); - } else { - cm->emergency_stop = 0; - if (is_ext_pwr_online(cm)) { - try_charger_enable(cm, true); - } + if (cm->battery_status != target) { + cm->battery_status = target; + power_supply_changed(&cm->charger_psy); } - return true; + return (cm->battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING); } /** @@ -673,12 +619,7 @@ static int charger_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_STATUS: - if (is_charging(cm)) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else if (is_ext_pwr_online(cm)) - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + val->intval = cm->battery_status; break; case POWER_SUPPLY_PROP_HEALTH: if (cm->emergency_stop > 0) diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index b56366e96c4..b7a58e788ce 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -228,6 +228,8 @@ struct charger_manager { struct device *dev; struct charger_desc *desc; + int battery_status; + struct power_supply *fuel_gauge; struct power_supply **charger_stat; |