Loading drivers/power/supply/qcom/qpnp-smb5.c +11 −6 Original line number Diff line number Diff line Loading @@ -1625,10 +1625,15 @@ static int smb5_configure_typec(struct smb_charger *chg) { int rc; /* disable apsd */ rc = smblib_configure_hvdcp_apsd(chg, false); smblib_apsd_enable(chg, true); smblib_hvdcp_detect_enable(chg, false); rc = smblib_masked_write(chg, TYPE_C_CFG_REG, BC1P2_START_ON_CC_BIT, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc); dev_err(chg->dev, "failed to write TYPE_C_CFG_REG rc=%d\n", rc); return rc; } Loading Loading @@ -2928,9 +2933,9 @@ static void smb5_shutdown(struct platform_device *pdev) HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0); smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT); /* force enable APSD */ smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT); /* force enable and rerun APSD */ smblib_apsd_enable(chg, true); smblib_masked_write(chg, CMD_APSD_REG, APSD_RERUN_BIT, APSD_RERUN_BIT); } static const struct of_device_id match_table[] = { Loading drivers/power/supply/qcom/smb1355-charger.c +1 −1 Original line number Diff line number Diff line Loading @@ -254,7 +254,7 @@ enum { static bool is_secure(struct smb1355 *chip, int addr) { if (addr == CLOCK_REQUEST_REG) if (addr == CLOCK_REQUEST_REG || addr == I2C_SS_DIG_PMIC_SID_REG) return true; /* assume everything above 0xA0 is secure */ Loading drivers/power/supply/qcom/smb5-lib.c +62 −43 Original line number Diff line number Diff line Loading @@ -791,25 +791,34 @@ int smblib_get_prop_from_bms(struct smb_charger *chg, return rc; } int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable) void smblib_apsd_enable(struct smb_charger *chg, bool enable) { int rc; u8 mask = (BC1P2_SRC_DETECT_BIT | HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT); u8 val = BC1P2_SRC_DETECT_BIT | (chg->hvdcp_disable ? 0 : (HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT)); rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, BC1P2_SRC_DETECT_BIT, enable ? BC1P2_SRC_DETECT_BIT : 0); if (rc < 0) smblib_err(chg, "failed to write USBIN_OPTIONS_1_CFG rc=%d\n", rc); } if (chg->pd_not_supported) return 0; void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable) { int rc; u8 mask; if (chg->hvdcp_disable) return; mask = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT; rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, mask, enable ? val : 0); enable ? mask : 0); if (rc < 0) smblib_err(chg, "failed to write USBIN_OPTIONS_1_CFG rc=%d\n", rc); return rc; return; } static int smblib_request_dpdm(struct smb_charger *chg, bool enable) Loading Loading @@ -1157,7 +1166,8 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT, icl_options); if (rc < 0) { smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; Loading Loading @@ -1576,6 +1586,20 @@ int smblib_get_prop_batt_capacity(struct smb_charger *chg, return rc; } static bool is_charging_paused(struct smb_charger *chg) { int rc; u8 val; rc = smblib_read(chg, CHARGING_PAUSE_CMD_REG, &val); if (rc < 0) { smblib_err(chg, "Couldn't read CHARGING_PAUSE_CMD rc=%d\n", rc); return false; } return val & CHARGING_PAUSE_CMD_BIT; } int smblib_get_prop_batt_status(struct smb_charger *chg, union power_supply_propval *val) { Loading Loading @@ -1641,6 +1665,11 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, break; } if (is_charging_paused(chg)) { val->intval = POWER_SUPPLY_STATUS_CHARGING; return 0; } if (val->intval != POWER_SUPPLY_STATUS_CHARGING) return 0; Loading Loading @@ -3555,15 +3584,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, chg->pd_active = val->intval; smblib_apsd_enable(chg, !chg->pd_active); if (chg->pd_active) { vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0); /* * Enforce 500mA for PD until the real vote comes in later. * Enforce 100mA for PD until the real vote comes in later. * It is guaranteed that pd_active is set prior to * pd_current_max */ vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_100MA); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); Loading Loading @@ -3595,16 +3626,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, "Couldn't enable secondary charger rc=%d\n", rc); /* PD hard resets failed, rerun apsd */ /* PD hard resets failed, proceed to detect QC2/3 */ if (chg->ok_to_pd) { chg->ok_to_pd = false; rc = smblib_configure_hvdcp_apsd(chg, true); if (rc < 0) { dev_err(chg->dev, "Couldn't enable APSD rc=%d\n", rc); return rc; } smblib_rerun_apsd_if_required(chg); smblib_hvdcp_detect_enable(chg, true); } } Loading Loading @@ -4204,11 +4229,9 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) /* * HVDCP 2/3, handled separately * For UNKNOWN(input not present) return without updating ICL */ if (pst == POWER_SUPPLY_TYPE_USB_HVDCP || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3 || pst == POWER_SUPPLY_TYPE_UNKNOWN) || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3) return; /* TypeC rp med or high, use rp value */ Loading Loading @@ -4248,6 +4271,7 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); break; case POWER_SUPPLY_TYPE_UNKNOWN: default: rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { Loading Loading @@ -4298,12 +4322,8 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data) int rc = 0; u8 stat; /* * Prepared to run PD or PD is active. At this moment, APSD is disabled, * but there still can be irq on apsd_done from previously unfinished * APSD run, skip it. */ if (chg->ok_to_pd) /* PD session is ongoing, ignore BC1.2 and QC detection */ if (chg->pd_active) return IRQ_HANDLED; rc = smblib_read(chg, APSD_STATUS_REG, &stat); Loading Loading @@ -4468,15 +4488,10 @@ static void typec_src_insertion(struct smb_charger *chg) chg->typec_legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT; chg->ok_to_pd = (!(chg->typec_legacy || chg->pd_disabled) || chg->early_usb_attach) && !chg->pd_not_supported; if (!chg->ok_to_pd) { rc = smblib_configure_hvdcp_apsd(chg, true); if (rc < 0) { dev_err(chg->dev, "Couldn't enable APSD rc=%d\n", rc); return; } smblib_rerun_apsd_if_required(chg); } /* allow apsd proceed to detect QC2/3 */ if (!chg->ok_to_pd) smblib_hvdcp_detect_enable(chg, true); } static void typec_sink_removal(struct smb_charger *chg) Loading Loading @@ -4506,11 +4521,7 @@ static void typec_src_removal(struct smb_charger *chg) dev_err(chg->dev, "Couldn't disable secondary charger rc=%d\n", rc); /* disable apsd */ rc = smblib_configure_hvdcp_apsd(chg, false); if (rc < 0) smblib_err(chg, "Couldn't disable APSD rc=%d\n", rc); smblib_hvdcp_detect_enable(chg, false); smblib_update_usb_type(chg); if (chg->wa_flags & BOOST_BACK_WA) { Loading Loading @@ -4601,6 +4612,11 @@ static void typec_src_removal(struct smb_charger *chg) chg->typec_legacy = false; } static void typec_mode_unattached(struct smb_charger *chg) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, USBIN_100MA); } static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) { const struct apsd_result *apsd = smblib_get_apsd_result(chg); Loading Loading @@ -4743,7 +4759,9 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) case SINK_MODE: typec_src_removal(chg); break; case UNATTACHED_MODE: default: typec_mode_unattached(chg); break; } Loading @@ -4751,6 +4769,7 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) chg->ok_to_pd = false; chg->sink_src_mode = UNATTACHED_MODE; chg->early_usb_attach = false; smblib_apsd_enable(chg, true); } if (chg->lpd_stage == LPD_STAGE_FLOAT_CANCEL) Loading drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -632,6 +632,8 @@ int smblib_icl_override(struct smb_charger *chg, bool override); enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm, ktime_t time); int smblib_toggle_smb_en(struct smb_charger *chg, int toggle); void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable); void smblib_apsd_enable(struct smb_charger *chg, bool enable); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading drivers/power/supply/qcom/smb5-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,9 @@ enum { #define CHARGING_ENABLE_CMD_REG (CHGR_BASE + 0x42) #define CHARGING_ENABLE_CMD_BIT BIT(0) #define CHARGING_PAUSE_CMD_REG (CHGR_BASE + 0x43) #define CHARGING_PAUSE_CMD_BIT BIT(0) #define CHGR_CFG2_REG (CHGR_BASE + 0x51) #define RECHG_MASK GENMASK(2, 1) #define VBAT_BASED_RECHG_BIT BIT(2) Loading Loading @@ -221,6 +224,9 @@ enum { #define USB_CMD_PULLDOWN_REG (USBIN_BASE + 0x45) #define EN_PULLDOWN_USB_IN_BIT BIT(0) #define TYPE_C_CFG_REG (USBIN_BASE + 0x58) #define BC1P2_START_ON_CC_BIT BIT(7) #define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B) #define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6) enum { Loading Loading
drivers/power/supply/qcom/qpnp-smb5.c +11 −6 Original line number Diff line number Diff line Loading @@ -1625,10 +1625,15 @@ static int smb5_configure_typec(struct smb_charger *chg) { int rc; /* disable apsd */ rc = smblib_configure_hvdcp_apsd(chg, false); smblib_apsd_enable(chg, true); smblib_hvdcp_detect_enable(chg, false); rc = smblib_masked_write(chg, TYPE_C_CFG_REG, BC1P2_START_ON_CC_BIT, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc); dev_err(chg->dev, "failed to write TYPE_C_CFG_REG rc=%d\n", rc); return rc; } Loading Loading @@ -2928,9 +2933,9 @@ static void smb5_shutdown(struct platform_device *pdev) HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0); smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT); /* force enable APSD */ smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT); /* force enable and rerun APSD */ smblib_apsd_enable(chg, true); smblib_masked_write(chg, CMD_APSD_REG, APSD_RERUN_BIT, APSD_RERUN_BIT); } static const struct of_device_id match_table[] = { Loading
drivers/power/supply/qcom/smb1355-charger.c +1 −1 Original line number Diff line number Diff line Loading @@ -254,7 +254,7 @@ enum { static bool is_secure(struct smb1355 *chip, int addr) { if (addr == CLOCK_REQUEST_REG) if (addr == CLOCK_REQUEST_REG || addr == I2C_SS_DIG_PMIC_SID_REG) return true; /* assume everything above 0xA0 is secure */ Loading
drivers/power/supply/qcom/smb5-lib.c +62 −43 Original line number Diff line number Diff line Loading @@ -791,25 +791,34 @@ int smblib_get_prop_from_bms(struct smb_charger *chg, return rc; } int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable) void smblib_apsd_enable(struct smb_charger *chg, bool enable) { int rc; u8 mask = (BC1P2_SRC_DETECT_BIT | HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT); u8 val = BC1P2_SRC_DETECT_BIT | (chg->hvdcp_disable ? 0 : (HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT)); rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, BC1P2_SRC_DETECT_BIT, enable ? BC1P2_SRC_DETECT_BIT : 0); if (rc < 0) smblib_err(chg, "failed to write USBIN_OPTIONS_1_CFG rc=%d\n", rc); } if (chg->pd_not_supported) return 0; void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable) { int rc; u8 mask; if (chg->hvdcp_disable) return; mask = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT; rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, mask, enable ? val : 0); enable ? mask : 0); if (rc < 0) smblib_err(chg, "failed to write USBIN_OPTIONS_1_CFG rc=%d\n", rc); return rc; return; } static int smblib_request_dpdm(struct smb_charger *chg, bool enable) Loading Loading @@ -1157,7 +1166,8 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT, icl_options); if (rc < 0) { smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; Loading Loading @@ -1576,6 +1586,20 @@ int smblib_get_prop_batt_capacity(struct smb_charger *chg, return rc; } static bool is_charging_paused(struct smb_charger *chg) { int rc; u8 val; rc = smblib_read(chg, CHARGING_PAUSE_CMD_REG, &val); if (rc < 0) { smblib_err(chg, "Couldn't read CHARGING_PAUSE_CMD rc=%d\n", rc); return false; } return val & CHARGING_PAUSE_CMD_BIT; } int smblib_get_prop_batt_status(struct smb_charger *chg, union power_supply_propval *val) { Loading Loading @@ -1641,6 +1665,11 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, break; } if (is_charging_paused(chg)) { val->intval = POWER_SUPPLY_STATUS_CHARGING; return 0; } if (val->intval != POWER_SUPPLY_STATUS_CHARGING) return 0; Loading Loading @@ -3555,15 +3584,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, chg->pd_active = val->intval; smblib_apsd_enable(chg, !chg->pd_active); if (chg->pd_active) { vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0); /* * Enforce 500mA for PD until the real vote comes in later. * Enforce 100mA for PD until the real vote comes in later. * It is guaranteed that pd_active is set prior to * pd_current_max */ vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_100MA); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); Loading Loading @@ -3595,16 +3626,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, "Couldn't enable secondary charger rc=%d\n", rc); /* PD hard resets failed, rerun apsd */ /* PD hard resets failed, proceed to detect QC2/3 */ if (chg->ok_to_pd) { chg->ok_to_pd = false; rc = smblib_configure_hvdcp_apsd(chg, true); if (rc < 0) { dev_err(chg->dev, "Couldn't enable APSD rc=%d\n", rc); return rc; } smblib_rerun_apsd_if_required(chg); smblib_hvdcp_detect_enable(chg, true); } } Loading Loading @@ -4204,11 +4229,9 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) /* * HVDCP 2/3, handled separately * For UNKNOWN(input not present) return without updating ICL */ if (pst == POWER_SUPPLY_TYPE_USB_HVDCP || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3 || pst == POWER_SUPPLY_TYPE_UNKNOWN) || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3) return; /* TypeC rp med or high, use rp value */ Loading Loading @@ -4248,6 +4271,7 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); break; case POWER_SUPPLY_TYPE_UNKNOWN: default: rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { Loading Loading @@ -4298,12 +4322,8 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data) int rc = 0; u8 stat; /* * Prepared to run PD or PD is active. At this moment, APSD is disabled, * but there still can be irq on apsd_done from previously unfinished * APSD run, skip it. */ if (chg->ok_to_pd) /* PD session is ongoing, ignore BC1.2 and QC detection */ if (chg->pd_active) return IRQ_HANDLED; rc = smblib_read(chg, APSD_STATUS_REG, &stat); Loading Loading @@ -4468,15 +4488,10 @@ static void typec_src_insertion(struct smb_charger *chg) chg->typec_legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT; chg->ok_to_pd = (!(chg->typec_legacy || chg->pd_disabled) || chg->early_usb_attach) && !chg->pd_not_supported; if (!chg->ok_to_pd) { rc = smblib_configure_hvdcp_apsd(chg, true); if (rc < 0) { dev_err(chg->dev, "Couldn't enable APSD rc=%d\n", rc); return; } smblib_rerun_apsd_if_required(chg); } /* allow apsd proceed to detect QC2/3 */ if (!chg->ok_to_pd) smblib_hvdcp_detect_enable(chg, true); } static void typec_sink_removal(struct smb_charger *chg) Loading Loading @@ -4506,11 +4521,7 @@ static void typec_src_removal(struct smb_charger *chg) dev_err(chg->dev, "Couldn't disable secondary charger rc=%d\n", rc); /* disable apsd */ rc = smblib_configure_hvdcp_apsd(chg, false); if (rc < 0) smblib_err(chg, "Couldn't disable APSD rc=%d\n", rc); smblib_hvdcp_detect_enable(chg, false); smblib_update_usb_type(chg); if (chg->wa_flags & BOOST_BACK_WA) { Loading Loading @@ -4601,6 +4612,11 @@ static void typec_src_removal(struct smb_charger *chg) chg->typec_legacy = false; } static void typec_mode_unattached(struct smb_charger *chg) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, USBIN_100MA); } static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) { const struct apsd_result *apsd = smblib_get_apsd_result(chg); Loading Loading @@ -4743,7 +4759,9 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) case SINK_MODE: typec_src_removal(chg); break; case UNATTACHED_MODE: default: typec_mode_unattached(chg); break; } Loading @@ -4751,6 +4769,7 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) chg->ok_to_pd = false; chg->sink_src_mode = UNATTACHED_MODE; chg->early_usb_attach = false; smblib_apsd_enable(chg, true); } if (chg->lpd_stage == LPD_STAGE_FLOAT_CANCEL) Loading
drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -632,6 +632,8 @@ int smblib_icl_override(struct smb_charger *chg, bool override); enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm, ktime_t time); int smblib_toggle_smb_en(struct smb_charger *chg, int toggle); void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable); void smblib_apsd_enable(struct smb_charger *chg, bool enable); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading
drivers/power/supply/qcom/smb5-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,9 @@ enum { #define CHARGING_ENABLE_CMD_REG (CHGR_BASE + 0x42) #define CHARGING_ENABLE_CMD_BIT BIT(0) #define CHARGING_PAUSE_CMD_REG (CHGR_BASE + 0x43) #define CHARGING_PAUSE_CMD_BIT BIT(0) #define CHGR_CFG2_REG (CHGR_BASE + 0x51) #define RECHG_MASK GENMASK(2, 1) #define VBAT_BASED_RECHG_BIT BIT(2) Loading Loading @@ -221,6 +224,9 @@ enum { #define USB_CMD_PULLDOWN_REG (USBIN_BASE + 0x45) #define EN_PULLDOWN_USB_IN_BIT BIT(0) #define TYPE_C_CFG_REG (USBIN_BASE + 0x58) #define BC1P2_START_ON_CC_BIT BIT(7) #define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B) #define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6) enum { Loading