Loading drivers/power/supply/qcom/qpnp-smb2.c +7 −0 Original line number Diff line number Diff line Loading @@ -1641,6 +1641,13 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't read float charger options rc=%d\n", rc); return rc; } switch (chip->dt.chg_inhibit_thr_mv) { case 50: rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, Loading drivers/power/supply/qcom/smb-lib.c +124 −31 Original line number Diff line number Diff line Loading @@ -514,10 +514,17 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg) const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); /* if PD is active, APSD is disabled so won't have a valid result */ if (chg->pd_active) if (chg->pd_active) { chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD; else } else { /* * Update real charger type only if its not FLOAT * detected as as SDP */ if (!(apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT && chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) chg->real_charger_type = apsd_result->pst; } smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n", apsd_result->name, chg->pd_active); Loading Loading @@ -785,6 +792,7 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; u8 icl_options; const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); /* power source is SDP */ switch (icl_ua) { Loading @@ -809,6 +817,21 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) return -EINVAL; } if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB && apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT) { /* * change the float charger configuration to SDP, if this * is the case of SDP being detected as FLOAT */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FORCE_FLOAT_SDP_CFG_BIT, FORCE_FLOAT_SDP_CFG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set float ICL options rc=%d\n", rc); return rc; } } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); if (rc < 0) { Loading Loading @@ -2402,6 +2425,31 @@ int smblib_get_prop_die_health(struct smb_charger *chg, return 0; } #define SDP_CURRENT_UA 500000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 #define HVDCP_CURRENT_UA 3000000 #define TYPEC_DEFAULT_CURRENT_UA 900000 #define TYPEC_MEDIUM_CURRENT_UA 1500000 #define TYPEC_HIGH_CURRENT_UA 3000000 static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; switch (typec_mode) { case POWER_SUPPLY_TYPEC_SOURCE_HIGH: rp_ua = TYPEC_HIGH_CURRENT_UA; break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: /* fall through */ default: rp_ua = DCP_CURRENT_UA; } return rp_ua; } /******************* * USB PSY SETTERS * * *****************/ Loading @@ -2419,14 +2467,54 @@ int smblib_set_prop_pd_current_max(struct smb_charger *chg, return rc; } static int smblib_handle_usb_current(struct smb_charger *chg, int usb_current) { int rc = 0, rp_ua, typec_mode; if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) { if (usb_current == -ETIMEDOUT) { /* * Valid FLOAT charger, report the current based * of Rp */ typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua); if (rc < 0) return rc; } else { /* * FLOAT charger detected as SDP by USB driver, * charge with the requested current and update the * real_charger_type */ chg->real_charger_type = POWER_SUPPLY_TYPE_USB; rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); if (rc < 0) return rc; rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0); if (rc < 0) return rc; } } else { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); } return rc; } int smblib_set_prop_usb_current_max(struct smb_charger *chg, const union power_supply_propval *val) { int rc = 0; if (!chg->pd_active) { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, val->intval); rc = smblib_handle_usb_current(chg, val->intval); } else if (chg->system_suspend_supported) { if (val->intval <= USBIN_25MA) rc = vote(chg->usb_icl_votable, Loading Loading @@ -2875,14 +2963,6 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg, /*********************** * USB MAIN PSY SETTERS * *************************/ #define SDP_CURRENT_UA 500000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 #define HVDCP_CURRENT_UA 3000000 #define TYPEC_DEFAULT_CURRENT_UA 900000 #define TYPEC_MEDIUM_CURRENT_UA 1500000 #define TYPEC_HIGH_CURRENT_UA 3000000 int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua) { Loading Loading @@ -3438,24 +3518,6 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg, rising ? "rising" : "falling"); } static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; switch (typec_mode) { case POWER_SUPPLY_TYPEC_SOURCE_HIGH: rp_ua = TYPEC_HIGH_CURRENT_UA; break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: /* fall through */ default: rp_ua = DCP_CURRENT_UA; } return rp_ua; } static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) { int typec_mode; Loading @@ -3481,11 +3543,17 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000); break; case POWER_SUPPLY_TYPE_USB_DCP: case POWER_SUPPLY_TYPE_USB_FLOAT: typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua); break; case POWER_SUPPLY_TYPE_USB_FLOAT: /* * limit ICL to 100mA, the USB driver will enumerate to check * if this is a SDP and appropriately set the current */ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000); break; case POWER_SUPPLY_TYPE_USB_HVDCP: case POWER_SUPPLY_TYPE_USB_HVDCP_3: vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000); Loading Loading @@ -3680,6 +3748,13 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) chg->pd_hard_reset = 0; chg->typec_legacy_valid = false; /* write back the default FLOAT charger configuration */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, (u8)FLOAT_OPTIONS_MASK, chg->float_cfg); if (rc < 0) smblib_err(chg, "Couldn't write float charger options rc=%d\n", rc); /* reset back to 120mS tCC debounce */ rc = smblib_masked_write(chg, MISC_CFG_REG, TCC_DEBOUNCE_20MS_BIT, 0); if (rc < 0) Loading Loading @@ -3774,6 +3849,24 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT)) return; /* * if APSD indicates FLOAT and the USB stack had detected SDP, * do not respond to Rp changes as we do not confirm that its * a legacy cable */ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB) return; /* * We want the ICL vote @ 100mA for a FLOAT charger * until the detection by the USB stack is complete. * Ignore the Rp changes unless there is a * pre-existing valid vote. */ if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT && get_client_vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER) <= 100000) return; /* * handle Rp change for DCP/FLOAT/OCP. * Update the current only if the Rp is different from Loading drivers/power/supply/qcom/smb-lib.h +1 −0 Original line number Diff line number Diff line Loading @@ -326,6 +326,7 @@ struct smb_charger { int typec_mode; int usb_icl_change_irq_enabled; u32 jeita_status; u8 float_cfg; /* workaround flag */ u32 wa_flags; Loading Loading
drivers/power/supply/qcom/qpnp-smb2.c +7 −0 Original line number Diff line number Diff line Loading @@ -1641,6 +1641,13 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't read float charger options rc=%d\n", rc); return rc; } switch (chip->dt.chg_inhibit_thr_mv) { case 50: rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, Loading
drivers/power/supply/qcom/smb-lib.c +124 −31 Original line number Diff line number Diff line Loading @@ -514,10 +514,17 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg) const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); /* if PD is active, APSD is disabled so won't have a valid result */ if (chg->pd_active) if (chg->pd_active) { chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD; else } else { /* * Update real charger type only if its not FLOAT * detected as as SDP */ if (!(apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT && chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) chg->real_charger_type = apsd_result->pst; } smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n", apsd_result->name, chg->pd_active); Loading Loading @@ -785,6 +792,7 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; u8 icl_options; const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); /* power source is SDP */ switch (icl_ua) { Loading @@ -809,6 +817,21 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) return -EINVAL; } if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB && apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT) { /* * change the float charger configuration to SDP, if this * is the case of SDP being detected as FLOAT */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FORCE_FLOAT_SDP_CFG_BIT, FORCE_FLOAT_SDP_CFG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set float ICL options rc=%d\n", rc); return rc; } } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); if (rc < 0) { Loading Loading @@ -2402,6 +2425,31 @@ int smblib_get_prop_die_health(struct smb_charger *chg, return 0; } #define SDP_CURRENT_UA 500000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 #define HVDCP_CURRENT_UA 3000000 #define TYPEC_DEFAULT_CURRENT_UA 900000 #define TYPEC_MEDIUM_CURRENT_UA 1500000 #define TYPEC_HIGH_CURRENT_UA 3000000 static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; switch (typec_mode) { case POWER_SUPPLY_TYPEC_SOURCE_HIGH: rp_ua = TYPEC_HIGH_CURRENT_UA; break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: /* fall through */ default: rp_ua = DCP_CURRENT_UA; } return rp_ua; } /******************* * USB PSY SETTERS * * *****************/ Loading @@ -2419,14 +2467,54 @@ int smblib_set_prop_pd_current_max(struct smb_charger *chg, return rc; } static int smblib_handle_usb_current(struct smb_charger *chg, int usb_current) { int rc = 0, rp_ua, typec_mode; if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) { if (usb_current == -ETIMEDOUT) { /* * Valid FLOAT charger, report the current based * of Rp */ typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua); if (rc < 0) return rc; } else { /* * FLOAT charger detected as SDP by USB driver, * charge with the requested current and update the * real_charger_type */ chg->real_charger_type = POWER_SUPPLY_TYPE_USB; rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); if (rc < 0) return rc; rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0); if (rc < 0) return rc; } } else { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); } return rc; } int smblib_set_prop_usb_current_max(struct smb_charger *chg, const union power_supply_propval *val) { int rc = 0; if (!chg->pd_active) { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, val->intval); rc = smblib_handle_usb_current(chg, val->intval); } else if (chg->system_suspend_supported) { if (val->intval <= USBIN_25MA) rc = vote(chg->usb_icl_votable, Loading Loading @@ -2875,14 +2963,6 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg, /*********************** * USB MAIN PSY SETTERS * *************************/ #define SDP_CURRENT_UA 500000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 #define HVDCP_CURRENT_UA 3000000 #define TYPEC_DEFAULT_CURRENT_UA 900000 #define TYPEC_MEDIUM_CURRENT_UA 1500000 #define TYPEC_HIGH_CURRENT_UA 3000000 int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua) { Loading Loading @@ -3438,24 +3518,6 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg, rising ? "rising" : "falling"); } static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; switch (typec_mode) { case POWER_SUPPLY_TYPEC_SOURCE_HIGH: rp_ua = TYPEC_HIGH_CURRENT_UA; break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: /* fall through */ default: rp_ua = DCP_CURRENT_UA; } return rp_ua; } static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) { int typec_mode; Loading @@ -3481,11 +3543,17 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000); break; case POWER_SUPPLY_TYPE_USB_DCP: case POWER_SUPPLY_TYPE_USB_FLOAT: typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua); break; case POWER_SUPPLY_TYPE_USB_FLOAT: /* * limit ICL to 100mA, the USB driver will enumerate to check * if this is a SDP and appropriately set the current */ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000); break; case POWER_SUPPLY_TYPE_USB_HVDCP: case POWER_SUPPLY_TYPE_USB_HVDCP_3: vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000); Loading Loading @@ -3680,6 +3748,13 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) chg->pd_hard_reset = 0; chg->typec_legacy_valid = false; /* write back the default FLOAT charger configuration */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, (u8)FLOAT_OPTIONS_MASK, chg->float_cfg); if (rc < 0) smblib_err(chg, "Couldn't write float charger options rc=%d\n", rc); /* reset back to 120mS tCC debounce */ rc = smblib_masked_write(chg, MISC_CFG_REG, TCC_DEBOUNCE_20MS_BIT, 0); if (rc < 0) Loading Loading @@ -3774,6 +3849,24 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT)) return; /* * if APSD indicates FLOAT and the USB stack had detected SDP, * do not respond to Rp changes as we do not confirm that its * a legacy cable */ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB) return; /* * We want the ICL vote @ 100mA for a FLOAT charger * until the detection by the USB stack is complete. * Ignore the Rp changes unless there is a * pre-existing valid vote. */ if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT && get_client_vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER) <= 100000) return; /* * handle Rp change for DCP/FLOAT/OCP. * Update the current only if the Rp is different from Loading
drivers/power/supply/qcom/smb-lib.h +1 −0 Original line number Diff line number Diff line Loading @@ -326,6 +326,7 @@ struct smb_charger { int typec_mode; int usb_icl_change_irq_enabled; u32 jeita_status; u8 float_cfg; /* workaround flag */ u32 wa_flags; Loading