Skip to content

Commit

Permalink
power: supply: ab8500: Standardize alert mode charging
Browse files Browse the repository at this point in the history
The AB8500 code is using a special current and voltage setting
when the battery is in "alert mode", i.e. when it is starting
to go outside normal operating conditions so it is too
cold or too hot. This makes sense as a way for the charging
algorithm to deal with hostile environments.

Add the needed members to the struct power_supply_battery_info,
and switch the AB8500 charging code over to using this.

Reviewed-by: Matti Vaittineen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
  • Loading branch information
Linus Walleij authored and Sebastian Reichel committed Feb 28, 2022
1 parent d72ce7d commit 0e8b903
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 22 deletions.
4 changes: 0 additions & 4 deletions drivers/power/supply/ab8500-bm.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,10 @@ struct ab8500_maxim_parameters {
* struct ab8500_battery_type - different batteries supported
* @resis_high: battery upper resistance limit
* @resis_low: battery lower resistance limit
* @low_high_cur_lvl: charger current in temp low/high state in mA
* @low_high_vol_lvl: charger voltage in temp low/high state in mV'
*/
struct ab8500_battery_type {
int resis_high;
int resis_low;
int low_high_cur_lvl;
int low_high_vol_lvl;
};

/**
Expand Down
15 changes: 13 additions & 2 deletions drivers/power/supply/ab8500_bmdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ static struct power_supply_maintenance_charge_table ab8500_maint_charg_table[] =
static struct ab8500_battery_type bat_type_thermistor_unknown = {
.resis_high = 0,
.resis_low = 0,
.low_high_cur_lvl = 300,
.low_high_vol_lvl = 4000,
};

static const struct ab8500_bm_capacity_levels cap_levels = {
Expand Down Expand Up @@ -192,6 +190,19 @@ int ab8500_bm_of_probe(struct power_supply *psy,
bi->maintenance_charge_size = ARRAY_SIZE(ab8500_maint_charg_table);
}

if (bi->alert_low_temp_charge_current_ua < 0 ||
bi->alert_low_temp_charge_voltage_uv < 0)
{
bi->alert_low_temp_charge_current_ua = 300000;
bi->alert_low_temp_charge_voltage_uv = 4000000;
}
if (bi->alert_high_temp_charge_current_ua < 0 ||
bi->alert_high_temp_charge_voltage_uv < 0)
{
bi->alert_high_temp_charge_current_ua = 300000;
bi->alert_high_temp_charge_voltage_uv = 4000000;
}

/*
* Internal resistance and factory resistance are tightly coupled
* so both MUST be defined or we fall back to defaults.
Expand Down
48 changes: 32 additions & 16 deletions drivers/power/supply/ab8500_chargalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ struct ab8500_chargalg_events {
bool batt_ovv;
bool batt_rem;
bool btemp_underover;
bool btemp_lowhigh;
bool btemp_low;
bool btemp_high;
bool main_thermal_prot;
bool usb_thermal_prot;
bool main_ovv;
Expand Down Expand Up @@ -684,26 +685,31 @@ static void ab8500_chargalg_check_temp(struct ab8500_chargalg *di)
di->batt_data.temp < (bi->temp_alert_max - di->t_hyst_norm)) {
/* Temp OK! */
di->events.btemp_underover = false;
di->events.btemp_lowhigh = false;
di->events.btemp_low = false;
di->events.btemp_high = false;
di->t_hyst_norm = 0;
di->t_hyst_lowhigh = 0;
} else {
if (((di->batt_data.temp >= bi->temp_alert_max) &&
(di->batt_data.temp <
(bi->temp_max - di->t_hyst_lowhigh))) ||
((di->batt_data.temp >
(bi->temp_min + di->t_hyst_lowhigh)) &&
(di->batt_data.temp <= bi->temp_alert_min))) {
/* TEMP minor!!!!! */
if ((di->batt_data.temp >= bi->temp_alert_max) &&
(di->batt_data.temp < (bi->temp_max - di->t_hyst_lowhigh))) {
/* Alert zone for high temperature */
di->events.btemp_underover = false;
di->events.btemp_lowhigh = true;
di->events.btemp_high = true;
di->t_hyst_norm = di->bm->temp_hysteresis;
di->t_hyst_lowhigh = 0;
} else if ((di->batt_data.temp > (bi->temp_min + di->t_hyst_lowhigh)) &&
(di->batt_data.temp <= bi->temp_alert_min)) {
/* Alert zone for low temperature */
di->events.btemp_underover = false;
di->events.btemp_low = true;
di->t_hyst_norm = di->bm->temp_hysteresis;
di->t_hyst_lowhigh = 0;
} else if (di->batt_data.temp <= bi->temp_min ||
di->batt_data.temp >= bi->temp_max) {
/* TEMP major!!!!! */
di->events.btemp_underover = true;
di->events.btemp_lowhigh = false;
di->events.btemp_low = false;
di->events.btemp_high = false;
di->t_hyst_norm = 0;
di->t_hyst_lowhigh = di->bm->temp_hysteresis;
} else {
Expand Down Expand Up @@ -1313,7 +1319,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
ab8500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT);
}
/* Battery temp high/low */
else if (di->events.btemp_lowhigh) {
else if (di->events.btemp_low || di->events.btemp_high) {
if (di->charge_state != STATE_TEMP_LOWHIGH)
ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT);
}
Expand Down Expand Up @@ -1510,17 +1516,27 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
break;

case STATE_TEMP_LOWHIGH_INIT:
ab8500_chargalg_start_charging(di,
di->bm->bat_type->low_high_vol_lvl,
di->bm->bat_type->low_high_cur_lvl);
if (di->events.btemp_low) {
ab8500_chargalg_start_charging(di,
bi->alert_low_temp_charge_voltage_uv,
bi->alert_low_temp_charge_current_ua);
} else if (di->events.btemp_high) {
ab8500_chargalg_start_charging(di,
bi->alert_high_temp_charge_voltage_uv,
bi->alert_high_temp_charge_current_ua);
} else {
dev_err(di->dev, "neither low or high temp event occured\n");
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
break;
}
ab8500_chargalg_stop_maintenance_timer(di);
di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
power_supply_changed(di->chargalg_psy);
fallthrough;

case STATE_TEMP_LOWHIGH:
if (!di->events.btemp_lowhigh)
if (!di->events.btemp_low && !di->events.btemp_high)
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
break;

Expand Down
4 changes: 4 additions & 0 deletions drivers/power/supply/power_supply_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
info->charge_restart_voltage_uv = -EINVAL;
info->overvoltage_limit_uv = -EINVAL;
info->maintenance_charge = NULL;
info->alert_low_temp_charge_current_ua = -EINVAL;
info->alert_low_temp_charge_voltage_uv = -EINVAL;
info->alert_high_temp_charge_current_ua = -EINVAL;
info->alert_high_temp_charge_voltage_uv = -EINVAL;
info->temp_ambient_alert_min = INT_MIN;
info->temp_ambient_alert_max = INT_MAX;
info->temp_alert_min = INT_MIN;
Expand Down
17 changes: 17 additions & 0 deletions include/linux/power_supply.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,19 @@ struct power_supply_maintenance_charge_table {
* after the main CC/CV charging phase is complete.
* @maintenance_charge_size: the number of maintenance charging settings in
* maintenance_charge.
* @alert_low_temp_charge_current_ua: The charging current to use if the battery
* enters low alert temperature, i.e. if the internal temperature is between
* temp_alert_min and temp_min. No matter the charging phase, this
* and alert_high_temp_charge_voltage_uv will be applied.
* @alert_low_temp_charge_voltage_uv: Same as alert_low_temp_charge_current_ua,
* but for the charging voltage.
* @alert_high_temp_charge_current_ua: The charging current to use if the
* battery enters high alert temperature, i.e. if the internal temperature is
* between temp_alert_max and temp_max. No matter the charging phase, this
* and alert_high_temp_charge_voltage_uv will be applied, usually lowering
* the charging current as an evasive manouver.
* @alert_high_temp_charge_voltage_uv: Same as
* alert_high_temp_charge_current_ua, but for the charging voltage.
* @factory_internal_resistance_uohm: the internal resistance of the battery
* at fabrication time, expressed in microohms. This resistance will vary
* depending on the lifetime and charge of the battery, so this is just a
Expand Down Expand Up @@ -595,6 +608,10 @@ struct power_supply_battery_info {
int constant_charge_voltage_max_uv;
struct power_supply_maintenance_charge_table *maintenance_charge;
int maintenance_charge_size;
int alert_low_temp_charge_current_ua;
int alert_low_temp_charge_voltage_uv;
int alert_high_temp_charge_current_ua;
int alert_high_temp_charge_voltage_uv;
int factory_internal_resistance_uohm;
int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX];
int temp_ambient_alert_min;
Expand Down

0 comments on commit 0e8b903

Please sign in to comment.