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
149 advertise to the partner. The currently used capabilities are in149 advertise to the partner. The currently used capabilities are in
150 brackets. Selection happens by writing to the file.150 brackets. Selection happens by writing to the file.
151 151
152What: /sys/class/typec/<port>/usb_capability
153Date: November 2024
154Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
155Description: 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
152USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)165USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
153 166
154What: /sys/class/typec/<port>-partner/accessory_mode167What: /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
219 char *buf);219 char *buf);
220static DEVICE_ATTR_RO(usb_power_delivery_revision);220static DEVICE_ATTR_RO(usb_power_delivery_revision);
221 221
222static 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
222/* ------------------------------------------------------------------------- */229/* ------------------------------------------------------------------------- */
223/* Alternate Modes */230/* Alternate Modes */
224 231
@@ -1289,6 +1296,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable); · 1064 unmodified lines
1289/* ------------------------------------------------------------------------- */1296/* ------------------------------------------------------------------------- */
1290/* USB Type-C ports */1297/* USB Type-C ports */
1291 1298
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 */
1307void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode)
1308{
1309 port->usb_mode = mode;
1310}
1311EXPORT_SYMBOL_GPL(typec_port_set_usb_mode);
1312
1313static ssize_t
1314usb_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
1335static ssize_t
1336usb_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}
1358static DEVICE_ATTR_RW(usb_capability);
1359
1292/**1360/**
1293 * typec_port_set_usb_power_delivery - Assign USB PD for port.1361 * typec_port_set_usb_power_delivery - Assign USB PD for port.
1294 * @port: USB Type-C port.1362 * @port: USB Type-C port.
@@ -1757,6 +1825,7 @@ static struct attribute *typec_attrs[] = { · 462 unmodified lines
1757 &dev_attr_vconn_source.attr,1825 &dev_attr_vconn_source.attr,
1758 &dev_attr_port_type.attr,1826 &dev_attr_port_type.attr,
1759 &dev_attr_orientation.attr,1827 &dev_attr_orientation.attr,
1828 &dev_attr_usb_capability.attr,
1760 NULL,1829 NULL,
1761};1830};
1762 1831
@@ -1790,6 +1859,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj, · 27 unmodified lines
1790 if (port->cap->orientation_aware)1859 if (port->cap->orientation_aware)
1791 return 0444;1860 return 0444;
1792 return 0;1861 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;
1793 }1867 }
1794 1868
1795 return attr->mode;1869 return attr->mode;
@@ -2428,6 +2502,13 @@ struct typec_port *typec_register_port(struct device *parent, · 632 unmodified lines
2428 port->con.attach = typec_partner_attach;2502 port->con.attach = typec_partner_attach;
2429 port->con.deattach = typec_partner_deattach;2503 port->con.deattach = typec_partner_deattach;
2430 2504
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
2431 device_initialize(&port->dev);2512 device_initialize(&port->dev);
2432 port->dev.class = &typec_class;2513 port->dev.class = &typec_class;
2433 port->dev.parent = parent;2514 port->dev.parent = parent;
drivers/usb/typec/class.h+1−0
@@ -55,6 +55,7 @@ struct typec_port { · 54 unmodified lines
55 enum typec_role vconn_role;55 enum typec_role vconn_role;
56 enum typec_pwr_opmode pwr_opmode;56 enum typec_pwr_opmode pwr_opmode;
57 enum typec_port_type port_type;57 enum typec_port_type port_type;
58 enum usb_mode usb_mode;
58 struct mutex port_type_lock;59 struct mutex port_type_lock;
59 60
60 enum typec_orientation orientation;61 enum typec_orientation orientation;
include/linux/usb/typec.h+17−0
@@ -87,6 +87,17 @@ enum typec_orientation { · 86 unmodified lines
87 TYPEC_ORIENTATION_REVERSE,87 TYPEC_ORIENTATION_REVERSE,
88};88};
89 89
90enum 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
90/*101/*
91 * struct enter_usb_data - Enter_USB Message details102 * struct enter_usb_data - Enter_USB Message details
92 * @eudo: Enter_USB Data Object103 * @eudo: Enter_USB Data Object
@@ -240,6 +251,7 @@ struct typec_partner_desc { · 147 unmodified lines
240 * @port_type_set: Set port type251 * @port_type_set: Set port type
241 * @pd_get: Get available USB Power Delivery Capabilities.252 * @pd_get: Get available USB Power Delivery Capabilities.
242 * @pd_set: Set USB Power Delivery Capabilities.253 * @pd_set: Set USB Power Delivery Capabilities.
254 * @default_usb_mode_set: USB Mode to be used by default with Enter_USB Message
243 */255 */
244struct typec_operations {256struct typec_operations {
245 int (*try_role)(struct typec_port *port, int role);257 int (*try_role)(struct typec_port *port, int role);
@@ -250,6 +262,7 @@ struct typec_operations { · 4 unmodified lines
250 enum typec_port_type type);262 enum typec_port_type type);
251 struct usb_power_delivery **(*pd_get)(struct typec_port *port);263 struct usb_power_delivery **(*pd_get)(struct typec_port *port);
252 int (*pd_set)(struct typec_port *port, struct usb_power_delivery *pd);264 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);
253};266};
254 267
255enum usb_pd_svdm_ver {268enum usb_pd_svdm_ver {
@@ -267,6 +280,7 @@ enum usb_pd_svdm_ver { · 11 unmodified lines
267 * @svdm_version: USB PD Structured VDM version if supported280 * @svdm_version: USB PD Structured VDM version if supported
268 * @prefer_role: Initial role preference (DRP ports).281 * @prefer_role: Initial role preference (DRP ports).
269 * @accessory: Supported Accessory Modes282 * @accessory: Supported Accessory Modes
283 * @usb_capability: Supported USB Modes
270 * @fwnode: Optional fwnode of the port284 * @fwnode: Optional fwnode of the port
271 * @driver_data: Private pointer for driver specific info285 * @driver_data: Private pointer for driver specific info
272 * @pd: Optional USB Power Delivery Support286 * @pd: Optional USB Power Delivery Support
@@ -283,6 +297,7 @@ struct typec_capability { · 10 unmodified lines
283 int prefer_role;297 int prefer_role;
284 enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];298 enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
285 unsigned int orientation_aware:1;299 unsigned int orientation_aware:1;
300 u8 usb_capability;
286 301
287 struct fwnode_handle *fwnode;302 struct fwnode_handle *fwnode;
288 void *driver_data;303 void *driver_data;
@@ -350,6 +365,8 @@ int typec_port_set_usb_power_delivery(struct typec_port *port, struct usb_power_ · 61 unmodified lines
350int typec_partner_set_usb_power_delivery(struct typec_partner *partner,365int typec_partner_set_usb_power_delivery(struct typec_partner *partner,
351 struct usb_power_delivery *pd);366 struct usb_power_delivery *pd);
352 367
368void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode);
369
353/**370/**
354 * struct typec_connector - Representation of Type-C port for external drivers371 * struct typec_connector - Representation of Type-C port for external drivers
355 * @attach: notification about device removal372 * @attach: notification about device removal