All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] common SVDM version and VDO from dt
@ 2021-01-26  8:45 Kyle Tso
  2021-01-26  8:45 ` [PATCH 1/3] usb: typec: Determine common SVDM Versions Kyle Tso
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Kyle Tso @ 2021-01-26  8:45 UTC (permalink / raw)
  To: linux, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree, Kyle Tso

The correct SVDM version we should use is the lowest common version             
between the port partners (plug) as stated in the PD3 Spec 6.4.4.2.3.           
It is determined in the Discovery Identity command so cache it and set          
the value to the version field of the VDM header in every later SVDM.           
                                                                                
Like the previous patch "usb: typec: tcpm: Create legacy PDOs for PD2           
connection"                                                                     
(https://lore.kernel.org/linux-usb/20210115163311.391332-1-kyletso@google.com/) 
The field is changed before sending it out of the port. I know this is          
not a good idea but at least it works.                                          
                                                                                
The other two patches are about to get the VDO from fwnode so as to give         
more flexibility.

Kyle Tso (3):
  usb: typec: Determine common SVDM Versions
  dt-bindings: connector: Add SVDM VDO properties
  usb: typec: tcpm: Get Sink VDO from fwnode

 drivers/usb/typec/altmodes/displayport.c |  6 ++-
 drivers/usb/typec/class.c                |  8 ++--
 drivers/usb/typec/tcpm/tcpm.c            | 56 ++++++++++++++++++++----
 drivers/usb/typec/ucsi/displayport.c     | 12 +++--
 include/dt-bindings/usb/pd.h             | 53 +++++++++++++++++++++-
 include/linux/usb/pd_vdo.h               | 40 ++++++++++++-----
 6 files changed, 147 insertions(+), 28 deletions(-)

-- 
2.30.0.280.ga3ce27912f-goog


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] usb: typec: Determine common SVDM Versions
  2021-01-26  8:45 [PATCH 0/3] common SVDM version and VDO from dt Kyle Tso
@ 2021-01-26  8:45 ` Kyle Tso
  2021-01-26 15:07   ` Guenter Roeck
  2021-01-26  8:45 ` [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties Kyle Tso
  2021-01-26  8:45 ` [PATCH 3/3] usb: typec: tcpm: Get Sink VDO from fwnode Kyle Tso
  2 siblings, 1 reply; 6+ messages in thread
From: Kyle Tso @ 2021-01-26  8:45 UTC (permalink / raw)
  To: linux, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree, Kyle Tso

PD Spec Revision 3.0 Version 2.0 + ECNs 2020-12-10
  6.4.4.2.3 Structured VDM Version
  "The Structured VDM Version field of the Discover Identity Command
  sent and received during VDM discovery Shall be used to determine the
  lowest common Structured VDM Version supported by the Port Partners or
  Cable Plug and Shall continue to operate using this Specification
  Revision until they are Detached."

Also clear the fields newly defined in SVDM version 2.0 for
compatibilities. And fix some ID Header fields changed in the Spec.

Signed-off-by: Kyle Tso <kyletso@google.com>
---
 drivers/usb/typec/altmodes/displayport.c |  6 +++-
 drivers/usb/typec/class.c                |  8 ++---
 drivers/usb/typec/tcpm/tcpm.c            | 44 +++++++++++++++++++-----
 drivers/usb/typec/ucsi/displayport.c     | 12 +++++--
 include/linux/usb/pd_vdo.h               | 40 +++++++++++++++------
 5 files changed, 83 insertions(+), 27 deletions(-)

diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index e62e5e3da01e..baf289acf707 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -15,7 +15,7 @@
 #include <linux/usb/typec_dp.h>
 #include "displayport.h"
 
-#define DP_HEADER(_dp, cmd)		(VDO((_dp)->alt->svid, 1, cmd) | \
+#define DP_HEADER(_dp, cmd)		(VDO((_dp)->alt->svid, 1, (_dp)->svdm_ver, cmd) | \
 					 VDO_OPOS(USB_TYPEC_DP_MODE))
 
 enum {
@@ -57,6 +57,7 @@ struct dp_altmode {
 	struct typec_displayport_data data;
 
 	enum dp_state state;
+	u32 svdm_ver;
 
 	struct mutex lock; /* device lock */
 	struct work_struct work;
@@ -266,6 +267,8 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
 	case CMDT_RSP_ACK:
 		switch (cmd) {
 		case CMD_ENTER_MODE:
+			if (PD_VDO_SVDM_VER(hdr) < SVDM_MAX_VER)
+				dp->svdm_ver = PD_VDO_SVDM_VER(hdr);
 			dp->state = DP_STATE_UPDATE;
 			break;
 		case CMD_EXIT_MODE:
@@ -536,6 +539,7 @@ int dp_altmode_probe(struct typec_altmode *alt)
 	mutex_init(&dp->lock);
 	dp->port = port;
 	dp->alt = alt;
+	dp->svdm_ver = SVDM_MAX_VER;
 
 	alt->desc = "DisplayPort";
 	alt->ops = &dp_altmode_ops;
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 8f77669f9cf4..862afb377752 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -86,7 +86,7 @@ static const char * const typec_accessory_modes[] = {
 
 /* Product types defined in USB PD Specification R3.0 V2.0 */
 static const char * const product_type_ufp[8] = {
-	[IDH_PTYPE_UNDEF]		= "undefined",
+	[IDH_PTYPE_NOT_UFP]		= "not_ufp",
 	[IDH_PTYPE_HUB]			= "hub",
 	[IDH_PTYPE_PERIPH]		= "peripheral",
 	[IDH_PTYPE_PSD]			= "psd",
@@ -94,17 +94,17 @@ static const char * const product_type_ufp[8] = {
 };
 
 static const char * const product_type_dfp[8] = {
-	[IDH_PTYPE_DFP_UNDEF]		= "undefined",
+	[IDH_PTYPE_NOT_DFP]		= "not_dfp",
 	[IDH_PTYPE_DFP_HUB]		= "hub",
 	[IDH_PTYPE_DFP_HOST]		= "host",
 	[IDH_PTYPE_DFP_PB]		= "power_brick",
-	[IDH_PTYPE_DFP_AMC]		= "amc",
 };
 
 static const char * const product_type_cable[8] = {
-	[IDH_PTYPE_UNDEF]		= "undefined",
+	[IDH_PTYPE_NOT_CABLE]		= "not_cable",
 	[IDH_PTYPE_PCABLE]		= "passive",
 	[IDH_PTYPE_ACABLE]		= "active",
+	[IDH_PTYPE_VPD]			= "vpd",
 };
 
 static struct usb_pd_identity *get_pd_identity(struct device *dev)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 0afd8ef692e8..c14cf7842520 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -408,6 +408,7 @@ struct tcpm_port {
 	u8 vdo_count;
 	/* VDO to retry if UFP responder replied busy */
 	u32 vdo_retry;
+	unsigned int svdm_version;
 
 	/* PPS */
 	struct pd_pps_data pps_data;
@@ -1500,10 +1501,21 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 			if (PD_VDO_VID(p[0]) != USB_SID_PD)
 				break;
 
+			if (PD_VDO_SVDM_VER(p[0]) <= SVDM_MAX_VER)
+				port->svdm_version = PD_VDO_SVDM_VER(p[0]);
 			/* 6.4.4.3.1: Only respond as UFP (device) */
 			if (port->data_role == TYPEC_DEVICE &&
 			    port->nr_snk_vdo) {
-				for (i = 0; i <  port->nr_snk_vdo; i++)
+				/*
+				 * Product Type DFP and Connector Type are not defined in SVDM
+				 * version 1.0 and shall be set to zero.
+				 */
+				if (port->svdm_version < SVDM_V20)
+					response[1] = port->snk_vdo[0] & ~IDH_DFP_MASK
+						      & ~IDH_CONN_MASK;
+				else
+					response[1] = port->snk_vdo[0];
+				for (i = 1; i <  port->nr_snk_vdo; i++)
 					response[i + 1] = port->snk_vdo[i];
 				rlen = port->nr_snk_vdo + 1;
 			}
@@ -1532,6 +1544,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 			response[0] = p[0] | VDO_CMDT(CMDT_RSP_BUSY);
 			rlen = 1;
 		}
+		response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
+			      (VDO_SVDM_VERS(port->svdm_version));
 		break;
 	case CMDT_RSP_ACK:
 		/* silently drop message if we are not connected */
@@ -1542,19 +1556,21 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 
 		switch (cmd) {
 		case CMD_DISCOVER_IDENT:
+			if (PD_VDO_SVDM_VER(p[0]) <= SVDM_MAX_VER)
+				port->svdm_version = PD_VDO_SVDM_VER(p[0]);
 			/* 6.4.4.3.1 */
 			svdm_consume_identity(port, p, cnt);
-			response[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
+			response[0] = VDO(USB_SID_PD, 1, port->svdm_version, CMD_DISCOVER_SVID);
 			rlen = 1;
 			break;
 		case CMD_DISCOVER_SVID:
 			/* 6.4.4.3.2 */
 			if (svdm_consume_svids(port, p, cnt)) {
-				response[0] = VDO(USB_SID_PD, 1,
+				response[0] = VDO(USB_SID_PD, 1, port->svdm_version,
 						  CMD_DISCOVER_SVID);
 				rlen = 1;
 			} else if (modep->nsvids && supports_modal(port)) {
-				response[0] = VDO(modep->svids[0], 1,
+				response[0] = VDO(modep->svids[0], 1, port->svdm_version,
 						  CMD_DISCOVER_MODES);
 				rlen = 1;
 			}
@@ -1565,7 +1581,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 			modep->svid_index++;
 			if (modep->svid_index < modep->nsvids) {
 				u16 svid = modep->svids[modep->svid_index];
-				response[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
+				response[0] = VDO(svid, 1, port->svdm_version,
+						  CMD_DISCOVER_MODES);
 				rlen = 1;
 			} else {
 				tcpm_register_partner_altmodes(port);
@@ -1592,6 +1609,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 			/* Unrecognized SVDM */
 			response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
 			rlen = 1;
+			response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
+				      (VDO_SVDM_VERS(port->svdm_version));
 			break;
 		}
 		break;
@@ -1611,6 +1630,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 			/* Unrecognized SVDM */
 			response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
 			rlen = 1;
+			response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
+				      (VDO_SVDM_VERS(port->svdm_version));
 			break;
 		}
 		port->vdm_sm_running = false;
@@ -1618,6 +1639,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
 	default:
 		response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
 		rlen = 1;
+		response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
+			      (VDO_SVDM_VERS(port->svdm_version));
 		port->vdm_sm_running = false;
 		break;
 	}
@@ -1695,7 +1718,7 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
 			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(adev->svid, 1, port->svdm_version, CMD_EXIT_MODE);
 				response[0] |= VDO_OPOS(adev->mode);
 				rlen = 1;
 			}
@@ -1729,7 +1752,8 @@ static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd,
 
 	/* set VDM header with VID & CMD */
 	header = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?
-			1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd);
+			1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION),
+			port->svdm_version, cmd);
 	tcpm_queue_vdm(port, header, data, count);
 }
 
@@ -2024,7 +2048,7 @@ static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo)
 	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);
 	u32 header;
 
-	header = VDO(altmode->svid, vdo ? 2 : 1, CMD_ENTER_MODE);
+	header = VDO(altmode->svid, vdo ? 2 : 1, port->svdm_version, CMD_ENTER_MODE);
 	header |= VDO_OPOS(altmode->mode);
 
 	tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0);
@@ -2036,7 +2060,7 @@ static int tcpm_altmode_exit(struct typec_altmode *altmode)
 	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);
 	u32 header;
 
-	header = VDO(altmode->svid, 1, CMD_EXIT_MODE);
+	header = VDO(altmode->svid, 1, port->svdm_version, CMD_EXIT_MODE);
 	header |= VDO_OPOS(altmode->mode);
 
 	tcpm_queue_vdm_unlocked(port, header, NULL, 0);
@@ -3716,6 +3740,7 @@ static void run_state_machine(struct tcpm_port *port)
 		port->pwr_opmode = TYPEC_PWR_MODE_USB;
 		port->caps_count = 0;
 		port->negotiated_rev = PD_MAX_REV;
+		port->svdm_version = SVDM_MAX_VER;
 		port->message_id = 0;
 		port->rx_msgid = -1;
 		port->explicit_contract = false;
@@ -3938,6 +3963,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->negotiated_rev = PD_MAX_REV;
+		port->svdm_version = SVDM_MAX_VER;
 		port->message_id = 0;
 		port->rx_msgid = -1;
 		port->explicit_contract = false;
diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
index 261131c9e37c..421ad3e0d976 100644
--- a/drivers/usb/typec/ucsi/displayport.c
+++ b/drivers/usb/typec/ucsi/displayport.c
@@ -28,6 +28,7 @@ struct ucsi_dp {
 	u32 header;
 	u32 *vdo_data;
 	u8 vdo_size;
+	u32 svdm_ver;
 };
 
 /*
@@ -83,7 +84,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
 	 * mode, and letting the alt mode driver continue.
 	 */
 
-	dp->header = VDO(USB_TYPEC_DP_SID, 1, CMD_ENTER_MODE);
+	dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, CMD_ENTER_MODE);
 	dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
 	dp->header |= VDO_CMDT(CMDT_RSP_ACK);
 
@@ -120,7 +121,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
 	if (ret < 0)
 		goto out_unlock;
 
-	dp->header = VDO(USB_TYPEC_DP_SID, 1, CMD_EXIT_MODE);
+	dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, CMD_EXIT_MODE);
 	dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
 	dp->header |= VDO_CMDT(CMDT_RSP_ACK);
 
@@ -200,7 +201,11 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
 
 	switch (cmd_type) {
 	case CMDT_INIT:
-		dp->header = VDO(USB_TYPEC_DP_SID, 1, cmd);
+		if (PD_VDO_SVDM_VER(header) != dp->svdm_ver &&
+		    PD_VDO_SVDM_VER(header) < SVDM_MAX_VER)
+			dp->svdm_ver = PD_VDO_SVDM_VER(header);
+
+		dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, cmd);
 		dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
 
 		switch (cmd) {
@@ -310,6 +315,7 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con,
 	dp->offset = offset;
 	dp->con = con;
 	dp->alt = alt;
+	dp->svdm_ver = SVDM_MAX_VER;
 
 	alt->ops = &ucsi_displayport_ops;
 	typec_altmode_set_drvdata(alt, dp);
diff --git a/include/linux/usb/pd_vdo.h b/include/linux/usb/pd_vdo.h
index 8c08eeb9a74b..5283a08527ce 100644
--- a/include/linux/usb/pd_vdo.h
+++ b/include/linux/usb/pd_vdo.h
@@ -16,27 +16,33 @@
 #define VDO_MAX_OBJECTS		6
 #define VDO_MAX_SIZE		(VDO_MAX_OBJECTS + 1)
 
+#define SVDM_V10		0
+#define SVDM_V20		1
+#define SVDM_MAX_VER		SVDM_V20
+
 /*
  * VDM header
  * ----------
  * <31:16>  :: SVID
  * <15>     :: VDM type ( 1b == structured, 0b == unstructured )
- * <14:13>  :: Structured VDM version (can only be 00 == 1.0 currently)
+ * <14:13>  :: Structured VDM version
  * <12:11>  :: reserved
  * <10:8>   :: object position (1-7 valid ... used for enter/exit mode only)
  * <7:6>    :: command type (SVDM only?)
  * <5>      :: reserved (SVDM), command type (UVDM)
  * <4:0>    :: command
  */
-#define VDO(vid, type, custom)				\
+#define VDO(vid, type, ver, custom)				\
 	(((vid) << 16) |				\
 	 ((type) << 15) |				\
+	 ((ver) << 13) |				\
 	 ((custom) & 0x7FFF))
 
 #define VDO_SVDM_TYPE		(1 << 15)
 #define VDO_SVDM_VERS(x)	((x) << 13)
 #define VDO_OPOS(x)		((x) << 8)
 #define VDO_CMDT(x)		((x) << 6)
+#define VDO_SVDM_VERS_MASK	VDO_SVDM_VERS(0x3)
 #define VDO_OPOS_MASK		VDO_OPOS(0x7)
 #define VDO_CMDT_MASK		VDO_CMDT(0x3)
 
@@ -74,6 +80,7 @@
 
 #define PD_VDO_VID(vdo)		((vdo) >> 16)
 #define PD_VDO_SVDM(vdo)	(((vdo) >> 15) & 1)
+#define PD_VDO_SVDM_VER(vdo)	(((vdo) >> 13) & 0x3)
 #define PD_VDO_OPOS(vdo)	(((vdo) >> 8) & 0x7)
 #define PD_VDO_CMD(vdo)		((vdo) & 0x1f)
 #define PD_VDO_CMDT(vdo)	(((vdo) >> 6) & 0x3)
@@ -103,34 +110,46 @@
  * --------------------
  * <31>     :: data capable as a USB host
  * <30>     :: data capable as a USB device
- * <29:27>  :: product type (UFP / Cable)
+ * <29:27>  :: product type (UFP / Cable / VPD)
  * <26>     :: modal operation supported (1b == yes)
- * <25:16>  :: product type (DFP)
+ * <25:23>  :: product type (DFP) (SVDM version 2.0+ only; set to zero in version 1.0)
+ * <22:21>  :: connector type (SVDM version 2.0+ only; set to zero in version 1.0)
+ * <20:16>  :: Reserved, Shall be set to zero
  * <15:0>   :: USB-IF assigned VID for this cable vendor
  */
-#define IDH_PTYPE_UNDEF		0
+/* SOP Product Type (UFP) */
+#define IDH_PTYPE_NOT_UFP	0
 #define IDH_PTYPE_HUB		1
 #define IDH_PTYPE_PERIPH	2
 #define IDH_PTYPE_PSD		3
 #define IDH_PTYPE_AMA		5
 
+/* SOP' Product Type (Cable Plug / VPD) */
+#define IDH_PTYPE_NOT_CABLE	0
 #define IDH_PTYPE_PCABLE	3
 #define IDH_PTYPE_ACABLE	4
+#define IDH_PTYPE_VPD		6
 
-#define IDH_PTYPE_DFP_UNDEF	0
+/* SOP Product Type (DFP) */
+#define IDH_PTYPE_NOT_DFP	0
 #define IDH_PTYPE_DFP_HUB	1
 #define IDH_PTYPE_DFP_HOST	2
 #define IDH_PTYPE_DFP_PB	3
-#define IDH_PTYPE_DFP_AMC	4
 
-#define VDO_IDH(usbh, usbd, ptype, is_modal, vid)		\
-	((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27	\
-	 | (is_modal) << 26 | ((vid) & 0xffff))
+/* ID Header Mask */
+#define IDH_DFP_MASK		GENMASK(25, 23)
+#define IDH_CONN_MASK		GENMASK(22, 21)
+
+#define VDO_IDH(usbh, usbd, ufp_cable, is_modal, dfp, conn, vid)		\
+	((usbh) << 31 | (usbd) << 30 | ((ufp_cable) & 0x7) << 27		\
+	 | (is_modal) << 26 | ((dfp) & 0x7) << 23 | ((conn) & 0x3) << 21	\
+	 | ((vid) & 0xffff))
 
 #define PD_IDH_PTYPE(vdo)	(((vdo) >> 27) & 0x7)
 #define PD_IDH_VID(vdo)		((vdo) & 0xffff)
 #define PD_IDH_MODAL_SUPP(vdo)	((vdo) & (1 << 26))
 #define PD_IDH_DFP_PTYPE(vdo)	(((vdo) >> 23) & 0x7)
+#define PD_IDH_CONN_TYPE(vdo)	(((vdo) >> 21) & 0x3)
 
 /*
  * Cert Stat VDO
@@ -138,6 +157,7 @@
  * <31:0>  : USB-IF assigned XID for this cable
  */
 #define PD_CSTAT_XID(vdo)	(vdo)
+#define VDO_CERT(xid)		((xid) & 0xffffffff)
 
 /*
  * Product VDO
-- 
2.30.0.280.ga3ce27912f-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties
  2021-01-26  8:45 [PATCH 0/3] common SVDM version and VDO from dt Kyle Tso
  2021-01-26  8:45 ` [PATCH 1/3] usb: typec: Determine common SVDM Versions Kyle Tso
@ 2021-01-26  8:45 ` Kyle Tso
  2021-01-26 15:15   ` Guenter Roeck
  2021-01-26  8:45 ` [PATCH 3/3] usb: typec: tcpm: Get Sink VDO from fwnode Kyle Tso
  2 siblings, 1 reply; 6+ messages in thread
From: Kyle Tso @ 2021-01-26  8:45 UTC (permalink / raw)
  To: linux, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree, Kyle Tso

Add bindings of VDO properties of USB PD SVDM so that they can be
defined in device tree.

Signed-off-by: Kyle Tso <kyletso@google.com>
---
 include/dt-bindings/usb/pd.h | 53 +++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/include/dt-bindings/usb/pd.h b/include/dt-bindings/usb/pd.h
index 0352893697f0..b99cb4a0cd12 100644
--- a/include/dt-bindings/usb/pd.h
+++ b/include/dt-bindings/usb/pd.h
@@ -93,4 +93,55 @@
 #define FRS_DEFAULT_POWER      1
 #define FRS_5V_1P5A            2
 #define FRS_5V_3A              3
- #endif /* __DT_POWER_DELIVERY_H */
+
+/*
+ * SVDM Identity Header
+ * --------------------
+ * <31>     :: data capable as a USB host
+ * <30>     :: data capable as a USB device
+ * <29:27>  :: product type (UFP / Cable / VPD)
+ * <26>     :: modal operation supported (1b == yes)
+ * <25:23>  :: product type (DFP) (SVDM version 2.0+ only; set to zero in version 1.0)
+ * <22:21>  :: connector type (SVDM version 2.0+ only; set to zero in version 1.0)
+ * <20:16>  :: Reserved, Shall be set to zero
+ * <15:0>   :: USB-IF assigned VID for this cable vendor
+ */
+/* SOP Product Type (UFP) */
+#define IDH_PTYPE_NOT_UFP       0
+#define IDH_PTYPE_HUB           1
+#define IDH_PTYPE_PERIPH        2
+#define IDH_PTYPE_PSD           3
+#define IDH_PTYPE_AMA           5
+
+/* SOP' Product Type (Cable Plug / VPD) */
+#define IDH_PTYPE_NOT_CABLE     0
+#define IDH_PTYPE_PCABLE        3
+#define IDH_PTYPE_ACABLE        4
+#define IDH_PTYPE_VPD           6
+
+/* SOP Product Type (DFP) */
+#define IDH_PTYPE_NOT_DFP       0
+#define IDH_PTYPE_DFP_HUB       1
+#define IDH_PTYPE_DFP_HOST      2
+#define IDH_PTYPE_DFP_PB        3
+
+#define VDO_IDH(usbh, usbd, ufp_cable, is_modal, dfp, conn, vid)                \
+	((usbh) << 31 | (usbd) << 30 | ((ufp_cable) & 0x7) << 27                \
+	 | (is_modal) << 26 | ((dfp) & 0x7) << 23 | ((conn) & 0x3) << 21        \
+	 | ((vid) & 0xffff))
+
+/*
+ * Cert Stat VDO
+ * -------------
+ * <31:0>  : USB-IF assigned XID for this cable
+ */
+#define VDO_CERT(xid)		((xid) & 0xffffffff)
+
+/*
+ * Product VDO
+ * -----------
+ * <31:16> : USB Product ID
+ * <15:0>  : USB bcdDevice
+ */
+#define VDO_PRODUCT(pid, bcd)   (((pid) & 0xffff) << 16 | ((bcd) & 0xffff))
+#endif /* __DT_POWER_DELIVERY_H */
-- 
2.30.0.280.ga3ce27912f-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] usb: typec: tcpm: Get Sink VDO from fwnode
  2021-01-26  8:45 [PATCH 0/3] common SVDM version and VDO from dt Kyle Tso
  2021-01-26  8:45 ` [PATCH 1/3] usb: typec: Determine common SVDM Versions Kyle Tso
  2021-01-26  8:45 ` [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties Kyle Tso
@ 2021-01-26  8:45 ` Kyle Tso
  2 siblings, 0 replies; 6+ messages in thread
From: Kyle Tso @ 2021-01-26  8:45 UTC (permalink / raw)
  To: linux, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree, Kyle Tso

Current design only allows TCPM to get the Sink VDO from TCPC configs.
Add an additional way from fwnode.

Signed-off-by: Kyle Tso <kyletso@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index c14cf7842520..7b797d14d9db 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -5673,6 +5673,18 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
 			port->new_source_frs_current = frs_current;
 	}
 
