diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 244ed77c4318..7be1f7bd4108 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -1382,7 +1382,8 @@ static int smb2_init_hw(struct smb2 *chip) } /* votes must be cast before configuring software control */ - vote(chg->usb_suspend_votable, + /* vote 0mA on usb_icl for non battery platforms */ + vote(chg->usb_icl_votable, DEFAULT_VOTER, chip->dt.no_battery, 0); vote(chg->dc_suspend_votable, DEFAULT_VOTER, chip->dt.no_battery, 0); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 280e2f811ab5..33339588599e 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -698,7 +698,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg) return; } - vote(chg->usb_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0); + vote(chg->usb_icl_votable, DEBUG_BOARD_VOTER, val.intval, 0); vote(chg->dc_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0); if (val.intval) pr_info("Input suspended: Fake battery\n"); @@ -741,18 +741,6 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg) * VOTABLE CALLBACKS * *********************/ -static int smblib_usb_suspend_vote_callback(struct votable *votable, void *data, - int suspend, const char *client) -{ - struct smb_charger *chg = data; - - /* resume input if suspend is invalid */ - if (suspend < 0) - suspend = 0; - - return smblib_set_usb_suspend(chg, (bool)suspend); -} - static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, int suspend, const char *client) { @@ -770,44 +758,12 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 -static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, - int icl_ua, const char *client) + + +static int set_sdp_current(struct smb_charger *chg, int icl_ua) { - struct smb_charger *chg = data; - int rc = 0; - bool suspend, override; - u8 icl_options = 0; - - override = true; - /* remove override if no voters or type = SDP or CDP */ - if (client == NULL - || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB - || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP) - override = false; - - suspend = false; - if (client && (icl_ua < USBIN_25MA)) - suspend = true; - - if (suspend) - goto out; - - if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) { - if (client) { - rc = smblib_set_charge_param(chg, &chg->param.usb_icl, - icl_ua - chg->icl_reduction_ua); - if (rc < 0) { - smblib_err(chg, "Couldn't set HC ICL rc=%d\n", - rc); - return rc; - } - } - - smblib_dbg(chg, PR_PARALLEL, - "icl_ua=%d icl_reduction=%d\n", - icl_ua, chg->icl_reduction_ua); - goto out; - } + int rc; + u8 icl_options; /* power source is SDP */ switch (icl_ua) { @@ -829,35 +785,97 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, break; default: smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua); - icl_options = 0; - break; + return -EINVAL; } -out: - if (override) - icl_options |= USBIN_MODE_CHG_BIT; - rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, - CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT, - icl_options); + CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); if (rc < 0) { smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; } - rc = vote(chg->usb_suspend_votable, PD_VOTER, suspend, 0); + return rc; +} + +static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, + int icl_ua, const char *client) +{ + struct smb_charger *chg = data; + int rc = 0; + bool override; + union power_supply_propval pval; + + /* suspend and return if 25mA or less is requested */ + if (client && (icl_ua < USBIN_25MA)) + return smblib_set_usb_suspend(chg, true); + + disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); + if (!client) + goto override_suspend_config; + + rc = smblib_get_prop_typec_mode(chg, &pval); if (rc < 0) { - smblib_err(chg, "Couldn't %s input rc=%d\n", - suspend ? "suspend" : "resume", rc); - return rc; + 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 + && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) { + rc = set_sdp_current(chg, icl_ua); + if (rc < 0) { + smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); + goto enable_icl_changed_interrupt; + } + } else { + rc = smblib_set_charge_param(chg, &chg->param.usb_icl, + icl_ua - chg->icl_reduction_ua); + if (rc < 0) { + smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); + goto enable_icl_changed_interrupt; + } + } + +override_suspend_config: + /* determine if override needs to be enforced */ + override = true; + if (client == NULL) { + /* remove override if no voters - hw defaults is desired */ + override = false; + } else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { + if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB) + /* For std cable with type = SDP never override */ + override = false; + else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP + && icl_ua - chg->icl_reduction_ua == 1500000) + /* + * For std cable with type = CDP override only if + * current is not 1500mA + */ + override = false; + } + + /* enforce override */ + rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, + USBIN_MODE_CHG_BIT, override ? USBIN_MODE_CHG_BIT : 0); + rc = smblib_icl_override(chg, override); if (rc < 0) { smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc); - return rc; + goto enable_icl_changed_interrupt; } + /* unsuspend after configuring current and override */ + rc = smblib_set_usb_suspend(chg, false); + if (rc < 0) { + smblib_err(chg, "Couldn't resume input rc=%d\n", rc); + goto enable_icl_changed_interrupt; + } + +enable_icl_changed_interrupt: + enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); + return rc; } @@ -1269,8 +1287,9 @@ int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev) int smblib_get_prop_input_suspend(struct smb_charger *chg, union power_supply_propval *val) { - val->intval = get_client_vote(chg->usb_suspend_votable, USER_VOTER) && - get_client_vote(chg->dc_suspend_votable, USER_VOTER); + val->intval + = (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0) + && get_client_vote(chg->dc_suspend_votable, USER_VOTER); return 0; } @@ -1567,7 +1586,8 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg, { int rc; - rc = vote(chg->usb_suspend_votable, USER_VOTER, (bool)val->intval, 0); + /* vote 0mA when suspended */ + rc = vote(chg->usb_icl_votable, USER_VOTER, (bool)val->intval, 0); if (rc < 0) { smblib_err(chg, "Couldn't vote to %s USB rc=%d\n", (bool)val->intval ? "suspend" : "resume", rc); @@ -1713,7 +1733,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, int rc = 0; u8 stat; - if (get_client_vote(chg->usb_suspend_votable, USER_VOTER)) { + if (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0) { val->intval = false; return rc; } @@ -2866,8 +2886,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) } } else { if (chg->wa_flags & BOOST_BACK_WA) - vote(chg->usb_suspend_votable, - BOOST_BACK_VOTER, false, 0); + vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0); if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) { smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n"); @@ -3145,6 +3164,13 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data) power_supply_changed(chg->usb_psy); + rc = smblib_read(chg, APSD_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc); + return IRQ_HANDLED; + } + smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat); + return IRQ_HANDLED; } @@ -3240,12 +3266,13 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) chg->vconn_attempts = 0; chg->otg_attempts = 0; - typec_source_removal(chg); - typec_sink_removal(chg); chg->usb_ever_removed = true; smblib_update_usb_type(chg); + + typec_source_removal(chg); + typec_sink_removal(chg); } static void smblib_handle_typec_insertion(struct smb_charger *chg, @@ -3428,15 +3455,15 @@ irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data) } if ((stat & USE_USBIN_BIT) && - get_effective_result(chg->usb_suspend_votable)) + get_effective_result(chg->usb_icl_votable) < USBIN_25MA) return IRQ_HANDLED; if (stat & USE_DCIN_BIT) return IRQ_HANDLED; if (is_storming(&irq_data->storm_data)) { - smblib_err(chg, "Reverse boost detected: suspending input\n"); - vote(chg->usb_suspend_votable, BOOST_BACK_VOTER, true, 0); + smblib_err(chg, "Reverse boost detected: voting 0mA to suspend input\n"); + vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0); } return IRQ_HANDLED; @@ -3785,14 +3812,6 @@ static int smblib_create_votables(struct smb_charger *chg) vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0); - chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY, - smblib_usb_suspend_vote_callback, - chg); - if (IS_ERR(chg->usb_suspend_votable)) { - rc = PTR_ERR(chg->usb_suspend_votable); - return rc; - } - chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY, smblib_dc_suspend_vote_callback, chg); @@ -3890,8 +3909,6 @@ static int smblib_create_votables(struct smb_charger *chg) static void smblib_destroy_votables(struct smb_charger *chg) { - if (chg->usb_suspend_votable) - destroy_votable(chg->usb_suspend_votable); if (chg->dc_suspend_votable) destroy_votable(chg->dc_suspend_votable); if (chg->usb_icl_votable) diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index b1fbba90c054..b2cfeeda5792 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -252,7 +252,6 @@ struct smb_charger { struct regulator *dpdm_reg; /* votables */ - struct votable *usb_suspend_votable; struct votable *dc_suspend_votable; struct votable *fcc_votable; struct votable *fv_votable; diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c index 554625adda7d..ba8a4c265f87 100644 --- a/drivers/power/supply/qcom/smb138x-charger.c +++ b/drivers/power/supply/qcom/smb138x-charger.c @@ -827,8 +827,6 @@ static int smb138x_init_hw(struct smb138x *chip) int rc = 0; /* votes must be cast before configuring software control */ - vote(chg->usb_suspend_votable, - DEFAULT_VOTER, chip->dt.suspend_input, 0); vote(chg->dc_suspend_votable, DEFAULT_VOTER, chip->dt.suspend_input, 0); vote(chg->fcc_votable,