From 1819bd4e4488bf9229cc8e1e403f1eee82df482a Mon Sep 17 00:00:00 2001 From: "choongryeol.lee" Date: Fri, 25 Jan 2013 16:48:36 -0800 Subject: [PATCH] power: pm8921-bms: fix soc rising from 99% to 100% during discharging We observed that SoC suddenly increase from 98% or 99% to 100% right after charger removal. This issue caused by charging adjusting algorithm which adjust SoC to sync 100% with end of charging. During charging adjustment, the adjusted SoC could be smaller than original SoC. So when we remove charger, charging adjusting algorithm stop adjusting SoC and then bms report original SoC which is larger than before. Previously, bms driver considered most of this case by using previous SoC when SoC increase during discharging. But if SoC is 100%, previous patch doesn't work. So this patch add SoC 100% case by checking if charger is enabled. Change-Id: I70945d391c9d821eaf875f1bcd1e8787077b98da --- drivers/power/pm8921-bms.c | 8 ++------ drivers/power/pm8921-charger.c | 14 ++++++++++++++ include/linux/mfd/pm8xxx/pm8921-charger.h | 1 + 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c index 247b721910d..7d140627b62 100644 --- a/drivers/power/pm8921-bms.c +++ b/drivers/power/pm8921-bms.c @@ -1968,10 +1968,6 @@ static int scale_soc_while_chg(struct pm8921_bms_chip *chip, if (the_chip->start_percent == -EINVAL) return prev_soc; - /* if soc is called in quick succession return the last soc */ - if (delta_time_us < USEC_PER_SEC) - return prev_soc; - chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC); catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC); pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec); @@ -2306,8 +2302,8 @@ static int report_state_of_charge(struct pm8921_bms_chip *chip) } /* last_soc < soc ... scale and catch up */ - if (last_soc != -EINVAL && soc != 100 - && (last_soc < soc || the_chip->start_percent != -EINVAL)) + if (last_soc != -EINVAL && last_soc < soc + && (soc != 100 || pm8921_is_chg_auto_enable())) soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc); if (chip->eoc_check_soc && is_eoc_adjust(chip, soc)) { diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c index 691171ec53f..bade65da634 100644 --- a/drivers/power/pm8921-charger.c +++ b/drivers/power/pm8921-charger.c @@ -1794,6 +1794,20 @@ int pm8921_charger_enable(bool enable) } EXPORT_SYMBOL(pm8921_charger_enable); +int pm8921_is_chg_auto_enable(void) +{ + u8 temp = 0; + + if (!the_chip) { + pr_err("called before init\n"); + return -EINVAL; + } + + pm8xxx_readb(the_chip->dev->parent, CHG_CNTRL_3, &temp); + return temp & CHG_EN_BIT; +} +EXPORT_SYMBOL(pm8921_is_chg_auto_enable); + int pm8921_force_start_charging(void) { int rc; diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h index b86efbd9d5f..7a53e32d6fb 100644 --- a/include/linux/mfd/pm8xxx/pm8921-charger.h +++ b/include/linux/mfd/pm8xxx/pm8921-charger.h @@ -291,6 +291,7 @@ int pm8921_usb_ovp_disable(int disable); int pm8921_get_batt_state(void); int pm8921_force_start_charging(void); int pm8921_get_batt_health(void); +int pm8921_is_chg_auto_enable(void); /** * pm8921_is_batfet_closed - battery fet status