+	ret = fwnode_property_read_u32_array(fwnode, "sink-vdos", NULL, 0);
+	if (ret <= 0 && ret != -EINVAL) {
+		return -EINVAL;
+	} else if (ret > 0) {
+		port->nr_snk_vdo = min(ret, VDO_MAX_OBJECTS);
+		ret = fwnode_property_read_u32_array(fwnode, "sink-vdos",
+						     port->snk_vdo,
+						     port->nr_snk_vdo);
+		if (ret < 0)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
2.30.0.280.ga3ce27912f-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] usb: typec: Determine common SVDM Versions
  2021-01-26  8:45 ` [PATCH 1/3] usb: typec: Determine common SVDM Versions Kyle Tso
@ 2021-01-26 15:07   ` Guenter Roeck
  0 siblings, 0 replies; 6+ messages in thread
From: Guenter Roeck @ 2021-01-26 15:07 UTC (permalink / raw)
  To: Kyle Tso, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree

On 1/26/21 12:45 AM, Kyle Tso wrote:
> PD Spec Revision 3.0 Version 2.0 + ECNs 2020-12-10
>   6.4.4.2.3 Structured VDM Version
>   "The Structured VDM Version field of the Discover Identity Command
>   sent and received during VDM discovery Shall be used to determine the
>   lowest common Structured VDM Version supported by the Port Partners or
>   Cable Plug and Shall continue to operate using this Specification
>   Revision until they are Detached."
> 
> Also clear the fields newly defined in SVDM version 2.0 for
> compatibilities. And fix some ID Header fields changed in the Spec.
> 

