diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-03 22:59:35 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-03 22:59:35 -0800 |
| commit | cbfe05e69faef8198eea33bc6fbda089a9580f56 (patch) | |
| tree | 651fe8cc251cf1ce2b6e926691f0f38fb8ff4cb5 /drivers | |
| parent | b1c46e3dc37a95a6edcbbc5b932900a82b511822 (diff) | |
| parent | 48734a7d0b79c316ad9def202f0e176204f2ea2c (diff) | |
Merge "qpnp-fg-gen3: Adjust recharge voltage to help SOC masking"
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/power/supply/qcom/fg-core.h | 5 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/qpnp-fg-gen3.c | 207 |
2 files changed, 169 insertions, 43 deletions
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index d71e3afd8d42..c0d30b96122c 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -156,7 +156,8 @@ enum fg_sram_param_id { FG_SRAM_ESR_TIMER_CHG_INIT, FG_SRAM_SYS_TERM_CURR, FG_SRAM_CHG_TERM_CURR, - FG_SRAM_DELTA_SOC_THR, + FG_SRAM_DELTA_MSOC_THR, + FG_SRAM_DELTA_BSOC_THR, FG_SRAM_RECHARGE_SOC_THR, FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_MED_DISCHG, @@ -205,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; @@ -345,6 +347,7 @@ struct fg_chip { bool esr_fcc_ctrl_en; bool soc_reporting_ready; bool esr_flt_cold_temp_en; + bool bsoc_delta_irq_en; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 744cbde7fc7f..92c8618ec440 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -48,8 +48,10 @@ #define KI_COEFF_HI_DISCHG_OFFSET 0 #define KI_COEFF_LOW_DISCHG_WORD 10 #define KI_COEFF_LOW_DISCHG_OFFSET 2 -#define DELTA_SOC_THR_WORD 12 -#define DELTA_SOC_THR_OFFSET 3 +#define DELTA_MSOC_THR_WORD 12 +#define DELTA_MSOC_THR_OFFSET 3 +#define DELTA_BSOC_THR_WORD 13 +#define DELTA_BSOC_THR_OFFSET 2 #define RECHARGE_SOC_THR_WORD 14 #define RECHARGE_SOC_THR_OFFSET 0 #define CHG_TERM_CURR_WORD 14 @@ -113,8 +115,10 @@ #define KI_COEFF_MED_DISCHG_v2_OFFSET 0 #define KI_COEFF_HI_DISCHG_v2_WORD 10 #define KI_COEFF_HI_DISCHG_v2_OFFSET 1 -#define DELTA_SOC_THR_v2_WORD 13 -#define DELTA_SOC_THR_v2_OFFSET 0 +#define DELTA_BSOC_THR_v2_WORD 12 +#define DELTA_BSOC_THR_v2_OFFSET 3 +#define DELTA_MSOC_THR_v2_WORD 13 +#define DELTA_MSOC_THR_v2_OFFSET 0 #define RECHARGE_SOC_THR_v2_WORD 14 #define RECHARGE_SOC_THR_v2_OFFSET 1 #define CHG_TERM_CURR_v2_WORD 15 @@ -143,6 +147,8 @@ static void fg_encode_current(struct fg_sram_param *sp, static void fg_encode_default(struct fg_sram_param *sp, enum fg_sram_param_id id, int val, u8 *buf); +static struct fg_irq_info fg_irqs[FG_IRQ_MAX]; + #define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \ _enc, _dec) \ [FG_SRAM_##_id] = { \ @@ -188,8 +194,10 @@ static struct fg_sram_param pmi8998_v1_sram_params[] = { 1000000, 122070, 0, fg_encode_current, NULL), PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1, 100000, 390625, 0, fg_encode_current, NULL), - PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048, - 100, 0, fg_encode_default, NULL), + PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, 1, + 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, 1, + 2048, 100, 0, fg_encode_default, NULL), PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD, @@ -248,8 +256,10 @@ static struct fg_sram_param pmi8998_v2_sram_params[] = { 1000000, 122070, 0, fg_encode_current, NULL), PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1, 100000, 390625, 0, fg_encode_current, NULL), - PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1, - 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_v2_WORD, DELTA_MSOC_THR_v2_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_v2_WORD, DELTA_BSOC_THR_v2_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD, RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), @@ -773,6 +783,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 BATT_MISS_SOC 50 #define EMPTY_SOC 0 static int fg_get_prop_capacity(struct fg_chip *chip, int *val) { @@ -783,6 +794,16 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } + if (chip->fg_restarting) { + *val = chip->last_soc; + return 0; + } + + if (chip->battery_missing) { + *val = BATT_MISS_SOC; + return 0; + } + if (is_batt_empty(chip)) { *val = EMPTY_SOC; return 0; @@ -1386,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, }; @@ -1398,6 +1449,16 @@ static int fg_charge_full_update(struct fg_chip *chip) if (!batt_psy_initialized(chip)) return 0; + if (!chip->charge_done && chip->bsoc_delta_irq_en) { + disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = false; + } else if (chip->charge_done && !chip->bsoc_delta_irq_en) { + enable_irq(fg_irqs[BSOC_DELTA_IRQ].irq); + enable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = true; + } + rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH, &prop); if (rc < 0) { @@ -1423,18 +1484,46 @@ static int fg_charge_full_update(struct fg_chip *chip) return rc; } - fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc, - 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) @@ -1539,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); @@ -1559,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 @@ -2062,7 +2157,6 @@ wait: goto wait; } else if (rc <= 0) { pr_err("wait for soc_ready timed out rc=%d\n", rc); - goto out; } rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0); @@ -2494,13 +2588,13 @@ static int fg_psy_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: - if (chip->fg_restarting) - pval->intval = chip->last_soc; - else - rc = fg_get_prop_capacity(chip, &pval->intval); + rc = fg_get_prop_capacity(chip, &pval->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - rc = fg_get_battery_voltage(chip, &pval->intval); + if (chip->battery_missing) + pval->intval = 3700000; + else + rc = fg_get_battery_voltage(chip, &pval->intval); break; case POWER_SUPPLY_PROP_CURRENT_NOW: rc = fg_get_battery_current(chip, &pval->intval); @@ -2753,15 +2847,27 @@ static int fg_hw_init(struct fg_chip *chip) } if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) { - fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR, + fg_encode(chip->sp, FG_SRAM_DELTA_MSOC_THR, + chip->dt.delta_soc_thr, buf); + rc = fg_sram_write(chip, + chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_word, + chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte, + buf, chip->sp[FG_SRAM_DELTA_MSOC_THR].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing delta_msoc_thr, rc=%d\n", rc); + return rc; + } + + fg_encode(chip->sp, FG_SRAM_DELTA_BSOC_THR, chip->dt.delta_soc_thr, buf); rc = fg_sram_write(chip, - chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word, - chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte, - buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len, + chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_word, + chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_byte, + buf, chip->sp[FG_SRAM_DELTA_BSOC_THR].len, FG_IMA_DEFAULT); if (rc < 0) { - pr_err("Error in writing delta_soc_thr, rc=%d\n", rc); + pr_err("Error in writing delta_bsoc_thr, rc=%d\n", rc); return rc; } } @@ -2774,18 +2880,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; } @@ -3052,7 +3151,20 @@ static irqreturn_t fg_soc_update_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) +static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data) +{ + struct fg_chip *chip = data; + int rc; + + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); + rc = fg_charge_full_update(chip); + if (rc < 0) + pr_err("Error in charge_full_update, rc=%d\n", rc); + + return IRQ_HANDLED; +} + +static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) { struct fg_chip *chip = data; int rc; @@ -3126,12 +3238,13 @@ static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = { }, [MSOC_DELTA_IRQ] = { .name = "msoc-delta", - .handler = fg_delta_soc_irq_handler, + .handler = fg_delta_msoc_irq_handler, .wakeable = true, }, [BSOC_DELTA_IRQ] = { .name = "bsoc-delta", - .handler = fg_dummy_irq_handler, + .handler = fg_delta_bsoc_irq_handler, + .wakeable = true, }, [SOC_READY_IRQ] = { .name = "soc-ready", @@ -3489,6 +3602,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; @@ -3746,6 +3862,13 @@ static int fg_gen3_probe(struct platform_device *pdev) if (fg_irqs[SOC_UPDATE_IRQ].irq) disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq); + /* Keep BSOC_DELTA_IRQ irq disabled until we require it */ + if (fg_irqs[BSOC_DELTA_IRQ].irq) { + disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = false; + } + rc = fg_debugfs_create(chip); if (rc < 0) { dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n", |
