power: qpnp-fg: configure irq_volt_empty in the fuel gauge

The empty soc interrupt in the fuel gauge is the last line of defense
for the fuel gauge to report 0% before the phone runs out of battery
power. Allow the threshold at which this interrupt triggers at to be
configured via the device tree in the fuel gauge driver as
qcom,irq-volt-empty-mv.

CRs-Fixed: 758265
Change-Id: I6f6fa07e3cca1119d7ff6e6cab9e20100e0eea80
Signed-off-by: Xiaozhe Shi <xiaozhes@codeaurora.org>
This commit is contained in:
Xiaozhe Shi 2014-11-25 15:56:21 -08:00
parent bbf9c0b869
commit eed97842d9
2 changed files with 28 additions and 0 deletions

View file

@ -57,6 +57,14 @@ Parent node optional properties:
property is in milliamps and should be
positive (e.g. 100mA to terminate at
-100mA).
- qcom,irq-volt-empty-mv: The voltage threshold that the empty
soc interrupt will be triggered. When
the empty soc interrupt fires, battery
soc will be pulled to 0 and the
userspace will be notified via the
power supply framework. The userspace
will read 0% soc and immediately
shutdown.
qcom,fg-soc node required properties:
- reg : offset and length of the PMIC peripheral register map.

View file

@ -119,6 +119,7 @@ enum fg_mem_setting_index {
FG_MEM_BCL_LM_THRESHOLD,
FG_MEM_BCL_MH_THRESHOLD,
FG_MEM_TERM_CURRENT,
FG_MEM_IRQ_VOLT_EMPTY,
FG_MEM_SETTING_MAX,
};
@ -151,6 +152,7 @@ static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = {
SETTING(BCL_LM_THRESHOLD, 0x47C, 2, 50),
SETTING(BCL_MH_THRESHOLD, 0x47C, 3, 752),
SETTING(TERM_CURRENT, 0x40C, 2, 250),
SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3350),
};
#define DATA(_idx, _address, _offset, _length, _value) \
@ -1950,6 +1952,22 @@ static void update_bcl_thresholds(struct fg_chip *chip)
data[lm_offset], data[mh_offset]);
}
#define VOLT_UV_TO_VOLTCMP8(volt_uv) \
((volt_uv - 2500000) / 9766)
static int update_irq_volt_empty(struct fg_chip *chip)
{
u8 data;
int volt_mv = settings[FG_MEM_IRQ_VOLT_EMPTY].value;
data = (u8)VOLT_UV_TO_VOLTCMP8(volt_mv * 1000);
if (fg_debug_mask & FG_STATUS)
pr_info("voltage = %d, converted_raw = %04x\n", volt_mv, data);
return fg_mem_write(chip, &data,
settings[FG_MEM_IRQ_VOLT_EMPTY].address, 1,
settings[FG_MEM_IRQ_VOLT_EMPTY].offset, 0);
}
#define CURRENT_UA_TO_ADC_RAW(cur_ua) \
(cur_ua * LSB_16B_DENMTR / LSB_16B_NUMRTR)
static int update_iterm(struct fg_chip *chip)
@ -1990,6 +2008,7 @@ static int fg_of_init(struct fg_chip *chip)
chip->use_thermal_coefficients = true;
}
OF_READ_SETTING(FG_MEM_RESUME_SOC, "resume-soc", rc, 1);
OF_READ_SETTING(FG_MEM_IRQ_VOLT_EMPTY, "irq-volt-empty-mv", rc, 1);
/* Get the use-otp-profile property */
chip->use_otp_profile = of_property_read_bool(
@ -2611,6 +2630,7 @@ static int fg_hw_init(struct fg_chip *chip)
int rc = 0;
update_iterm(chip);
update_irq_volt_empty(chip);
update_bcl_thresholds(chip);
rc = fg_set_auto_recharge(chip);
if (rc) {