Couple of concerns:
- svdm_ver is kept in three different data structures. I'd like to understand
  why there isn't a single version associated with the port.
- Version comparisons are against SVDM_MAX_VER, not against svdm_ver.
  That makes me slightly uncomfortable. Is there a reason for doing that
  (other than "it should not matter") ?

Thanks,
Guenter

> Signed-off-by: Kyle Tso <kyletso@google.com>
> ---
>  drivers/usb/typec/altmodes/displayport.c |  6 +++-
>  drivers/usb/typec/class.c                |  8 ++---
>  drivers/usb/typec/tcpm/tcpm.c            | 44 +++++++++++++++++++-----
>  drivers/usb/typec/ucsi/displayport.c     | 12 +++++--
>  include/linux/usb/pd_vdo.h               | 40 +++++++++++++++------
>  5 files changed, 83 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> index e62e5e3da01e..baf289acf707 100644
> --- a/drivers/usb/typec/altmodes/displayport.c
> +++ b/drivers/usb/typec/altmodes/displayport.c
> @@ -15,7 +15,7 @@
>  #include <linux/usb/typec_dp.h>
>  #include "displayport.h"
>  
> -#define DP_HEADER(_dp, cmd)		(VDO((_dp)->alt->svid, 1, cmd) | \
> +#define DP_HEADER(_dp, cmd)		(VDO((_dp)->alt->svid, 1, (_dp)->svdm_ver, cmd) | \
>  					 VDO_OPOS(USB_TYPEC_DP_MODE))
>  
>  enum {
> @@ -57,6 +57,7 @@ struct dp_altmode {
>  	struct typec_displayport_data data;
>  
>  	enum dp_state state;
> +	u32 svdm_ver;
>  
>  	struct mutex lock; /* device lock */
>  	struct work_struct work;
> @@ -266,6 +267,8 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
>  	case CMDT_RSP_ACK:
>  		switch (cmd) {
>  		case CMD_ENTER_MODE:
> +			if (PD_VDO_SVDM_VER(hdr) < SVDM_MAX_VER)
> +				dp->svdm_ver = PD_VDO_SVDM_VER(hdr);
>  			dp->state = DP_STATE_UPDATE;
>  			break;
>  		case CMD_EXIT_MODE:
> @@ -536,6 +539,7 @@ int dp_altmode_probe(struct typec_altmode *alt)
>  	mutex_init(&dp->lock);
>  	dp->port = port;
>  	dp->alt = alt;
> +	dp->svdm_ver = SVDM_MAX_VER;
>  
>  	alt->desc = "DisplayPort";
>  	alt->ops = &dp_altmode_ops;
> diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> index 8f77669f9cf4..862afb377752 100644
> --- a/drivers/usb/typec/class.c
> +++ b/drivers/usb/typec/class.c
> @@ -86,7 +86,7 @@ static const char * const typec_accessory_modes[] = {
>  
>  /* Product types defined in USB PD Specification R3.0 V2.0 */
>  static const char * const product_type_ufp[8] = {
> -	[IDH_PTYPE_UNDEF]		= "undefined",
> +	[IDH_PTYPE_NOT_UFP]		= "not_ufp",
>  	[IDH_PTYPE_HUB]			= "hub",
>  	[IDH_PTYPE_PERIPH]		= "peripheral",
>  	[IDH_PTYPE_PSD]			= "psd",
> @@ -94,17 +94,17 @@ static const char * const product_type_ufp[8] = {
>  };
>  
>  static const char * const product_type_dfp[8] = {
> -	[IDH_PTYPE_DFP_UNDEF]		= "undefined",
> +	[IDH_PTYPE_NOT_DFP]		= "not_dfp",
>  	[IDH_PTYPE_DFP_HUB]		= "hub",
>  	[IDH_PTYPE_DFP_HOST]		= "host",
>  	[IDH_PTYPE_DFP_PB]		= "power_brick",
> -	[IDH_PTYPE_DFP_AMC]		= "amc",
>  };
>  
>  static const char * const product_type_cable[8] = {
> -	[IDH_PTYPE_UNDEF]		= "undefined",
> +	[IDH_PTYPE_NOT_CABLE]		= "not_cable",
>  	[IDH_PTYPE_PCABLE]		= "passive",
>  	[IDH_PTYPE_ACABLE]		= "active",
> +	[IDH_PTYPE_VPD]			= "vpd",
>  };
>  
>  static struct usb_pd_identity *get_pd_identity(struct device *dev)
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index 0afd8ef692e8..c14cf7842520 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -408,6 +408,7 @@ struct tcpm_port {
>  	u8 vdo_count;
>  	/* VDO to retry if UFP responder replied busy */
>  	u32 vdo_retry;
> +	unsigned int svdm_version;
>  
>  	/* PPS */
>  	struct pd_pps_data pps_data;
> @@ -1500,10 +1501,21 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  			if (PD_VDO_VID(p[0]) != USB_SID_PD)
>  				break;
>  
> +			if (PD_VDO_SVDM_VER(p[0]) <= SVDM_MAX_VER)
> +				port->svdm_version = PD_VDO_SVDM_VER(p[0]);
>  			/* 6.4.4.3.1: Only respond as UFP (device) */
>  			if (port->data_role == TYPEC_DEVICE &&
>  			    port->nr_snk_vdo) {
> -				for (i = 0; i <  port->nr_snk_vdo; i++)
> +				/*
> +				 * Product Type DFP and Connector Type are not defined in SVDM
> +				 * version 1.0 and shall be set to zero.
> +				 */
> +				if (port->svdm_version < SVDM_V20)
> +					response[1] = port->snk_vdo[0] & ~IDH_DFP_MASK
> +						      & ~IDH_CONN_MASK;
> +				else
> +					response[1] = port->snk_vdo[0];
> +				for (i = 1; i <  port->nr_snk_vdo; i++)
>  					response[i + 1] = port->snk_vdo[i];
>  				rlen = port->nr_snk_vdo + 1;
>  			}
> @@ -1532,6 +1544,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  			response[0] = p[0] | VDO_CMDT(CMDT_RSP_BUSY);
>  			rlen = 1;
>  		}
> +		response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
> +			      (VDO_SVDM_VERS(port->svdm_version));
>  		break;
>  	case CMDT_RSP_ACK:
>  		/* silently drop message if we are not connected */
> @@ -1542,19 +1556,21 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  
>  		switch (cmd) {
>  		case CMD_DISCOVER_IDENT:
> +			if (PD_VDO_SVDM_VER(p[0]) <= SVDM_MAX_VER)
> +				port->svdm_version = PD_VDO_SVDM_VER(p[0]);
>  			/* 6.4.4.3.1 */
>  			svdm_consume_identity(port, p, cnt);
> -			response[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
> +			response[0] = VDO(USB_SID_PD, 1, port->svdm_version, CMD_DISCOVER_SVID);
>  			rlen = 1;
>  			break;
>  		case CMD_DISCOVER_SVID:
>  			/* 6.4.4.3.2 */
>  			if (svdm_consume_svids(port, p, cnt)) {
> -				response[0] = VDO(USB_SID_PD, 1,
> +				response[0] = VDO(USB_SID_PD, 1, port->svdm_version,
>  						  CMD_DISCOVER_SVID);
>  				rlen = 1;
>  			} else if (modep->nsvids && supports_modal(port)) {
> -				response[0] = VDO(modep->svids[0], 1,
> +				response[0] = VDO(modep->svids[0], 1, port->svdm_version,
>  						  CMD_DISCOVER_MODES);
>  				rlen = 1;
>  			}
> @@ -1565,7 +1581,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  			modep->svid_index++;
>  			if (modep->svid_index < modep->nsvids) {
>  				u16 svid = modep->svids[modep->svid_index];
> -				response[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
> +				response[0] = VDO(svid, 1, port->svdm_version,
> +						  CMD_DISCOVER_MODES);
>  				rlen = 1;
>  			} else {
>  				tcpm_register_partner_altmodes(port);
> @@ -1592,6 +1609,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  			/* Unrecognized SVDM */
>  			response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
>  			rlen = 1;
> +			response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
> +				      (VDO_SVDM_VERS(port->svdm_version));
>  			break;
>  		}
>  		break;
> @@ -1611,6 +1630,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  			/* Unrecognized SVDM */
>  			response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
>  			rlen = 1;
> +			response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
> +				      (VDO_SVDM_VERS(port->svdm_version));
>  			break;
>  		}
>  		port->vdm_sm_running = false;
> @@ -1618,6 +1639,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
>  	default:
>  		response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
>  		rlen = 1;
> +		response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
> +			      (VDO_SVDM_VERS(port->svdm_version));
>  		port->vdm_sm_running = false;
>  		break;
>  	}
> @@ -1695,7 +1718,7 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
>  			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(adev->svid, 1, port->svdm_version, CMD_EXIT_MODE);
>  				response[0] |= VDO_OPOS(adev->mode);
>  				rlen = 1;
>  			}
> @@ -1729,7 +1752,8 @@ static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd,
>  
>  	/* set VDM header with VID & CMD */
>  	header = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?
> -			1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd);
> +			1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION),
> +			port->svdm_version, cmd);
>  	tcpm_queue_vdm(port, header, data, count);
>  }
>  
> @@ -2024,7 +2048,7 @@ static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo)
>  	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);
>  	u32 header;
>  
> -	header = VDO(altmode->svid, vdo ? 2 : 1, CMD_ENTER_MODE);
> +	header = VDO(altmode->svid, vdo ? 2 : 1, port->svdm_version, CMD_ENTER_MODE);
>  	header |= VDO_OPOS(altmode->mode);
>  
>  	tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0);
> @@ -2036,7 +2060,7 @@ static int tcpm_altmode_exit(struct typec_altmode *altmode)
>  	struct tcpm_port *port = typec_altmode_get_drvdata(altmode);
>  	u32 header;
>  
> -	header = VDO(altmode->svid, 1, CMD_EXIT_MODE);
> +	header = VDO(altmode->svid, 1, port->svdm_version, CMD_EXIT_MODE);
>  	header |= VDO_OPOS(altmode->mode);
>  
>  	tcpm_queue_vdm_unlocked(port, header, NULL, 0);
> @@ -3716,6 +3740,7 @@ static void run_state_machine(struct tcpm_port *port)
>  		port->pwr_opmode = TYPEC_PWR_MODE_USB;
>  		port->caps_count = 0;
>  		port->negotiated_rev = PD_MAX_REV;
> +		port->svdm_version = SVDM_MAX_VER;
>  		port->message_id = 0;
>  		port->rx_msgid = -1;
>  		port->explicit_contract = false;
> @@ -3938,6 +3963,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->negotiated_rev = PD_MAX_REV;
> +		port->svdm_version = SVDM_MAX_VER;
>  		port->message_id = 0;
>  		port->rx_msgid = -1;
>  		port->explicit_contract = false;
> diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
> index 261131c9e37c..421ad3e0d976 100644
> --- a/drivers/usb/typec/ucsi/displayport.c
> +++ b/drivers/usb/typec/ucsi/displayport.c
> @@ -28,6 +28,7 @@ struct ucsi_dp {
>  	u32 header;
>  	u32 *vdo_data;
>  	u8 vdo_size;
> +	u32 svdm_ver;
>  };
>  
>  /*
> @@ -83,7 +84,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
>  	 * mode, and letting the alt mode driver continue.
>  	 */
>  
> -	dp->header = VDO(USB_TYPEC_DP_SID, 1, CMD_ENTER_MODE);
> +	dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, CMD_ENTER_MODE);
>  	dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
>  	dp->header |= VDO_CMDT(CMDT_RSP_ACK);
>  
> @@ -120,7 +121,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
>  	if (ret < 0)
>  		goto out_unlock;
>  
> -	dp->header = VDO(USB_TYPEC_DP_SID, 1, CMD_EXIT_MODE);
> +	dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, CMD_EXIT_MODE);
>  	dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
>  	dp->header |= VDO_CMDT(CMDT_RSP_ACK);
>  
> @@ -200,7 +201,11 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
>  
>  	switch (cmd_type) {
>  	case CMDT_INIT:
> -		dp->header = VDO(USB_TYPEC_DP_SID, 1, cmd);
> +		if (PD_VDO_SVDM_VER(header) != dp->svdm_ver &&
> +		    PD_VDO_SVDM_VER(header) < SVDM_MAX_VER)
> +			dp->svdm_ver = PD_VDO_SVDM_VER(header);
> +
> +		dp->header = VDO(USB_TYPEC_DP_SID, 1, dp->svdm_ver, cmd);
>  		dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
>  
>  		switch (cmd) {
> @@ -310,6 +315,7 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con,
>  	dp->offset = offset;
>  	dp->con = con;
>  	dp->alt = alt;
> +	dp->svdm_ver = SVDM_MAX_VER;
>  
>  	alt->ops = &ucsi_displayport_ops;
>  	typec_altmode_set_drvdata(alt, dp);
> diff --git a/include/linux/usb/pd_vdo.h b/include/linux/usb/pd_vdo.h
> index 8c08eeb9a74b..5283a08527ce 100644
> --- a/include/linux/usb/pd_vdo.h
> +++ b/include/linux/usb/pd_vdo.h
> @@ -16,27 +16,33 @@
>  #define VDO_MAX_OBJECTS		6
>  #define VDO_MAX_SIZE		(VDO_MAX_OBJECTS + 1)
>  
> +#define SVDM_V10		0
> +#define SVDM_V20		1
> +#define SVDM_MAX_VER		SVDM_V20
> +
>  /*
>   * VDM header
>   * ----------
>   * <31:16>  :: SVID
>   * <15>     :: VDM type ( 1b == structured, 0b == unstructured )
> - * <14:13>  :: Structured VDM version (can only be 00 == 1.0 currently)
> + * <14:13>  :: Structured VDM version
>   * <12:11>  :: reserved
>   * <10:8>   :: object position (1-7 valid ... used for enter/exit mode only)
>   * <7:6>    :: command type (SVDM only?)
>   * <5>      :: reserved (SVDM), command type (UVDM)
>   * <4:0>    :: command
>   */
> -#define VDO(vid, type, custom)				\
> +#define VDO(vid, type, ver, custom)				\
>  	(((vid) << 16) |				\
>  	 ((type) << 15) |				\
> +	 ((ver) << 13) |				\
>  	 ((custom) & 0x7FFF))
>  
>  #define VDO_SVDM_TYPE		(1 << 15)
>  #define VDO_SVDM_VERS(x)	((x) << 13)
>  #define VDO_OPOS(x)		((x) << 8)
>  #define VDO_CMDT(x)		((x) << 6)
> +#define VDO_SVDM_VERS_MASK	VDO_SVDM_VERS(0x3)
>  #define VDO_OPOS_MASK		VDO_OPOS(0x7)
>  #define VDO_CMDT_MASK		VDO_CMDT(0x3)
>  
> @@ -74,6 +80,7 @@
>  
>  #define PD_VDO_VID(vdo)		((vdo) >> 16)
>  #define PD_VDO_SVDM(vdo)	(((vdo) >> 15) & 1)
> +#define PD_VDO_SVDM_VER(vdo)	(((vdo) >> 13) & 0x3)
>  #define PD_VDO_OPOS(vdo)	(((vdo) >> 8) & 0x7)
>  #define PD_VDO_CMD(vdo)		((vdo) & 0x1f)
>  #define PD_VDO_CMDT(vdo)	(((vdo) >> 6) & 0x3)
> @@ -103,34 +110,46 @@
>   * --------------------
>   * <31>     :: data capable as a USB host
>   * <30>     :: data capable as a USB device
> - * <29:27>  :: product type (UFP / Cable)
> + * <29:27>  :: product type (UFP / Cable / VPD)
>   * <26>     :: modal operation supported (1b == yes)
> - * <25:16>  :: product type (DFP)
> + * <25:23>  :: product type (DFP) (SVDM version 2.0+ only; set to zero in version 1.0)
> + * <22:21>  :: connector type (SVDM version 2.0+ only; set to zero in version 1.0)
> + * <20:16>  :: Reserved, Shall be set to zero
>   * <15:0>   :: USB-IF assigned VID for this cable vendor
>   */
> -#define IDH_PTYPE_UNDEF		0
> +/* SOP Product Type (UFP) */
> +#define IDH_PTYPE_NOT_UFP	0
>  #define IDH_PTYPE_HUB		1
>  #define IDH_PTYPE_PERIPH	2
>  #define IDH_PTYPE_PSD		3
>  #define IDH_PTYPE_AMA		5
>  
> +/* SOP' Product Type (Cable Plug / VPD) */
> +#define IDH_PTYPE_NOT_CABLE	0
>  #define IDH_PTYPE_PCABLE	3
>  #define IDH_PTYPE_ACABLE	4
> +#define IDH_PTYPE_VPD		6
>  
> -#define IDH_PTYPE_DFP_UNDEF	0
> +/* SOP Product Type (DFP) */
> +#define IDH_PTYPE_NOT_DFP	0
>  #define IDH_PTYPE_DFP_HUB	1
>  #define IDH_PTYPE_DFP_HOST	2
>  #define IDH_PTYPE_DFP_PB	3
> -#define IDH_PTYPE_DFP_AMC	4
>  
> -#define VDO_IDH(usbh, usbd, ptype, is_modal, vid)		\
> -	((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27	\
> -	 | (is_modal) << 26 | ((vid) & 0xffff))
> +/* ID Header Mask */
> +#define IDH_DFP_MASK		GENMASK(25, 23)
> +#define IDH_CONN_MASK		GENMASK(22, 21)
> +
> +#define VDO_IDH(usbh, usbd, ufp_cable, is_modal, dfp, conn, vid)		\
> +	((usbh) << 31 | (usbd) << 30 | ((ufp_cable) & 0x7) << 27		\
> +	 | (is_modal) << 26 | ((dfp) & 0x7) << 23 | ((conn) & 0x3) << 21	\
> +	 | ((vid) & 0xffff))
>  
>  #define PD_IDH_PTYPE(vdo)	(((vdo) >> 27) & 0x7)
>  #define PD_IDH_VID(vdo)		((vdo) & 0xffff)
>  #define PD_IDH_MODAL_SUPP(vdo)	((vdo) & (1 << 26))
>  #define PD_IDH_DFP_PTYPE(vdo)	(((vdo) >> 23) & 0x7)
> +#define PD_IDH_CONN_TYPE(vdo)	(((vdo) >> 21) & 0x3)
>  
>  /*
>   * Cert Stat VDO
> @@ -138,6 +157,7 @@
>   * <31:0>  : USB-IF assigned XID for this cable
>   */
>  #define PD_CSTAT_XID(vdo)	(vdo)
> +#define VDO_CERT(xid)		((xid) & 0xffffffff)
>  
>  /*
>   * Product VDO
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties
  2021-01-26  8:45 ` [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties Kyle Tso
@ 2021-01-26 15:15   ` Guenter Roeck
  0 siblings, 0 replies; 6+ messages in thread
From: Guenter Roeck @ 2021-01-26 15:15 UTC (permalink / raw)
  To: Kyle Tso, heikki.krogerus, gregkh, robh+dt, hdegoede, badhri
  Cc: linux-usb, linux-kernel, devicetree

On 1/26/21 12:45 AM, Kyle Tso wrote:
> Add bindings of VDO properties of USB PD SVDM so that they can be
> defined in device tree.
> 
> Signed-off-by: Kyle Tso <kyletso@google.com>

Are you also going to update
Documentation/devicetree/bindings/connector/usb-connector.yaml ?

Thanks,
Guenter

> ---
>  include/dt-bindings/usb/pd.h | 53 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/include/dt-bindings/usb/pd.h b/include/dt-bindings/usb/pd.h
> index 0352893697f0..b99cb4a0cd12 100644
> --- a/include/dt-bindings/usb/pd.h
> +++ b/include/dt-bindings/usb/pd.h
> @@ -93,4 +93,55 @@
>  #define FRS_DEFAULT_POWER      1
>  #define FRS_5V_1P5A            2
>  #define FRS_5V_3A              3
> - #endif /* __DT_POWER_DELIVERY_H */
> +
> +/*
> + * SVDM Identity Header
> + * --------------------
> + * <31>     :: data capable as a USB host
> + * <30>     :: data capable as a USB device
> + * <29:27>  :: product type (UFP / Cable / VPD)
> + * <26>     :: modal operation supported (1b == yes)
> + * <25:23>  :: product type (DFP) (SVDM version 2.0+ only; set to zero in version 1.0)
> + * <22:21>  :: connector type (SVDM version 2.0+ only; set to zero in version 1.0)
> + * <20:16>  :: Reserved, Shall be set to zero
> + * <15:0>   :: USB-IF assigned VID for this cable vendor
> + */
> +/* SOP Product Type (UFP) */
> +#define IDH_PTYPE_NOT_UFP       0
> +#define IDH_PTYPE_HUB           1
> +#define IDH_PTYPE_PERIPH        2
> +#define IDH_PTYPE_PSD           3
> +#define IDH_PTYPE_AMA           5
> +
> +/* SOP' Product Type (Cable Plug / VPD) */
> +#define IDH_PTYPE_NOT_CABLE     0
> +#define IDH_PTYPE_PCABLE        3
> +#define IDH_PTYPE_ACABLE        4
> +#define IDH_PTYPE_VPD           6
> +
> +/* SOP Product Type (DFP) */
> +#define IDH_PTYPE_NOT_DFP       0
> +#define IDH_PTYPE_DFP_HUB       1
> +#define IDH_PTYPE_DFP_HOST      2
> +#define IDH_PTYPE_DFP_PB        3
> +
> +#define VDO_IDH(usbh, usbd, ufp_cable, is_modal, dfp, conn, vid)                \
> +	((usbh) << 31 | (usbd) << 30 | ((ufp_cable) & 0x7) << 27                \
> +	 | (is_modal) << 26 | ((dfp) & 0x7) << 23 | ((conn) & 0x3) << 21        \
> +	 | ((vid) & 0xffff))
> +
> +/*
> + * Cert Stat VDO
> + * -------------
> + * <31:0>  : USB-IF assigned XID for this cable
> + */
> +#define VDO_CERT(xid)		((xid) & 0xffffffff)
> +
> +/*
> + * Product VDO
> + * -----------
> + * <31:16> : USB Product ID
> + * <15:0>  : USB bcdDevice
> + */
> +#define VDO_PRODUCT(pid, bcd)   (((pid) & 0xffff) << 16 | ((bcd) & 0xffff))
> +#endif /* __DT_POWER_DELIVERY_H */
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-26 17:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-26  8:45 [PATCH 0/3] common SVDM version and VDO from dt Kyle Tso
2021-01-26  8:45 ` [PATCH 1/3] usb: typec: Determine common SVDM Versions Kyle Tso
2021-01-26 15:07   ` Guenter Roeck
2021-01-26  8:45 ` [PATCH 2/3] dt-bindings: connector: Add SVDM VDO properties Kyle Tso
2021-01-26 15:15   ` Guenter Roeck
2021-01-26  8:45 ` [PATCH 3/3] usb: typec: tcpm: Get Sink VDO from fwnode Kyle Tso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.