diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index fa4232d4436c..803851d2b3ef 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -455,8 +455,7 @@ static int smb2_usb_get_prop(struct power_supply *psy, if (!val->intval) break; - rc = smblib_get_prop_typec_mode(chg, val); - if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || + if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || chg->micro_usb_mode) && chg->real_charger_type == POWER_SUPPLY_TYPE_USB) val->intval = 0; @@ -493,7 +492,7 @@ static int smb2_usb_get_prop(struct power_supply *psy, else if (chip->bad_part) val->intval = POWER_SUPPLY_TYPEC_SOURCE_DEFAULT; else - rc = smblib_get_prop_typec_mode(chg, val); + val->intval = chg->typec_mode; break; case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE: if (chg->micro_usb_mode) @@ -678,8 +677,7 @@ static int smb2_usb_port_get_prop(struct power_supply *psy, if (!val->intval) break; - rc = smblib_get_prop_typec_mode(chg, val); - if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || + if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || chg->micro_usb_mode) && chg->real_charger_type == POWER_SUPPLY_TYPE_USB) val->intval = 1; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index dee387bc87e7..7848ca4396d9 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -841,7 +841,6 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) { int rc = 0; bool override; - union power_supply_propval pval; /* suspend and return if 25mA or less is requested */ if (icl_ua < USBIN_25MA) @@ -851,14 +850,8 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) if (icl_ua == INT_MAX) goto override_suspend_config; - rc = smblib_get_prop_typec_mode(chg, &pval); - if (rc < 0) { - smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc); - goto enable_icl_changed_interrupt; - } - /* configure current */ - if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT + if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) { rc = set_sdp_current(chg, icl_ua); if (rc < 0) { @@ -880,7 +873,7 @@ override_suspend_config: if (icl_ua == INT_MAX) { /* remove override if no voters - hw defaults is desired */ override = false; - } else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { + } else if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB) /* For std cable with type = SDP never override */ override = false; @@ -920,15 +913,8 @@ int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua) int rc = 0; u8 load_cfg; bool override; - union power_supply_propval pval; - rc = smblib_get_prop_typec_mode(chg, &pval); - if (rc < 0) { - smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc); - return rc; - } - - if ((pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT + if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || chg->micro_usb_mode) && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) { rc = get_sdp_current(chg, icl_ua); @@ -2219,8 +2205,6 @@ static const char * const smblib_typec_mode_name[] = { static int smblib_get_prop_ufp_mode(struct smb_charger *chg) { switch (chg->typec_status[0]) { - case 0: - return POWER_SUPPLY_TYPEC_NONE; case UFP_TYPEC_RDSTD_BIT: return POWER_SUPPLY_TYPEC_SOURCE_DEFAULT; case UFP_TYPEC_RD1P5_BIT: @@ -2231,7 +2215,7 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg) break; } - return POWER_SUPPLY_TYPEC_NON_COMPLIANT; + return POWER_SUPPLY_TYPEC_NONE; } static int smblib_get_prop_dfp_mode(struct smb_charger *chg) @@ -2245,8 +2229,6 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg) return POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE; case DFP_RD_OPEN_BIT: return POWER_SUPPLY_TYPEC_SINK; - case DFP_RA_OPEN_BIT: - return POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY; default: break; } @@ -2254,20 +2236,12 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg) return POWER_SUPPLY_TYPEC_NONE; } -int smblib_get_prop_typec_mode(struct smb_charger *chg, - union power_supply_propval *val) +static int smblib_get_prop_typec_mode(struct smb_charger *chg) { - if (!(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) { - val->intval = POWER_SUPPLY_TYPEC_NONE; - return 0; - } - if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT) - val->intval = smblib_get_prop_dfp_mode(chg); + return smblib_get_prop_dfp_mode(chg); else - val->intval = smblib_get_prop_ufp_mode(chg); - - return 0; + return smblib_get_prop_ufp_mode(chg); } int smblib_get_prop_typec_power_role(struct smb_charger *chg, @@ -2555,24 +2529,12 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, const union power_supply_propval *val) { int rc; - bool orientation, cc_debounced, sink_attached, hvdcp; + bool orientation, sink_attached, hvdcp; u8 stat; if (!get_effective_result(chg->pd_allowed_votable)) return -EINVAL; - rc = smblib_read(chg, APSD_STATUS_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read APSD status rc=%d\n", rc); - return rc; - } - - cc_debounced = (bool) - (chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT); - sink_attached = (bool) - (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT); - hvdcp = stat & QC_CHARGER_BIT; - chg->pd_active = val->intval; if (chg->pd_active) { vote(chg->apsd_disable_votable, PD_VOTER, true, 0); @@ -2624,6 +2586,14 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, if (rc < 0) smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc); } else { + rc = smblib_read(chg, APSD_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read APSD status rc=%d\n", + rc); + return rc; + } + + hvdcp = stat & QC_CHARGER_BIT; vote(chg->apsd_disable_votable, PD_VOTER, false, 0); vote(chg->pd_allowed_votable, PD_VOTER, true, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0); @@ -2643,8 +2613,8 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, * and data could be interrupted. Non-legacy DCP could also draw * more, but it may impact compliance. */ - if (!chg->typec_legacy_valid && cc_debounced && - !sink_attached && hvdcp) + sink_attached = chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT; + if (!chg->typec_legacy_valid && !sink_attached && hvdcp) schedule_work(&chg->legacy_detection_work); } @@ -2766,6 +2736,7 @@ static int smblib_cc2_sink_removal_enter(struct smb_charger *chg) smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); return rc; } + ccout = (stat & CC_ATTACHED_BIT) ? (!!(stat & CC_ORIENTATION_BIT) + 1) : 0; ufp_mode = (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT) ? @@ -3684,8 +3655,7 @@ unlock: smblib_update_usb_type(chg); } -static void smblib_handle_typec_insertion(struct smb_charger *chg, - bool sink_attached) +static void smblib_handle_typec_insertion(struct smb_charger *chg) { int rc; @@ -3697,45 +3667,37 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg, smblib_err(chg, "Couldn't disable APSD_START_ON_CC rc=%d\n", rc); - if (sink_attached) + if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT) typec_sink_insertion(chg); else typec_sink_removal(chg); } -static void smblib_handle_typec_debounce_done(struct smb_charger *chg, - bool rising, bool sink_attached) +static void smblib_handle_typec_cc_state_change(struct smb_charger *chg) { - int rc; - union power_supply_propval pval = {0, }; + if (chg->pr_swap_in_progress) + return; - if (rising) { - if (!chg->typec_present && !chg->pr_swap_in_progress) { - chg->typec_present = true; - smblib_dbg(chg, PR_MISC, "TypeC insertion\n"); - smblib_handle_typec_insertion(chg, sink_attached); - } - } else { - if (chg->typec_present && !chg->pr_swap_in_progress) { - chg->typec_present = false; - smblib_dbg(chg, PR_MISC, "TypeC removal\n"); - smblib_handle_typec_removal(chg); - } + chg->typec_mode = smblib_get_prop_typec_mode(chg); + if (!chg->typec_present && chg->typec_mode != POWER_SUPPLY_TYPEC_NONE) { + chg->typec_present = true; + smblib_dbg(chg, PR_MISC, "TypeC %s insertion\n", + smblib_typec_mode_name[chg->typec_mode]); + smblib_handle_typec_insertion(chg); + } else if (chg->typec_present && + chg->typec_mode == POWER_SUPPLY_TYPEC_NONE) { + chg->typec_present = false; + smblib_dbg(chg, PR_MISC, "TypeC removal\n"); + smblib_handle_typec_removal(chg); } - rc = smblib_get_prop_typec_mode(chg, &pval); - if (rc < 0) - smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc); - - smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n", - rising ? "rising" : "falling", - smblib_typec_mode_name[pval.intval]); + smblib_dbg(chg, PR_INTERRUPT, "IRQ: cc-state-change; Type-C %s detected\n", + smblib_typec_mode_name[chg->typec_mode]); } static void smblib_usb_typec_change(struct smb_charger *chg) { int rc; - bool debounce_done, sink_attached; rc = smblib_multibyte_read(chg, TYPE_C_STATUS_1_REG, chg->typec_status, 5); @@ -3744,12 +3706,7 @@ static void smblib_usb_typec_change(struct smb_charger *chg) return; } - debounce_done = - (bool)(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT); - sink_attached = - (bool)(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT); - - smblib_handle_typec_debounce_done(chg, debounce_done, sink_attached); + smblib_handle_typec_cc_state_change(chg); if (chg->typec_status[3] & TYPEC_VBUS_ERROR_STATUS_BIT) smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n"); @@ -4264,8 +4221,7 @@ static void smblib_legacy_detection_work(struct work_struct *work) chg->typec_legacy_valid = true; vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0); legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT; - rp_high = smblib_get_prop_ufp_mode(chg) == - POWER_SUPPLY_TYPEC_SOURCE_HIGH; + rp_high = chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_HIGH; if (!legacy || !rp_high) vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, false, 0); diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 70219e259e05..8ba0a1dfe19f 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -322,6 +322,7 @@ struct smb_charger { bool typec_legacy_valid; int fake_input_current_limited; bool pr_swap_in_progress; + int typec_mode; /* workaround flag */ u32 wa_flags; @@ -453,8 +454,6 @@ int smblib_get_prop_usb_current_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg, union power_supply_propval *val); -int smblib_get_prop_typec_mode(struct smb_charger *chg, - union power_supply_propval *val); int smblib_get_prop_typec_power_role(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_pd_allowed(struct smb_charger *chg, diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h index 167666a8c548..d8671ab1fd06 100644 --- a/drivers/power/supply/qcom/smb-reg.h +++ b/drivers/power/supply/qcom/smb-reg.h @@ -486,11 +486,11 @@ enum { #define UFP_TYPEC_OPEN_OPEN_BIT BIT(0) #define TYPE_C_STATUS_2_REG (USBIN_BASE + 0x0C) -#define DFP_TYPEC_MASK 0x8F #define DFP_RA_OPEN_BIT BIT(7) #define TIMER_STAGE_BIT BIT(6) #define EXIT_UFP_MODE_BIT BIT(5) #define EXIT_DFP_MODE_BIT BIT(4) +#define DFP_TYPEC_MASK GENMASK(3, 0) #define DFP_RD_OPEN_BIT BIT(3) #define DFP_RD_RA_VCONN_BIT BIT(2) #define DFP_RD_RD_BIT BIT(1) diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c index 694591c3ec56..0ee53b100ae2 100644 --- a/drivers/power/supply/qcom/smb138x-charger.c +++ b/drivers/power/supply/qcom/smb138x-charger.c @@ -248,7 +248,7 @@ static int smb138x_usb_get_prop(struct power_supply *psy, val->intval = chg->usb_psy_desc.type; break; case POWER_SUPPLY_PROP_TYPEC_MODE: - rc = smblib_get_prop_typec_mode(chg, val); + val->intval = chg->typec_mode; break; case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE: rc = smblib_get_prop_typec_power_role(chg, val);