diff options
author | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2016-11-09 16:40:27 -0800 |
---|---|---|
committer | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2016-11-10 12:14:50 -0800 |
commit | 361a315fe3557a88de665ff33b4233e429a12e3f (patch) | |
tree | 2c8f645795172cd1e438295ac07b8e43d50172b5 | |
parent | bc17be09dac840cd3d0e00c8bf70e749080908d8 (diff) |
qpnp-fg-gen3: Fix empty SOC handling
Currently, a flag is set when the empty SOC interrupt fires to
indicate SOC 0 to the users. This is not cleared when the battery
voltage goes up. This needs to be fixed. Remove the flag and use
the realtime status of BATT_SOC peripheral to decide it. To make
that even more robust, validate the battery voltage with the
cutoff voltage. While at it, add a print in the driver's probe to
print the battery SOC and voltage. This will be helpful to debug
different battery charging scenarios.
CRs-Fixed: 1086715
Change-Id: Icbbe0d4ab74c6f9bf6f2278a11020a9bc6c41930
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
-rw-r--r-- | drivers/power/qcom-charger/fg-core.h | 1 | ||||
-rw-r--r-- | drivers/power/qcom-charger/fg-memif.c | 2 | ||||
-rw-r--r-- | drivers/power/qcom-charger/fg-reg.h | 3 | ||||
-rw-r--r-- | drivers/power/qcom-charger/qpnp-fg-gen3.c | 64 |
4 files changed, 54 insertions, 16 deletions
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 2167eb8bae59..3f67f49377b4 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -289,7 +289,6 @@ struct fg_chip { bool battery_missing; bool fg_restarting; bool charge_full; - bool charge_empty; bool recharge_soc_adjusted; bool ki_coeff_dischg_en; bool esr_fcc_ctrl_en; diff --git a/drivers/power/qcom-charger/fg-memif.c b/drivers/power/qcom-charger/fg-memif.c index 88c96bc55ec4..a98ff7d765e3 100644 --- a/drivers/power/qcom-charger/fg-memif.c +++ b/drivers/power/qcom-charger/fg-memif.c @@ -221,7 +221,7 @@ int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts) return rc; } - fg_dbg(chip, FG_STATUS, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", + fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", err_sts, exp_sts, hw_sts); if (check_hw_sts) { diff --git a/drivers/power/qcom-charger/fg-reg.h b/drivers/power/qcom-charger/fg-reg.h index 183a1819ab3c..ffc46f328f91 100644 --- a/drivers/power/qcom-charger/fg-reg.h +++ b/drivers/power/qcom-charger/fg-reg.h @@ -26,6 +26,9 @@ #define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52) #define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56) +/* BATT_SOC_INT_RT_STS */ +#define MSOC_EMPTY_BIT BIT(5) + /* BATT_SOC_EN_CTL */ #define FG_ALGORITHM_EN_BIT BIT(7) diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index d9ae95c45f83..dfbf1adc5a38 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -655,6 +655,35 @@ static int fg_get_msoc_raw(struct fg_chip *chip, int *val) return 0; } +static bool is_batt_empty(struct fg_chip *chip) +{ + u8 status; + int rc, vbatt_uv, msoc; + + rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_SOC_INT_RT_STS(chip), rc); + return false; + } + + if (!(status & MSOC_EMPTY_BIT)) + return false; + + rc = fg_get_battery_voltage(chip, &vbatt_uv); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + return false; + } + + rc = fg_get_msoc_raw(chip, &msoc); + if (!rc) + pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status, + vbatt_uv, msoc); + + return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); +} + #define DEBUG_BATT_ID_KOHMS 7 static bool is_debug_batt_id(struct fg_chip *chip) { @@ -686,7 +715,7 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } - if (chip->charge_empty) { + if (is_batt_empty(chip)) { *val = EMPTY_SOC; return 0; } @@ -2394,14 +2423,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) struct fg_chip *chip = data; int rc; + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); if (chip->cyc_ctr.en) schedule_work(&chip->cycle_count_work); - if (is_charger_available(chip)) - power_supply_changed(chip->batt_psy); - - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); - if (chip->cl.active) fg_cap_learning_update(chip); @@ -2413,6 +2438,9 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) if (rc < 0) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); + if (is_charger_available(chip)) + power_supply_changed(chip->batt_psy); + return IRQ_HANDLED; } @@ -2420,11 +2448,10 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data) { struct fg_chip *chip = data; - chip->charge_empty = true; + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); if (is_charger_available(chip)) power_supply_changed(chip->batt_psy); - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); return IRQ_HANDLED; } @@ -2438,9 +2465,7 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *data) static irqreturn_t fg_dummy_irq_handler(int irq, void *data) { - struct fg_chip *chip = data; - - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); + pr_debug("irq %d triggered\n", irq); return IRQ_HANDLED; } @@ -2930,7 +2955,7 @@ static int fg_gen3_probe(struct platform_device *pdev) { struct fg_chip *chip; struct power_supply_config fg_psy_cfg; - int rc; + int rc, msoc, volt_uv, batt_temp; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -3023,11 +3048,22 @@ static int fg_gen3_probe(struct platform_device *pdev) goto exit; } + rc = fg_get_battery_voltage(chip, &volt_uv); + if (!rc) + rc = fg_get_prop_capacity(chip, &msoc); + + if (!rc) + rc = fg_get_battery_temp(chip, &batt_temp); + + if (!rc) + pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n", + msoc, volt_uv, batt_temp, chip->batt_id_kohms); + + device_init_wakeup(chip->dev, true); if (chip->profile_available) schedule_delayed_work(&chip->profile_load_work, 0); - device_init_wakeup(chip->dev, true); - pr_debug("FG GEN3 driver successfully probed\n"); + pr_debug("FG GEN3 driver probed successfully\n"); return 0; exit: fg_cleanup(chip); |