linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] platform/chrome: typec: Add mux support
@ 2020-05-28 11:36 Prashant Malani
  2020-05-28 11:36 ` [PATCH 1/4] platform/chrome: cros_ec: Update mux state bits Prashant Malani
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Prashant Malani @ 2020-05-28 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	Enric Balletbo i Serra, Fabien Lahoudere, Guenter Roeck,
	Gwendal Grignou, Lee Jones, Tzung-Bi Shih

This series adds mux control support for USB and DP alternate modes on
devices using the cros-ec-typec driver with Type C switch handles
provided by firmware bindings.

The first patch imports some recent updates to the
EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
code base[1], while the rest add the aforementioned functionality.

This series depends on the following patch :
https://lkml.org/lkml/2020/5/19/1219

[1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h

Prashant Malani (4):
  platform/chrome: cros_ec: Update mux state bits
  platform/chrome: typec: Register PD CTRL cmd v2
  platform/chrome: typec: Add USB mux control
  platform/chrome: typec: Support DP alt mode

 drivers/platform/chrome/cros_ec_typec.c       | 190 ++++++++++++++++--
 .../linux/platform_data/cros_ec_commands.h    |  14 +-
 2 files changed, 187 insertions(+), 17 deletions(-)

-- 
2.27.0.rc0.183.gde8f92d652-goog


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

* [PATCH 1/4] platform/chrome: cros_ec: Update mux state bits
  2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
@ 2020-05-28 11:36 ` Prashant Malani
  2020-05-28 11:36 ` [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2 Prashant Malani
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Prashant Malani @ 2020-05-28 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	Enric Balletbo i Serra, Fabien Lahoudere, Guenter Roeck,
	Gwendal Grignou, Lee Jones, Tzung-Bi Shih

Sync the EC_CMD_USB_PD_MUX_INFO mux state bit fields with the Chrome EC
code base. The newly added bit fields will be used for cros-ec-typec mux
control.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
---
 include/linux/platform_data/cros_ec_commands.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 69210881ebac..a7b0fc440c35 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -5207,11 +5207,15 @@ struct ec_params_usb_pd_mux_info {
 } __ec_align1;
 
 /* Flags representing mux state */
-#define USB_PD_MUX_USB_ENABLED       BIT(0) /* USB connected */
-#define USB_PD_MUX_DP_ENABLED        BIT(1) /* DP connected */
-#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */
-#define USB_PD_MUX_HPD_IRQ           BIT(3) /* HPD IRQ is asserted */
-#define USB_PD_MUX_HPD_LVL           BIT(4) /* HPD level is asserted */
+#define USB_PD_MUX_NONE               0      /* Open switch */
+#define USB_PD_MUX_USB_ENABLED        BIT(0) /* USB connected */
+#define USB_PD_MUX_DP_ENABLED         BIT(1) /* DP connected */
+#define USB_PD_MUX_POLARITY_INVERTED  BIT(2) /* CC line Polarity inverted */
+#define USB_PD_MUX_HPD_IRQ            BIT(3) /* HPD IRQ is asserted */
+#define USB_PD_MUX_HPD_LVL            BIT(4) /* HPD level is asserted */
+#define USB_PD_MUX_SAFE_MODE          BIT(5) /* DP is in safe mode */
+#define USB_PD_MUX_TBT_COMPAT_ENABLED BIT(6) /* TBT compat enabled */
+#define USB_PD_MUX_USB4_ENABLED       BIT(7) /* USB4 enabled */
 
 struct ec_response_usb_pd_mux_info {
 	uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */
-- 
2.27.0.rc0.183.gde8f92d652-goog


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

* [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2
  2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
  2020-05-28 11:36 ` [PATCH 1/4] platform/chrome: cros_ec: Update mux state bits Prashant Malani
@ 2020-05-28 11:36 ` Prashant Malani
  2020-06-16  7:27   ` Heikki Krogerus
  2020-05-28 11:36 ` [PATCH 3/4] platform/chrome: typec: Add USB mux control Prashant Malani
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Prashant Malani @ 2020-05-28 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	Enric Balletbo i Serra, Fabien Lahoudere, Guenter Roeck,
	Gwendal Grignou, Lee Jones, Tzung-Bi Shih

Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in
order to process Type C mux information (like DP alt mode pin
configuration), which is needed by the Type C Connector class API to
configure the Type C muxes correctly

While we are here, rename the struct member storing this version number
from cmd_ver to pd_ctrl_ver, which more accurately reflects what is
being stored.

Also, slightly change the logic for calling
cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0,
and v1 is called otherwise.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
---
 drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 6e79f917314b..d69a88464cef 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -37,7 +37,7 @@ struct cros_typec_data {
 	struct device *dev;
 	struct cros_ec_device *ec;
 	int num_ports;
-	unsigned int cmd_ver;
+	unsigned int pd_ctrl_ver;
 	/* Array of ports, indexed by port number. */
 	struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
 	struct notifier_block nb;
@@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 	req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
 	req.swap = USB_PD_CTRL_SWAP_NONE;
 
-	ret = cros_typec_ec_command(typec, typec->cmd_ver,
+	ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver,
 				    EC_CMD_USB_PD_CONTROL, &req, sizeof(req),
 				    &resp, sizeof(resp));
 	if (ret < 0)
@@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 	dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
 	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
 
-	if (typec->cmd_ver == 1)
+	if (typec->pd_ctrl_ver != 0)
 		cros_typec_set_port_params_v1(typec, port_num, &resp);
 	else
 		cros_typec_set_port_params_v0(typec, port_num,
@@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
 	if (ret < 0)
 		return ret;
 
-	if (resp.version_mask & EC_VER_MASK(1))
-		typec->cmd_ver = 1;
+	if (resp.version_mask & EC_VER_MASK(2))
+		typec->pd_ctrl_ver = 2;
+	else if (resp.version_mask & EC_VER_MASK(1))
+		typec->pd_ctrl_ver = 1;
 	else
-		typec->cmd_ver = 0;
+		typec->pd_ctrl_ver = 0;
 
 	dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n",
-		typec->cmd_ver);
+		typec->pd_ctrl_ver);
 
 	return 0;
 }
-- 
2.27.0.rc0.183.gde8f92d652-goog


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

* [PATCH 3/4] platform/chrome: typec: Add USB mux control
  2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
  2020-05-28 11:36 ` [PATCH 1/4] platform/chrome: cros_ec: Update mux state bits Prashant Malani
  2020-05-28 11:36 ` [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2 Prashant Malani
@ 2020-05-28 11:36 ` Prashant Malani
  2020-06-05  9:12   ` Prashant Malani
  2020-06-16  8:19   ` Heikki Krogerus
  2020-05-28 11:36 ` [PATCH 4/4] platform/chrome: typec: Support DP alt mode Prashant Malani
  2020-06-25 11:56 ` [PATCH 0/4] platform/chrome: typec: Add mux support Enric Balletbo i Serra
  4 siblings, 2 replies; 12+ messages in thread
