diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 024c968e484a..2a4617a7359d 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -427,6 +427,7 @@ static enum power_supply_property smb2_usb_props[] = { POWER_SUPPLY_PROP_PE_START, POWER_SUPPLY_PROP_CTM_CURRENT_MAX, POWER_SUPPLY_PROP_HW_CURRENT_MAX, + POWER_SUPPLY_PROP_REAL_TYPE, }; static int smb2_usb_get_prop(struct power_supply *psy, @@ -446,6 +447,16 @@ static int smb2_usb_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_ONLINE: rc = smblib_get_prop_usb_online(chg, val); + if (!val->intval) + break; + + rc = smblib_get_prop_typec_mode(chg, val); + if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || + chg->micro_usb_mode) && + chg->real_charger_type == POWER_SUPPLY_TYPE_USB) + val->intval = 0; + else + val->intval = 1; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN: val->intval = chg->voltage_min_uv; @@ -463,10 +474,13 @@ static int smb2_usb_get_prop(struct power_supply *psy, rc = smblib_get_prop_usb_current_max(chg, val); break; case POWER_SUPPLY_PROP_TYPE: + val->intval = POWER_SUPPLY_TYPE_USB_PD; + break; + case POWER_SUPPLY_PROP_REAL_TYPE: if (chip->bad_part) - val->intval = POWER_SUPPLY_TYPE_USB; + val->intval = POWER_SUPPLY_TYPE_USB_PD; else - val->intval = chg->usb_psy_desc.type; + val->intval = chg->real_charger_type; break; case POWER_SUPPLY_PROP_TYPEC_MODE: if (chg->micro_usb_mode) @@ -608,7 +622,7 @@ static int smb2_init_usb_psy(struct smb2 *chip) struct smb_charger *chg = &chip->chg; chg->usb_psy_desc.name = "usb"; - chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; + chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD; chg->usb_psy_desc.properties = smb2_usb_props; chg->usb_psy_desc.num_properties = ARRAY_SIZE(smb2_usb_props); chg->usb_psy_desc.get_property = smb2_usb_get_prop; @@ -628,6 +642,97 @@ static int smb2_init_usb_psy(struct smb2 *chip) return 0; } +/******************************** + * USB PC_PORT PSY REGISTRATION * + ********************************/ +static enum power_supply_property smb2_usb_port_props[] = { + POWER_SUPPLY_PROP_TYPE, + POWER_SUPPLY_PROP_ONLINE, +}; + +static int smb2_usb_port_get_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct smb2 *chip = power_supply_get_drvdata(psy); + struct smb_charger *chg = &chip->chg; + int rc = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_TYPE: + val->intval = POWER_SUPPLY_TYPE_USB; + break; + case POWER_SUPPLY_PROP_ONLINE: + rc = smblib_get_prop_usb_online(chg, val); + if (!val->intval) + break; + + rc = smblib_get_prop_typec_mode(chg, val); + if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || + chg->micro_usb_mode) && + chg->real_charger_type == POWER_SUPPLY_TYPE_USB) + val->intval = 1; + else + val->intval = 0; + break; + default: + pr_err_ratelimited("Get prop %d is not supported in pc_port\n", + psp); + return -EINVAL; + } + + if (rc < 0) { + pr_debug("Couldn't get prop %d rc = %d\n", psp, rc); + return -ENODATA; + } + + return 0; +} + +static int smb2_usb_port_set_prop(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + int rc = 0; + + switch (psp) { + default: + pr_err_ratelimited("Set prop %d is not supported in pc_port\n", + psp); + rc = -EINVAL; + break; + } + + return rc; +} + +static const struct power_supply_desc usb_port_psy_desc = { + .name = "pc_port", + .type = POWER_SUPPLY_TYPE_USB, + .properties = smb2_usb_port_props, + .num_properties = ARRAY_SIZE(smb2_usb_port_props), + .get_property = smb2_usb_port_get_prop, + .set_property = smb2_usb_port_set_prop, +}; + +static int smb2_init_usb_port_psy(struct smb2 *chip) +{ + struct power_supply_config usb_port_cfg = {}; + struct smb_charger *chg = &chip->chg; + + usb_port_cfg.drv_data = chip; + usb_port_cfg.of_node = chg->dev->of_node; + chg->usb_port_psy = power_supply_register(chg->dev, + &usb_port_psy_desc, + &usb_port_cfg); + if (IS_ERR(chg->usb_port_psy)) { + pr_err("Couldn't register USB pc_port power supply\n"); + return PTR_ERR(chg->usb_port_psy); + } + + return 0; +} + /***************************** * USB MAIN PSY REGISTRATION * *****************************/ @@ -2266,7 +2371,13 @@ static int smb2_probe(struct platform_device *pdev) rc = smb2_init_usb_main_psy(chip); if (rc < 0) { - pr_err("Couldn't initialize usb psy rc=%d\n", rc); + pr_err("Couldn't initialize usb main psy rc=%d\n", rc); + goto cleanup; + } + + rc = smb2_init_usb_port_psy(chip); + if (rc < 0) { + pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc); goto cleanup; } @@ -2324,7 +2435,7 @@ static int smb2_probe(struct platform_device *pdev) device_init_wakeup(chg->dev, true); pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n", - usb_present, chg->usb_psy_desc.type, + usb_present, chg->real_charger_type, batt_present, batt_health, batt_charge_type); return rc; @@ -2336,6 +2447,8 @@ cleanup: power_supply_unregister(chg->usb_main_psy); if (chg->usb_psy) power_supply_unregister(chg->usb_psy); + if (chg->usb_port_psy) + power_supply_unregister(chg->usb_port_psy); if (chg->dc_psy) power_supply_unregister(chg->dc_psy); if (chg->vconn_vreg && chg->vconn_vreg->rdev) @@ -2356,6 +2469,7 @@ static int smb2_remove(struct platform_device *pdev) power_supply_unregister(chg->batt_psy); power_supply_unregister(chg->usb_psy); + power_supply_unregister(chg->usb_port_psy); regulator_unregister(chg->vconn_vreg->rdev); regulator_unregister(chg->vbus_vreg->rdev); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index ecfb532e5b3c..64e3edeec3d5 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -550,9 +550,9 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg) /* if PD is active, APSD is disabled so won't have a valid result */ if (chg->pd_active) - chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD; + chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD; else - chg->usb_psy_desc.type = apsd_result->pst; + chg->real_charger_type = apsd_result->pst; smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n", apsd_result->name, chg->pd_active); @@ -858,7 +858,7 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) /* configure current */ if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT - && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) { + && (chg->real_charger_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); @@ -879,10 +879,10 @@ override_suspend_config: /* 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) + if (chg->real_charger_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 + else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP && icl_ua == 1500000) /* * For std cable with type = CDP override only if @@ -3314,7 +3314,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg) int pulses; power_supply_changed(chg->usb_main_psy); - if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) { + if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP) { rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, @@ -3342,7 +3342,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg) } } - if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) { + if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) { rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index d14ea86bf0c6..76de955c303b 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -244,6 +244,8 @@ struct smb_charger { struct power_supply *bms_psy; struct power_supply_desc usb_psy_desc; struct power_supply *usb_main_psy; + struct power_supply *usb_port_psy; + enum power_supply_type real_charger_type; /* notifiers */ struct notifier_block nb; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index e394f123f918..ad9d6cc4e23f 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -3597,7 +3597,8 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) } } - power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_TYPE, &pval); + power_supply_get_property(mdwc->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, &pval); if (pval.intval != POWER_SUPPLY_TYPE_USB) return 0; diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index c76ca5a94557..055c6203577a 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -2365,7 +2365,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) pd->vbus_present = val.intval; ret = power_supply_get_property(pd->usb_psy, - POWER_SUPPLY_PROP_TYPE, &val); + POWER_SUPPLY_PROP_REAL_TYPE, &val); if (ret) { usbpd_err(&pd->dev, "Unable to read USB TYPE: %d\n", ret); return ret;