From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Cc: "Dmitry Baryshkov" <dmitry.baryshkov@linaro.org>,
"Łukasz Bartosik" <ukaszb@chromium.org>,
"Benson Leung" <bleung@chromium.org>,
"Jameson Thies" <jthies@google.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org
Subject: [PATCH v1 1/4] usb: typec: Add attribute file showing the supported USB modes of the port
Date: Fri, 4 Oct 2024 17:04:36 +0300 [thread overview]
Message-ID: <20241004140440.1882311-2-heikki.krogerus@linux.intel.com> (raw)
In-Reply-To: <20241004140440.1882311-1-heikki.krogerus@linux.intel.com>
This attribute file, named "usb_capability", will show the
supported USB modes, which are USB 2.0, USB 3.2 and USB4.
These modes are defined in the USB Type-C (R2.0) and USB
Power Delivery (R3.0 V2.0) Specifications.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
Documentation/ABI/testing/sysfs-class-typec | 13 ++++
drivers/usb/typec/class.c | 81 +++++++++++++++++++++
drivers/usb/typec/class.h | 1 +
include/linux/usb/typec.h | 17 +++++
4 files changed, 112 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
index 281b995beb05..7c307f02d99e 100644
--- a/Documentation/ABI/testing/sysfs-class-typec
+++ b/Documentation/ABI/testing/sysfs-class-typec
@@ -149,6 +149,19 @@ Description:
advertise to the partner. The currently used capabilities are in
brackets. Selection happens by writing to the file.
+What: /sys/class/typec/<port>/usb_capability
+Date: May 2024
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description: Lists the supported USB Modes. The default USB mode that is used
+ next time with the Enter_USB Message is in brackets. The default
+ mode can be changed by writing to the file when supported by the
+ driver.
+
+ Valid values:
+ - usb2 (USB 2.0)
+ - usb3 (USB 3.2)
+ - usb4 (USB4)
+
USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
What: /sys/class/typec/<port>-partner/accessory_mode
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 9262fcd4144f..9c26d2ad40df 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -219,6 +219,13 @@ static ssize_t usb_power_delivery_revision_show(struct device *dev,
char *buf);
static DEVICE_ATTR_RO(usb_power_delivery_revision);
+static const char * const usb_modes[] = {
+ [USB_MODE_NONE] = "none",
+ [USB_MODE_USB2] = "usb2",
+ [USB_MODE_USB3] = "usb3",
+ [USB_MODE_USB4] = "usb4"
+};
+
/* ------------------------------------------------------------------------- */
/* Alternate Modes */
@@ -1289,6 +1296,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable);
/* ------------------------------------------------------------------------- */
/* USB Type-C ports */
+/**
+ * typec_port_set_usb_mode - Set the operational USB mode for the port
+ * @port: USB Type-C port
+ * @mode: USB Mode (USB2, USB3 or USB4)
+ *
+ * @mode will be used with the next Enter_USB message. Existing connections are
+ * not affected.
+ */
+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode)
+{
+ port->usb_mode = mode;
+}
+EXPORT_SYMBOL_GPL(typec_port_set_usb_mode);
+
+static ssize_t
+usb_capability_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ enum usb_mode mode = to_typec_port(dev)->usb_mode;
+ u8 cap = to_typec_port(dev)->cap->usb_capability;
+ int len = 0;
+ int i;
+
+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
+ if (!(BIT(i - 1) & cap))
+ continue;
+
+ if (i == mode)
+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
+ else
+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
+ }
+
+ buf[len - 1] = '\n';
+ return len;
+}
+
+static ssize_t
+usb_capability_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int ret = 0;
+ int mode;
+
+ if (!port->ops || !port->ops->usb_mode_set)
+ return -EOPNOTSUPP;
+
+ mode = sysfs_match_string(usb_modes, buf);
+ if (mode < 0)
+ return mode;
+
+ ret = port->ops->usb_mode_set(port, mode);
+ if (ret)
+ return ret;
+
+ port->usb_mode = mode;
+
+ return size;
+}
+static DEVICE_ATTR_RW(usb_capability);
+
/**
* typec_port_set_usb_power_delivery - Assign USB PD for port.
* @port: USB Type-C port.
@@ -1757,6 +1825,7 @@ static struct attribute *typec_attrs[] = {
&dev_attr_vconn_source.attr,
&dev_attr_port_type.attr,
&dev_attr_orientation.attr,
+ &dev_attr_usb_capability.attr,
NULL,
};
@@ -1790,6 +1859,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj,
if (port->cap->orientation_aware)
return 0444;
return 0;
+ } else if (attr == &dev_attr_usb_capability.attr) {
+ if (!port->cap->usb_capability)
+ return 0;
+ if (!port->ops || !port->ops->usb_mode_set)
+ return 0444;
}
return attr->mode;
@@ -2428,6 +2502,13 @@ struct typec_port *typec_register_port(struct device *parent,
port->con.attach = typec_partner_attach;
port->con.deattach = typec_partner_deattach;
+ if (cap->usb_capability & USB_CAPABILITY_USB4)
+ port->usb_mode = USB_MODE_USB4;
+ else if (cap->usb_capability & USB_CAPABILITY_USB3)
+ port->usb_mode = USB_MODE_USB3;
+ else if (cap->usb_capability & USB_CAPABILITY_USB2)
+ port->usb_mode = USB_MODE_USB2;
+
device_initialize(&port->dev);
port->dev.class = &typec_class;
port->dev.parent = parent;
diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h
index 7485cdb9dd20..85bc50aa54f7 100644
--- a/drivers/usb/typec/class.h
+++ b/drivers/usb/typec/class.h
@@ -55,6 +55,7 @@ struct typec_port {
enum typec_role vconn_role;
enum typec_pwr_opmode pwr_opmode;
enum typec_port_type port_type;
+ enum usb_mode usb_mode;
struct mutex port_type_lock;
enum typec_orientation orientation;
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 549275f8ac1b..d8999472212d 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -87,6 +87,17 @@ enum typec_orientation {
TYPEC_ORIENTATION_REVERSE,
};
+enum usb_mode {
+ USB_MODE_NONE,
+ USB_MODE_USB2,
+ USB_MODE_USB3,
+ USB_MODE_USB4
+};
+
+#define USB_CAPABILITY_USB2 BIT(0)
+#define USB_CAPABILITY_USB3 BIT(1)
+#define USB_CAPABILITY_USB4 BIT(2)
+
/*
* struct enter_usb_data - Enter_USB Message details
* @eudo: Enter_USB Data Object
@@ -240,6 +251,7 @@ struct typec_partner_desc {
* @port_type_set: Set port type
* @pd_get: Get available USB Power Delivery Capabilities.
* @pd_set: Set USB Power Delivery Capabilities.
+ * @usb_mode_set: Set the USB Mode to be used with Enter_USB message
*/
struct typec_operations {
int (*try_role)(struct typec_port *port, int role);
@@ -250,6 +262,7 @@ struct typec_operations {
enum typec_port_type type);
struct usb_power_delivery **(*pd_get)(struct typec_port *port);
int (*pd_set)(struct typec_port *port, struct usb_power_delivery *pd);
+ int (*usb_mode_set)(struct typec_port *port, enum usb_mode mode);
};
enum usb_pd_svdm_ver {
@@ -267,6 +280,7 @@ enum usb_pd_svdm_ver {
* @svdm_version: USB PD Structured VDM version if supported
* @prefer_role: Initial role preference (DRP ports).
* @accessory: Supported Accessory Modes
+ * @usb_capability: Supported USB Modes
* @fwnode: Optional fwnode of the port
* @driver_data: Private pointer for driver specific info
* @pd: Optional USB Power Delivery Support
@@ -283,6 +297,7 @@ struct typec_capability {
int prefer_role;
enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
unsigned int orientation_aware:1;
+ u8 usb_capability;
struct fwnode_handle *fwnode;
void *driver_data;
@@ -350,6 +365,8 @@ int typec_port_set_usb_power_delivery(struct typec_port *port, struct usb_power_
int typec_partner_set_usb_power_delivery(struct typec_partner *partner,
struct usb_power_delivery *pd);
+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode);
+
/**
* struct typec_connector - Representation of Type-C port for external drivers
* @attach: notification about device removal
--
2.45.2
next prev parent reply other threads:[~2024-10-04 14:04 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-04 14:04 [PATCH v1 0/3] usb: typec: USB Modes Heikki Krogerus
2024-10-04 14:04 ` Heikki Krogerus [this message]
2024-10-06 16:35 ` [PATCH v1 1/4] usb: typec: Add attribute file showing the supported USB modes of the port Dmitry Baryshkov
2024-10-04 14:04 ` [PATCH v1 2/4] usb: typec: Add attribute file showing the USB Modes of the partner Heikki Krogerus
2024-10-05 7:25 ` kernel test robot
2024-10-06 16:22 ` Dmitry Baryshkov
2024-10-09 8:34 ` Heikki Krogerus
2024-10-04 14:04 ` [PATCH v1 3/4] usb: typec: ucsi: Supply the USB capabilities to the ports Heikki Krogerus
2024-10-06 16:36 ` Dmitry Baryshkov
2024-10-04 14:04 ` [PATCH v1 4/4] usb: typec: ucsi: Add support for the partner USB Modes Heikki Krogerus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241004140440.1882311-2-heikki.krogerus@linux.intel.com \
--to=heikki.krogerus@linux.intel.com \
--cc=abhishekpandit@chromium.org \
--cc=bleung@chromium.org \
--cc=dmitry.baryshkov@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=jthies@google.com \
--cc=linux-usb@vger.kernel.org \
--cc=ukaszb@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.