From: Prashant Malani @ 2020-05-28 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	Enric Balletbo i Serra, Guenter Roeck

Add support to configure various Type C switches appropriately using the
Type C connector class API, when the Chrome OS EC informs the AP that
the USB operating mode has been entered.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
---
 drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index d69a88464cef..9ebf9abed16f 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -14,6 +14,7 @@
 #include <linux/platform_data/cros_usbpd_notify.h>
 #include <linux/platform_device.h>
 #include <linux/usb/typec.h>
+#include <linux/usb/typec_altmode.h>
 #include <linux/usb/typec_mux.h>
 #include <linux/usb/role.h>
 
@@ -30,6 +31,10 @@ struct cros_typec_port {
 	struct typec_switch *ori_sw;
 	struct typec_mux *mux;
 	struct usb_role_switch *role_sw;
+
+	/* Variables keeping track of switch state. */
+	struct typec_mux_state state;
+	uint8_t mux_flags;
 };
 
 /* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
 	return ret;
 }
 
+static void cros_typec_remove_partner(struct cros_typec_data *typec,
+				     int port_num)
+{
+	struct cros_typec_port *port = typec->ports[port_num];
+
+	port->state.alt = NULL;
+	port->state.mode = TYPEC_STATE_USB;
+	port->state.data = NULL;
+
+	usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
+	typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
+	typec_mux_set(port->mux, &port->state);
+
+	typec_unregister_partner(port->partner);
+	port->partner = NULL;
+}
+
 static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
 		int port_num, struct ec_response_usb_pd_control *resp)
 {
@@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
 	} else {
 		if (!typec->ports[port_num]->partner)
 			return;
+		cros_typec_remove_partner(typec, port_num);
+	}
+}
+
+static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
+				   struct ec_response_usb_pd_mux_info *resp)
+{
+	struct ec_params_usb_pd_mux_info req = {
+		.port = port_num,
+	};
+
+	return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
+				     sizeof(req), resp, sizeof(*resp));
+}
+
+static int cros_typec_usb_safe_state(struct cros_typec_port *port)
+{
+	port->state.mode = TYPEC_STATE_SAFE;
+
+	return typec_mux_set(port->mux, &port->state);
+}
 
-		typec_unregister_partner(typec->ports[port_num]->partner);
-		typec->ports[port_num]->partner = NULL;
+int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
+			     uint8_t mux_flags)
+{
+	struct cros_typec_port *port = typec->ports[port_num];
+	enum typec_orientation orientation;
+	int ret;
+
+	if (!port->partner)
+		return 0;
+
+	if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
+		orientation = TYPEC_ORIENTATION_REVERSE;
+	else
+		orientation = TYPEC_ORIENTATION_NORMAL;
+
+	ret = typec_switch_set(port->ori_sw, orientation);
+	if (ret)
+		return ret;
+
+	port->state.alt = NULL;
+	port->state.mode = TYPEC_STATE_USB;
+
+	if (mux_flags & USB_PD_MUX_SAFE_MODE)
+		ret = cros_typec_usb_safe_state(port);
+	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
+		ret = typec_mux_set(port->mux, &port->state);
+	else {
+		dev_info(typec->dev,
+			 "Unsupported mode requested, mux flags: %x\n",
+			 mux_flags);
+		ret = -ENOTSUPP;
 	}
+
+	return ret;
 }
 
 static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 {
 	struct ec_params_usb_pd_control req;
 	struct ec_response_usb_pd_control_v1 resp;
+	struct ec_response_usb_pd_mux_info mux_resp;
 	int ret;
 
 	if (port_num < 0 || port_num >= typec->num_ports) {
@@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 		cros_typec_set_port_params_v0(typec, port_num,
 			(struct ec_response_usb_pd_control *) &resp);
 
-	return 0;
+	/* Update the switches if they exist, according to requested state */
+	ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
+	if (ret < 0) {
+		dev_warn(typec->dev,
+			 "Failed to get mux info for port: %d, err = %d\n",
+			 port_num, ret);
+		return 0;
+	}
+
+	/* No change needs to be made, let's exit early. */
+	if (typec->ports[port_num]->mux_flags == mux_resp.flags)
+		return 0;
+
+	typec->ports[port_num]->mux_flags = mux_resp.flags;
+	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
+	if (ret)
+		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
+
+	return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
+					!!(resp.role & PD_CTRL_RESP_ROLE_DATA));
 }
 
 static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
-- 
2.27.0.rc0.183.gde8f92d652-goog


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

* [PATCH 4/4] platform/chrome: typec: Support DP alt mode
  2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
                   ` (2 preceding siblings ...)
  2020-05-28 11:36 ` [PATCH 3/4] platform/chrome: typec: Add USB mux control Prashant Malani
@ 2020-05-28 11:36 ` Prashant Malani
  2020-06-05  9:12   ` Prashant Malani
  2020-06-16 10:31   ` Heikki Krogerus
  2020-06-25 11:56 ` [PATCH 0/4] platform/chrome: typec: Add mux support Enric Balletbo i Serra
  4 siblings, 2 replies; 12+ messages in thread
