diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-11-08 11:19:11 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-11-08 11:19:11 -0800 |
| commit | bd04f6926ffd8fa1bce6ce31a7d338b0d9bbb984 (patch) | |
| tree | dc36f13301f7d05a2fd2de15c8166b662e31d669 | |
| parent | 27df8e442563c4ca7313fd30fb7f158703865e3e (diff) | |
| parent | e0520b6c77382bd72264be8a4993a9d70af7dd1d (diff) | |
Merge "qpnp-fg-gen3: support configuring ESR FCC based on charging status"
| -rw-r--r-- | Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt | 2 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt | 9 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi | 5 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/fg-core.h | 3 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-fg-gen3.c | 90 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-smb2.c | 43 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-reg.h | 4 |
7 files changed, 152 insertions, 4 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 caabcd347a72..4f5e0a117b2d 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -55,7 +55,7 @@ First Level Node - FG Gen3 device be notified via the power supply framework. The userspace will read 0% soc and immediately shutdown. If this property is not specified, then the default value used will be - 3100mV. + 2800mV. - qcom,fg-vbatt-low-thr Usage: optional diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt index 82386ba9b082..7090426c68f8 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt @@ -129,6 +129,15 @@ Charger specific properties: happen but the adapter won't be asked to switch to a higher voltage point. +- qcom,chg-inhibit-threshold-mv + Usage: optional + Value type: <u32> + Definition: Charge inhibit threshold in milli-volts. Charging will be + inhibited when the battery voltage is within this threshold + from Vfloat at charger insertion. If this is not specified + then charge inhibit will be disabled by default. + Allowed values are: 50, 100, 200, 300. + ============================================= Second Level Nodes - SMB2 Charger Peripherals ============================================= diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index a5243aff4282..f4ca25668814 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -321,7 +321,7 @@ qcom,pmic-revid = <&pmicobalt_revid>; io-channels = <&pmicobalt_rradc 0>; io-channel-names = "rradc_batt_id"; - qcom,fg-esr-timer-awake = <64>; + qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; status = "okay"; @@ -334,7 +334,8 @@ <0x2 0x40 0x2 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x3 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x40 0x5 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x40 0x5 + IRQ_TYPE_EDGE_RISING>, <0x2 0x40 0x6 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x7 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "soc-update", diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index cb5880189fbf..3f8f66f1f7d8 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -259,6 +259,7 @@ struct fg_chip { struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; + struct power_supply *parallel_psy; struct iio_channel *batt_id_chan; struct fg_memif *sram; struct fg_irq_info *irqs; @@ -288,8 +289,10 @@ struct fg_chip { bool battery_missing; bool fg_restarting; bool charge_full; + bool charge_empty; bool recharge_soc_adjusted; bool ki_coeff_dischg_en; + bool esr_fcc_ctrl_en; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index c9edc667f35d..00a3f3ecdc20 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -676,6 +676,7 @@ static bool is_debug_batt_id(struct fg_chip *chip) #define FULL_CAPACITY 100 #define FULL_SOC_RAW 255 #define DEBUG_BATT_SOC 67 +#define EMPTY_SOC 0 static int fg_get_prop_capacity(struct fg_chip *chip, int *val) { int rc, msoc; @@ -685,6 +686,11 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } + if (chip->charge_empty) { + *val = EMPTY_SOC; + return 0; + } + if (chip->charge_full) { *val = FULL_CAPACITY; return 0; @@ -903,6 +909,17 @@ static bool is_charger_available(struct fg_chip *chip) return true; } +static bool is_parallel_charger_available(struct fg_chip *chip) +{ + if (!chip->parallel_psy) + chip->parallel_psy = power_supply_get_by_name("parallel"); + + if (!chip->parallel_psy) + return false; + + return true; +} + static int fg_save_learned_cap_to_sram(struct fg_chip *chip) { int16_t cc_mah; @@ -1375,6 +1392,72 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip) return 0; } +static int fg_esr_fcc_config(struct fg_chip *chip) +{ + union power_supply_propval prop = {0, }; + int rc; + bool parallel_en = false; + + if (is_parallel_charger_available(chip)) { + rc = power_supply_get_property(chip->parallel_psy, + POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop); + if (rc < 0) { + pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n", + rc); + return rc; + } + parallel_en = prop.intval; + } + + fg_dbg(chip, FG_POWER_SUPPLY, "status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n", + chip->status, parallel_en, chip->esr_fcc_ctrl_en); + + if (chip->status == POWER_SUPPLY_STATUS_CHARGING && parallel_en) { + if (chip->esr_fcc_ctrl_en) + return 0; + + /* + * When parallel charging is enabled, configure ESR FCC to + * 300mA to trigger an ESR pulse. Without this, FG can ask + * the main charger to increase FCC when it is supposed to + * decrease it. + */ + rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip), + ESR_FAST_CRG_IVAL_MASK | + ESR_FAST_CRG_CTL_EN_BIT, + ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_INFO_ESR_FAST_CRG_CFG(chip), rc); + return rc; + } + + chip->esr_fcc_ctrl_en = true; + } else { + if (!chip->esr_fcc_ctrl_en) + return 0; + + /* + * If we're here, then it means either the device is not in + * charging state or parallel charging is disabled. Disable + * ESR fast charge current control in SW. + */ + rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip), + ESR_FAST_CRG_CTL_EN_BIT, 0); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_INFO_ESR_FAST_CRG_CFG(chip), rc); + return rc; + } + + chip->esr_fcc_ctrl_en = false; + } + + fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n", + chip->esr_fcc_ctrl_en); + return 0; +} + static void status_change_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, @@ -1422,6 +1505,10 @@ static void status_change_work(struct work_struct *work) rc = fg_adjust_ki_coeff_dischg(chip); if (rc < 0) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); + + rc = fg_esr_fcc_config(chip); + if (rc < 0) + pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc); out: pm_relax(chip->dev); } @@ -2302,6 +2389,7 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data) { struct fg_chip *chip = data; + chip->charge_empty = true; if (is_charger_available(chip)) power_supply_changed(chip->batt_psy); @@ -2523,7 +2611,7 @@ static int fg_parse_ki_coefficients(struct fg_chip *chip) } #define DEFAULT_CUTOFF_VOLT_MV 3200 -#define DEFAULT_EMPTY_VOLT_MV 3100 +#define DEFAULT_EMPTY_VOLT_MV 2800 #define DEFAULT_CHG_TERM_CURR_MA 100 #define DEFAULT_SYS_TERM_CURR_MA -125 #define DEFAULT_DELTA_SOC_THR 1 diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 92c2238de350..a00ad8343a88 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -225,6 +225,7 @@ struct smb_dt_props { s32 step_cc_delta[STEP_CHARGING_MAX_STEPS]; struct device_node *revid_dev_node; int float_option; + int chg_inhibit_thr_mv; bool hvdcp_disable; }; @@ -335,6 +336,14 @@ static int smb2_parse_dt(struct smb2 *chip) chip->dt.hvdcp_disable = of_property_read_bool(node, "qcom,hvdcp-disable"); + of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv", + &chip->dt.chg_inhibit_thr_mv); + if ((chip->dt.chg_inhibit_thr_mv < 0 || + chip->dt.chg_inhibit_thr_mv > 300)) { + pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n"); + return -EINVAL; + } + return 0; } @@ -1213,6 +1222,40 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } + switch (chip->dt.chg_inhibit_thr_mv) { + case 50: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_50MV); + break; + case 100: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_100MV); + break; + case 200: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_200MV); + break; + case 300: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_300MV); + break; + case 0: + rc = smblib_masked_write(chg, CHGR_CFG2_REG, + CHARGER_INHIBIT_BIT, 0); + default: + break; + } + + if (rc < 0) { + dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n", + rc); + return rc; + } + return rc; } diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index a74fcf730a8c..2aed4cf294a2 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -184,6 +184,10 @@ enum { #define CHARGE_INHIBIT_THRESHOLD_CFG_REG (CHGR_BASE + 0x72) #define CHARGE_INHIBIT_THRESHOLD_MASK GENMASK(1, 0) +#define CHARGE_INHIBIT_THRESHOLD_50MV 0 +#define CHARGE_INHIBIT_THRESHOLD_100MV 1 +#define CHARGE_INHIBIT_THRESHOLD_200MV 2 +#define CHARGE_INHIBIT_THRESHOLD_300MV 3 #define RECHARGE_THRESHOLD_CFG_REG (CHGR_BASE + 0x73) #define RECHARGE_THRESHOLD_MASK GENMASK(1, 0) |
