diff mbox series

[v2,04/12] usb: typec: tcpci: add tcpm_transmit_type to tcpm_pd_receive

Message ID 20231214230850.379863-18-rdbabiera@google.com
State New
Headers show
Series usb: typec: add SOP' support to the tcpm and alt mode drivers | expand

Commit Message

RD Babiera Dec. 14, 2023, 11:08 p.m. UTC
tcpm_pd_receive adds the SOP type as a parameter, and passes it within the
pd_rx_event struct for tcpm_pd_rx_handler to use. For now, the handler
drops all SOP' messages.

Maxim based tcpci drivers are capable of SOP' communication, so process_rx
now takes the SOP type into account and passes the value to
tcpm_pd_receive.

tcpci_set_pd_rx now utilizes the cable_comm_capable flag to determine if
TCPC_RX_DETECT_SOP1 should be added to the bitfield when enabling PD
message reception.

For all other consumers of tcpm_pd_receive, default the new field to
TCPC_TX_SOP.

Signed-off-by: RD Babiera <rdbabiera@google.com>
---
 drivers/usb/typec/tcpm/fusb302.c              |  2 +-
 .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c   |  2 +-
 drivers/usb/typec/tcpm/tcpci.c                |  7 +++++--
 drivers/usb/typec/tcpm/tcpci_maxim_core.c     | 20 ++++++++++++++++---
 drivers/usb/typec/tcpm/tcpm.c                 | 10 +++++++++-
 drivers/usb/typec/tcpm/wcove.c                |  2 +-
 include/linux/usb/tcpci.h                     |  1 +
 include/linux/usb/tcpm.h                      |  3 ++-
 8 files changed, 37 insertions(+), 10 deletions(-)

Comments

