mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 01:59:54 -04:00
usb: typec: ucsi: support delaying GET_PDOS for device
Qualcomm firmware doesn't return sane information for device's PDOs unless the partner is also using a PD mode. On SC8280XP this even results in the Error bit being set in the UCSI response (with 0 error status). Add a quirk to delay reading USB PD capabilities for a device until we detect a partner in PD mode. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20240329-qcom-ucsi-fixes-v2-7-0f5d37ed04db@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ad4bc68bef
commit
16cad51998
@@ -821,6 +821,28 @@ static int ucsi_check_altmodes(struct ucsi_connector *con)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ucsi_register_device_pdos(struct ucsi_connector *con)
|
||||
{
|
||||
struct ucsi *ucsi = con->ucsi;
|
||||
struct usb_power_delivery_desc desc = { ucsi->cap.pd_version };
|
||||
struct usb_power_delivery_capabilities *pd_cap;
|
||||
|
||||
if (con->pd)
|
||||
return;
|
||||
|
||||
con->pd = usb_power_delivery_register(ucsi->dev, &desc);
|
||||
|
||||
pd_cap = ucsi_get_pd_caps(con, TYPEC_SOURCE, false);
|
||||
if (!IS_ERR(pd_cap))
|
||||
con->port_source_caps = pd_cap;
|
||||
|
||||
pd_cap = ucsi_get_pd_caps(con, TYPEC_SINK, false);
|
||||
if (!IS_ERR(pd_cap))
|
||||
con->port_sink_caps = pd_cap;
|
||||
|
||||
typec_port_set_usb_power_delivery(con->port, con->pd);
|
||||
}
|
||||
|
||||
static int ucsi_register_partner_pdos(struct ucsi_connector *con)
|
||||
{
|
||||
struct usb_power_delivery_desc desc = { con->ucsi->cap.pd_version };
|
||||
@@ -981,6 +1003,9 @@ static int ucsi_register_partner(struct ucsi_connector *con)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD)
|
||||
ucsi_register_device_pdos(con);
|
||||
|
||||
desc.identity = &con->partner_identity;
|
||||
desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
|
||||
desc.pd_revision = UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);
|
||||
@@ -1471,8 +1496,6 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
|
||||
|
||||
static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
|
||||
{
|
||||
struct usb_power_delivery_desc desc = { ucsi->cap.pd_version};
|
||||
struct usb_power_delivery_capabilities *pd_cap;
|
||||
struct typec_capability *cap = &con->typec_cap;
|
||||
enum typec_accessory *accessory = cap->accessory;
|
||||
enum usb_role u_role = USB_ROLE_NONE;
|
||||
@@ -1550,17 +1573,8 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
|
||||
goto out;
|
||||
}
|
||||
|
||||
con->pd = usb_power_delivery_register(ucsi->dev, &desc);
|
||||
|
||||
pd_cap = ucsi_get_pd_caps(con, TYPEC_SOURCE, false);
|
||||
if (!IS_ERR(pd_cap))
|
||||
con->port_source_caps = pd_cap;
|
||||
|
||||
pd_cap = ucsi_get_pd_caps(con, TYPEC_SINK, false);
|
||||
if (!IS_ERR(pd_cap))
|
||||
con->port_sink_caps = pd_cap;
|
||||
|
||||
typec_port_set_usb_power_delivery(con->port, con->pd);
|
||||
if (!(ucsi->quirks & UCSI_DELAY_DEVICE_PDOS))
|
||||
ucsi_register_device_pdos(con);
|
||||
|
||||
/* Alternate modes */
|
||||
ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON);
|
||||
@@ -1623,6 +1637,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
|
||||
if (con->partner &&
|
||||
UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
|
||||
UCSI_CONSTAT_PWR_OPMODE_PD) {
|
||||
ucsi_register_device_pdos(con);
|
||||
ucsi_get_src_pdos(con);
|
||||
ucsi_check_altmodes(con);
|
||||
}
|
||||
|
||||
@@ -408,6 +408,7 @@ struct ucsi {
|
||||
|
||||
unsigned long quirks;
|
||||
#define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */
|
||||
#define UCSI_DELAY_DEVICE_PDOS BIT(1) /* Reading PDOs fails until the parter is in PD mode */
|
||||
};
|
||||
|
||||
#define UCSI_MAX_SVID 5
|
||||
|
||||
Reference in New Issue
Block a user