summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/power/supply/ab8500-bm.h4
-rw-r--r--drivers/power/supply/ab8500_bmdata.c15
-rw-r--r--drivers/power/supply/ab8500_chargalg.c48
-rw-r--r--drivers/power/supply/power_supply_core.c4
-rw-r--r--include/linux/power_supply.h17
5 files changed, 66 insertions, 22 deletions
diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h
index 4d74d21cf1eb..91ef9d4a5222 100644
--- a/drivers/power/supply/ab8500-bm.h
+++ b/drivers/power/supply/ab8500-bm.h
@@ -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;
};
/**
diff --git a/drivers/power/supply/ab8500_bmdata.c b/drivers/power/supply/ab8500_bmdata.c
index 66a454942c7c..bf0b74773eee 100644
--- a/drivers/power/supply/ab8500_bmdata.c
+++ b/drivers/power/supply/ab8500_bmdata.c
@@ -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 = {
@@ -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.
diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c
index 6054996b6260..c9c7f7028af6 100644
--- a/drivers/power/supply/ab8500_chargalg.c
+++ b/drivers/power/supply/ab8500_chargalg.c
@@ -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;
@@ -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 {
@@ -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);
}
@@ -1510,9 +1516,19 @@ 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);
@@ -1520,7 +1536,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
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;
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index accbbd36bfe7..e3d6d3ff492a 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -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;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 8ced6550caa7..f8601598d3d3 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -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
@@ -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;