aboutsummaryrefslogtreecommitdiffstats
diff options
authorAndrei Kuchynski <akuchynski@chromium.org>2025-02-10 13:04:19 +0000
committerTzung-Bi Shih <tzungbi@kernel.org>2025-02-21 01:42:22 +0000
commit9fc83373f0ffb8834da48b1446a5c2fef9525bb1 (patch)
tree5cea1454ddfe2f38d1ab48f142b5af963a61e3a6
parent435a3d78b87a93c52a4f84e36ba4a0857554c958 (diff)
downloadlinux-for-6.15.tar.gz
platform/chrome: cros_ec_typec: Add support for setting USB mode via sysfschrome-platform-v6.15for-6.15
This patch implements USB mode setting via a sysfs interface in cros_ec_typec driver. User-space applications can now change the current USB mode by writing to "usb_mode" sysfs entry, replacing the previous ioctl-based method. The embedded controller (EC) currently supports only entering USB4 mode and exiting all modes (including altmodes). Both of these operations trigger Data Reset Message, even if no USB Mode is active. Additionally, the patch exposes the USB modes supported by the port via "usb_capability" sysfs attribute. Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org> Link: https://lore.kernel.org/r/20250210130419.4110130-1-akuchynski@chromium.org Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c28
-rw-r--r--drivers/platform/chrome/cros_ec_typec.h1
2 files changed, 29 insertions, 0 deletions
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 6ee182101bc934..d2228720991ffe 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -42,6 +42,24 @@ static void cros_typec_role_switch_quirk(struct fwnode_handle *fwnode)
#endif
}
+static int cros_typec_enter_usb_mode(struct typec_port *tc_port, enum usb_mode mode)
+{
+ struct cros_typec_port *port = typec_get_drvdata(tc_port);
+ struct ec_params_typec_control req = {
+ .port = port->port_num,
+ .command = (mode == USB_MODE_USB4) ?
+ TYPEC_CONTROL_COMMAND_ENTER_MODE : TYPEC_CONTROL_COMMAND_EXIT_MODES,
+ .mode_to_enter = CROS_EC_ALTMODE_USB4
+ };
+
+ return cros_ec_cmd(port->typec_data->ec, 0, EC_CMD_TYPEC_CONTROL,
+ &req, sizeof(req), NULL, 0);
+}
+
+static const struct typec_operations cros_typec_usb_mode_ops = {
+ .enter_usb_mode = cros_typec_enter_usb_mode
+};
+
static int cros_typec_parse_port_props(struct typec_capability *cap,
struct fwnode_handle *fwnode,
struct device *dev)
@@ -84,6 +102,13 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
cap->prefer_role = ret;
}
+ if (fwnode_property_present(fwnode, "usb2-port"))
+ cap->usb_capability |= USB_CAPABILITY_USB2;
+ if (fwnode_property_present(fwnode, "usb3-port"))
+ cap->usb_capability |= USB_CAPABILITY_USB3;
+ if (fwnode_property_present(fwnode, "usb4-port"))
+ cap->usb_capability |= USB_CAPABILITY_USB4;
+
cros_typec_role_switch_quirk(fwnode);
cap->fwnode = fwnode;
@@ -379,6 +404,9 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
if (ret < 0)
goto unregister_ports;
+ cap->driver_data = cros_port;
+ cap->ops = &cros_typec_usb_mode_ops;
+
cros_port->port = typec_register_port(dev, cap);
if (IS_ERR(cros_port->port)) {
ret = PTR_ERR(cros_port->port);
diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h
index 9fd5342bb0ad14..f9c31f04c1021a 100644
--- a/drivers/platform/chrome/cros_ec_typec.h
+++ b/drivers/platform/chrome/cros_ec_typec.h
@@ -18,6 +18,7 @@
enum {
CROS_EC_ALTMODE_DP = 0,
CROS_EC_ALTMODE_TBT,
+ CROS_EC_ALTMODE_USB4,
CROS_EC_ALTMODE_MAX,
};