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>
This commit is contained in:
parent
4fa5fdc375
commit
48734a7d0b
3 changed files with 97 additions and 27 deletions
|
@ -156,12 +156,12 @@ First Level Node - FG Gen3 device
|
|||
|
||||
- qcom,cycle-counter-en
|
||||
Usage: optional
|
||||
Value type: <bool>
|
||||
Value type: <empty>
|
||||
Definition: Enables the cycle counter feature.
|
||||
|
||||
- qcom,fg-force-load-profile
|
||||
Usage: optional
|
||||
Value type: <bool>
|
||||
Value type: <empty>
|
||||
Definition: If set, battery profile will be force loaded if the profile
|
||||
loaded earlier by bootloader doesn't match with the profile
|
||||
available in the device tree.
|
||||
|
@ -229,13 +229,13 @@ First Level Node - FG Gen3 device
|
|||
Definition: Battery temperature delta interrupt threshold. Possible
|
||||
values are: 2, 4, 6 and 10. Unit is in Kelvin.
|
||||
|
||||
- qcom,hold-soc-while-full:
|
||||
- qcom,hold-soc-while-full
|
||||
Usage: optional
|
||||
Value type: <bool>
|
||||
Value type: <empty>
|
||||
Definition: A boolean property that when defined holds SOC at 100% when
|
||||
the battery is full.
|
||||
|
||||
- qcom,ki-coeff-soc-dischg:
|
||||
- qcom,ki-coeff-soc-dischg
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Array of monotonic SOC threshold values to change the ki
|
||||
|
@ -243,7 +243,7 @@ First Level Node - FG Gen3 device
|
|||
This should be defined in the ascending order and in the
|
||||
range of 0-100. Array limit is set to 3.
|
||||
|
||||
- qcom,ki-coeff-med-dischg:
|
||||
- qcom,ki-coeff-med-dischg
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Array of ki coefficient values for medium discharge current
|
||||
|
@ -254,7 +254,7 @@ First Level Node - FG Gen3 device
|
|||
is specified to make it fully functional. Value has no
|
||||
unit. Allowed range is 0 to 62200 in micro units.
|
||||
|
||||
- qcom,ki-coeff-hi-dischg:
|
||||
- qcom,ki-coeff-hi-dischg
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Array of ki coefficient values for high discharge current
|
||||
|
@ -311,6 +311,15 @@ First Level Node - FG Gen3 device
|
|||
148438 (14.84 %) will be used. Lowest possible value is
|
||||
1954 (0.19 %).
|
||||
|
||||
- qcom,fg-auto-recharge-soc
|
||||
Usage: optional
|
||||
Value type: <empty>
|
||||
Definition: A boolean property when defined will configure automatic
|
||||
recharge SOC threshold. If not specified, automatic
|
||||
recharge voltage threshold will be configured. This has
|
||||
to be configured in conjunction with the charger side
|
||||
configuration for proper functionality.
|
||||
|
||||
==========================================================
|
||||
Second Level Nodes - Peripherals managed by FG Gen3 driver
|
||||
==========================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue