History

usb: typec: Add attribute file showing the supported USB modes of the port

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.

Heikki Krogerus committed 2 years ago

Commit 8060bcb1 parent 0990e5c4 files · +112 −0Browse files

Unified · Split

4 files
  1. Documentation/ABI/testing/sysfs-class-typec +13 −0
  2. drivers/usb/typec/class.c +81 −0
  3. drivers/usb/typec/class.h +1 −0
  4. include/linux/usb/typec.h +17 −0
Documentation/ABI/testing/sysfs-class-typec+13−0
@@ -149,6 +149,19 @@ Description: · 148 unmodified lines
149149 advertise to the partner. The currently used capabilities are in
150150 brackets. Selection happens by writing to the file.
151151
152+What: /sys/class/typec/<port>/usb_capability
153+Date: November 2024
154+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
155+Description: Lists the supported USB Modes. The default USB mode that is used
156+ next time with the Enter_USB Message is in brackets. The default
157+ mode can be changed by writing to the file when supported by the
158+ driver.
159+
160+ Valid values:
161+ - usb2 (USB 2.0)
162+ - usb3 (USB 3.2)
163+ - usb4 (USB4)
164+
152165 USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
153166
154167 What: /sys/class/typec/<port>-partner/accessory_mode
drivers/usb/typec/class.c+81−0
@@ -219,6 +219,13 @@ static ssize_t usb_power_delivery_revision_show(struct device *dev, · 218 unmodified lines
219219 char *buf);
220220 static DEVICE_ATTR_RO(usb_power_delivery_revision);
221221
222+static const char * const usb_modes[] = {
223+ [USB_MODE_NONE] = "none",
224+ [USB_MODE_USB2] = "usb2",
225+ [USB_MODE_USB3] = "usb3",
226+ [USB_MODE_USB4] = "usb4"
227+};
228+
222229 /* ------------------------------------------------------------------------- */
223230 /* Alternate Modes */
224231
@@ -1289,6 +1296,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable); · 1064 unmodified lines
12891296 /* ------------------------------------------------------------------------- */
12901297 /* USB Type-C ports */
12911298
1299+/**
1300+ * typec_port_set_usb_mode - Set the operational USB mode for the port
1301+ * @port: USB Type-C port
1302+ * @mode: USB Mode (USB2, USB3 or USB4)
1303+ *
1304+ * @mode will be used with the next Enter_USB message. Existing connections are
1305+ * not affected.
1306+ */
1307+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode)
1308+{
1309+ port->usb_mode = mode;
1310+}
1311+EXPORT_SYMBOL_GPL(typec_port_set_usb_mode);
1312+
1313+static ssize_t
1314+usb_capability_show(struct device *dev, struct device_attribute *attr, char *buf)
1315+{
1316+ struct typec_port *port = to_typec_port(dev);
1317+ int len = 0;
1318+ int i;
1319+
1320+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
1321+ if (!(BIT(i - 1) & port->cap->usb_capability))
1322+ continue;
1323+
1324+ if (i == port->usb_mode)
1325+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
1326+ else
1327+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
1328+ }
1329+
1330+ sysfs_emit_at(buf, len - 1, "\n");
1331+
1332+ return len;
1333+}
1334+
1335+static ssize_t
1336+usb_capability_store(struct device *dev, struct device_attribute *attr,
1337+ const char *buf, size_t size)
1338+{
1339+ struct typec_port *port = to_typec_port(dev);
1340+ int ret = 0;
1341+ int mode;
1342+
1343+ if (!port->ops || !port->ops->default_usb_mode_set)
1344+ return -EOPNOTSUPP;
1345+
1346+ mode = sysfs_match_string(usb_modes, buf);
1347+ if (mode < 0)
1348+ return mode;
1349+
1350+ ret = port->ops->default_usb_mode_set(port, mode);
1351+ if (ret)
1352+ return ret;
1353+
1354+ port->usb_mode = mode;
1355+
1356+ return size;
1357+}
1358+static DEVICE_ATTR_RW(usb_capability);
1359+
12921360 /**
12931361 * typec_port_set_usb_power_delivery - Assign USB PD for port.
12941362 * @port: USB Type-C port.
@@ -1757,6 +1825,7 @@ static struct attribute *typec_attrs[] = { · 462 unmodified lines
17571825 &dev_attr_vconn_source.attr,
17581826 &dev_attr_port_type.attr,
17591827 &dev_attr_orientation.attr,
1828+ &dev_attr_usb_capability.attr,
17601829 NULL,
17611830 };
17621831
@@ -1790,6 +1859,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj, · 27 unmodified lines
17901859 if (port->cap->orientation_aware)
17911860 return 0444;
17921861 return 0;
1862+ } else if (attr == &dev_attr_usb_capability.attr) {
1863+ if (!port->cap->usb_capability)
1864+ return 0;
1865+ if (!port->ops || !port->ops->default_usb_mode_set)
1866+ return 0444;
17931867 }
17941868
17951869 return attr->mode;
@@ -2428,6 +2502,13 @@ struct typec_port *typec_register_port(struct device *parent, · 632 unmodified lines
24282502 port->con.attach = typec_partner_attach;
24292503 port->con.deattach = typec_partner_deattach;
24302504
2505+ if (cap->usb_capability & USB_CAPABILITY_USB4)
2506+ port->usb_mode = USB_MODE_USB4;
2507+ else if (cap->usb_capability & USB_CAPABILITY_USB3)
2508+ port->usb_mode = USB_MODE_USB3;
2509+ else if (cap->usb_capability & USB_CAPABILITY_USB2)
2510+ port->usb_mode = USB_MODE_USB2;
2511+
24312512 device_initialize(&port->dev);
24322513 port->dev.class = &typec_class;
24332514 port->dev.parent = parent;
drivers/usb/typec/class.h+1−0
@@ -55,6 +55,7 @@ struct typec_port { · 54 unmodified lines
5555 enum typec_role vconn_role;
5656 enum typec_pwr_opmode pwr_opmode;
5757 enum typec_port_type port_type;
58+ enum usb_mode usb_mode;
5859 struct mutex port_type_lock;
5960
6061 enum typec_orientation orientation;
include/linux/usb/typec.h+17−0
@@ -87,6 +87,17 @@ enum typec_orientation { · 86 unmodified lines
8787 TYPEC_ORIENTATION_REVERSE,
8888 };
8989
90+enum usb_mode {
91+ USB_MODE_NONE,
92+ USB_MODE_USB2,
93+ USB_MODE_USB3,
94+ USB_MODE_USB4
95+};
96+
97+#define USB_CAPABILITY_USB2 BIT(0)
98+#define USB_CAPABILITY_USB3 BIT(1)
99+#define USB_CAPABILITY_USB4 BIT(2)
100+
90101 /*
91102 * struct enter_usb_data - Enter_USB Message details
92103 * @eudo: Enter_USB Data Object
@@ -240,6 +251,7 @@ struct typec_partner_desc { · 147 unmodified lines
240251 * @port_type_set: Set port type
241252 * @pd_get: Get available USB Power Delivery Capabilities.
242253 * @pd_set: Set USB Power Delivery Capabilities.
254+ * @default_usb_mode_set: USB Mode to be used by default with Enter_USB Message
243255 */
244256 struct typec_operations {
245257 int (*try_role)(struct typec_port *port, int role);
@@ -250,6 +262,7 @@ struct typec_operations { · 4 unmodified lines
250262 enum typec_port_type type);
251263 struct usb_power_delivery **(*pd_get)(struct typec_port *port);
252264 int (*pd_set)(struct typec_port *port, struct usb_power_delivery *pd);
265+ int (*default_usb_mode_set)(struct typec_port *port, enum usb_mode mode);
253266 };
254267
255268 enum usb_pd_svdm_ver {
@@ -267,6 +280,7 @@ enum usb_pd_svdm_ver { · 11 unmodified lines
267280 * @svdm_version: USB PD Structured VDM version if supported
268281 * @prefer_role: Initial role preference (DRP ports).
269282 * @accessory: Supported Accessory Modes
283+ * @usb_capability: Supported USB Modes
270284 * @fwnode: Optional fwnode of the port
271285 * @driver_data: Private pointer for driver specific info
272286 * @pd: Optional USB Power Delivery Support
@@ -283,6 +297,7 @@ struct typec_capability { · 10 unmodified lines
283297 int prefer_role;
284298 enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
285299 unsigned int orientation_aware:1;
300+ u8 usb_capability;
286301
287302 struct fwnode_handle *fwnode;
288303 void *driver_data;
@@ -350,6 +365,8 @@ int typec_port_set_usb_power_delivery(struct typec_port *port, struct usb_power_ · 61 unmodified lines
350365 int typec_partner_set_usb_power_delivery(struct typec_partner *partner,
351366 struct usb_power_delivery *pd);
352367
368+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode);
369+
353370 /**
354371 * struct typec_connector - Representation of Type-C port for external drivers
355372 * @attach: notification about device removal