power: pm8921-bms: limit voltage correction
The "adjust_soc" algorithm where we change the open circuit voltage (ocv) in steps so that the state of charge (soc) starts approaching the estimated soc, causes nonlinearity in the soc curves if an incorrect resistance value is fed to the algorithm. As battery ages and temperature changes, it is hard to estimate the exact battery resistance. So to fix the nonlinearity, limit the amount by which the ocv is changed. Make it proportional to the current, i.e. change ocv by small amounts in light load and let it change by proportionally large amounts in heavy load situations. Also, make the point where the soc is adjusted configurable via platform data instead of forcing it to 25%. Change-Id: Idc141e6bf3172dab278afe1900f5a1f9cdd624dd Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
committed by
Stephen Boyd
parent
29a6bcf6e4
commit
fbb8dc031a
@@ -394,6 +394,7 @@ apq8064_pm8921_bms_pdata __devinitdata = {
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
};
|
||||
|
||||
static struct pm8921_platform_data
|
||||
|
||||
@@ -345,6 +345,7 @@ static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
};
|
||||
|
||||
static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
|
||||
|
||||
@@ -426,6 +426,7 @@ static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.rconn_mohm = 18,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
};
|
||||
|
||||
#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
|
||||
|
||||
@@ -142,6 +142,7 @@ struct pm8921_bms_chip {
|
||||
int ignore_shutdown_soc;
|
||||
int prev_iavg_ua;
|
||||
int prev_uuc_iavg_ma;
|
||||
int adjust_soc_low_threshold;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1440,6 +1441,7 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
||||
int soc_new = 0;
|
||||
int m = 0;
|
||||
int rc = 0;
|
||||
int delta_ocv_uv_limit = 0;
|
||||
|
||||
rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
|
||||
&ibat_ua,
|
||||
@@ -1452,6 +1454,9 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
||||
|
||||
if (ibat_ua < 0)
|
||||
goto out;
|
||||
|
||||
delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
|
||||
|
||||
ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
|
||||
pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
|
||||
soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
|
||||
@@ -1469,7 +1474,8 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
||||
* and cause a bad user experience
|
||||
*/
|
||||
if (soc_est == soc
|
||||
|| (is_between(45, 25, soc_est) && is_between(50, 20, soc))
|
||||
|| (is_between(45, chip->adjust_soc_low_threshold, soc_est)
|
||||
&& is_between(50, chip->adjust_soc_low_threshold - 5, soc))
|
||||
|| soc >= 90)
|
||||
goto out;
|
||||
|
||||
@@ -1504,6 +1510,18 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
||||
|
||||
delta_ocv_uv = div_s64((soc - soc_est) * (s64)m * 1000,
|
||||
n * (pc - pc_new));
|
||||
|
||||
if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
|
||||
pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
|
||||
delta_ocv_uv_limit);
|
||||
|
||||
if (delta_ocv_uv > 0)
|
||||
delta_ocv_uv = delta_ocv_uv_limit;
|
||||
else
|
||||
delta_ocv_uv = -1 * delta_ocv_uv_limit;
|
||||
pr_debug("new delta ocv = %d\n", delta_ocv_uv);
|
||||
}
|
||||
|
||||
chip->last_ocv_uv -= delta_ocv_uv;
|
||||
|
||||
if (chip->last_ocv_uv >= chip->max_voltage_uv)
|
||||
@@ -3038,6 +3056,10 @@ static int __devinit pm8921_bms_probe(struct platform_device *pdev)
|
||||
chip->start_percent = -EINVAL;
|
||||
chip->end_percent = -EINVAL;
|
||||
chip->shutdown_soc_valid_limit = pdata->shutdown_soc_valid_limit;
|
||||
chip->adjust_soc_low_threshold = pdata->adjust_soc_low_threshold;
|
||||
if (chip->adjust_soc_low_threshold >= 45)
|
||||
chip->adjust_soc_low_threshold = 45;
|
||||
|
||||
chip->ignore_shutdown_soc = pdata->ignore_shutdown_soc;
|
||||
rc = set_battery_data(chip);
|
||||
if (rc) {
|
||||
|
||||
@@ -132,6 +132,7 @@ struct pm8921_bms_platform_data {
|
||||
int enable_fcc_learning;
|
||||
int shutdown_soc_valid_limit;
|
||||
int ignore_shutdown_soc;
|
||||
int adjust_soc_low_threshold;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
|
||||
|
||||
Reference in New Issue
Block a user