From: Prashant Malani @ 2020-05-28 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	Enric Balletbo i Serra, Guenter Roeck

Handle Chrome EC mux events to configure on-board muxes correctly while
entering DP alternate mode. Since we don't surface SVID and VDO
information regarding the DP alternate mode, configure the Type C
muxes directly from the port driver. Later, when mode discovery
information is correctly surfaced to the driver, we can register the DP
alternate mode driver and let it handle the mux configuration.

Also, modify the struct_typec_state state management to account for the
addition of DP alternate mode.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
---
 drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
 1 file changed, 80 insertions(+), 10 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 9ebf9abed16f..509fc761906b 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -15,11 +15,18 @@
 #include <linux/platform_device.h>
 #include <linux/usb/typec.h>
 #include <linux/usb/typec_altmode.h>
+#include <linux/usb/typec_dp.h>
 #include <linux/usb/typec_mux.h>
 #include <linux/usb/role.h>
 
 #define DRV_NAME "cros-ec-typec"
 
+/* Supported alt modes. */
+enum {
+	CROS_EC_ALTMODE_DP = 0,
+	CROS_EC_ALTMODE_MAX,
+};
+
 /* Per port data. */
 struct cros_typec_port {
 	struct typec_port *port;
@@ -35,6 +42,9 @@ struct cros_typec_port {
 	/* Variables keeping track of switch state. */
 	struct typec_mux_state state;
 	uint8_t mux_flags;
+
+	/* Port alt modes. */
+	struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
 };
 
 /* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
 	}
 }
 
+/*
+ * Fake the alt mode structs until we actually start registering Type C port
+ * and partner alt modes.
+ */
+static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
+					      int port_num)
+{
+	struct cros_typec_port *port = typec->ports[port_num];
+
+	/* All PD capable CrOS devices are assumed to support DP altmode. */
+	port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
+	port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
+
+	port->state.alt = NULL;
+	port->state.mode = TYPEC_STATE_USB;
+	port->state.data = NULL;
+}
+
 static int cros_typec_init_ports(struct cros_typec_data *typec)
 {
 	struct device *dev = typec->dev;
@@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
 		if (ret)
 			dev_dbg(dev, "No switch control for port %d\n",
 				port_num);
+
+		cros_typec_register_port_altmodes(typec, port_num);
 	}
 
 	return 0;
@@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
 	return typec_mux_set(port->mux, &port->state);
 }
 
+/* Spoof the VDOs that were likely communicated by the partner. */
+static int cros_typec_enable_dp(struct cros_typec_data *typec,
+				int port_num,
+				struct ec_response_usb_pd_control_v2 *pd_ctrl)
+{
+	struct cros_typec_port *port = typec->ports[port_num];
+	struct typec_displayport_data dp_data;
+	int ret;
+
+	if (typec->pd_ctrl_ver < 2) {
+		dev_err(typec->dev,
+			"PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
+		return -ENOTSUPP;
+	}
+
+	/* Status VDO. */
+	dp_data.status = DP_STATUS_ENABLED;
+	if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
+		dp_data.status |= DP_STATUS_IRQ_HPD;
+	if (port->mux_flags & USB_PD_MUX_HPD_LVL)
+		dp_data.status |= DP_STATUS_HPD_STATE;
+
+	/* Configuration VDO. */
+	dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
+	if (!port->state.alt) {
+		port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
+		ret = cros_typec_usb_safe_state(port);
+		if (ret)
+			return ret;
+	}
+
+	port->state.data = &dp_data;
+	port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
+
+	return typec_mux_set(port->mux, &port->state);
+}
+
 int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
-			     uint8_t mux_flags)
+			     uint8_t mux_flags,
+			     struct ec_response_usb_pd_control_v2 *pd_ctrl)
 {
 	struct cros_typec_port *port = typec->ports[port_num];
 	enum typec_orientation orientation;
@@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 	if (ret)
 		return ret;
 
-	port->state.alt = NULL;
-	port->state.mode = TYPEC_STATE_USB;
-
-	if (mux_flags & USB_PD_MUX_SAFE_MODE)
+	if (mux_flags & USB_PD_MUX_DP_ENABLED) {
+		ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
+	} else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
 		ret = cros_typec_usb_safe_state(port);
-	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
+	} else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
+		port->state.alt = NULL;
+		port->state.mode = TYPEC_STATE_USB;
 		ret = typec_mux_set(port->mux, &port->state);
