diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt | 7 | ||||
-rw-r--r-- | arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/qcom/msm-pmi8998.dtsi | 1 | ||||
-rw-r--r-- | drivers/power/qcom-charger/fg-core.h | 9 | ||||
-rw-r--r-- | drivers/power/qcom-charger/fg-reg.h | 4 | ||||
-rw-r--r-- | drivers/power/qcom-charger/qpnp-fg-gen3.c | 66 |
6 files changed, 77 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt index 808e18b495d5..baf534695cc1 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -36,6 +36,12 @@ First Level Node - FG Gen3 device Definition: For details about IIO bindings see: Documentation/devicetree/bindings/iio/iio-bindings.txt +- qcom,rradc-base + Usage: required + Value type: <u32> + Definition: Should specify the base address of RR_ADC peripheral. This + is used for reading certain peripheral registers under it. + - qcom,fg-cutoff-voltage Usage: optional Value type: <u32> @@ -290,6 +296,7 @@ pmi8998_fg: qpnp,fg { qcom,pmic-revid = <&pmi8998_revid>; io-channels = <&pmi8998_rradc 3>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,ki-coeff-soc-dischg = <30 60 90>; qcom,ki-coeff-med-dischg = <800 1000 1400>; qcom,ki-coeff-hi-dischg = <1200 1500 2100>; diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi index 37e39b776613..0168cb2cddb3 100644 --- a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi @@ -506,6 +506,7 @@ qcom,pmic-revid = <&pmfalcon_revid>; io-channels = <&pmfalcon_rradc 0>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi index 0dc9da9289e2..3fa85d918f6c 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi @@ -321,6 +321,7 @@ qcom,pmic-revid = <&pmi8998_revid>; io-channels = <&pmi8998_rradc 0>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 9ddd18800f9d..e284de8bdff1 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -39,6 +39,12 @@ pr_debug(fmt, ##__VA_ARGS__); \ } while (0) +#define is_between(left, right, value) \ + (((left) >= (right) && (left) >= (value) \ + && (value) >= (right)) \ + || ((left) <= (right) && (left) <= (value) \ + && (value) <= (right))) + /* Awake votable reasons */ #define SRAM_READ "fg_sram_read" #define SRAM_WRITE "fg_sram_write" @@ -310,8 +316,9 @@ struct fg_chip { u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; + u32 rradc_base; u32 wa_flags; - int batt_id_kohms; + int batt_id_ohms; int charge_status; int prev_charge_status; int charge_done; diff --git a/drivers/power/qcom-charger/fg-reg.h b/drivers/power/qcom-charger/fg-reg.h index ffc46f328f91..7ad26215e469 100644 --- a/drivers/power/qcom-charger/fg-reg.h +++ b/drivers/power/qcom-charger/fg-reg.h @@ -13,6 +13,10 @@ #ifndef __FG_REG_H__ #define __FG_REG_H__ +/* FG_ADC_RR register definitions used only for READ */ +#define ADC_RR_FAKE_BATT_LOW_LSB(chip) (chip->rradc_base + 0x58) +#define ADC_RR_FAKE_BATT_HIGH_LSB(chip) (chip->rradc_base + 0x5A) + /* FG_BATT_SOC register definitions */ #define BATT_SOC_FG_ALG_STS(chip) (chip->batt_soc_base + 0x06) #define BATT_SOC_FG_ALG_AUX_STS0(chip) (chip->batt_soc_base + 0x07) diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 74fa041738ff..fbafade817e0 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -693,18 +693,57 @@ static bool is_batt_empty(struct fg_chip *chip) return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); } -#define DEBUG_BATT_ID_KOHMS 7 +static int fg_get_debug_batt_id(struct fg_chip *chip, int *batt_id) +{ + int rc; + u64 temp; + u8 buf[2]; + + rc = fg_read(chip, ADC_RR_FAKE_BATT_LOW_LSB(chip), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + ADC_RR_FAKE_BATT_LOW_LSB(chip), rc); + return rc; + } + + /* + * Fake battery threshold is encoded in the following format. + * Threshold (code) = (battery_id in Ohms) * 0.00015 * 2^10 / 2.5 + */ + temp = (buf[1] << 8 | buf[0]) * 2500000; + do_div(temp, 150 * 1024); + batt_id[0] = temp; + rc = fg_read(chip, ADC_RR_FAKE_BATT_HIGH_LSB(chip), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + ADC_RR_FAKE_BATT_HIGH_LSB(chip), rc); + return rc; + } + + temp = (buf[1] << 8 | buf[0]) * 2500000; + do_div(temp, 150 * 1024); + batt_id[1] = temp; + pr_debug("debug batt_id range: [%d %d]\n", batt_id[0], batt_id[1]); + return 0; +} + static bool is_debug_batt_id(struct fg_chip *chip) { - int batt_id_delta = 0; + int debug_batt_id[2], rc; - if (!chip->batt_id_kohms) + if (!chip->batt_id_ohms) return false; - batt_id_delta = abs(chip->batt_id_kohms - DEBUG_BATT_ID_KOHMS); - if (batt_id_delta <= 1) { - fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dKohms\n", - chip->batt_id_kohms); + rc = fg_get_debug_batt_id(chip, debug_batt_id); + if (rc < 0) { + pr_err("Failed to get debug batt_id, rc=%d\n", rc); + return false; + } + + if (is_between(debug_batt_id[0], debug_batt_id[1], + chip->batt_id_ohms)) { + fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dohms\n", + chip->batt_id_ohms); return true; } @@ -792,8 +831,8 @@ static int fg_get_batt_profile(struct fg_chip *chip) return rc; } + chip->batt_id_ohms = batt_id; batt_id /= 1000; - chip->batt_id_kohms = batt_id; batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { pr_err("Batterydata not available\n"); @@ -3076,10 +3115,17 @@ static int fg_parse_dt(struct fg_chip *chip) } } + rc = of_property_read_u32(node, "qcom,rradc-base", &base); + if (rc < 0) { + dev_err(chip->dev, "rradc-base not specified, rc=%d\n", rc); + return rc; + } + chip->rradc_base = base; + rc = fg_get_batt_profile(chip); if (rc < 0) pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", - chip->batt_id_kohms, rc); + chip->batt_id_ohms / 1000, rc); /* Read all the optional properties below */ rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp); @@ -3362,7 +3408,7 @@ static int fg_gen3_probe(struct platform_device *pdev) if (!rc) pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n", - msoc, volt_uv, batt_temp, chip->batt_id_kohms); + msoc, volt_uv, batt_temp, chip->batt_id_ohms / 1000); device_init_wakeup(chip->dev, true); if (chip->profile_available) |