aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/supply/ab8500_chargalg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/supply/ab8500_chargalg.c')
-rw-r--r--drivers/power/supply/ab8500_chargalg.c70
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 = {