diff options
Diffstat (limited to 'drivers/usb/typec')
| -rw-r--r-- | drivers/usb/typec/altmodes/displayport.c | 3 | ||||
| -rw-r--r-- | drivers/usb/typec/class.c | 2 | ||||
| -rw-r--r-- | drivers/usb/typec/mux/intel_pmc_mux.c | 72 | ||||
| -rw-r--r-- | drivers/usb/typec/tcpm/fusb302.c | 1 | ||||
| -rw-r--r-- | drivers/usb/typec/tcpm/tcpci.c | 9 | ||||
| -rw-r--r-- | drivers/usb/typec/tcpm/tcpci.h | 1 | ||||
| -rw-r--r-- | drivers/usb/typec/tcpm/tcpm.c | 212 | ||||
| -rw-r--r-- | drivers/usb/typec/tps6598x.c | 2 | ||||
| -rw-r--r-- | drivers/usb/typec/ucsi/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/usb/typec/ucsi/ucsi.c | 3 | 
10 files changed, 217 insertions, 90 deletions
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 0edfb89e04a8..7b20073d7fc0 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -1,5 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/** +/*   * USB Typec-C DisplayPort Alternate Mode driver   *   * Copyright (C) 2018 Intel Corporation @@ -13,6 +13,7 @@  #include <linux/module.h>  #include <linux/usb/pd_vdo.h>  #include <linux/usb/typec_dp.h> +#include "displayport.h"  #define DP_HEADER(_dp, cmd)		(VDO((_dp)->alt->svid, 1, cmd) | \  					 VDO_OPOS(USB_TYPEC_DP_MODE)) diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index c9234748537a..02655694f200 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -580,7 +580,7 @@ EXPORT_SYMBOL_GPL(typec_partner_set_identity);   * SVID listed in response to Discover Modes command need to be listed in an   * array in @desc.   * - * Returns handle to the alternate mode on success or NULL on failure. + * Returns handle to the alternate mode on success or ERR_PTR on failure.   */  struct typec_altmode *  typec_partner_register_altmode(struct typec_partner *partner, diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index 70ddc9d6d49e..e4021e13af40 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -10,6 +10,7 @@  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/property.h> +#include <linux/usb/pd.h>  #include <linux/usb/role.h>  #include <linux/usb/typec_mux.h>  #include <linux/usb/typec_dp.h> @@ -19,6 +20,10 @@  #define PMC_USBC_CMD		0xa7 +/* Response status bits */ +#define PMC_USB_RESP_STATUS_FAILURE	BIT(0) +#define PMC_USB_RESP_STATUS_FATAL	BIT(1) +  /* "Usage" OOB Message field values */  enum {  	PMC_USB_CONNECT, @@ -130,8 +135,8 @@ static int pmc_usb_command(struct pmc_usb_port *port, u8 *msg, u32 len)  	 */  	intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg, len,  				  response, sizeof(response)); -	if (response[2]) { -		if (response[2] & BIT(1)) +	if (response[2] & PMC_USB_RESP_STATUS_FAILURE) { +		if (response[2] & PMC_USB_RESP_STATUS_FATAL)  			return -EIO;  		return -EBUSY;  	} @@ -227,6 +232,43 @@ pmc_usb_mux_tbt(struct pmc_usb_port *port, struct typec_mux_state *state)  	return pmc_usb_command(port, (void *)&req, sizeof(req));  } +static int +pmc_usb_mux_usb4(struct pmc_usb_port *port, struct typec_mux_state *state) +{ +	struct enter_usb_data *data = state->data; +	struct altmode_req req = { }; +	u8 cable_speed; + +	req.usage = PMC_USB_ALT_MODE; +	req.usage |= port->usb3_port << PMC_USB_MSG_USB3_PORT_SHIFT; +	req.mode_type = PMC_USB_MODE_TYPE_TBT << PMC_USB_MODE_TYPE_SHIFT; + +	/* USB4 Mode */ +	req.mode_data = PMC_USB_ALTMODE_FORCE_LSR; + +	if (data->active_link_training) +		req.mode_data |= PMC_USB_ALTMODE_ACTIVE_LINK; + +	req.mode_data |= (port->orientation - 1) << PMC_USB_ALTMODE_ORI_SHIFT; +	req.mode_data |= (port->role - 1) << PMC_USB_ALTMODE_UFP_SHIFT; + +	switch ((data->eudo & EUDO_CABLE_TYPE_MASK) >> EUDO_CABLE_TYPE_SHIFT) { +	case EUDO_CABLE_TYPE_PASSIVE: +		break; +	case EUDO_CABLE_TYPE_OPTICAL: +		req.mode_data |= PMC_USB_ALTMODE_CABLE_TYPE; +		fallthrough; +	default: +		req.mode_data |= PMC_USB_ALTMODE_ACTIVE_CABLE; +		break; +	} + +	cable_speed = (data->eudo & EUDO_CABLE_SPEED_MASK) >> EUDO_CABLE_SPEED_SHIFT; +	req.mode_data |= PMC_USB_ALTMODE_CABLE_SPD(cable_speed); + +	return pmc_usb_command(port, (void *)&req, sizeof(req)); +} +  static int pmc_usb_mux_safe_state(struct pmc_usb_port *port)  {  	u8 msg; @@ -268,17 +310,31 @@ pmc_usb_mux_set(struct typec_mux *mux, struct typec_mux_state *state)  {  	struct pmc_usb_port *port = typec_mux_get_drvdata(mux); -	if (!state->alt) +	if (port->orientation == TYPEC_ORIENTATION_NONE || port->role == USB_ROLE_NONE)  		return 0;  	if (state->mode == TYPEC_STATE_SAFE)  		return pmc_usb_mux_safe_state(port); +	if (state->mode == TYPEC_STATE_USB) +		return pmc_usb_connect(port); -	switch (state->alt->svid) { -	case USB_TYPEC_TBT_SID: -		return pmc_usb_mux_tbt(port, state); -	case USB_TYPEC_DP_SID: -		return pmc_usb_mux_dp(port, state); +	if (state->alt) { +		switch (state->alt->svid) { +		case USB_TYPEC_TBT_SID: +			return pmc_usb_mux_tbt(port, state); +		case USB_TYPEC_DP_SID: +			return pmc_usb_mux_dp(port, state); +		} +	} else { +		switch (state->mode) { +		case TYPEC_MODE_USB2: +			/* REVISIT: Try with usb3_port set to 0? */ +			break; +		case TYPEC_MODE_USB3: +			return pmc_usb_connect(port); +		case TYPEC_MODE_USB4: +			return pmc_usb_mux_usb4(port, state); +		}  	}  	return -EOPNOTSUPP; diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index b28facece43c..99562cc65ca6 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -178,6 +178,7 @@ abort:  	mutex_unlock(&chip->logbuffer_lock);  } +__printf(2, 3)  static void fusb302_log(struct fusb302_chip *chip, const char *fmt, ...)  {  	va_list args; diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 753645bb2527..f57d91fd0e09 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -227,6 +227,14 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)  				enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);  } +static int tcpci_set_bist_data(struct tcpc_dev *tcpc, bool enable) +{ +	struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + +	return regmap_update_bits(tcpci->regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_BIST_TM, +				 enable ? TCPC_TCPC_CTRL_BIST_TM : 0); +} +  static int tcpci_set_roles(struct tcpc_dev *tcpc, bool attached,  			   enum typec_role role, enum typec_data_role data)  { @@ -530,6 +538,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)  	tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx;  	tcpci->tcpc.set_roles = tcpci_set_roles;  	tcpci->tcpc.pd_transmit = tcpci_pd_transmit; +	tcpci->tcpc.set_bist_data = tcpci_set_bist_data;  	err = tcpci_parse_config(tcpci);  	if (err < 0) diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 303ebde26546..11c36d086c86 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -36,6 +36,7 @@  #define TCPC_TCPC_CTRL			0x19  #define TCPC_TCPC_CTRL_ORIENTATION	BIT(0) +#define TCPC_TCPC_CTRL_BIST_TM		BIT(1)  #define TCPC_ROLE_CTRL			0x1a  #define TCPC_ROLE_CTRL_DRP		BIT(6) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 82b19ebd7838..3ef37202ee37 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -159,6 +159,14 @@ enum pd_msg_request {  	PD_MSG_DATA_SOURCE_CAP,  }; +enum adev_actions { +	ADEV_NONE = 0, +	ADEV_NOTIFY_USB_AND_QUEUE_VDM, +	ADEV_QUEUE_VDM, +	ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL, +	ADEV_ATTENTION, +}; +  /* Events from low level driver */  #define TCPM_CC_EVENT		BIT(0) @@ -961,24 +969,38 @@ static void tcpm_queue_message(struct tcpm_port *port,  static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,  			   const u32 *data, int cnt)  { +	WARN_ON(!mutex_is_locked(&port->lock)); + +	/* Make sure we are not still processing a previous VDM packet */ +	WARN_ON(port->vdm_state > VDM_STATE_DONE); +  	port->vdo_count = cnt + 1;  	port->vdo_data[0] = header;  	memcpy(&port->vdo_data[1], data, sizeof(u32) * cnt);  	/* Set ready, vdm state machine will actually send */  	port->vdm_retries = 0;  	port->vdm_state = VDM_STATE_READY; + +	mod_delayed_work(port->wq, &port->vdm_state_machine, 0);  } -static void svdm_consume_identity(struct tcpm_port *port, const __le32 *payload, -				  int cnt) +static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, +				    const u32 *data, int cnt)  { -	u32 vdo = le32_to_cpu(payload[VDO_INDEX_IDH]); -	u32 product = le32_to_cpu(payload[VDO_INDEX_PRODUCT]); +	mutex_lock(&port->lock); +	tcpm_queue_vdm(port, header, data, cnt); +	mutex_unlock(&port->lock); +} + +static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt) +{ +	u32 vdo = p[VDO_INDEX_IDH]; +	u32 product = p[VDO_INDEX_PRODUCT];  	memset(&port->mode_data, 0, sizeof(port->mode_data));  	port->partner_ident.id_header = vdo; -	port->partner_ident.cert_stat = le32_to_cpu(payload[VDO_INDEX_CSTAT]); +	port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];  	port->partner_ident.product = product;  	typec_partner_set_identity(port->partner); @@ -988,17 +1010,15 @@ static void svdm_consume_identity(struct tcpm_port *port, const __le32 *payload,  		 PD_PRODUCT_PID(product), product & 0xffff);  } -static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload, -			       int cnt) +static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt)  {  	struct pd_mode_data *pmdata = &port->mode_data;  	int i;  	for (i = 1; i < cnt; i++) { -		u32 p = le32_to_cpu(payload[i]);  		u16 svid; -		svid = (p >> 16) & 0xffff; +		svid = (p[i] >> 16) & 0xffff;  		if (!svid)  			return false; @@ -1008,7 +1028,7 @@ static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload,  		pmdata->svids[pmdata->nsvids++] = svid;  		tcpm_log(port, "SVID %d: 0x%x", pmdata->nsvids, svid); -		svid = p & 0xffff; +		svid = p[i] & 0xffff;  		if (!svid)  			return false; @@ -1024,8 +1044,7 @@ abort:  	return false;  } -static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload, -			       int cnt) +static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt)  {  	struct pd_mode_data *pmdata = &port->mode_data;  	struct typec_altmode_desc *paltmode; @@ -1042,7 +1061,7 @@ static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload,  		paltmode->svid = pmdata->svids[pmdata->svid_index];  		paltmode->mode = i; -		paltmode->vdo = le32_to_cpu(payload[i]); +		paltmode->vdo = p[i];  		tcpm_log(port, " Alternate mode %d: SVID 0x%04x, VDO %d: 0x%08x",  			 pmdata->altmodes, paltmode->svid, @@ -1061,30 +1080,28 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)  	for (i = 0; i < modep->altmodes; i++) {  		altmode = typec_partner_register_altmode(port->partner,  						&modep->altmode_desc[i]); -		if (!altmode) +		if (IS_ERR(altmode)) {  			tcpm_log(port, "Failed to register partner SVID 0x%04x",  				 modep->altmode_desc[i].svid); +			altmode = NULL; +		}  		port->partner_altmode[i] = altmode;  	}  }  #define supports_modal(port)	PD_IDH_MODAL_SUPP((port)->partner_ident.id_header) -static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, -			u32 *response) +static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, +			const u32 *p, int cnt, u32 *response, +			enum adev_actions *adev_action)  { -	struct typec_altmode *adev;  	struct typec_altmode *pdev;  	struct pd_mode_data *modep; -	u32 p[PD_MAX_PAYLOAD];  	int rlen = 0;  	int cmd_type;  	int cmd;  	int i; -	for (i = 0; i < cnt; i++) -		p[i] = le32_to_cpu(payload[i]); -  	cmd_type = PD_VDO_CMDT(p[0]);  	cmd = PD_VDO_CMD(p[0]); @@ -1093,9 +1110,6 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  	modep = &port->mode_data; -	adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX, -				   PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0])); -  	pdev = typec_match_altmode(port->partner_altmode, ALTMODE_DISCOVERY_MAX,  				   PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0])); @@ -1121,8 +1135,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  			break;  		case CMD_ATTENTION:  			/* Attention command does not have response */ -			if (adev) -				typec_altmode_attention(adev, p[1]); +			*adev_action = ADEV_ATTENTION;  			return 0;  		default:  			break; @@ -1145,13 +1158,13 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  		switch (cmd) {  		case CMD_DISCOVER_IDENT:  			/* 6.4.4.3.1 */ -			svdm_consume_identity(port, payload, cnt); +			svdm_consume_identity(port, p, cnt);  			response[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);  			rlen = 1;  			break;  		case CMD_DISCOVER_SVID:  			/* 6.4.4.3.2 */ -			if (svdm_consume_svids(port, payload, cnt)) { +			if (svdm_consume_svids(port, p, cnt)) {  				response[0] = VDO(USB_SID_PD, 1,  						  CMD_DISCOVER_SVID);  				rlen = 1; @@ -1163,7 +1176,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  			break;  		case CMD_DISCOVER_MODES:  			/* 6.4.4.3.3 */ -			svdm_consume_modes(port, payload, cnt); +			svdm_consume_modes(port, p, cnt);  			modep->svid_index++;  			if (modep->svid_index < modep->nsvids) {  				u16 svid = modep->svids[modep->svid_index]; @@ -1176,23 +1189,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  		case CMD_ENTER_MODE:  			if (adev && pdev) {  				typec_altmode_update_active(pdev, true); - -				if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) { -					response[0] = VDO(adev->svid, 1, -							  CMD_EXIT_MODE); -					response[0] |= VDO_OPOS(adev->mode); -					return 1; -				} +				*adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL;  			}  			return 0;  		case CMD_EXIT_MODE:  			if (adev && pdev) {  				typec_altmode_update_active(pdev, false); -  				/* Back to USB Operation */ -				WARN_ON(typec_altmode_notify(adev, -							     TYPEC_STATE_USB, -							     NULL)); +				*adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM; +				return 0;  			}  			break;  		default: @@ -1203,11 +1208,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  		switch (cmd) {  		case CMD_ENTER_MODE:  			/* Back to USB Operation */ -			if (adev) -				WARN_ON(typec_altmode_notify(adev, -							     TYPEC_STATE_USB, -							     NULL)); -			break; +			*adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM; +			return 0;  		default:  			break;  		} @@ -1217,24 +1219,30 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,  	}  	/* Informing the alternate mode drivers about everything */ -	if (adev) -		typec_altmode_vdm(adev, p[0], &p[1], cnt); - +	*adev_action = ADEV_QUEUE_VDM;  	return rlen;  }  static void tcpm_handle_vdm_request(struct tcpm_port *port,  				    const __le32 *payload, int cnt)  { -	int rlen = 0; +	enum adev_actions adev_action = ADEV_NONE; +	struct typec_altmode *adev; +	u32 p[PD_MAX_PAYLOAD];  	u32 response[8] = { }; -	u32 p0 = le32_to_cpu(payload[0]); +	int i, rlen = 0; + +	for (i = 0; i < cnt; i++) +		p[i] = le32_to_cpu(payload[i]); + +	adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX, +				   PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));  	if (port->vdm_state == VDM_STATE_BUSY) {  		/* If UFP responded busy retry after timeout */ -		if (PD_VDO_CMDT(p0) == CMDT_RSP_BUSY) { +		if (PD_VDO_CMDT(p[0]) == CMDT_RSP_BUSY) {  			port->vdm_state = VDM_STATE_WAIT_RSP_BUSY; -			port->vdo_retry = (p0 & ~VDO_CMDT_MASK) | +			port->vdo_retry = (p[0] & ~VDO_CMDT_MASK) |  				CMDT_INIT;  			mod_delayed_work(port->wq, &port->vdm_state_machine,  					 msecs_to_jiffies(PD_T_VDM_BUSY)); @@ -1243,13 +1251,65 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,  		port->vdm_state = VDM_STATE_DONE;  	} -	if (PD_VDO_SVDM(p0)) -		rlen = tcpm_pd_svdm(port, payload, cnt, response); +	if (PD_VDO_SVDM(p[0])) +		rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action); -	if (rlen > 0) { -		tcpm_queue_vdm(port, response[0], &response[1], rlen - 1); -		mod_delayed_work(port->wq, &port->vdm_state_machine, 0); +	/* +	 * We are done with any state stored in the port struct now, except +	 * for any port struct changes done by the tcpm_queue_vdm() call +	 * below, which is a separate operation. +	 * +	 * So we can safely release the lock here; and we MUST release the +	 * lock here to avoid an AB BA lock inversion: +	 * +	 * If we keep the lock here then the lock ordering in this path is: +	 * 1. tcpm_pd_rx_handler take the tcpm port lock +	 * 2. One of the typec_altmode_* calls below takes the alt-mode's lock +	 * +	 * And we also have this ordering: +	 * 1. alt-mode driver takes the alt-mode's lock +	 * 2. alt-mode driver calls tcpm_altmode_enter which takes the +	 *    tcpm port lock +	 * +	 * Dropping our lock here avoids this. +	 */ +	mutex_unlock(&port->lock); + +	if (adev) { +		switch (adev_action) { +		case ADEV_NONE: +			break; +		case ADEV_NOTIFY_USB_AND_QUEUE_VDM: +			WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); +			typec_altmode_vdm(adev, p[0], &p[1], cnt); +			break; +		case ADEV_QUEUE_VDM: +			typec_altmode_vdm(adev, p[0], &p[1], cnt); +			break; +		case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: +			if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) { +				response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE); +				response[0] |= VDO_OPOS(adev->mode); +				rlen = 1; +			} +			break; +		case ADEV_ATTENTION: +			typec_altmode_attention(adev, p[1]); +			break; +		}  	} + +	/* +	 * We must re-take the lock here to balance the unlock in +	 * tcpm_pd_rx_handler, note that no changes, other then the +	 * tcpm_queue_vdm call, are made while the lock is held again. +	 * All that is done after the call is unwinding the call stack until +	 * we return to tcpm_pd_rx_handler and do the unlock there. +	 */ +	mutex_lock(&port->lock); + +	if (rlen > 0) +		tcpm_queue_vdm(port, response[0], &response[1], rlen - 1);  }  static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd, @@ -1264,8 +1324,6 @@ static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd,  	header = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?  			1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd);  	tcpm_queue_vdm(port, header, data, count); - -	mod_delayed_work(port->wq, &port->vdm_state_machine, 0);  }  static unsigned int vdm_ready_timeout(u32 vdm_hdr) @@ -1508,14 +1566,10 @@ static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo)  	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);  	u32 header; -	mutex_lock(&port->lock);  	header = VDO(altmode->svid, vdo ? 2 : 1, CMD_ENTER_MODE);  	header |= VDO_OPOS(altmode->mode); -	tcpm_queue_vdm(port, header, vdo, vdo ? 1 : 0); -	mod_delayed_work(port->wq, &port->vdm_state_machine, 0); -	mutex_unlock(&port->lock); - +	tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0);  	return 0;  } @@ -1524,14 +1578,10 @@ static int tcpm_altmode_exit(struct typec_altmode *altmode)  	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);  	u32 header; -	mutex_lock(&port->lock);  	header = VDO(altmode->svid, 1, CMD_EXIT_MODE);  	header |= VDO_OPOS(altmode->mode); -	tcpm_queue_vdm(port, header, NULL, 0); -	mod_delayed_work(port->wq, &port->vdm_state_machine, 0); -	mutex_unlock(&port->lock); - +	tcpm_queue_vdm_unlocked(port, header, NULL, 0);  	return 0;  } @@ -1540,11 +1590,7 @@ static int tcpm_altmode_vdm(struct typec_altmode *altmode,  {  	struct tcpm_port *port = typec_altmode_get_drvdata(altmode); -	mutex_lock(&port->lock); -	tcpm_queue_vdm(port, header, data, count - 1); -	mod_delayed_work(port->wq, &port->vdm_state_machine, 0); -	mutex_unlock(&port->lock); - +	tcpm_queue_vdm_unlocked(port, header, data, count - 1);  	return 0;  } @@ -2746,6 +2792,11 @@ static void tcpm_detach(struct tcpm_port *port)  	if (!port->attached)  		return; +	if (port->tcpc->set_bist_data) { +		tcpm_log(port, "disable BIST MODE TESTDATA"); +		port->tcpc->set_bist_data(port->tcpc, false); +	} +  	if (tcpm_port_is_disconnected(port))  		port->hard_reset_count = 0; @@ -3554,12 +3605,18 @@ static void run_state_machine(struct tcpm_port *port)  		switch (BDO_MODE_MASK(port->bist_request)) {  		case BDO_MODE_CARRIER2:  			tcpm_pd_transmit(port, TCPC_TX_BIST_MODE_2, NULL); +			tcpm_set_state(port, unattached_state(port), +				       PD_T_BIST_CONT_MODE); +			break; +		case BDO_MODE_TESTDATA: +			if (port->tcpc->set_bist_data) { +				tcpm_log(port, "Enable BIST MODE TESTDATA"); +				port->tcpc->set_bist_data(port->tcpc, true); +			}  			break;  		default:  			break;  		} -		/* Always switch to unattached state */ -		tcpm_set_state(port, unattached_state(port), 0);  		break;  	case GET_STATUS_SEND:  		tcpm_pd_send_control(port, PD_CTRL_GET_STATUS); @@ -3949,6 +4006,9 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)  static void _tcpm_pd_hard_reset(struct tcpm_port *port)  {  	tcpm_log_force(port, "Received hard reset"); +	if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data) +		port->tcpc->set_bist_data(port->tcpc, false); +  	/*  	 * If we keep receiving hard reset requests, executing the hard reset  	 * must have failed. Revert to error recovery if that happens. diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index b7c9fe5caabe..3db33bb622c3 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -100,7 +100,7 @@ struct tps6598x {  /*   * Max data bytes for Data1, Data2, and other registers. See ch 1.3.2: - * http://www.ti.com/lit/ug/slvuan1a/slvuan1a.pdf + * https://www.ti.com/lit/ug/slvuan1a/slvuan1a.pdf   */  #define TPS_MAX_LEN	64 diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig index 15c2ac7db02d..2192d7c4fec7 100644 --- a/drivers/usb/typec/ucsi/Kconfig +++ b/drivers/usb/typec/ucsi/Kconfig @@ -18,7 +18,7 @@ config TYPEC_UCSI  	  for every supported interface method.  	  The UCSI specification can be downloaded from: -	  http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html +	  https://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html  	  To compile the driver as a module, choose M here: the module will be  	  called typec_ucsi. diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index d0c63afaf345..affd024190c9 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1002,7 +1002,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)   *   * Registers all ports @ucsi has and enables all notification events.   */ -int ucsi_init(struct ucsi *ucsi) +static int ucsi_init(struct ucsi *ucsi)  {  	struct ucsi_connector *con;  	u64 command; @@ -1078,7 +1078,6 @@ err:  	return ret;  } -EXPORT_SYMBOL_GPL(ucsi_init);  static void ucsi_init_work(struct work_struct *work)  {  | 
