qpnp-fg-gen3: qnovo ESR/IADC workarounds

When FG IADC measurement period coincides with qnovo discharge pulses
it reads incorrect IADC values. That causes issues with SOC accuracy
and capacity learning amongst others.

The fix to IADC inaccuracy is to set a bit in the FG
peripheral while Qnovo is active.

A side effect of IADC inaccuracy fix is that the ESR
measurement goes haywire. To overcome that, disable ESR when
Qnovo is active and force an esr measurement when its between pulses.

Realize this by disabling ESR and enabling the bit when
Qnovo becomes active. The qnovo driver will set CHARGE_QNOVO_ENABLE
property on the bms psy when its active. Also provide code to
force an ESR measurement via a write to RESISTANCE property in
bms psy.

Change-Id: I7160ad6288362c17d28d67b38ec09332d9a6cbd2
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
Abhijeet Dharmapurikar 2017-07-06 18:45:32 -07:00
parent 7b5b0b5914
commit 18cb81a94f

View file

@ -75,6 +75,8 @@
#define ESR_TIMER_CHG_MAX_OFFSET 0
#define ESR_TIMER_CHG_INIT_WORD 18
#define ESR_TIMER_CHG_INIT_OFFSET 2
#define ESR_EXTRACTION_ENABLE_WORD 19
#define ESR_EXTRACTION_ENABLE_OFFSET 0
#define PROFILE_LOAD_WORD 24
#define PROFILE_LOAD_OFFSET 0
#define ESR_RSLOW_DISCHG_WORD 34
@ -3032,6 +3034,89 @@ static int fg_esr_validate(struct fg_chip *chip)
return 0;
}
static int fg_force_esr_meas(struct fg_chip *chip)
{
int rc;
int esr_uohms;
/* force esr extraction enable */
rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), BIT(0),
FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("failed to enable esr extn rc=%d\n", rc);
return rc;
}
rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
LD_REG_CTRL_BIT, 0);
if (rc < 0) {
pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
return rc;
}
rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT);
if (rc < 0) {
pr_err("Error in configuring force ESR rc=%d\n", rc);
return rc;
}
/* wait 1.5 seconds for hw to measure ESR */
msleep(1500);
rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
0);
if (rc < 0) {
pr_err("Error in restoring force ESR rc=%d\n", rc);
return rc;
}
rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
LD_REG_CTRL_BIT, LD_REG_CTRL_BIT);
if (rc < 0) {
pr_err("Error in restoring qnovo_cfg rc=%d\n", rc);
return rc;
}
/* force esr extraction disable */
rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), 0,
FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("failed to disable esr extn rc=%d\n", rc);
return rc;
}
fg_get_battery_resistance(chip, &esr_uohms);
fg_dbg(chip, FG_STATUS, "ESR uohms = %d\n", esr_uohms);
return rc;
}
static int fg_prepare_for_qnovo(struct fg_chip *chip, int qnovo_enable)
{
int rc;
/* force esr extraction disable when qnovo enables */
rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
ESR_EXTRACTION_ENABLE_OFFSET,
BIT(0), qnovo_enable ? 0 : BIT(0),
FG_IMA_DEFAULT);
if (rc < 0)
pr_err("Error in configuring esr extraction rc=%d\n", rc);
rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
LD_REG_CTRL_BIT,
qnovo_enable ? LD_REG_CTRL_BIT : 0);
if (rc < 0) {
pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
return rc;
}
fg_dbg(chip, FG_STATUS, "Prepared for Qnovo\n");
return 0;
}
/* PSY CALLBACKS STAY HERE */
static int fg_psy_get_property(struct power_supply *psy,
@ -3140,6 +3225,12 @@ static int fg_psy_set_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
rc = fg_set_constant_chg_voltage(chip, pval->intval);
break;
case POWER_SUPPLY_PROP_RESISTANCE:
rc = fg_force_esr_meas(chip);
break;
case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
rc = fg_prepare_for_qnovo(chip, pval->intval);
break;
default:
break;
}