diff options
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-smb2.c | 4 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.c | 66 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.h | 4 |
3 files changed, 53 insertions, 21 deletions
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 9340b98dc883..b7369a300e95 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -1037,6 +1037,10 @@ static int smb2_init_hw(struct smb2 *chip) DEFAULT_VOTER, true, chip->dt.dc_icl_ua); vote(chg->hvdcp_disable_votable, DEFAULT_VOTER, chip->dt.hvdcp_disable, 0); + vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, + true, 0); + vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, + true, 0); /* Configure charge enable for software control; active high */ rc = smblib_masked_write(chg, CHGR_CFG2_REG, diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index b9f8202e0a9e..3e4d39303641 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -442,7 +442,7 @@ static int smblib_update_usb_type(struct smb_charger *chg) return rc; } -static int smblib_detach_usb(struct smb_charger *chg) +static int smblib_detach_typec(struct smb_charger *chg) { int rc; @@ -469,7 +469,9 @@ static int smblib_detach_usb(struct smb_charger *chg) return rc; } - vote(chg->pd_allowed_votable, DEFAULT_VOTER, false, 0); + /* cc removed, disable pd_allowed */ + vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0); + vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0); return rc; } @@ -777,6 +779,18 @@ suspend: return rc; } +static int smblib_pd_disallowed_votable_indirect_callback( + struct votable *votable, void *data, int disallowed, const char *client) +{ + struct smb_charger *chg = data; + int rc; + + rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER, + !disallowed, 0); + + return rc; +} + static int smblib_awake_vote_callback(struct votable *votable, void *data, int awake, const char *client) { @@ -2154,10 +2168,10 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, bool rising, bool qc_charger) { - if (rising && !qc_charger) { - vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0); - power_supply_changed(chg->usb_psy); - } + /* Hold off PD only until hvdcp 2.0 detection timeout */ + if (rising) + vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, + false, 0); smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n", rising ? "rising" : "falling"); @@ -2191,7 +2205,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) case CDP_CHARGER_BIT: case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: - vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0); + /* if not DCP then no hvdcp timeout happens. Enable pd here */ + vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, + false, 0); break; case DCP_CHARGER_BIT: if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT) @@ -2256,7 +2272,7 @@ static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached) int rc; if (!attached) { - rc = smblib_detach_usb(chg); + rc = smblib_detach_typec(chg); if (rc < 0) dev_err(chg->dev, "Couldn't detach USB rc=%d\n", rc); } @@ -2266,14 +2282,15 @@ static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached) } static void smblib_handle_typec_debounce_done(struct smb_charger *chg, - bool rising, bool sink_attached) + bool attached, bool rising, bool sink_attached) { int rc; union power_supply_propval pval = {0, }; - /* allow PD for attached sinks */ - if (rising && sink_attached) - vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0); + /* allow PD when cc is attached and debounced */ + if (attached && rising) + vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, + false, 0); rc = smblib_get_prop_typec_mode(chg, &pval); if (rc < 0) @@ -2317,6 +2334,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) smblib_handle_typec_cc(chg, (bool)(stat & CC_ATTACHED_BIT)); smblib_handle_typec_debounce_done(chg, + (bool)(stat & CC_ATTACHED_BIT), (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT), (bool)(stat & UFP_DFP_MODE_STATUS_BIT)); @@ -2348,14 +2366,10 @@ static void smblib_hvdcp_detect_work(struct work_struct *work) { struct smb_charger *chg = container_of(work, struct smb_charger, hvdcp_detect_work.work); - const struct apsd_result *apsd_result; - apsd_result = smblib_get_apsd_result(chg); - if (apsd_result->bit && - !(apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT))) { - vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0); - power_supply_changed(chg->usb_psy); - } + vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, + false, 0); + power_supply_changed(chg->usb_psy); } static void bms_update_work(struct work_struct *work) @@ -2496,8 +2510,16 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->pd_allowed_votable = create_votable("PD_ALLOWED", VOTE_SET_ANY, - NULL, NULL); + chg->pd_disallowed_votable_indirect + = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY, + smblib_pd_disallowed_votable_indirect_callback, chg); + if (IS_ERR(chg->pd_disallowed_votable_indirect)) { + rc = PTR_ERR(chg->pd_disallowed_votable_indirect); + return rc; + } + + chg->pd_allowed_votable = create_votable("PD_ALLOWED", + VOTE_SET_ANY, NULL, NULL); if (IS_ERR(chg->pd_allowed_votable)) { rc = PTR_ERR(chg->pd_allowed_votable); return rc; @@ -2563,6 +2585,8 @@ static void smblib_destroy_votables(struct smb_charger *chg) destroy_votable(chg->usb_icl_votable); if (chg->dc_icl_votable) destroy_votable(chg->dc_icl_votable); + if (chg->pd_disallowed_votable_indirect) + destroy_votable(chg->pd_disallowed_votable_indirect); if (chg->pd_allowed_votable) destroy_votable(chg->pd_allowed_votable); if (chg->awake_votable) diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index e2a525a525b1..c6a1203f6bdb 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -37,6 +37,9 @@ enum print_reason { #define TAPER_END_VOTER "TAPER_END_VOTER" #define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER" #define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER" +#define CC_DETACHED_VOTER "CC_DETACHED_VOTER" +#define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER" +#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER" enum smb_mode { PARALLEL_MASTER = 0, @@ -144,6 +147,7 @@ struct smb_charger { struct votable *fv_votable; struct votable *usb_icl_votable; struct votable *dc_icl_votable; + struct votable *pd_disallowed_votable_indirect; struct votable *pd_allowed_votable; struct votable *awake_votable; struct votable *pl_disable_votable; |
