From b9c7f086575a916b4c56aea5fd04f013421efb19 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 5 Jun 2017 11:59:15 -0700 Subject: power: qpnp-fg-gen3: Qualify aborting capacity learning Currently, capacity learning algorithm is aborted when the charging status goes to not charging. This can happen with qnovo enabled charging where stopping the pulsing can lead to charging status change. Qualify aborting capacity learning based on the qnovo enable status and input presence. While at it, abort the capacity learning when the charging status goes to discharging and charger is removed. Change-Id: I4546e8880be0658748157cb13f048610eee932a3 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 1 + drivers/power/supply/qcom/fg-util.c | 41 +++++++++++++++++++++++++------- drivers/power/supply/qcom/qpnp-fg-gen3.c | 34 +++++++++++++++++++------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 25c9d0251cf1..1522facb6f98 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -460,6 +460,7 @@ extern void dump_sram(u8 *buf, int addr, int len); extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos); extern s64 fg_float_decode(u16 val); extern bool is_input_present(struct fg_chip *chip); +extern bool is_qnovo_en(struct fg_chip *chip); extern void fg_circ_buf_add(struct fg_circ_buf *, int); extern void fg_circ_buf_clr(struct fg_circ_buf *); extern int fg_circ_buf_avg(struct fg_circ_buf *, int *); diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c index f2395b6ba4ab..9635044e02a5 100644 --- a/drivers/power/supply/qcom/fg-util.c +++ b/drivers/power/supply/qcom/fg-util.c @@ -106,14 +106,17 @@ static struct fg_dbgfs dbgfs_data = { static bool is_usb_present(struct fg_chip *chip) { union power_supply_propval pval = {0, }; + int rc; if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); - if (chip->usb_psy) - power_supply_get_property(chip->usb_psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - else + if (!chip->usb_psy) + return false; + + rc = power_supply_get_property(chip->usb_psy, + POWER_SUPPLY_PROP_PRESENT, &pval); + if (rc < 0) return false; return pval.intval != 0; @@ -122,14 +125,17 @@ static bool is_usb_present(struct fg_chip *chip) static bool is_dc_present(struct fg_chip *chip) { union power_supply_propval pval = {0, }; + int rc; if (!chip->dc_psy) chip->dc_psy = power_supply_get_by_name("dc"); - if (chip->dc_psy) - power_supply_get_property(chip->dc_psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - else + if (!chip->dc_psy) + return false; + + rc = power_supply_get_property(chip->dc_psy, + POWER_SUPPLY_PROP_PRESENT, &pval); + if (rc < 0) return false; return pval.intval != 0; @@ -140,6 +146,25 @@ bool is_input_present(struct fg_chip *chip) return is_usb_present(chip) || is_dc_present(chip); } +bool is_qnovo_en(struct fg_chip *chip) +{ + union power_supply_propval pval = {0, }; + int rc; + + if (!chip->batt_psy) + chip->batt_psy = power_supply_get_by_name("battery"); + + if (!chip->batt_psy) + return false; + + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &pval); + if (rc < 0) + return false; + + return pval.intval != 0; +} + #define EXPONENT_SHIFT 11 #define EXPONENT_OFFSET -9 #define MANTISSA_SIGN_BIT 10 diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 42915c5481e1..a07907d3d76f 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -1397,6 +1397,7 @@ out: static void fg_cap_learning_update(struct fg_chip *chip) { int rc, batt_soc, batt_soc_msb; + bool input_present = is_input_present(chip); mutex_lock(&chip->cl.lock); @@ -1437,11 +1438,29 @@ static void fg_cap_learning_update(struct fg_chip *chip) chip->cl.init_cc_uah = 0; } + if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { + if (!input_present) { + fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", + batt_soc_msb); + chip->cl.active = false; + chip->cl.init_cc_uah = 0; + } + } + if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { - fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", - batt_soc_msb); - chip->cl.active = false; - chip->cl.init_cc_uah = 0; + if (is_qnovo_en(chip) && input_present) { + /* + * Don't abort the capacity learning when qnovo + * is enabled and input is present where the + * charging status can go to "not charging" + * intermittently. + */ + } else { + fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", + batt_soc_msb); + chip->cl.active = false; + chip->cl.init_cc_uah = 0; + } } } @@ -1976,7 +1995,7 @@ static int fg_esr_fcc_config(struct fg_chip *chip) { union power_supply_propval prop = {0, }; int rc; - bool parallel_en = false, qnovo_en = false; + bool parallel_en = false, qnovo_en; if (is_parallel_charger_available(chip)) { rc = power_supply_get_property(chip->parallel_psy, @@ -1989,10 +2008,7 @@ static int fg_esr_fcc_config(struct fg_chip *chip) parallel_en = prop.intval; } - rc = power_supply_get_property(chip->batt_psy, - POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &prop); - if (!rc) - qnovo_en = prop.intval; + qnovo_en = is_qnovo_en(chip); fg_dbg(chip, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n", chip->charge_status, parallel_en, qnovo_en, -- cgit v1.2.3