summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-12-22 18:55:25 -0800
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>2017-02-02 21:02:40 -0800
commit48734a7d0b79c316ad9def202f0e176204f2ea2c (patch)
tree94e3bfc05107aedb164051c7d199e0c8b1dd3cf1 /drivers
parent4fa5fdc375d8f80271aadab4022c94132580cb45 (diff)
qpnp-fg-gen3: Adjust recharge voltage to help SOC masking
When SOC masking algorithm is enabled, a SOC of 100 will be shown to the user when certain conditions are met. When the device starts discharging after charge termination, auto recharge will be triggered once the SOC or Vbatt goes below the threshold. When the recharge is based on Vbatt, a fluctutation in Vbatt can cause issues in SOC masking algorithm. To make it robust, adjust the recharge voltage dynamically based on charging status and battery SOC. Add a device tree property to allow configuring auto recharge to be based off SOC or battery voltage. This will help the user to select auto recharge configuration easily. Change-Id: I2d749806aa51b9fa747967b592b6622cc12bee65 Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/supply/qcom/fg-core.h1
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c100
2 files changed, 81 insertions, 20 deletions
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index c9cc03b6c53a..c0d30b96122c 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -206,6 +206,7 @@ enum wa_flags {
struct fg_dt_props {
bool force_load_profile;
bool hold_soc_while_full;
+ bool auto_recharge_soc;
int cutoff_volt_mv;
int empty_volt_mv;
int vbatt_low_thr_mv;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 6d77823071ca..4498591fee4c 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1407,6 +1407,36 @@ static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
return 0;
}
+static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv)
+{
+ u8 buf;
+ int rc;
+
+ if (chip->dt.auto_recharge_soc)
+ return 0;
+
+ /* This configuration is available only for pmicobalt v2.0 and above */
+ if (chip->wa_flags & PMI8998_V1_REV_WA)
+ return 0;
+
+ fg_dbg(chip, FG_STATUS, "Setting recharge voltage to %dmV\n",
+ voltage_mv);
+ fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, voltage_mv, &buf);
+ rc = fg_sram_write(chip,
+ chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
+ chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
+ &buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
+ FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+#define AUTO_RECHG_VOLT_LOW_LIMIT_MV 3700
static int fg_charge_full_update(struct fg_chip *chip)
{
union power_supply_propval prop = {0, };
@@ -1454,18 +1484,46 @@ static int fg_charge_full_update(struct fg_chip *chip)
return rc;
}
- fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d\n",
- msoc, bsoc, chip->health, chip->charge_status);
- if (chip->charge_done) {
- if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
+ fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n",
+ msoc, bsoc, chip->health, chip->charge_status,
+ chip->charge_full);
+ if (chip->charge_done && !chip->charge_full) {
+ if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) {
+ fg_dbg(chip, FG_STATUS, "Setting charge_full to true\n");
chip->charge_full = true;
- else
+ /*
+ * Lower the recharge voltage so that VBAT_LT_RECHG
+ * signal will not be asserted soon.
+ */
+ rc = fg_set_recharge_voltage(chip,
+ AUTO_RECHG_VOLT_LOW_LIMIT_MV);
+ if (rc < 0) {
+ pr_err("Error in reducing recharge voltage, rc=%d\n",
+ rc);
+ return rc;
+ }
+ } else {
fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
msoc);
- } else if ((bsoc >> 8) <= recharge_soc) {
+ }
+ } else if ((bsoc >> 8) <= recharge_soc && chip->charge_full) {
fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
bsoc >> 8, recharge_soc);
chip->charge_full = false;
+ /*
+ * Raise the recharge voltage so that VBAT_LT_RECHG signal
+ * will be asserted soon as battery SOC had dropped below
+ * the recharge SOC threshold.
+ */
+ rc = fg_set_recharge_voltage(chip,
+ chip->dt.recharge_volt_thr_mv);
+ if (rc < 0) {
+ pr_err("Error in setting recharge voltage, rc=%d\n",
+ rc);
+ return rc;
+ }
+ } else {
+ return 0;
}
if (!chip->charge_full)
@@ -1570,13 +1628,16 @@ static int fg_rconn_config(struct fg_chip *chip)
static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
{
- u8 buf[4];
+ u8 buf;
int rc;
- fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
+ if (!chip->dt.auto_recharge_soc)
+ return 0;
+
+ fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, &buf);
rc = fg_sram_write(chip,
chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
- chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
+ chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, &buf,
chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
@@ -1590,6 +1651,9 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip)
{
int rc, msoc, recharge_soc, new_recharge_soc = 0;
+ if (!chip->dt.auto_recharge_soc)
+ return 0;
+
recharge_soc = chip->dt.recharge_soc_thr;
/*
* If the input is present and charging had been terminated, adjust
@@ -2812,18 +2876,11 @@ static int fg_hw_init(struct fg_chip *chip)
}
}
- /* This configuration is available only for pmicobalt v2.0 and above */
- if (!(chip->wa_flags & PMI8998_V1_REV_WA) &&
- chip->dt.recharge_volt_thr_mv > 0) {
- fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR,
- chip->dt.recharge_volt_thr_mv, buf);
- rc = fg_sram_write(chip,
- chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
- chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
- buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
- FG_IMA_DEFAULT);
+ if (chip->dt.recharge_volt_thr_mv > 0) {
+ rc = fg_set_recharge_voltage(chip,
+ chip->dt.recharge_volt_thr_mv);
if (rc < 0) {
- pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
+ pr_err("Error in setting recharge_voltage, rc=%d\n",
rc);
return rc;
}
@@ -3541,6 +3598,9 @@ static int fg_parse_dt(struct fg_chip *chip)
else
chip->dt.recharge_volt_thr_mv = temp;
+ chip->dt.auto_recharge_soc = of_property_read_bool(node,
+ "qcom,fg-auto-recharge-soc");
+
rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
if (rc < 0)
chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;