Heikki Krogerus Dec. 19, 2023, 1:59 p.m. UTC | #1
On Thu, Dec 14, 2023 at 11:08:48PM +0000, RD Babiera wrote:
> tcpm_pd_receive adds the SOP type as a parameter, and passes it within the
> pd_rx_event struct for tcpm_pd_rx_handler to use. For now, the handler
> drops all SOP' messages.
> 
> Maxim based tcpci drivers are capable of SOP' communication, so process_rx
> now takes the SOP type into account and passes the value to
> tcpm_pd_receive.
> 
> tcpci_set_pd_rx now utilizes the cable_comm_capable flag to determine if
> TCPC_RX_DETECT_SOP1 should be added to the bitfield when enabling PD
> message reception.
> 
> For all other consumers of tcpm_pd_receive, default the new field to
> TCPC_TX_SOP.
> 
> Signed-off-by: RD Babiera <rdbabiera@google.com>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tcpm/fusb302.c              |  2 +-
>  .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c   |  2 +-
>  drivers/usb/typec/tcpm/tcpci.c                |  7 +++++--
>  drivers/usb/typec/tcpm/tcpci_maxim_core.c     | 20 ++++++++++++++++---
>  drivers/usb/typec/tcpm/tcpm.c                 | 10 +++++++++-
>  drivers/usb/typec/tcpm/wcove.c                |  2 +-
>  include/linux/usb/tcpci.h                     |  1 +
>  include/linux/usb/tcpm.h                      |  3 ++-
>  8 files changed, 37 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> index bc21006e979c..ef18a448b740 100644
> --- a/drivers/usb/typec/tcpm/fusb302.c
> +++ b/drivers/usb/typec/tcpm/fusb302.c
> @@ -1467,7 +1467,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
>  	if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC))
>  		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS);
>  	else
> -		tcpm_pd_receive(chip->tcpm_port, msg);
> +		tcpm_pd_receive(chip->tcpm_port, msg, TCPC_TX_SOP);
>  
>  	return ret;
>  }
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> index 52c81378e36e..a3154085ae32 100644
> --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> @@ -299,7 +299,7 @@ static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec
>  
>  	if (!ret) {
>  		dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
> -		tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg);
> +		tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg, TCPC_TX_SOP);
>  	}
>  }
>  
> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index 1ededbcecc09..8ea4ed159a13 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c
> @@ -445,8 +445,11 @@ static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable)
>  	unsigned int reg = 0;
>  	int ret;
>  
> -	if (enable)
> +	if (enable) {
>  		reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
> +		if (tcpci->data->cable_comm_capable)
> +			reg |= TCPC_RX_DETECT_SOP1;
> +	}
>  	ret = regmap_write(tcpci->regmap, TCPC_RX_DETECT, reg);
>  	if (ret < 0)
>  		return ret;
> @@ -719,7 +722,7 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
>  		/* Read complete, clear RX status alert bit */
>  		tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
>  
> -		tcpm_pd_receive(tcpci->port, &msg);
> +		tcpm_pd_receive(tcpci->port, &msg, TCPC_TX_SOP);
>  	}
>  
>  	if (tcpci->data->vbus_vsafe0v && (status & TCPC_ALERT_EXTENDED_STATUS)) {
> diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> index 7b2d4e6e52a2..f9f838df43f7 100644
> --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> @@ -128,6 +128,7 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status)
>  	u8 count, frame_type, rx_buf[TCPC_RECEIVE_BUFFER_LEN];
>  	int ret, payload_index;
>  	u8 *rx_buf_ptr;
> +	enum tcpm_transmit_type rx_type;
>  
>  	/*
>  	 * READABLE_BYTE_COUNT: Indicates the number of bytes in the RX_BUF_BYTE_x registers
> @@ -143,10 +144,23 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status)
>  	count = rx_buf[TCPC_RECEIVE_BUFFER_COUNT_OFFSET];
>  	frame_type = rx_buf[TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET];
>  
> -	if (count == 0 || frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP) {
> +	switch (frame_type) {
> +	case TCPC_RX_BUF_FRAME_TYPE_SOP1:
> +		rx_type = TCPC_TX_SOP_PRIME;
> +		break;
> +	case TCPC_RX_BUF_FRAME_TYPE_SOP:
> +		rx_type = TCPC_TX_SOP;
> +		break;
> +	default:
> +		rx_type = TCPC_TX_SOP;
> +		break;
> +	}
> +
> +	if (count == 0 || (frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP &&
> +	    frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP1)) {
>  		max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
>  		dev_err(chip->dev, "%s\n", count ==  0 ? "error: count is 0" :
> -			"error frame_type is not SOP");
> +			"error frame_type is not SOP/SOP'");
>  		return;
>  	}
>  
> @@ -183,7 +197,7 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status)
>  	if (ret < 0)
>  		return;
>  
> -	tcpm_pd_receive(chip->port, &msg);
> +	tcpm_pd_receive(chip->port, &msg, rx_type);
>  }
>  
>  static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink)
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index ff67553b6932..b05325dcd7ac 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -506,6 +506,7 @@ struct pd_rx_event {
>  	struct kthread_work work;
>  	struct tcpm_port *port;
>  	struct pd_message msg;
> +	enum tcpm_transmit_type rx_sop_type;
>  };
>  
>  static const char * const pd_rev[] = {
> @@ -2969,12 +2970,17 @@ static void tcpm_pd_rx_handler(struct kthread_work *work)
>  	const struct pd_message *msg = &event->msg;
>  	unsigned int cnt = pd_header_cnt_le(msg->header);
>  	struct tcpm_port *port = event->port;
> +	enum tcpm_transmit_type rx_sop_type = event->rx_sop_type;
>  
>  	mutex_lock(&port->lock);
>  
>  	tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header),
>  		 port->attached);
>  
> +	/* Ignore SOP' for now */
> +	if (rx_sop_type == TCPC_TX_SOP_PRIME)
> +		goto done;
> +
>  	if (port->attached) {
>  		enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
>  		unsigned int msgid = pd_header_msgid_le(msg->header);
> @@ -3016,7 +3022,8 @@ static void tcpm_pd_rx_handler(struct kthread_work *work)
>  	kfree(event);
>  }
>  
> -void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
> +void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg,
> +		     enum tcpm_transmit_type rx_sop_type)
>  {
>  	struct pd_rx_event *event;
>  
> @@ -3026,6 +3033,7 @@ void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
>  
>  	kthread_init_work(&event->work, tcpm_pd_rx_handler);
>  	event->port = port;
> +	event->rx_sop_type = rx_sop_type;
>  	memcpy(&event->msg, msg, sizeof(*msg));
>  	kthread_queue_work(port->wq, &event->work);
>  }
> diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
> index 87d4abde0ea2..cf719307b3f6 100644
> --- a/drivers/usb/typec/tcpm/wcove.c
> +++ b/drivers/usb/typec/tcpm/wcove.c
> @@ -535,7 +535,7 @@ static irqreturn_t wcove_typec_irq(int irq, void *data)
>  				goto err;
>  			}
>  
> -			tcpm_pd_receive(wcove->tcpm, &msg);
> +			tcpm_pd_receive(wcove->tcpm, &msg, TCPC_TX_SOP);
>  
>  			ret = regmap_read(wcove->regmap, USBC_RXSTATUS,
>  					  &status);
> diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h
> index 1d0b849defd0..9ed6d62c9c5f 100644
> --- a/include/linux/usb/tcpci.h
> +++ b/include/linux/usb/tcpci.h
> @@ -145,6 +145,7 @@
>  #define TCPC_RX_BYTE_CNT		0x30
>  #define TCPC_RX_BUF_FRAME_TYPE		0x31
>  #define TCPC_RX_BUF_FRAME_TYPE_SOP	0
> +#define TCPC_RX_BUF_FRAME_TYPE_SOP1	1
>  #define TCPC_RX_HDR			0x32
>  #define TCPC_RX_DATA			0x34 /* through 0x4f */
>  
> diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
> index 430fa3ec69bb..41d1ac9c8bbf 100644
> --- a/include/linux/usb/tcpm.h
> +++ b/include/linux/usb/tcpm.h
> @@ -170,7 +170,8 @@ void tcpm_cc_change(struct tcpm_port *port);
>  void tcpm_sink_frs(struct tcpm_port *port);
>  void tcpm_sourcing_vbus(struct tcpm_port *port);
>  void tcpm_pd_receive(struct tcpm_port *port,
> -		     const struct pd_message *msg);
> +		     const struct pd_message *msg,
> +		     enum tcpm_transmit_type rx_sop_type);
>  void tcpm_pd_transmit_complete(struct tcpm_port *port,
>  			       enum tcpm_transmit_status status);
>  void tcpm_pd_hard_reset(struct tcpm_port *port);
> -- 
> 2.43.0.472.g3155946c3a-goog
diff mbox series

