diff options
Diffstat (limited to 'drivers/power/supply/ab8500_chargalg.c')
-rw-r--r-- | drivers/power/supply/ab8500_chargalg.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c index 431bbc352d1b..ae4be553f424 100644 --- a/drivers/power/supply/ab8500_chargalg.c +++ b/drivers/power/supply/ab8500_chargalg.c @@ -246,9 +246,6 @@ struct ab8500_chargalg { struct kobject chargalg_kobject; }; -/*External charger prepare notifier*/ -BLOCKING_NOTIFIER_HEAD(charger_notifier_list); - /* Main battery properties */ static enum power_supply_property ab8500_chargalg_props[] = { POWER_SUPPLY_PROP_STATUS, @@ -343,8 +340,7 @@ static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di) return di->usb_chg->ops.check_enable(di->usb_chg, bi->constant_charge_voltage_max_uv, bi->constant_charge_current_max_ua); - } else if ((di->chg_info.charger_type & AC_CHG) && - !(di->ac_chg->external)) { + } else if (di->chg_info.charger_type & AC_CHG) { return di->ac_chg->ops.check_enable(di->ac_chg, bi->constant_charge_voltage_max_uv, bi->constant_charge_current_max_ua); @@ -473,15 +469,6 @@ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di) /* Check if charger exists and kick watchdog if charging */ if (di->ac_chg && di->ac_chg->ops.kick_wd && di->chg_info.online_chg & AC_CHG) { - /* - * If AB charger watchdog expired, pm2xxx charging - * gets disabled. To be safe, kick both AB charger watchdog - * and pm2xxx watchdog. - */ - if (di->ac_chg->external && - di->usb_chg && di->usb_chg->ops.kick_wd) - di->usb_chg->ops.kick_wd(di->usb_chg); - return di->ac_chg->ops.kick_wd(di->ac_chg); } else if (di->usb_chg && di->usb_chg->ops.kick_wd && di->chg_info.online_chg & USB_CHG) @@ -517,14 +504,6 @@ static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable, di->chg_info.ac_iset_ua = iset_ua; di->chg_info.ac_vset_uv = vset_uv; - /* Enable external charger */ - if (enable && di->ac_chg->external && - !ab8500_chargalg_ex_ac_enable_toggle) { - blocking_notifier_call_chain(&charger_notifier_list, - 0, di->dev); - ab8500_chargalg_ex_ac_enable_toggle++; - } - return di->ac_chg->ops.enable(di->ac_chg, enable, vset_uv, iset_ua); } @@ -1217,6 +1196,34 @@ static void ab8500_chargalg_external_power_changed(struct power_supply *psy) } /** + * ab8500_chargalg_time_to_restart() - time to restart CC/CV charging? + * @di: charging algorithm state + * + * This checks if the voltage or capacity of the battery has fallen so + * low that we need to restart the CC/CV charge cycle. + */ +static bool ab8500_chargalg_time_to_restart(struct ab8500_chargalg *di) +{ + struct power_supply_battery_info *bi = di->bm->bi; + + /* Sanity check - these need to have some reasonable values */ + if (!di->batt_data.volt_uv || !di->batt_data.percent) + return false; + + /* Some batteries tell us at which voltage we should restart charging */ + if (bi->charge_restart_voltage_uv > 0) { + if (di->batt_data.volt_uv <= bi->charge_restart_voltage_uv) + return true; + /* Else we restart as we reach a certain capacity */ + } else { + if (di->batt_data.percent <= AB8500_RECHARGE_CAP) + return true; + } + + return false; +} + +/** * ab8500_chargalg_algorithm() - Main function for the algorithm * @di: pointer to the ab8500_chargalg structure * @@ -1459,7 +1466,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) fallthrough; case STATE_WAIT_FOR_RECHARGE: - if (di->batt_data.percent <= AB8500_RECHARGE_CAP) + if (ab8500_chargalg_time_to_restart(di)) ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); break; @@ -1486,6 +1493,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ab8500_chargalg_stop_maintenance_timer(di); ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT); } + /* + * This happens if the voltage drops too quickly during + * maintenance charging, especially in older batteries. + */ + if (ab8500_chargalg_time_to_restart(di)) { + ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); + dev_info(di->dev, "restarted charging from maintenance state A - battery getting old?\n"); + } break; case STATE_MAINTENANCE_B_INIT: @@ -1510,6 +1525,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ab8500_chargalg_stop_maintenance_timer(di); ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); } + /* + * This happens if the voltage drops too quickly during + * maintenance charging, especially in older batteries. + */ + if (ab8500_chargalg_time_to_restart(di)) { + ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); + dev_info(di->dev, "restarted charging from maintenance state B - battery getting old?\n"); + } break; case STATE_TEMP_LOWHIGH_INIT: @@ -1746,7 +1769,6 @@ static void ab8500_chargalg_unbind(struct device *dev, struct device *master, /* Delete the work queue */ destroy_workqueue(di->chargalg_wq); - flush_scheduled_work(); } static const struct component_ops ab8500_chargalg_component_ops = { |