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.
Unified · Split
| @@ -149,6 +149,19 @@ Description: · 148 unmodified lines | ||
| 149 | 149 | advertise to the partner. The currently used capabilities are in |
| 150 | 150 | brackets. Selection happens by writing to the file. |
| 151 | 151 | |
| 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 | + | |
| 152 | 165 | USB Type-C partner devices (eg. /sys/class/typec/port0-partner/) |
| 153 | 166 | |
| 154 | 167 | What: /sys/class/typec/<port>-partner/accessory_mode |
| @@ -219,6 +219,13 @@ static ssize_t usb_power_delivery_revision_show(struct device *dev, · 218 unmodified lines | ||
| 219 | 219 | char *buf); |
| 220 | 220 | static DEVICE_ATTR_RO(usb_power_delivery_revision); |
| 221 | 221 | |
| 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 | + | |
| 222 | 229 | /* ------------------------------------------------------------------------- */ |
| 223 | 230 | /* Alternate Modes */ |
| 224 | 231 | |
| @@ -1289,6 +1296,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable); · 1064 unmodified lines | ||
| 1289 | 1296 | /* ------------------------------------------------------------------------- */ |
| 1290 | 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 | + */ | |
| 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 | + | |
| 1292 | 1360 | /** |
| 1293 | 1361 | * typec_port_set_usb_power_delivery - Assign USB PD for port. |
| 1294 | 1362 | * @port: USB Type-C port. |
| @@ -1757,6 +1825,7 @@ static struct attribute *typec_attrs[] = { · 462 unmodified lines | ||
| 1757 | 1825 | &dev_attr_vconn_source.attr, |
| 1758 | 1826 | &dev_attr_port_type.attr, |
| 1759 | 1827 | &dev_attr_orientation.attr, |
| 1828 | + &dev_attr_usb_capability.attr, | |
| 1760 | 1829 | NULL, |
| 1761 | 1830 | }; |
| 1762 | 1831 | |
| @@ -1790,6 +1859,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj, · 27 unmodified lines | ||
| 1790 | 1859 | if (port->cap->orientation_aware) |
| 1791 | 1860 | return 0444; |
| 1792 | 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 | 1869 | return attr->mode; |
| @@ -2428,6 +2502,13 @@ struct typec_port *typec_register_port(struct device *parent, · 632 unmodified lines | ||
| 2428 | 2502 | port->con.attach = typec_partner_attach; |
| 2429 | 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 | 2512 | device_initialize(&port->dev); |
| 2432 | 2513 | port->dev.class = &typec_class; |
| 2433 | 2514 | port->dev.parent = parent; |
| @@ -55,6 +55,7 @@ struct typec_port { · 54 unmodified lines | ||
| 55 | 55 | enum typec_role vconn_role; |
| 56 | 56 | enum typec_pwr_opmode pwr_opmode; |
| 57 | 57 | enum typec_port_type port_type; |
| 58 | + enum usb_mode usb_mode; | |
| 58 | 59 | struct mutex port_type_lock; |
| 59 | 60 | |
| 60 | 61 | enum typec_orientation orientation; |
| @@ -87,6 +87,17 @@ enum typec_orientation { · 86 unmodified lines | ||
| 87 | 87 | TYPEC_ORIENTATION_REVERSE, |
| 88 | 88 | }; |
| 89 | 89 | |
| 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 | + | |
| 90 | 101 | /* |
| 91 | 102 | * struct enter_usb_data - Enter_USB Message details |
| 92 | 103 | * @eudo: Enter_USB Data Object |
| @@ -240,6 +251,7 @@ struct typec_partner_desc { · 147 unmodified lines | ||
| 240 | 251 | * @port_type_set: Set port type |
| 241 | 252 | * @pd_get: Get available USB Power Delivery Capabilities. |
| 242 | 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 | */ |
| 244 | 256 | struct typec_operations { |
| 245 | 257 | int (*try_role)(struct typec_port *port, int role); |
| @@ -250,6 +262,7 @@ struct typec_operations { · 4 unmodified lines | ||
| 250 | 262 | enum typec_port_type type); |
| 251 | 263 | struct usb_power_delivery **(*pd_get)(struct typec_port *port); |
| 252 | 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 | |
| 255 | 268 | enum usb_pd_svdm_ver { |
| @@ -267,6 +280,7 @@ enum usb_pd_svdm_ver { · 11 unmodified lines | ||
| 267 | 280 | * @svdm_version: USB PD Structured VDM version if supported |
| 268 | 281 | * @prefer_role: Initial role preference (DRP ports). |
| 269 | 282 | * @accessory: Supported Accessory Modes |
| 283 | + * @usb_capability: Supported USB Modes | |
| 270 | 284 | * @fwnode: Optional fwnode of the port |
| 271 | 285 | * @driver_data: Private pointer for driver specific info |
| 272 | 286 | * @pd: Optional USB Power Delivery Support |
| @@ -283,6 +297,7 @@ struct typec_capability { · 10 unmodified lines | ||
| 283 | 297 | int prefer_role; |
| 284 | 298 | enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; |
| 285 | 299 | unsigned int orientation_aware:1; |
| 300 | + u8 usb_capability; | |
| 286 | 301 | |
| 287 | 302 | struct fwnode_handle *fwnode; |
| 288 | 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 | ||
| 350 | 365 | int typec_partner_set_usb_power_delivery(struct typec_partner *partner, |
| 351 | 366 | struct usb_power_delivery *pd); |
| 352 | 367 | |
| 368 | +void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode); | |
| 369 | + | |
| 353 | 370 | /** |
| 354 | 371 | * struct typec_connector - Representation of Type-C port for external drivers |
| 355 | 372 | * @attach: notification about device removal |