summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-11-09 16:40:27 -0800
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-11-10 12:14:50 -0800
commit361a315fe3557a88de665ff33b4233e429a12e3f (patch)
tree2c8f645795172cd1e438295ac07b8e43d50172b5
parentbc17be09dac840cd3d0e00c8bf70e749080908d8 (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.h1
-rw-r--r--drivers/power/qcom-charger/fg-memif.c2
-rw-r--r--drivers/power/qcom-charger/fg-reg.h3
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c64
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);