mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
power: pm8921-bms: charging curve adjustments
It was observed that while charging the reported soc sometimes reaches 100% before end of charging happens. At other times it does not reach 100% at end of charge and a abrupt jump to 100% soc happens. Fix this by linearly increasing soc based on battery charge current after constant voltage phase is reached. Constant voltage phase is reached when battery voltage reaches the max value. Also once constant voltage phase is reached and the voltage or charge current decreases keep reporting the earlier soc. This could be because of a transient system load. Change-Id: I14c2f42d7897041db038ce85ce1124cf1ef261af Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
parent
ce95e6e6ce
commit
2acc8a93ff
5 changed files with 95 additions and 27 deletions
|
@ -360,6 +360,7 @@ static int apq8064_pm8921_therm_mitigation[] = {
|
|||
};
|
||||
|
||||
#define MAX_VOLTAGE_MV 4200
|
||||
#define CHG_TERM_MA 100
|
||||
static struct pm8921_charger_platform_data
|
||||
apq8064_pm8921_chg_pdata __devinitdata = {
|
||||
.safety_time = 180,
|
||||
|
@ -368,7 +369,7 @@ apq8064_pm8921_chg_pdata __devinitdata = {
|
|||
.min_voltage = 3200,
|
||||
.uvd_thresh_voltage = 4050,
|
||||
.resume_voltage_delta = 100,
|
||||
.term_current = 100,
|
||||
.term_current = CHG_TERM_MA,
|
||||
.cool_temp = 10,
|
||||
.warm_temp = 40,
|
||||
.temp_check_period = 1,
|
||||
|
@ -389,12 +390,14 @@ apq8064_pm8xxx_ccadc_pdata = {
|
|||
|
||||
static struct pm8921_bms_platform_data
|
||||
apq8064_pm8921_bms_pdata __devinitdata = {
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.rconn_mohm = 18,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.chg_term_ua = CHG_TERM_MA * 1000,
|
||||
};
|
||||
|
||||
static struct pm8921_platform_data
|
||||
|
|
|
@ -207,6 +207,7 @@ static int pm8921_therm_mitigation[] = {
|
|||
};
|
||||
|
||||
#define MAX_VOLTAGE_MV 4200
|
||||
#define CHG_TERM_MA 100
|
||||
static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
|
||||
.safety_time = 180,
|
||||
.update_time = 60000,
|
||||
|
@ -214,7 +215,7 @@ static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
|
|||
.min_voltage = 3200,
|
||||
.uvd_thresh_voltage = 4050,
|
||||
.resume_voltage_delta = 100,
|
||||
.term_current = 100,
|
||||
.term_current = CHG_TERM_MA,
|
||||
.cool_temp = 10,
|
||||
.warm_temp = 40,
|
||||
.temp_check_period = 1,
|
||||
|
@ -340,12 +341,13 @@ static struct pm8xxx_spk_platform_data pm8xxx_spk_pdata = {
|
|||
};
|
||||
|
||||
static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.chg_term_ua = CHG_TERM_MA * 1000,
|
||||
};
|
||||
|
||||
static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
|
||||
|
|
|
@ -394,6 +394,7 @@ static int pm8921_therm_mitigation[] = {
|
|||
};
|
||||
|
||||
#define MAX_VOLTAGE_MV 4200
|
||||
#define CHG_TERM_MA 100
|
||||
static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
|
||||
.safety_time = 180,
|
||||
.update_time = 60000,
|
||||
|
@ -401,7 +402,7 @@ static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
|
|||
.min_voltage = 3200,
|
||||
.uvd_thresh_voltage = 4050,
|
||||
.resume_voltage_delta = 100,
|
||||
.term_current = 100,
|
||||
.term_current = CHG_TERM_MA,
|
||||
.cool_temp = 10,
|
||||
.warm_temp = 40,
|
||||
.temp_check_period = 1,
|
||||
|
@ -420,13 +421,14 @@ static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
|
|||
};
|
||||
|
||||
static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.rconn_mohm = 18,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.battery_type = BATT_UNKNOWN,
|
||||
.r_sense = 10,
|
||||
.v_cutoff = 3400,
|
||||
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
|
||||
.rconn_mohm = 18,
|
||||
.shutdown_soc_valid_limit = 20,
|
||||
.adjust_soc_low_threshold = 25,
|
||||
.chg_term_ua = CHG_TERM_MA * 1000,
|
||||
};
|
||||
|
||||
#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
|
||||
|
|
|
@ -122,6 +122,7 @@ struct pm8921_bms_chip {
|
|||
int cc_reading_at_100;
|
||||
int max_voltage_uv;
|
||||
|
||||
int chg_term_ua;
|
||||
int default_rbatt_mohm;
|
||||
int amux_2_trim_delta;
|
||||
uint16_t prev_last_good_ocv_raw;
|
||||
|
@ -144,6 +145,10 @@ struct pm8921_bms_chip {
|
|||
int prev_uuc_iavg_ma;
|
||||
int prev_pc_unusable;
|
||||
int adjust_soc_low_threshold;
|
||||
|
||||
int ibat_at_cv_ua;
|
||||
int soc_at_cv;
|
||||
int prev_chg_soc;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1510,6 +1515,53 @@ static int bound_soc(int soc)
|
|||
return soc;
|
||||
}
|
||||
|
||||
static int charging_adjustments(struct pm8921_bms_chip *chip,
|
||||
int soc, int vbat_uv, int ibat_ua)
|
||||
{
|
||||
int chg_soc;
|
||||
|
||||
if (chip->soc_at_cv == -EINVAL) {
|
||||
/* In constant current charging return the calc soc */
|
||||
if (vbat_uv <= chip->max_voltage_uv)
|
||||
pr_debug("CC CHG SOC %d\n", soc);
|
||||
|
||||
/* Note the CC to CV point */
|
||||
if (vbat_uv >= chip->max_voltage_uv) {
|
||||
chip->soc_at_cv = soc;
|
||||
chip->prev_chg_soc = soc;
|
||||
chip->ibat_at_cv_ua = ibat_ua;
|
||||
pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
|
||||
ibat_ua, soc);
|
||||
}
|
||||
return soc;
|
||||
}
|
||||
|
||||
/*
|
||||
* battery is in CV phase - begin liner inerpolation of soc based on
|
||||
* battery charge current
|
||||
*/
|
||||
|
||||
/*
|
||||
* if voltage lessened (possibly because of a system load)
|
||||
* keep reporting the prev chg soc
|
||||
*/
|
||||
if (vbat_uv <= chip->max_voltage_uv) {
|
||||
pr_debug("CC CHG SOC %d\n", chip->prev_chg_soc);
|
||||
return chip->prev_chg_soc;
|
||||
}
|
||||
|
||||
chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
|
||||
100, -100000,
|
||||
ibat_ua);
|
||||
|
||||
/* always report a higher soc */
|
||||
if (chg_soc > chip->prev_chg_soc)
|
||||
chip->prev_chg_soc = chg_soc;
|
||||
|
||||
pr_debug("CHG SOC %d\n", chip->prev_chg_soc);
|
||||
return chip->prev_chg_soc;
|
||||
}
|
||||
|
||||
static int last_soc_est = -EINVAL;
|
||||
static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
||||
int rbatt , int fcc_uah, int uuc_uah, int cc_uah)
|
||||
|
@ -1534,9 +1586,6 @@ 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;
|
||||
|
@ -1545,6 +1594,11 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
|||
(s64)fcc_uah - uuc_uah);
|
||||
soc_est = bound_soc(soc_est);
|
||||
|
||||
if (ibat_ua < 0) {
|
||||
soc = charging_adjustments(chip, soc, vbat_uv, ibat_ua);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* do not adjust
|
||||
* if soc is same as what bms calculated
|
||||
|
@ -1628,10 +1682,10 @@ static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
|
|||
out:
|
||||
pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, "
|
||||
"soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, "
|
||||
"pc_new = %d, soc_new = %d\n",
|
||||
"pc_new = %d, soc_new = %d, rbatt = %d, m = %d\n",
|
||||
ibat_ua, vbat_uv, ocv_est_uv, pc_est,
|
||||
soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
|
||||
pc_new, soc_new);
|
||||
pc_new, soc_new, rbatt, m);
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
@ -2402,6 +2456,9 @@ void pm8921_bms_charging_began(void)
|
|||
IBAT_TOL_MASK, IBAT_TOL_DEFAULT);
|
||||
the_chip->charge_time_us = 0;
|
||||
the_chip->catch_up_time_us = 0;
|
||||
|
||||
the_chip->soc_at_cv = -EINVAL;
|
||||
the_chip->prev_chg_soc = -EINVAL;
|
||||
pr_debug("start_percent = %u%%\n", the_chip->start_percent);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
|
||||
|
@ -2507,6 +2564,8 @@ void pm8921_bms_charging_end(int is_battery_full)
|
|||
the_chip->end_percent = -EINVAL;
|
||||
the_chip->charge_time_us = 0;
|
||||
the_chip->catch_up_time_us = 0;
|
||||
the_chip->soc_at_cv = -EINVAL;
|
||||
the_chip->prev_chg_soc = -EINVAL;
|
||||
pm_bms_masked_write(the_chip, BMS_TOLERANCES,
|
||||
IBAT_TOL_MASK, IBAT_TOL_NOCHG);
|
||||
}
|
||||
|
@ -3107,6 +3166,7 @@ static int __devinit pm8921_bms_probe(struct platform_device *pdev)
|
|||
chip->r_sense = pdata->r_sense;
|
||||
chip->v_cutoff = pdata->v_cutoff;
|
||||
chip->max_voltage_uv = pdata->max_voltage_uv;
|
||||
chip->chg_term_ua = pdata->chg_term_ua;
|
||||
chip->batt_type = pdata->battery_type;
|
||||
chip->rconn_mohm = pdata->rconn_mohm;
|
||||
chip->start_percent = -EINVAL;
|
||||
|
|
|
@ -133,6 +133,7 @@ struct pm8921_bms_platform_data {
|
|||
int shutdown_soc_valid_limit;
|
||||
int ignore_shutdown_soc;
|
||||
int adjust_soc_low_threshold;
|
||||
int chg_term_ua;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
|
||||
|
|
Loading…
Reference in a new issue