Loading drivers/power/qpnp-charger.c +71 −25 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ #define BOOST_ILIM 0x78 #define USB_SPARE 0xDF #define DC_COMP_OVR1 0xE9 #define CHGR_COMP_OVR1 0xEE #define REG_OFFSET_PERP_SUBTYPE 0x05 Loading Loading @@ -390,6 +391,8 @@ struct qpnp_chg_chip { bool power_stage_workaround_enable; }; static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip); static struct of_device_id qpnp_charger_match_table[] = { { .compatible = QPNP_CHARGER_DEV_NAME, }, Loading Loading @@ -1857,6 +1860,29 @@ static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip) return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0; } #define VBATDET_BYPASS 0x01 static int bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass) { int rc; pr_debug("bypass %d\n", bypass); rc = qpnp_chg_masked_write(chip, chip->chgr_base + SEC_ACCESS, 0xA5, 0xA5, 1); rc |= qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_COMP_OVR1, 0xFF, bypass ? VBATDET_BYPASS : 0, 1); if (rc) { pr_err("Failed to bypass vbatdet comp rc = %d\n", rc); return rc; } return rc; } static irqreturn_t qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) { Loading Loading @@ -1885,6 +1911,11 @@ qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) if (fastchg_on) { chip->chg_done = false; bypass_vbatdet_comp(chip, 1); if (chip->bat_is_warm || chip->bat_is_cool) { qpnp_chg_set_appropriate_vddmax(chip); qpnp_chg_set_appropriate_battery_current(chip); } if (chip->resuming_charging) { chip->resuming_charging = false; Loading @@ -1901,6 +1932,8 @@ qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) } else { if (chip->parallel_ovp_mode) switch_parallel_ovp_mode(chip, 0); if (!chip->bat_is_warm && !chip->bat_is_cool) bypass_vbatdet_comp(chip, 0); } } Loading Loading @@ -2771,6 +2804,25 @@ static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes) return 0; } static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip) { unsigned int chg_current = chip->max_bat_chg_current; if (chip->bat_is_cool) chg_current = min(chg_current, chip->cool_bat_chg_ma); if (chip->bat_is_warm) chg_current = min(chg_current, chip->warm_bat_chg_ma); if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation) chg_current = min(chg_current, chip->thermal_mitigation[chip->therm_lvl_sel]); pr_debug("setting %d mA\n", chg_current); qpnp_chg_ibatmax_set(chip, chg_current); } static int qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage) { Loading Loading @@ -2978,25 +3030,6 @@ qpnp_boost_vget_uv(struct qpnp_chg_chip *chip) return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV); } static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip) { unsigned int chg_current = chip->max_bat_chg_current; if (chip->bat_is_cool) chg_current = min(chg_current, chip->cool_bat_chg_ma); if (chip->bat_is_warm) chg_current = min(chg_current, chip->warm_bat_chg_ma); if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation) chg_current = min(chg_current, chip->thermal_mitigation[chip->therm_lvl_sel]); pr_debug("setting %d mA\n", chg_current); qpnp_chg_ibatmax_set(chip, chg_current); } static void qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel) { Loading Loading @@ -3571,9 +3604,6 @@ qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx) chip->bat_is_cool = bat_cool; chip->bat_is_warm = bat_warm; if (bat_cool || bat_warm) chip->resuming_charging = false; /** * set appropriate voltages and currents. * Loading @@ -3581,9 +3611,25 @@ qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx) * driver will not resume with SoC. Only vbatdet is used to * determine resume of charging. */ if (bat_cool || bat_warm) { chip->resuming_charging = false; qpnp_chg_set_appropriate_vbatdet(chip); /* To avoid ARB, only vbatdet is configured in * warm/cold zones. Once vbat < vbatdet the * appropriate vddmax/ibatmax adjustments will * be made in the fast charge interrupt. */ bypass_vbatdet_comp(chip, 1); qpnp_chg_charge_en(chip, !chip->charging_disabled); qpnp_chg_charge_en(chip, chip->charging_disabled); qpnp_chg_charge_en(chip, !chip->charging_disabled); } else { bypass_vbatdet_comp(chip, 0); /* restore normal parameters */ qpnp_chg_set_appropriate_vbatdet(chip); qpnp_chg_set_appropriate_vddmax(chip); qpnp_chg_set_appropriate_battery_current(chip); qpnp_chg_set_appropriate_vbatdet(chip); } } pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n", Loading Loading
drivers/power/qpnp-charger.c +71 −25 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ #define BOOST_ILIM 0x78 #define USB_SPARE 0xDF #define DC_COMP_OVR1 0xE9 #define CHGR_COMP_OVR1 0xEE #define REG_OFFSET_PERP_SUBTYPE 0x05 Loading Loading @@ -390,6 +391,8 @@ struct qpnp_chg_chip { bool power_stage_workaround_enable; }; static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip); static struct of_device_id qpnp_charger_match_table[] = { { .compatible = QPNP_CHARGER_DEV_NAME, }, Loading Loading @@ -1857,6 +1860,29 @@ static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip) return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0; } #define VBATDET_BYPASS 0x01 static int bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass) { int rc; pr_debug("bypass %d\n", bypass); rc = qpnp_chg_masked_write(chip, chip->chgr_base + SEC_ACCESS, 0xA5, 0xA5, 1); rc |= qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_COMP_OVR1, 0xFF, bypass ? VBATDET_BYPASS : 0, 1); if (rc) { pr_err("Failed to bypass vbatdet comp rc = %d\n", rc); return rc; } return rc; } static irqreturn_t qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) { Loading Loading @@ -1885,6 +1911,11 @@ qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) if (fastchg_on) { chip->chg_done = false; bypass_vbatdet_comp(chip, 1); if (chip->bat_is_warm || chip->bat_is_cool) { qpnp_chg_set_appropriate_vddmax(chip); qpnp_chg_set_appropriate_battery_current(chip); } if (chip->resuming_charging) { chip->resuming_charging = false; Loading @@ -1901,6 +1932,8 @@ qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip) } else { if (chip->parallel_ovp_mode) switch_parallel_ovp_mode(chip, 0); if (!chip->bat_is_warm && !chip->bat_is_cool) bypass_vbatdet_comp(chip, 0); } } Loading Loading @@ -2771,6 +2804,25 @@ static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes) return 0; } static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip) { unsigned int chg_current = chip->max_bat_chg_current; if (chip->bat_is_cool) chg_current = min(chg_current, chip->cool_bat_chg_ma); if (chip->bat_is_warm) chg_current = min(chg_current, chip->warm_bat_chg_ma); if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation) chg_current = min(chg_current, chip->thermal_mitigation[chip->therm_lvl_sel]); pr_debug("setting %d mA\n", chg_current); qpnp_chg_ibatmax_set(chip, chg_current); } static int qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage) { Loading Loading @@ -2978,25 +3030,6 @@ qpnp_boost_vget_uv(struct qpnp_chg_chip *chip) return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV); } static void qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip) { unsigned int chg_current = chip->max_bat_chg_current; if (chip->bat_is_cool) chg_current = min(chg_current, chip->cool_bat_chg_ma); if (chip->bat_is_warm) chg_current = min(chg_current, chip->warm_bat_chg_ma); if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation) chg_current = min(chg_current, chip->thermal_mitigation[chip->therm_lvl_sel]); pr_debug("setting %d mA\n", chg_current); qpnp_chg_ibatmax_set(chip, chg_current); } static void qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel) { Loading Loading @@ -3571,9 +3604,6 @@ qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx) chip->bat_is_cool = bat_cool; chip->bat_is_warm = bat_warm; if (bat_cool || bat_warm) chip->resuming_charging = false; /** * set appropriate voltages and currents. * Loading @@ -3581,9 +3611,25 @@ qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx) * driver will not resume with SoC. Only vbatdet is used to * determine resume of charging. */ if (bat_cool || bat_warm) { chip->resuming_charging = false; qpnp_chg_set_appropriate_vbatdet(chip); /* To avoid ARB, only vbatdet is configured in * warm/cold zones. Once vbat < vbatdet the * appropriate vddmax/ibatmax adjustments will * be made in the fast charge interrupt. */ bypass_vbatdet_comp(chip, 1); qpnp_chg_charge_en(chip, !chip->charging_disabled); qpnp_chg_charge_en(chip, chip->charging_disabled); qpnp_chg_charge_en(chip, !chip->charging_disabled); } else { bypass_vbatdet_comp(chip, 0); /* restore normal parameters */ qpnp_chg_set_appropriate_vbatdet(chip); qpnp_chg_set_appropriate_vddmax(chip); qpnp_chg_set_appropriate_battery_current(chip); qpnp_chg_set_appropriate_vbatdet(chip); } } pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n", Loading