Patch

diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index bc21006e979c..ef18a448b740 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -1467,7 +1467,7 @@  static int fusb302_pd_read_message(struct fusb302_chip *chip,
 	if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC))
 		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS);
 	else
-		tcpm_pd_receive(chip->tcpm_port, msg);
+		tcpm_pd_receive(chip->tcpm_port, msg, TCPC_TX_SOP);
 
 	return ret;
 }
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
index 52c81378e36e..a3154085ae32 100644
--- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
@@ -299,7 +299,7 @@  static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec
 
 	if (!ret) {
 		dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
-		tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg);
+		tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg, TCPC_TX_SOP);
 	}
 }
 
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 1ededbcecc09..8ea4ed159a13 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -445,8 +445,11 @@  static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable)
 	unsigned int reg = 0;
 	int ret;
 
-	if (enable)
+	if (enable) {
 		reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
+		if (tcpci->data->cable_comm_capable)
+			reg |= TCPC_RX_DETECT_SOP1;
+	}
 	ret = regmap_write(tcpci->regmap, TCPC_RX_DETECT, reg);
 	if (ret < 0)
 		return ret;
@@ -719,7 +722,7 @@  irqreturn_t tcpci_irq(struct tcpci *tcpci)
 		/* Read complete, clear RX status alert bit */
 		tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
 