-	else {
+	} else {
 		dev_info(typec->dev,
 			 "Unsupported mode requested, mux flags: %x\n",
 			 mux_flags);
@@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 {
 	struct ec_params_usb_pd_control req;
-	struct ec_response_usb_pd_control_v1 resp;
+	struct ec_response_usb_pd_control_v2 resp;
 	struct ec_response_usb_pd_mux_info mux_resp;
 	int ret;
 
@@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
 
 	if (typec->pd_ctrl_ver != 0)
-		cros_typec_set_port_params_v1(typec, port_num, &resp);
+		cros_typec_set_port_params_v1(typec, port_num,
+			(struct ec_response_usb_pd_control_v1 *)&resp);
 	else
 		cros_typec_set_port_params_v0(typec, port_num,
 			(struct ec_response_usb_pd_control *) &resp);
@@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 		return 0;
 
 	typec->ports[port_num]->mux_flags = mux_resp.flags;
-	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
+	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
 	if (ret)
 		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
 
-- 
2.27.0.rc0.183.gde8f92d652-goog


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

* Re: [PATCH 3/4] platform/chrome: typec: Add USB mux control
  2020-05-28 11:36 ` [PATCH 3/4] platform/chrome: typec: Add USB mux control Prashant Malani
@ 2020-06-05  9:12   ` Prashant Malani
  2020-06-16  8:19   ` Heikki Krogerus
  1 sibling, 0 replies; 12+ messages in thread
From: Prashant Malani @ 2020-06-05  9:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Benson Leung, Enric Balletbo i Serra, Guenter Roeck

Hi,

On Thu, May 28, 2020 at 04:36:07AM -0700, Prashant Malani wrote:
> Add support to configure various Type C switches appropriately using the
> Type C connector class API, when the Chrome OS EC informs the AP that
> the USB operating mode has been entered.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>
Forgot to mention (and will add in subsequent versions):
Suggested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
>  1 file changed, 97 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index d69a88464cef..9ebf9abed16f 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -14,6 +14,7 @@
>  #include <linux/platform_data/cros_usbpd_notify.h>
>  #include <linux/platform_device.h>
>  #include <linux/usb/typec.h>
> +#include <linux/usb/typec_altmode.h>
>  #include <linux/usb/typec_mux.h>
>  #include <linux/usb/role.h>
>  
> @@ -30,6 +31,10 @@ struct cros_typec_port {
>  	struct typec_switch *ori_sw;
>  	struct typec_mux *mux;
>  	struct usb_role_switch *role_sw;
> +
> +	/* Variables keeping track of switch state. */
> +	struct typec_mux_state state;
> +	uint8_t mux_flags;
>  };
>  
>  /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
>  	return ret;
>  }
>  
> +static void cros_typec_remove_partner(struct cros_typec_data *typec,
> +				     int port_num)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +	port->state.data = NULL;
> +
> +	usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
> +	typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
> +	typec_mux_set(port->mux, &port->state);
> +
> +	typec_unregister_partner(port->partner);
> +	port->partner = NULL;
> +}
> +
>  static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
>  		int port_num, struct ec_response_usb_pd_control *resp)
>  {
> @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
>  	} else {
>  		if (!typec->ports[port_num]->partner)
>  			return;
> +		cros_typec_remove_partner(typec, port_num);
> +	}
> +}
> +
> +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
> +				   struct ec_response_usb_pd_mux_info *resp)
> +{
> +	struct ec_params_usb_pd_mux_info req = {
> +		.port = port_num,
> +	};
> +
> +	return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
> +				     sizeof(req), resp, sizeof(*resp));
> +}
> +
> +static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> +{
> +	port->state.mode = TYPEC_STATE_SAFE;
> +
> +	return typec_mux_set(port->mux, &port->state);
> +}
>  
> -		typec_unregister_partner(typec->ports[port_num]->partner);
> -		typec->ports[port_num]->partner = NULL;
> +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> +			     uint8_t mux_flags)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +	enum typec_orientation orientation;
> +	int ret;
> +
> +	if (!port->partner)
> +		return 0;
> +
> +	if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
> +		orientation = TYPEC_ORIENTATION_REVERSE;
> +	else
> +		orientation = TYPEC_ORIENTATION_NORMAL;
> +
> +	ret = typec_switch_set(port->ori_sw, orientation);
> +	if (ret)
> +		return ret;
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +
> +	if (mux_flags & USB_PD_MUX_SAFE_MODE)
> +		ret = cros_typec_usb_safe_state(port);
> +	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> +		ret = typec_mux_set(port->mux, &port->state);
> +	else {
> +		dev_info(typec->dev,
> +			 "Unsupported mode requested, mux flags: %x\n",
> +			 mux_flags);
> +		ret = -ENOTSUPP;
>  	}
> +
> +	return ret;
>  }
>  
>  static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  {
>  	struct ec_params_usb_pd_control req;
>  	struct ec_response_usb_pd_control_v1 resp;
> +	struct ec_response_usb_pd_mux_info mux_resp;
>  	int ret;
>  
>  	if (port_num < 0 || port_num >= typec->num_ports) {
> @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  		cros_typec_set_port_params_v0(typec, port_num,
>  			(struct ec_response_usb_pd_control *) &resp);
>  
> -	return 0;
> +	/* Update the switches if they exist, according to requested state */
> +	ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
> +	if (ret < 0) {
> +		dev_warn(typec->dev,
> +			 "Failed to get mux info for port: %d, err = %d\n",
> +			 port_num, ret);
> +		return 0;
> +	}
> +
> +	/* No change needs to be made, let's exit early. */
> +	if (typec->ports[port_num]->mux_flags == mux_resp.flags)
> +		return 0;
> +
> +	typec->ports[port_num]->mux_flags = mux_resp.flags;
> +	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> +	if (ret)
> +		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
> +
> +	return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> +					!!(resp.role & PD_CTRL_RESP_ROLE_DATA));
>  }
>  
>  static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
> -- 
> 2.27.0.rc0.183.gde8f92d652-goog
> 

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

* Re: [PATCH 4/4] platform/chrome: typec: Support DP alt mode
  2020-05-28 11:36 ` [PATCH 4/4] platform/chrome: typec: Support DP alt mode Prashant Malani
@ 2020-06-05  9:12   ` Prashant Malani
  2020-06-16 10:31   ` Heikki Krogerus
  1 sibling, 0 replies; 12+ messages in thread
From: Prashant Malani @ 2020-06-05  9:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: heikki.krogerus, Benson Leung, Enric Balletbo i Serra, Guenter Roeck

Hi,
On Thu, May 28, 2020 at 04:36:10AM -0700, Prashant Malani wrote:
> Handle Chrome EC mux events to configure on-board muxes correctly while
> entering DP alternate mode. Since we don't surface SVID and VDO
> information regarding the DP alternate mode, configure the Type C
> muxes directly from the port driver. Later, when mode discovery
> information is correctly surfaced to the driver, we can register the DP
> alternate mode driver and let it handle the mux configuration.
> 
> Also, modify the struct_typec_state state management to account for the
> addition of DP alternate mode.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>
Sorry, forgot to mention (and will add to subsequent versions):
Suggested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
>  1 file changed, 80 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 9ebf9abed16f..509fc761906b 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -15,11 +15,18 @@
>  #include <linux/platform_device.h>
>  #include <linux/usb/typec.h>
>  #include <linux/usb/typec_altmode.h>
> +#include <linux/usb/typec_dp.h>
>  #include <linux/usb/typec_mux.h>
>  #include <linux/usb/role.h>
>  
>  #define DRV_NAME "cros-ec-typec"
>  
> +/* Supported alt modes. */
> +enum {
> +	CROS_EC_ALTMODE_DP = 0,
> +	CROS_EC_ALTMODE_MAX,
> +};
> +
>  /* Per port data. */
>  struct cros_typec_port {
>  	struct typec_port *port;
> @@ -35,6 +42,9 @@ struct cros_typec_port {
>  	/* Variables keeping track of switch state. */
>  	struct typec_mux_state state;
>  	uint8_t mux_flags;
> +
> +	/* Port alt modes. */
> +	struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
>  };
>  
>  /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
>  	}
>  }
>  
> +/*
> + * Fake the alt mode structs until we actually start registering Type C port
> + * and partner alt modes.
> + */
> +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
> +					      int port_num)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +
> +	/* All PD capable CrOS devices are assumed to support DP altmode. */
> +	port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
> +	port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +	port->state.data = NULL;
> +}
> +
>  static int cros_typec_init_ports(struct cros_typec_data *typec)
>  {
>  	struct device *dev = typec->dev;
> @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
>  		if (ret)
>  			dev_dbg(dev, "No switch control for port %d\n",
>  				port_num);
> +
> +		cros_typec_register_port_altmodes(typec, port_num);
>  	}
>  
>  	return 0;
> @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
>  	return typec_mux_set(port->mux, &port->state);
>  }
>  
> +/* Spoof the VDOs that were likely communicated by the partner. */
> +static int cros_typec_enable_dp(struct cros_typec_data *typec,
> +				int port_num,
> +				struct ec_response_usb_pd_control_v2 *pd_ctrl)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +	struct typec_displayport_data dp_data;
> +	int ret;
> +
> +	if (typec->pd_ctrl_ver < 2) {
> +		dev_err(typec->dev,
> +			"PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
> +		return -ENOTSUPP;
> +	}
> +
> +	/* Status VDO. */
> +	dp_data.status = DP_STATUS_ENABLED;
> +	if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
> +		dp_data.status |= DP_STATUS_IRQ_HPD;
> +	if (port->mux_flags & USB_PD_MUX_HPD_LVL)
> +		dp_data.status |= DP_STATUS_HPD_STATE;
> +
> +	/* Configuration VDO. */
> +	dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
> +	if (!port->state.alt) {
> +		port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
> +		ret = cros_typec_usb_safe_state(port);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	port->state.data = &dp_data;
> +	port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
> +
> +	return typec_mux_set(port->mux, &port->state);
> +}
> +
>  int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> -			     uint8_t mux_flags)
> +			     uint8_t mux_flags,
> +			     struct ec_response_usb_pd_control_v2 *pd_ctrl)
>  {
>  	struct cros_typec_port *port = typec->ports[port_num];
>  	enum typec_orientation orientation;
> @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
>  	if (ret)
>  		return ret;
>  
> -	port->state.alt = NULL;
> -	port->state.mode = TYPEC_STATE_USB;
> -
> -	if (mux_flags & USB_PD_MUX_SAFE_MODE)
> +	if (mux_flags & USB_PD_MUX_DP_ENABLED) {
> +		ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
> +	} else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
>  		ret = cros_typec_usb_safe_state(port);
> -	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> +	} else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
> +		port->state.alt = NULL;
> +		port->state.mode = TYPEC_STATE_USB;
>  		ret = typec_mux_set(port->mux, &port->state);
> -	else {
> +	} else {
>  		dev_info(typec->dev,
>  			 "Unsupported mode requested, mux flags: %x\n",
>  			 mux_flags);
> @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
>  static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  {
>  	struct ec_params_usb_pd_control req;
> -	struct ec_response_usb_pd_control_v1 resp;
> +	struct ec_response_usb_pd_control_v2 resp;
>  	struct ec_response_usb_pd_mux_info mux_resp;
>  	int ret;
>  
> @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>  
>  	if (typec->pd_ctrl_ver != 0)
> -		cros_typec_set_port_params_v1(typec, port_num, &resp);
> +		cros_typec_set_port_params_v1(typec, port_num,
> +			(struct ec_response_usb_pd_control_v1 *)&resp);
>  	else
>  		cros_typec_set_port_params_v0(typec, port_num,
>  			(struct ec_response_usb_pd_control *) &resp);
> @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  		return 0;
>  
>  	typec->ports[port_num]->mux_flags = mux_resp.flags;
> -	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> +	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
>  	if (ret)
>  		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
>  
> -- 
> 2.27.0.rc0.183.gde8f92d652-goog
> 

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

* Re: [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2
  2020-05-28 11:36 ` [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2 Prashant Malani
@ 2020-06-16  7:27   ` Heikki Krogerus
  0 siblings, 0 replies; 12+ messages in thread
From: Heikki Krogerus @ 2020-06-16  7:27 UTC (permalink / raw)
  To: Prashant Malani
  Cc: linux-kernel, Benson Leung, Enric Balletbo i Serra,
	Fabien Lahoudere, Guenter Roeck, Gwendal Grignou, Lee Jones,
	Tzung-Bi Shih

On Thu, May 28, 2020 at 04:36:05AM -0700, Prashant Malani wrote:
> Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in
> order to process Type C mux information (like DP alt mode pin
> configuration), which is needed by the Type C Connector class API to
> configure the Type C muxes correctly
> 
> While we are here, rename the struct member storing this version number
> from cmd_ver to pd_ctrl_ver, which more accurately reflects what is
> being stored.
> 
> Also, slightly change the logic for calling
> cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0,
> and v1 is called otherwise.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>

LGTM. One nitpick bellow, but don't prepare v2 just because of that.
FWIW:

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

> ---
>  drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 6e79f917314b..d69a88464cef 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -37,7 +37,7 @@ struct cros_typec_data {
>  	struct device *dev;
>  	struct cros_ec_device *ec;
>  	int num_ports;
> -	unsigned int cmd_ver;
> +	unsigned int pd_ctrl_ver;
>  	/* Array of ports, indexed by port number. */
>  	struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
>  	struct notifier_block nb;
> @@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  	req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
>  	req.swap = USB_PD_CTRL_SWAP_NONE;
>  
> -	ret = cros_typec_ec_command(typec, typec->cmd_ver,
> +	ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver,
>  				    EC_CMD_USB_PD_CONTROL, &req, sizeof(req),
>  				    &resp, sizeof(resp));
>  	if (ret < 0)
> @@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  	dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
>  	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>  
> -	if (typec->cmd_ver == 1)
> +	if (typec->pd_ctrl_ver != 0)

How about:

        if (typec->pd_ctrl_ver)

>  		cros_typec_set_port_params_v1(typec, port_num, &resp);
>  	else
>  		cros_typec_set_port_params_v0(typec, port_num,
> @@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
>  	if (ret < 0)
>  		return ret;
>  
> -	if (resp.version_mask & EC_VER_MASK(1))
> -		typec->cmd_ver = 1;
> +	if (resp.version_mask & EC_VER_MASK(2))
> +		typec->pd_ctrl_ver = 2;
> +	else if (resp.version_mask & EC_VER_MASK(1))
> +		typec->pd_ctrl_ver = 1;
>  	else
> -		typec->cmd_ver = 0;
> +		typec->pd_ctrl_ver = 0;
>  
>  	dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n",
> -		typec->cmd_ver);
> +		typec->pd_ctrl_ver);
>  
>  	return 0;
>  }

thanks,

-- 
heikki

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

* Re: [PATCH 3/4] platform/chrome: typec: Add USB mux control
  2020-05-28 11:36 ` [PATCH 3/4] platform/chrome: typec: Add USB mux control Prashant Malani
  2020-06-05  9:12   ` Prashant Malani
@ 2020-06-16  8:19   ` Heikki Krogerus
  1 sibling, 0 replies; 12+ messages in thread
From: Heikki Krogerus @ 2020-06-16  8:19 UTC (permalink / raw)
  To: Prashant Malani
  Cc: linux-kernel, Benson Leung, Enric Balletbo i Serra, Guenter Roeck

On Thu, May 28, 2020 at 04:36:07AM -0700, Prashant Malani wrote:
> Add support to configure various Type C switches appropriately using the
> Type C connector class API, when the Chrome OS EC informs the AP that
> the USB operating mode has been entered.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>

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

> ---
>  drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
>  1 file changed, 97 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index d69a88464cef..9ebf9abed16f 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -14,6 +14,7 @@
>  #include <linux/platform_data/cros_usbpd_notify.h>
>  #include <linux/platform_device.h>
>  #include <linux/usb/typec.h>
> +#include <linux/usb/typec_altmode.h>
>  #include <linux/usb/typec_mux.h>
>  #include <linux/usb/role.h>
>  
> @@ -30,6 +31,10 @@ struct cros_typec_port {
>  	struct typec_switch *ori_sw;
>  	struct typec_mux *mux;
>  	struct usb_role_switch *role_sw;
> +
> +	/* Variables keeping track of switch state. */
> +	struct typec_mux_state state;
> +	uint8_t mux_flags;
>  };
>  
>  /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
>  	return ret;
>  }
>  
> +static void cros_typec_remove_partner(struct cros_typec_data *typec,
> +				     int port_num)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +	port->state.data = NULL;
> +
> +	usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
> +	typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
> +	typec_mux_set(port->mux, &port->state);
> +
> +	typec_unregister_partner(port->partner);
> +	port->partner = NULL;
> +}
> +
>  static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
>  		int port_num, struct ec_response_usb_pd_control *resp)
>  {
> @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
>  	} else {
>  		if (!typec->ports[port_num]->partner)
>  			return;
> +		cros_typec_remove_partner(typec, port_num);
> +	}
> +}
> +
> +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
> +				   struct ec_response_usb_pd_mux_info *resp)
> +{
> +	struct ec_params_usb_pd_mux_info req = {
> +		.port = port_num,
> +	};
> +
> +	return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
> +				     sizeof(req), resp, sizeof(*resp));
> +}
> +
> +static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> +{
> +	port->state.mode = TYPEC_STATE_SAFE;
> +
> +	return typec_mux_set(port->mux, &port->state);
> +}
>  
> -		typec_unregister_partner(typec->ports[port_num]->partner);
> -		typec->ports[port_num]->partner = NULL;
> +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> +			     uint8_t mux_flags)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +	enum typec_orientation orientation;
> +	int ret;
> +
> +	if (!port->partner)
> +		return 0;
> +
> +	if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
> +		orientation = TYPEC_ORIENTATION_REVERSE;
> +	else
> +		orientation = TYPEC_ORIENTATION_NORMAL;
> +
> +	ret = typec_switch_set(port->ori_sw, orientation);
> +	if (ret)
> +		return ret;
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +
> +	if (mux_flags & USB_PD_MUX_SAFE_MODE)
> +		ret = cros_typec_usb_safe_state(port);
> +	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> +		ret = typec_mux_set(port->mux, &port->state);
> +	else {
> +		dev_info(typec->dev,
> +			 "Unsupported mode requested, mux flags: %x\n",
> +			 mux_flags);
> +		ret = -ENOTSUPP;
>  	}
> +
> +	return ret;
>  }
>  
>  static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  {
>  	struct ec_params_usb_pd_control req;
>  	struct ec_response_usb_pd_control_v1 resp;
> +	struct ec_response_usb_pd_mux_info mux_resp;
>  	int ret;
>  
>  	if (port_num < 0 || port_num >= typec->num_ports) {
> @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  		cros_typec_set_port_params_v0(typec, port_num,
>  			(struct ec_response_usb_pd_control *) &resp);
>  
> -	return 0;
> +	/* Update the switches if they exist, according to requested state */
> +	ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
> +	if (ret < 0) {
> +		dev_warn(typec->dev,
> +			 "Failed to get mux info for port: %d, err = %d\n",
> +			 port_num, ret);
> +		return 0;
> +	}
> +
> +	/* No change needs to be made, let's exit early. */
> +	if (typec->ports[port_num]->mux_flags == mux_resp.flags)
> +		return 0;
> +
> +	typec->ports[port_num]->mux_flags = mux_resp.flags;
> +	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> +	if (ret)
> +		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
> +
> +	return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> +					!!(resp.role & PD_CTRL_RESP_ROLE_DATA));
>  }
>  
>  static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
> -- 
> 2.27.0.rc0.183.gde8f92d652-goog

-- 
heikki

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

* Re: [PATCH 4/4] platform/chrome: typec: Support DP alt mode
  2020-05-28 11:36 ` [PATCH 4/4] platform/chrome: typec: Support DP alt mode Prashant Malani
  2020-06-05  9:12   ` Prashant Malani
@ 2020-06-16 10:31   ` Heikki Krogerus
  1 sibling, 0 replies; 12+ messages in thread
From: Heikki Krogerus @ 2020-06-16 10:31 UTC (permalink / raw)
  To: Prashant Malani
  Cc: linux-kernel, Benson Leung, Enric Balletbo i Serra, Guenter Roeck

On Thu, May 28, 2020 at 04:36:10AM -0700, Prashant Malani wrote:
> Handle Chrome EC mux events to configure on-board muxes correctly while
> entering DP alternate mode. Since we don't surface SVID and VDO
> information regarding the DP alternate mode, configure the Type C
> muxes directly from the port driver. Later, when mode discovery
> information is correctly surfaced to the driver, we can register the DP
> alternate mode driver and let it handle the mux configuration.
> 
> Also, modify the struct_typec_state state management to account for the
> addition of DP alternate mode.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>

FWIW:

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

> ---
>  drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
>  1 file changed, 80 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 9ebf9abed16f..509fc761906b 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -15,11 +15,18 @@
>  #include <linux/platform_device.h>
>  #include <linux/usb/typec.h>
>  #include <linux/usb/typec_altmode.h>
> +#include <linux/usb/typec_dp.h>
>  #include <linux/usb/typec_mux.h>
>  #include <linux/usb/role.h>
>  
>  #define DRV_NAME "cros-ec-typec"
>  
> +/* Supported alt modes. */
> +enum {
> +	CROS_EC_ALTMODE_DP = 0,
> +	CROS_EC_ALTMODE_MAX,
> +};
> +
>  /* Per port data. */
>  struct cros_typec_port {
>  	struct typec_port *port;
> @@ -35,6 +42,9 @@ struct cros_typec_port {
>  	/* Variables keeping track of switch state. */
>  	struct typec_mux_state state;
>  	uint8_t mux_flags;
> +
> +	/* Port alt modes. */
> +	struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
>  };
>  
>  /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
>  	}
>  }
>  
> +/*
> + * Fake the alt mode structs until we actually start registering Type C port
> + * and partner alt modes.
> + */
> +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
> +					      int port_num)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +
> +	/* All PD capable CrOS devices are assumed to support DP altmode. */
> +	port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
> +	port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
> +
> +	port->state.alt = NULL;
> +	port->state.mode = TYPEC_STATE_USB;
> +	port->state.data = NULL;
> +}
> +
>  static int cros_typec_init_ports(struct cros_typec_data *typec)
>  {
>  	struct device *dev = typec->dev;
> @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
>  		if (ret)
>  			dev_dbg(dev, "No switch control for port %d\n",
>  				port_num);
> +
> +		cros_typec_register_port_altmodes(typec, port_num);
>  	}
>  
>  	return 0;
> @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
>  	return typec_mux_set(port->mux, &port->state);
>  }
>  
> +/* Spoof the VDOs that were likely communicated by the partner. */
> +static int cros_typec_enable_dp(struct cros_typec_data *typec,
> +				int port_num,
> +				struct ec_response_usb_pd_control_v2 *pd_ctrl)
> +{
> +	struct cros_typec_port *port = typec->ports[port_num];
> +	struct typec_displayport_data dp_data;
> +	int ret;
> +
> +	if (typec->pd_ctrl_ver < 2) {
> +		dev_err(typec->dev,
> +			"PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
> +		return -ENOTSUPP;
> +	}
> +
> +	/* Status VDO. */
> +	dp_data.status = DP_STATUS_ENABLED;
> +	if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
> +		dp_data.status |= DP_STATUS_IRQ_HPD;
> +	if (port->mux_flags & USB_PD_MUX_HPD_LVL)
> +		dp_data.status |= DP_STATUS_HPD_STATE;
> +
> +	/* Configuration VDO. */
> +	dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
> +	if (!port->state.alt) {
> +		port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
> +		ret = cros_typec_usb_safe_state(port);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	port->state.data = &dp_data;
> +	port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
> +
> +	return typec_mux_set(port->mux, &port->state);
> +}
> +
>  int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> -			     uint8_t mux_flags)
> +			     uint8_t mux_flags,
> +			     struct ec_response_usb_pd_control_v2 *pd_ctrl)
>  {
>  	struct cros_typec_port *port = typec->ports[port_num];
>  	enum typec_orientation orientation;
> @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
>  	if (ret)
>  		return ret;
>  
> -	port->state.alt = NULL;
> -	port->state.mode = TYPEC_STATE_USB;
> -
> -	if (mux_flags & USB_PD_MUX_SAFE_MODE)
> +	if (mux_flags & USB_PD_MUX_DP_ENABLED) {
> +		ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
> +	} else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
>  		ret = cros_typec_usb_safe_state(port);
> -	else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> +	} else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
> +		port->state.alt = NULL;
> +		port->state.mode = TYPEC_STATE_USB;
>  		ret = typec_mux_set(port->mux, &port->state);
> -	else {
> +	} else {
>  		dev_info(typec->dev,
>  			 "Unsupported mode requested, mux flags: %x\n",
>  			 mux_flags);
> @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
>  static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  {
>  	struct ec_params_usb_pd_control req;
> -	struct ec_response_usb_pd_control_v1 resp;
> +	struct ec_response_usb_pd_control_v2 resp;
>  	struct ec_response_usb_pd_mux_info mux_resp;
>  	int ret;
>  
> @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>  
>  	if (typec->pd_ctrl_ver != 0)
> -		cros_typec_set_port_params_v1(typec, port_num, &resp);
> +		cros_typec_set_port_params_v1(typec, port_num,
> +			(struct ec_response_usb_pd_control_v1 *)&resp);
>  	else
>  		cros_typec_set_port_params_v0(typec, port_num,
>  			(struct ec_response_usb_pd_control *) &resp);
> @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
>  		return 0;
>  
>  	typec->ports[port_num]->mux_flags = mux_resp.flags;
> -	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> +	ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
>  	if (ret)
>  		dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
>  
> -- 
> 2.27.0.rc0.183.gde8f92d652-goog

thanks,

-- 
heikki

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

* Re: [PATCH 0/4] platform/chrome: typec: Add mux support
  2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
                   ` (3 preceding siblings ...)
  2020-05-28 11:36 ` [PATCH 4/4] platform/chrome: typec: Support DP alt mode Prashant Malani
@ 2020-06-25 11:56 ` Enric Balletbo i Serra
  2020-06-25 16:10   ` Prashant Malani
  4 siblings, 1 reply; 12+ messages in thread
From: Enric Balletbo i Serra @ 2020-06-25 11:56 UTC (permalink / raw)
  To: Prashant Malani, linux-kernel
  Cc: heikki.krogerus, Benson Leung, Guenter Roeck, Gwendal Grignou,
	Lee Jones, Tzung-Bi Shih

Hi Prashant,

On 28/5/20 13:36, Prashant Malani wrote:
> This series adds mux control support for USB and DP alternate modes on
> devices using the cros-ec-typec driver with Type C switch handles
> provided by firmware bindings.
> 
> The first patch imports some recent updates to the
> EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
> code base[1], while the rest add the aforementioned functionality.
> 
> This series depends on the following patch :
> https://lkml.org/lkml/2020/5/19/1219
> 
> [1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h
> 
> Prashant Malani (4):
>   platform/chrome: cros_ec: Update mux state bits
>   platform/chrome: typec: Register PD CTRL cmd v2
>   platform/chrome: typec: Add USB mux control
>   platform/chrome: typec: Support DP alt mode
> 
>  drivers/platform/chrome/cros_ec_typec.c       | 190 ++++++++++++++++--
>  .../linux/platform_data/cros_ec_commands.h    |  14 +-
>  2 files changed, 187 insertions(+), 17 deletions(-)
> 

Tweaked a bit the subject, s/typec/cros_ec_typec/ and queued the four patches
for 5.9.

Thanks,
 Enric

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

* Re: [PATCH 0/4] platform/chrome: typec: Add mux support
  2020-06-25 11:56 ` [PATCH 0/4] platform/chrome: typec: Add mux support Enric Balletbo i Serra
@ 2020-06-25 16:10   ` Prashant Malani
  0 siblings, 0 replies; 12+ messages in thread
From: Prashant Malani @ 2020-06-25 16:10 UTC (permalink / raw)
  To: Enric Balletbo i Serra
  Cc: Linux Kernel Mailing List, Heikki Krogerus, Benson Leung,
	Guenter Roeck, Gwendal Grignou, Lee Jones, Tzung-Bi Shih

Thanks Enric!

On Thu, Jun 25, 2020 at 4:56 AM Enric Balletbo i Serra
<enric.balletbo@collabora.com> wrote:
>
> Hi Prashant,
>
> On 28/5/20 13:36, Prashant Malani wrote:
> > This series adds mux control support for USB and DP alternate modes on
> > devices using the cros-ec-typec driver with Type C switch handles
> > provided by firmware bindings.
> >
> > The first patch imports some recent updates to the
> > EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
> > code base[1], while the rest add the aforementioned functionality.
> >
> > This series depends on the following patch :
> > https://lkml.org/lkml/2020/5/19/1219
> >
> > [1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h
> >
> > Prashant Malani (4):
> >   platform/chrome: cros_ec: Update mux state bits
> >   platform/chrome: typec: Register PD CTRL cmd v2
> >   platform/chrome: typec: Add USB mux control
> >   platform/chrome: typec: Support DP alt mode
> >
> >  drivers/platform/chrome/cros_ec_typec.c       | 190 ++++++++++++++++--
> >  .../linux/platform_data/cros_ec_commands.h    |  14 +-
> >  2 files changed, 187 insertions(+), 17 deletions(-)
> >
>
> Tweaked a bit the subject, s/typec/cros_ec_typec/ and queued the four patches
> for 5.9.
>
> Thanks,
>  Enric

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

end of thread, other threads:[~2020-06-25 16:11 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-28 11:36 [PATCH 0/4] platform/chrome: typec: Add mux support Prashant Malani
2020-05-28 11:36 ` [PATCH 1/4] platform/chrome: cros_ec: Update mux state bits Prashant Malani
2020-05-28 11:36 ` [PATCH 2/4] platform/chrome: typec: Register PD CTRL cmd v2 Prashant Malani
2020-06-16  7:27   ` Heikki Krogerus
2020-05-28 11:36 ` [PATCH 3/4] platform/chrome: typec: Add USB mux control Prashant Malani
2020-06-05  9:12   ` Prashant Malani
2020-06-16  8:19   ` Heikki Krogerus
2020-05-28 11:36 ` [PATCH 4/4] platform/chrome: typec: Support DP alt mode Prashant Malani
2020-06-05  9:12   ` Prashant Malani
2020-06-16 10:31   ` Heikki Krogerus
2020-06-25 11:56 ` [PATCH 0/4] platform/chrome: typec: Add mux support Enric Balletbo i Serra
2020-06-25 16:10   ` Prashant Malani

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).