Loading drivers/power/supply/qcom/qpnp-smbcharger.c +148 −61 Original line number Original line Diff line number Diff line Loading @@ -352,6 +352,7 @@ enum wake_reason { #define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" #define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" #define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" #define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" #define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" #define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" #define SHUTDOWN_WORKAROUND_ICL_VOTER "SHUTDOWN_WORKAROUND_ICL_VOTER" /* USB SUSPEND VOTERS */ /* USB SUSPEND VOTERS */ /* userspace has suspended charging altogether */ /* userspace has suspended charging altogether */ Loading Loading @@ -1061,6 +1062,33 @@ static int get_prop_batt_current_now(struct smbchg_chip *chip) return ua; return ua; } } #define DEFAULT_BATT_RESISTANCE_ID 0 static int get_prop_batt_resistance_id(struct smbchg_chip *chip) { int rbatt, rc; rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE_ID, &rbatt); if (rc) { pr_smb(PR_STATUS, "Couldn't get resistance id rc = %d\n", rc); rbatt = DEFAULT_BATT_RESISTANCE_ID; } return rbatt; } #define DEFAULT_BATT_FULL_CHG_CAPACITY 0 static int get_prop_batt_full_charge(struct smbchg_chip *chip) { int bfc, rc; rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CHARGE_FULL, &bfc); if (rc) { pr_smb(PR_STATUS, "Couldn't get charge_full rc = %d\n", rc); bfc = DEFAULT_BATT_FULL_CHG_CAPACITY; } return bfc; } #define DEFAULT_BATT_VOLTAGE_NOW 0 #define DEFAULT_BATT_VOLTAGE_NOW 0 static int get_prop_batt_voltage_now(struct smbchg_chip *chip) static int get_prop_batt_voltage_now(struct smbchg_chip *chip) { { Loading Loading @@ -1876,6 +1904,7 @@ static int smbchg_sw_esr_pulse_en(struct smbchg_chip *chip, bool en) return 0; return 0; } } fg_current_now = abs(fg_current_now) / 1000; icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA, icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA, fg_current_now - ESR_PULSE_CURRENT_DELTA_MA); fg_current_now - ESR_PULSE_CURRENT_DELTA_MA); rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma); rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma); Loading Loading @@ -4013,11 +4042,11 @@ static void smbchg_chg_led_blink_set(struct smbchg_chip *chip, reg = CHG_LED_OFF << CHG_LED_SHIFT; reg = CHG_LED_OFF << CHG_LED_SHIFT; } else { } else { if (blinking == 1) if (blinking == 1) reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; else if (blinking == 2) reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; else else if (blinking == 2) reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; else reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; } } rc = smbchg_sec_masked_write(chip, rc = smbchg_sec_masked_write(chip, Loading Loading @@ -4410,6 +4439,20 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, if (type == POWER_SUPPLY_TYPE_UNKNOWN) if (type == POWER_SUPPLY_TYPE_UNKNOWN) chip->usb_supply_type = type; chip->usb_supply_type = type; /* * Update TYPE property to DCP for HVDCP/HVDCP3 charger types * so that they can be recongized as AC chargers by healthd. * Don't report UNKNOWN charger type to prevent healthd missing * detecting this power_supply status change. */ if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 || chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB_DCP; else if (chip->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB; else chip->usb_psy_d.type = chip->usb_supply_type; if (!chip->skip_usb_notification) if (!chip->skip_usb_notification) power_supply_changed(chip->usb_psy); power_supply_changed(chip->usb_psy); Loading Loading @@ -4602,6 +4645,8 @@ static void handle_usb_removal(struct smbchg_chip *chip) /* Clear typec current status */ /* Clear typec current status */ if (chip->typec_psy) if (chip->typec_psy) chip->typec_current_ma = 0; chip->typec_current_ma = 0; /* cancel/wait for hvdcp pending work if any */ cancel_delayed_work_sync(&chip->hvdcp_det_work); smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present); extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present); if (chip->dpdm_reg) if (chip->dpdm_reg) Loading Loading @@ -5226,6 +5271,15 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) */ */ chip->parallel.enabled_once = false; chip->parallel.enabled_once = false; /* Enable AICL */ pr_smb(PR_MISC, "Enable AICL\n"); rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, AICL_EN_BIT); if (rc < 0) { pr_err("Couldn't enable AICL rc=%d\n", rc); goto out; } /* fake an insertion */ /* fake an insertion */ pr_smb(PR_MISC, "Faking Insertion\n"); pr_smb(PR_MISC, "Faking Insertion\n"); rc = fake_insertion_removal(chip, true); rc = fake_insertion_removal(chip, true); Loading @@ -5235,15 +5289,6 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) } } chip->hvdcp_3_det_ignore_uv = false; chip->hvdcp_3_det_ignore_uv = false; /* Enable AICL */ pr_smb(PR_MISC, "Enable AICL\n"); rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, 0); if (rc < 0) { pr_err("Couldn't enable AICL rc=%d\n", rc); return rc; } out: out: /* /* * There are many QC 2.0 chargers that collapse before the aicl deglitch * There are many QC 2.0 chargers that collapse before the aicl deglitch Loading Loading @@ -5276,49 +5321,63 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) #define APSD_RERUN BIT(0) #define APSD_RERUN BIT(0) static int rerun_apsd(struct smbchg_chip *chip) static int rerun_apsd(struct smbchg_chip *chip) { { int rc; int rc = 0; chip->hvdcp_3_det_ignore_uv = true; if (chip->schg_version == QPNP_SCHG_LITE) { pr_smb(PR_STATUS, "Re-running APSD\n"); reinit_completion(&chip->src_det_raised); reinit_completion(&chip->src_det_raised); reinit_completion(&chip->usbin_uv_lowered); reinit_completion(&chip->usbin_uv_lowered); reinit_completion(&chip->src_det_lowered); reinit_completion(&chip->src_det_lowered); reinit_completion(&chip->usbin_uv_raised); reinit_completion(&chip->usbin_uv_raised); /* re-run APSD */ /* re-run APSD */ rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD, rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD, APSD_RERUN, APSD_RERUN); APSD_RERUN, APSD_RERUN); if (rc) { if (rc) { pr_err("Couldn't re-run APSD rc=%d\n", rc); pr_err("Couldn't re-run APSD rc=%d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on rising usbin uv\n"); pr_smb(PR_MISC, "Waiting on rising usbin uv\n"); rc = wait_for_usbin_uv(chip, true); rc = wait_for_usbin_uv(chip, true); if (rc < 0) { if (rc < 0) { pr_err("wait for usbin uv failed rc = %d\n", rc); pr_err("wait for usbin uv failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on falling src det\n"); pr_smb(PR_MISC, "Waiting on falling src det\n"); rc = wait_for_src_detect(chip, false); rc = wait_for_src_detect(chip, false); if (rc < 0) { if (rc < 0) { pr_err("wait for src detect failed rc = %d\n", rc); pr_err("wait for src detect failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on falling usbin uv\n"); pr_smb(PR_MISC, "Waiting on falling usbin uv\n"); rc = wait_for_usbin_uv(chip, false); rc = wait_for_usbin_uv(chip, false); if (rc < 0) { if (rc < 0) { pr_err("wait for usbin uv failed rc = %d\n", rc); pr_err("wait for usbin uv failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on rising src det\n"); pr_smb(PR_MISC, "Waiting on rising src det\n"); rc = wait_for_src_detect(chip, true); rc = wait_for_src_detect(chip, true); if (rc < 0) { if (rc < 0) { pr_err("wait for src detect failed rc = %d\n", rc); pr_err("wait for src detect failed rc = %d\n", rc); return rc; goto out; } } else { pr_smb(PR_STATUS, "Faking Removal\n"); rc = fake_insertion_removal(chip, false); msleep(500); pr_smb(PR_STATUS, "Faking Insertion\n"); rc = fake_insertion_removal(chip, true); } } out: chip->hvdcp_3_det_ignore_uv = false; return rc; return rc; } } Loading Loading @@ -5395,8 +5454,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, 0); AICL_EN_BIT, 0); chip->hvdcp_3_det_ignore_uv = true; /* re-run APSD */ /* re-run APSD */ rc = rerun_apsd(chip); rc = rerun_apsd(chip); if (rc) { if (rc) { Loading @@ -5404,8 +5461,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) goto out; goto out; } } chip->hvdcp_3_det_ignore_uv = false; pr_smb(PR_MISC, "Enable AICL\n"); pr_smb(PR_MISC, "Enable AICL\n"); smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, AICL_EN_BIT); AICL_EN_BIT, AICL_EN_BIT); Loading Loading @@ -5434,6 +5489,10 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) out: out: chip->hvdcp_3_det_ignore_uv = false; chip->hvdcp_3_det_ignore_uv = false; restore_from_hvdcp_detection(chip); restore_from_hvdcp_detection(chip); if (!is_src_detect_high(chip)) { pr_smb(PR_MISC, "HVDCP removed - force removal\n"); update_usb_status(chip, 0, true); } return rc; return rc; } } Loading @@ -5453,6 +5512,10 @@ static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip) if (rc < 0) if (rc < 0) pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); if (!is_src_detect_high(chip)) { pr_smb(PR_MISC, "HVDCP removed\n"); update_usb_status(chip, 0, 0); } smbchg_handle_hvdcp3_disable(chip); smbchg_handle_hvdcp3_disable(chip); return rc; return rc; Loading Loading @@ -5631,6 +5694,9 @@ static int smbchg_usb_get_property(struct power_supply *psy, val->intval = chip->usb_online; val->intval = chip->usb_online; break; break; case POWER_SUPPLY_PROP_TYPE: case POWER_SUPPLY_PROP_TYPE: val->intval = chip->usb_psy_d.type; break; case POWER_SUPPLY_PROP_REAL_TYPE: val->intval = chip->usb_supply_type; val->intval = chip->usb_supply_type; break; break; case POWER_SUPPLY_PROP_HEALTH: case POWER_SUPPLY_PROP_HEALTH: Loading Loading @@ -5688,6 +5754,7 @@ static enum power_supply_property smbchg_usb_properties[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_REAL_TYPE, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH, }; }; Loading Loading @@ -5733,6 +5800,8 @@ static enum power_supply_property smbchg_battery_properties[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_RESISTANCE_ID, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE, POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE, POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, Loading Loading @@ -5924,6 +5993,12 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = get_prop_batt_voltage_now(chip); val->intval = get_prop_batt_voltage_now(chip); break; break; case POWER_SUPPLY_PROP_RESISTANCE_ID: val->intval = get_prop_batt_resistance_id(chip); break; case POWER_SUPPLY_PROP_CHARGE_FULL: val->intval = get_prop_batt_full_charge(chip); break; case POWER_SUPPLY_PROP_TEMP: case POWER_SUPPLY_PROP_TEMP: val->intval = get_prop_batt_temp(chip); val->intval = get_prop_batt_temp(chip); break; break; Loading Loading @@ -7968,20 +8043,18 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n", pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n", rc); rc); pr_smb(PR_STATUS, "Faking Removal\n"); rc = rerun_apsd(chip); fake_insertion_removal(chip, false); if (rc) msleep(500); pr_err("APSD rerun failed rc=%d\n", rc); pr_smb(PR_STATUS, "Faking Insertion\n"); fake_insertion_removal(chip, true); read_usb_type(chip, &usb_type_name, &usb_supply_type); read_usb_type(chip, &usb_type_name, &usb_supply_type); if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) { if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) { msleep(500); msleep(500); pr_smb(PR_STATUS, "Fake Removal again as type!=DCP\n"); pr_smb(PR_STATUS, "Rerun APSD as type !=DCP\n"); fake_insertion_removal(chip, false); msleep(500); rc = rerun_apsd(chip); pr_smb(PR_STATUS, "Fake Insert again as type!=DCP\n"); if (rc) fake_insertion_removal(chip, true); pr_err("APSD rerun failed rc=%d\n", rc); } } rc = vote(chip->usb_icl_votable, rc = vote(chip->usb_icl_votable, Loading @@ -7989,6 +8062,14 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) if (rc < 0) if (rc < 0) pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n", pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n", rc); rc); /* Schedule work for HVDCP detection */ if (!chip->hvdcp_not_supported) { cancel_delayed_work_sync(&chip->hvdcp_det_work); smbchg_stay_awake(chip, PM_DETECT_HVDCP); schedule_delayed_work(&chip->hvdcp_det_work, msecs_to_jiffies(HVDCP_NOTIFY_MS)); } } } } } Loading Loading @@ -8385,6 +8466,12 @@ static void smbchg_shutdown(struct platform_device *pdev) if (!is_hvdcp_present(chip)) if (!is_hvdcp_present(chip)) return; return; pr_smb(PR_MISC, "Reducing to 500mA\n"); rc = vote(chip->usb_icl_votable, SHUTDOWN_WORKAROUND_ICL_VOTER, true, 500); if (rc < 0) pr_err("Couldn't vote 500mA ICL\n"); pr_smb(PR_MISC, "Disable Parallel\n"); pr_smb(PR_MISC, "Disable Parallel\n"); mutex_lock(&chip->parallel.lock); mutex_lock(&chip->parallel.lock); smbchg_parallel_en = 0; smbchg_parallel_en = 0; Loading Loading
drivers/power/supply/qcom/qpnp-smbcharger.c +148 −61 Original line number Original line Diff line number Diff line Loading @@ -352,6 +352,7 @@ enum wake_reason { #define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" #define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" #define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" #define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" #define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" #define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" #define SHUTDOWN_WORKAROUND_ICL_VOTER "SHUTDOWN_WORKAROUND_ICL_VOTER" /* USB SUSPEND VOTERS */ /* USB SUSPEND VOTERS */ /* userspace has suspended charging altogether */ /* userspace has suspended charging altogether */ Loading Loading @@ -1061,6 +1062,33 @@ static int get_prop_batt_current_now(struct smbchg_chip *chip) return ua; return ua; } } #define DEFAULT_BATT_RESISTANCE_ID 0 static int get_prop_batt_resistance_id(struct smbchg_chip *chip) { int rbatt, rc; rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE_ID, &rbatt); if (rc) { pr_smb(PR_STATUS, "Couldn't get resistance id rc = %d\n", rc); rbatt = DEFAULT_BATT_RESISTANCE_ID; } return rbatt; } #define DEFAULT_BATT_FULL_CHG_CAPACITY 0 static int get_prop_batt_full_charge(struct smbchg_chip *chip) { int bfc, rc; rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CHARGE_FULL, &bfc); if (rc) { pr_smb(PR_STATUS, "Couldn't get charge_full rc = %d\n", rc); bfc = DEFAULT_BATT_FULL_CHG_CAPACITY; } return bfc; } #define DEFAULT_BATT_VOLTAGE_NOW 0 #define DEFAULT_BATT_VOLTAGE_NOW 0 static int get_prop_batt_voltage_now(struct smbchg_chip *chip) static int get_prop_batt_voltage_now(struct smbchg_chip *chip) { { Loading Loading @@ -1876,6 +1904,7 @@ static int smbchg_sw_esr_pulse_en(struct smbchg_chip *chip, bool en) return 0; return 0; } } fg_current_now = abs(fg_current_now) / 1000; icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA, icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA, fg_current_now - ESR_PULSE_CURRENT_DELTA_MA); fg_current_now - ESR_PULSE_CURRENT_DELTA_MA); rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma); rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma); Loading Loading @@ -4013,11 +4042,11 @@ static void smbchg_chg_led_blink_set(struct smbchg_chip *chip, reg = CHG_LED_OFF << CHG_LED_SHIFT; reg = CHG_LED_OFF << CHG_LED_SHIFT; } else { } else { if (blinking == 1) if (blinking == 1) reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; else if (blinking == 2) reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; else else if (blinking == 2) reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; else reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; } } rc = smbchg_sec_masked_write(chip, rc = smbchg_sec_masked_write(chip, Loading Loading @@ -4410,6 +4439,20 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, if (type == POWER_SUPPLY_TYPE_UNKNOWN) if (type == POWER_SUPPLY_TYPE_UNKNOWN) chip->usb_supply_type = type; chip->usb_supply_type = type; /* * Update TYPE property to DCP for HVDCP/HVDCP3 charger types * so that they can be recongized as AC chargers by healthd. * Don't report UNKNOWN charger type to prevent healthd missing * detecting this power_supply status change. */ if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 || chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB_DCP; else if (chip->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB; else chip->usb_psy_d.type = chip->usb_supply_type; if (!chip->skip_usb_notification) if (!chip->skip_usb_notification) power_supply_changed(chip->usb_psy); power_supply_changed(chip->usb_psy); Loading Loading @@ -4602,6 +4645,8 @@ static void handle_usb_removal(struct smbchg_chip *chip) /* Clear typec current status */ /* Clear typec current status */ if (chip->typec_psy) if (chip->typec_psy) chip->typec_current_ma = 0; chip->typec_current_ma = 0; /* cancel/wait for hvdcp pending work if any */ cancel_delayed_work_sync(&chip->hvdcp_det_work); smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present); extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present); if (chip->dpdm_reg) if (chip->dpdm_reg) Loading Loading @@ -5226,6 +5271,15 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) */ */ chip->parallel.enabled_once = false; chip->parallel.enabled_once = false; /* Enable AICL */ pr_smb(PR_MISC, "Enable AICL\n"); rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, AICL_EN_BIT); if (rc < 0) { pr_err("Couldn't enable AICL rc=%d\n", rc); goto out; } /* fake an insertion */ /* fake an insertion */ pr_smb(PR_MISC, "Faking Insertion\n"); pr_smb(PR_MISC, "Faking Insertion\n"); rc = fake_insertion_removal(chip, true); rc = fake_insertion_removal(chip, true); Loading @@ -5235,15 +5289,6 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) } } chip->hvdcp_3_det_ignore_uv = false; chip->hvdcp_3_det_ignore_uv = false; /* Enable AICL */ pr_smb(PR_MISC, "Enable AICL\n"); rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, 0); if (rc < 0) { pr_err("Couldn't enable AICL rc=%d\n", rc); return rc; } out: out: /* /* * There are many QC 2.0 chargers that collapse before the aicl deglitch * There are many QC 2.0 chargers that collapse before the aicl deglitch Loading Loading @@ -5276,49 +5321,63 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) #define APSD_RERUN BIT(0) #define APSD_RERUN BIT(0) static int rerun_apsd(struct smbchg_chip *chip) static int rerun_apsd(struct smbchg_chip *chip) { { int rc; int rc = 0; chip->hvdcp_3_det_ignore_uv = true; if (chip->schg_version == QPNP_SCHG_LITE) { pr_smb(PR_STATUS, "Re-running APSD\n"); reinit_completion(&chip->src_det_raised); reinit_completion(&chip->src_det_raised); reinit_completion(&chip->usbin_uv_lowered); reinit_completion(&chip->usbin_uv_lowered); reinit_completion(&chip->src_det_lowered); reinit_completion(&chip->src_det_lowered); reinit_completion(&chip->usbin_uv_raised); reinit_completion(&chip->usbin_uv_raised); /* re-run APSD */ /* re-run APSD */ rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD, rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD, APSD_RERUN, APSD_RERUN); APSD_RERUN, APSD_RERUN); if (rc) { if (rc) { pr_err("Couldn't re-run APSD rc=%d\n", rc); pr_err("Couldn't re-run APSD rc=%d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on rising usbin uv\n"); pr_smb(PR_MISC, "Waiting on rising usbin uv\n"); rc = wait_for_usbin_uv(chip, true); rc = wait_for_usbin_uv(chip, true); if (rc < 0) { if (rc < 0) { pr_err("wait for usbin uv failed rc = %d\n", rc); pr_err("wait for usbin uv failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on falling src det\n"); pr_smb(PR_MISC, "Waiting on falling src det\n"); rc = wait_for_src_detect(chip, false); rc = wait_for_src_detect(chip, false); if (rc < 0) { if (rc < 0) { pr_err("wait for src detect failed rc = %d\n", rc); pr_err("wait for src detect failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on falling usbin uv\n"); pr_smb(PR_MISC, "Waiting on falling usbin uv\n"); rc = wait_for_usbin_uv(chip, false); rc = wait_for_usbin_uv(chip, false); if (rc < 0) { if (rc < 0) { pr_err("wait for usbin uv failed rc = %d\n", rc); pr_err("wait for usbin uv failed rc = %d\n", rc); return rc; goto out; } } pr_smb(PR_MISC, "Waiting on rising src det\n"); pr_smb(PR_MISC, "Waiting on rising src det\n"); rc = wait_for_src_detect(chip, true); rc = wait_for_src_detect(chip, true); if (rc < 0) { if (rc < 0) { pr_err("wait for src detect failed rc = %d\n", rc); pr_err("wait for src detect failed rc = %d\n", rc); return rc; goto out; } } else { pr_smb(PR_STATUS, "Faking Removal\n"); rc = fake_insertion_removal(chip, false); msleep(500); pr_smb(PR_STATUS, "Faking Insertion\n"); rc = fake_insertion_removal(chip, true); } } out: chip->hvdcp_3_det_ignore_uv = false; return rc; return rc; } } Loading Loading @@ -5395,8 +5454,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, 0); AICL_EN_BIT, 0); chip->hvdcp_3_det_ignore_uv = true; /* re-run APSD */ /* re-run APSD */ rc = rerun_apsd(chip); rc = rerun_apsd(chip); if (rc) { if (rc) { Loading @@ -5404,8 +5461,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) goto out; goto out; } } chip->hvdcp_3_det_ignore_uv = false; pr_smb(PR_MISC, "Enable AICL\n"); pr_smb(PR_MISC, "Enable AICL\n"); smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, AICL_EN_BIT); AICL_EN_BIT, AICL_EN_BIT); Loading Loading @@ -5434,6 +5489,10 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) out: out: chip->hvdcp_3_det_ignore_uv = false; chip->hvdcp_3_det_ignore_uv = false; restore_from_hvdcp_detection(chip); restore_from_hvdcp_detection(chip); if (!is_src_detect_high(chip)) { pr_smb(PR_MISC, "HVDCP removed - force removal\n"); update_usb_status(chip, 0, true); } return rc; return rc; } } Loading @@ -5453,6 +5512,10 @@ static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip) if (rc < 0) if (rc < 0) pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); if (!is_src_detect_high(chip)) { pr_smb(PR_MISC, "HVDCP removed\n"); update_usb_status(chip, 0, 0); } smbchg_handle_hvdcp3_disable(chip); smbchg_handle_hvdcp3_disable(chip); return rc; return rc; Loading Loading @@ -5631,6 +5694,9 @@ static int smbchg_usb_get_property(struct power_supply *psy, val->intval = chip->usb_online; val->intval = chip->usb_online; break; break; case POWER_SUPPLY_PROP_TYPE: case POWER_SUPPLY_PROP_TYPE: val->intval = chip->usb_psy_d.type; break; case POWER_SUPPLY_PROP_REAL_TYPE: val->intval = chip->usb_supply_type; val->intval = chip->usb_supply_type; break; break; case POWER_SUPPLY_PROP_HEALTH: case POWER_SUPPLY_PROP_HEALTH: Loading Loading @@ -5688,6 +5754,7 @@ static enum power_supply_property smbchg_usb_properties[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_REAL_TYPE, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH, }; }; Loading Loading @@ -5733,6 +5800,8 @@ static enum power_supply_property smbchg_battery_properties[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_RESISTANCE_ID, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE, POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE, POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, Loading Loading @@ -5924,6 +5993,12 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = get_prop_batt_voltage_now(chip); val->intval = get_prop_batt_voltage_now(chip); break; break; case POWER_SUPPLY_PROP_RESISTANCE_ID: val->intval = get_prop_batt_resistance_id(chip); break; case POWER_SUPPLY_PROP_CHARGE_FULL: val->intval = get_prop_batt_full_charge(chip); break; case POWER_SUPPLY_PROP_TEMP: case POWER_SUPPLY_PROP_TEMP: val->intval = get_prop_batt_temp(chip); val->intval = get_prop_batt_temp(chip); break; break; Loading Loading @@ -7968,20 +8043,18 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n", pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n", rc); rc); pr_smb(PR_STATUS, "Faking Removal\n"); rc = rerun_apsd(chip); fake_insertion_removal(chip, false); if (rc) msleep(500); pr_err("APSD rerun failed rc=%d\n", rc); pr_smb(PR_STATUS, "Faking Insertion\n"); fake_insertion_removal(chip, true); read_usb_type(chip, &usb_type_name, &usb_supply_type); read_usb_type(chip, &usb_type_name, &usb_supply_type); if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) { if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) { msleep(500); msleep(500); pr_smb(PR_STATUS, "Fake Removal again as type!=DCP\n"); pr_smb(PR_STATUS, "Rerun APSD as type !=DCP\n"); fake_insertion_removal(chip, false); msleep(500); rc = rerun_apsd(chip); pr_smb(PR_STATUS, "Fake Insert again as type!=DCP\n"); if (rc) fake_insertion_removal(chip, true); pr_err("APSD rerun failed rc=%d\n", rc); } } rc = vote(chip->usb_icl_votable, rc = vote(chip->usb_icl_votable, Loading @@ -7989,6 +8062,14 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) if (rc < 0) if (rc < 0) pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n", pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n", rc); rc); /* Schedule work for HVDCP detection */ if (!chip->hvdcp_not_supported) { cancel_delayed_work_sync(&chip->hvdcp_det_work); smbchg_stay_awake(chip, PM_DETECT_HVDCP); schedule_delayed_work(&chip->hvdcp_det_work, msecs_to_jiffies(HVDCP_NOTIFY_MS)); } } } } } Loading Loading @@ -8385,6 +8466,12 @@ static void smbchg_shutdown(struct platform_device *pdev) if (!is_hvdcp_present(chip)) if (!is_hvdcp_present(chip)) return; return; pr_smb(PR_MISC, "Reducing to 500mA\n"); rc = vote(chip->usb_icl_votable, SHUTDOWN_WORKAROUND_ICL_VOTER, true, 500); if (rc < 0) pr_err("Couldn't vote 500mA ICL\n"); pr_smb(PR_MISC, "Disable Parallel\n"); pr_smb(PR_MISC, "Disable Parallel\n"); mutex_lock(&chip->parallel.lock); mutex_lock(&chip->parallel.lock); smbchg_parallel_en = 0; smbchg_parallel_en = 0; Loading