-		tcpm_pd_receive(tcpci->port, &msg);
+		tcpm_pd_receive(tcpci->port, &msg, TCPC_TX_SOP);
 	}
 
 	if (tcpci->data->vbus_vsafe0v && (status & TCPC_ALERT_EXTENDED_STATUS)) {
diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
index 7b2d4e6e52a2..f9f838df43f7 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
@@ -128,6 +128,7 @@  static void process_rx(struct max_tcpci_chip *chip, u16 status)
 	u8 count, frame_type, rx_buf[TCPC_RECEIVE_BUFFER_LEN];
 	int ret, payload_index;
 	u8 *rx_buf_ptr;
+	enum tcpm_transmit_type rx_type;
 
 	/*
 	 * READABLE_BYTE_COUNT: Indicates the number of bytes in the RX_BUF_BYTE_x registers
@@ -143,10 +144,23 @@  static void process_rx(struct max_tcpci_chip *chip, u16 status)
 	count = rx_buf[TCPC_RECEIVE_BUFFER_COUNT_OFFSET];
 	frame_type = rx_buf[TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET];
 
-	if (count == 0 || frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP) {
+	switch (frame_type) {
+	case TCPC_RX_BUF_FRAME_TYPE_SOP1:
+		rx_type = TCPC_TX_SOP_PRIME;
+		break;
+	case TCPC_RX_BUF_FRAME_TYPE_SOP:
+		rx_type = TCPC_TX_SOP;
+		break;
+	default:
+		rx_type = TCPC_TX_SOP;
+		break;
+	}
+
+	if (count == 0 || (frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP &&
+	    frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP1)) {
 		max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
 		dev_err(chip->dev, "%s\n", count ==  0 ? "error: count is 0" :
-			"error frame_type is not SOP");
+			"error frame_type is not SOP/SOP'");
 		return;
 	}
 
@@ -183,7 +197,7 @@  static void process_rx(struct max_tcpci_chip *chip, u16 status)
 	if (ret < 0)
 		return;
 
-	tcpm_pd_receive(chip->port, &msg);
+	tcpm_pd_receive(chip->port, &msg, rx_type);
 }
 
 static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index ff67553b6932..b05325dcd7ac 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -506,6 +506,7 @@  struct pd_rx_event {
 	struct kthread_work work;
 	struct tcpm_port *port;
 	struct pd_message msg;
+	enum tcpm_transmit_type rx_sop_type;
 };
 
 static const char * const pd_rev[] = {
@@ -2969,12 +2970,17 @@  static void tcpm_pd_rx_handler(struct kthread_work *work)
 	const struct pd_message *msg = &event->msg;
 	unsigned int cnt = pd_header_cnt_le(msg->header);
 	struct tcpm_port *port = event->port;
+	enum tcpm_transmit_type rx_sop_type = event->rx_sop_type;
 
 	mutex_lock(&port->lock);
 
 	tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header),
 		 port->attached);
 
+	/* Ignore SOP' for now */
+	if (rx_sop_type == TCPC_TX_SOP_PRIME)
+		goto done;
+
 	if (port->attached) {
 		enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
 		unsigned int msgid = pd_header_msgid_le(msg->header);
@@ -3016,7 +3022,8 @@  static void tcpm_pd_rx_handler(struct kthread_work *work)
 	kfree(event);
 }
 
-void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
+void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg,
+		     enum tcpm_transmit_type rx_sop_type)
 {
 	struct pd_rx_event *event;
 
@@ -3026,6 +3033,7 @@  void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
 
 	kthread_init_work(&event->work, tcpm_pd_rx_handler);
 	event->port = port;
+	event->rx_sop_type = rx_sop_type;
 	memcpy(&event->msg, msg, sizeof(*msg));
 	kthread_queue_work(port->wq, &event->work);
 }
diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
index 87d4abde0ea2..cf719307b3f6 100644
--- a/drivers/usb/typec/tcpm/wcove.c
+++ b/drivers/usb/typec/tcpm/wcove.c
@@ -535,7 +535,7 @@  static irqreturn_t wcove_typec_irq(int irq, void *data)
 				goto err;
 			}
 
-			tcpm_pd_receive(wcove->tcpm, &msg);
+			tcpm_pd_receive(wcove->tcpm, &msg, TCPC_TX_SOP);
 
 			ret = regmap_read(wcove->regmap, USBC_RXSTATUS,
 					  &status);
diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h
index 1d0b849defd0..9ed6d62c9c5f 100644
--- a/include/linux/usb/tcpci.h
+++ b/include/linux/usb/tcpci.h
@@ -145,6 +145,7 @@ 
 #define TCPC_RX_BYTE_CNT		0x30
 #define TCPC_RX_BUF_FRAME_TYPE		0x31
 #define TCPC_RX_BUF_FRAME_TYPE_SOP	0
+#define TCPC_RX_BUF_FRAME_TYPE_SOP1	1
 #define TCPC_RX_HDR			0x32
 #define TCPC_RX_DATA			0x34 /* through 0x4f */
 
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 430fa3ec69bb..41d1ac9c8bbf 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -170,7 +170,8 @@  void tcpm_cc_change(struct tcpm_port *port);
 void tcpm_sink_frs(struct tcpm_port *port);
 void tcpm_sourcing_vbus(struct tcpm_port *port);
 void tcpm_pd_receive(struct tcpm_port *port,
-		     const struct pd_message *msg);
+		     const struct pd_message *msg,
+		     enum tcpm_transmit_type rx_sop_type);
 void tcpm_pd_transmit_complete(struct tcpm_port *port,
 			       enum tcpm_transmit_status status);
 void tcpm_pd_hard_reset(struct tcpm_port *port);