From 765b15bf79400b059a7a7faee24a21e140ad4fb7 Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Fri, 23 Dec 2022 11:20:43 +0800 Subject: [PATCH] usb: typec: tcpm: amend pd negotiated revision Try to get the maximum PD revision which Type-C controller can support from DT, and use this value to init the PD negotiated revision instead of hard coded values 0x0300 (PD3.0). This can fix at least the following two Type-C controllers issues: 1. FUSB302 failed to response PD Message "Get Source Cap Ext" if used the default negotiated revision PD_MAX_REV (PD_REV30) with MacBook (test on macOS 12.2.1). 2. ET7301B failed to detect the voltage status of the measured CC pin for vRd-3.0 if used the default negotiated revision PD_MAX_REV (PD_REV30) with some Type-C DP monitors. Signed-off-by: Frank Wang Signed-off-by: William Wu Change-Id: I2c9bcc06ff2b3d678a6eab5013cec7f45cbda3dd --- drivers/usb/typec/tcpm/tcpm.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index bf84a1ef4a3d..877108263f51 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2438,7 +2438,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port, } if (rev < PD_MAX_REV) - port->negotiated_rev = rev; + port->negotiated_rev = min_t(u16, rev, port->negotiated_rev); if (port->pwr_role == TYPEC_SOURCE) { if (port->ams == GET_SOURCE_CAPABILITIES) @@ -2490,7 +2490,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port, } if (rev < PD_MAX_REV) - port->negotiated_rev = rev; + port->negotiated_rev = min_t(u16, rev, port->negotiated_rev); if (port->pwr_role != TYPEC_SOURCE || cnt != 1) { tcpm_pd_handle_msg(port, @@ -3993,7 +3993,7 @@ static void run_state_machine(struct tcpm_port *port) typec_set_pwr_opmode(port->typec_port, opmode); port->pwr_opmode = TYPEC_PWR_MODE_USB; port->caps_count = 0; - port->negotiated_rev = PD_MAX_REV; + port->negotiated_rev = (((port->typec_caps.pd_revision >> 8) & 0xff) - 1); port->message_id = 0; port->rx_msgid = -1; port->explicit_contract = false; @@ -4244,7 +4244,7 @@ static void run_state_machine(struct tcpm_port *port) port->cc2 : port->cc1); typec_set_pwr_opmode(port->typec_port, opmode); port->pwr_opmode = TYPEC_PWR_MODE_USB; - port->negotiated_rev = PD_MAX_REV; + port->negotiated_rev = (((port->typec_caps.pd_revision >> 8) & 0xff) - 1); port->message_id = 0; port->rx_msgid = -1; port->explicit_contract = false; @@ -6047,7 +6047,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, { const char *cap_str; int ret; - u32 mw, frs_current; + u32 mw, frs_current, pd_revision; if (!fwnode) return -EINVAL; @@ -6155,6 +6155,13 @@ sink: return ret; } + ret = fwnode_property_read_u32(fwnode, "pd-revision", + &pd_revision); + if (ret < 0) + port->typec_caps.pd_revision = 0x0300; + else + port->typec_caps.pd_revision = pd_revision & 0xffff; + return 0; } @@ -6550,7 +6557,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) port->typec_caps.fwnode = tcpc->fwnode; port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ - port->typec_caps.pd_revision = 0x0300; /* USB-PD spec release 3.0 */ port->typec_caps.svdm_version = SVDM_VER_2_0; port->typec_caps.driver_data = port; port->typec_caps.ops = &tcpm_ops;