| .. | .. |
|---|
| 15 | 15 | #include <linux/usb/of.h> |
|---|
| 16 | 16 | #include <linux/usb/otg.h> |
|---|
| 17 | 17 | #include <linux/of_platform.h> |
|---|
| 18 | +#include <linux/debugfs.h> |
|---|
| 19 | +#include "common.h" |
|---|
| 20 | + |
|---|
| 21 | +static const char *const ep_type_names[] = { |
|---|
| 22 | + [USB_ENDPOINT_XFER_CONTROL] = "ctrl", |
|---|
| 23 | + [USB_ENDPOINT_XFER_ISOC] = "isoc", |
|---|
| 24 | + [USB_ENDPOINT_XFER_BULK] = "bulk", |
|---|
| 25 | + [USB_ENDPOINT_XFER_INT] = "intr", |
|---|
| 26 | +}; |
|---|
| 27 | + |
|---|
| 28 | +/** |
|---|
| 29 | + * usb_ep_type_string() - Returns human readable-name of the endpoint type. |
|---|
| 30 | + * @ep_type: The endpoint type to return human-readable name for. If it's not |
|---|
| 31 | + * any of the types: USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT}, |
|---|
| 32 | + * usually got by usb_endpoint_type(), the string 'unknown' will be returned. |
|---|
| 33 | + */ |
|---|
| 34 | +const char *usb_ep_type_string(int ep_type) |
|---|
| 35 | +{ |
|---|
| 36 | + if (ep_type < 0 || ep_type >= ARRAY_SIZE(ep_type_names)) |
|---|
| 37 | + return "unknown"; |
|---|
| 38 | + |
|---|
| 39 | + return ep_type_names[ep_type]; |
|---|
| 40 | +} |
|---|
| 41 | +EXPORT_SYMBOL_GPL(usb_ep_type_string); |
|---|
| 18 | 42 | |
|---|
| 19 | 43 | const char *usb_otg_state_string(enum usb_otg_state state) |
|---|
| 20 | 44 | { |
|---|
| .. | .. |
|---|
| 51 | 75 | [USB_SPEED_SUPER_PLUS] = "super-speed-plus", |
|---|
| 52 | 76 | }; |
|---|
| 53 | 77 | |
|---|
| 78 | +static const char *const ssp_rate[] = { |
|---|
| 79 | + [USB_SSP_GEN_UNKNOWN] = "UNKNOWN", |
|---|
| 80 | + [USB_SSP_GEN_2x1] = "super-speed-plus-gen2x1", |
|---|
| 81 | + [USB_SSP_GEN_1x2] = "super-speed-plus-gen1x2", |
|---|
| 82 | + [USB_SSP_GEN_2x2] = "super-speed-plus-gen2x2", |
|---|
| 83 | +}; |
|---|
| 84 | + |
|---|
| 85 | +/** |
|---|
| 86 | + * usb_speed_string() - Returns human readable-name of the speed. |
|---|
| 87 | + * @speed: The speed to return human-readable name for. If it's not |
|---|
| 88 | + * any of the speeds defined in usb_device_speed enum, string for |
|---|
| 89 | + * USB_SPEED_UNKNOWN will be returned. |
|---|
| 90 | + */ |
|---|
| 54 | 91 | const char *usb_speed_string(enum usb_device_speed speed) |
|---|
| 55 | 92 | { |
|---|
| 56 | 93 | if (speed < 0 || speed >= ARRAY_SIZE(speed_names)) |
|---|
| .. | .. |
|---|
| 59 | 96 | } |
|---|
| 60 | 97 | EXPORT_SYMBOL_GPL(usb_speed_string); |
|---|
| 61 | 98 | |
|---|
| 99 | +/** |
|---|
| 100 | + * usb_get_maximum_speed - Get maximum requested speed for a given USB |
|---|
| 101 | + * controller. |
|---|
| 102 | + * @dev: Pointer to the given USB controller device |
|---|
| 103 | + * |
|---|
| 104 | + * The function gets the maximum speed string from property "maximum-speed", |
|---|
| 105 | + * and returns the corresponding enum usb_device_speed. |
|---|
| 106 | + */ |
|---|
| 62 | 107 | enum usb_device_speed usb_get_maximum_speed(struct device *dev) |
|---|
| 63 | 108 | { |
|---|
| 64 | 109 | const char *maximum_speed; |
|---|
| .. | .. |
|---|
| 68 | 113 | if (ret < 0) |
|---|
| 69 | 114 | return USB_SPEED_UNKNOWN; |
|---|
| 70 | 115 | |
|---|
| 71 | | - ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed); |
|---|
| 116 | + ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed); |
|---|
| 117 | + if (ret > 0) |
|---|
| 118 | + return USB_SPEED_SUPER_PLUS; |
|---|
| 72 | 119 | |
|---|
| 120 | + ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed); |
|---|
| 73 | 121 | return (ret < 0) ? USB_SPEED_UNKNOWN : ret; |
|---|
| 74 | 122 | } |
|---|
| 75 | 123 | EXPORT_SYMBOL_GPL(usb_get_maximum_speed); |
|---|
| 76 | 124 | |
|---|
| 125 | +/** |
|---|
| 126 | + * usb_get_maximum_ssp_rate - Get the signaling rate generation and lane count |
|---|
| 127 | + * of a SuperSpeed Plus capable device. |
|---|
| 128 | + * @dev: Pointer to the given USB controller device |
|---|
| 129 | + * |
|---|
| 130 | + * If the string from "maximum-speed" property is super-speed-plus-genXxY where |
|---|
| 131 | + * 'X' is the generation number and 'Y' is the number of lanes, then this |
|---|
| 132 | + * function returns the corresponding enum usb_ssp_rate. |
|---|
| 133 | + */ |
|---|
| 134 | +enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev) |
|---|
| 135 | +{ |
|---|
| 136 | + const char *maximum_speed; |
|---|
| 137 | + int ret; |
|---|
| 138 | + |
|---|
| 139 | + ret = device_property_read_string(dev, "maximum-speed", &maximum_speed); |
|---|
| 140 | + if (ret < 0) |
|---|
| 141 | + return USB_SSP_GEN_UNKNOWN; |
|---|
| 142 | + |
|---|
| 143 | + ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed); |
|---|
| 144 | + return (ret < 0) ? USB_SSP_GEN_UNKNOWN : ret; |
|---|
| 145 | +} |
|---|
| 146 | +EXPORT_SYMBOL_GPL(usb_get_maximum_ssp_rate); |
|---|
| 147 | + |
|---|
| 148 | +/** |
|---|
| 149 | + * usb_state_string - Returns human readable name for the state. |
|---|
| 150 | + * @state: The state to return a human-readable name for. If it's not |
|---|
| 151 | + * any of the states devices in usb_device_state_string enum, |
|---|
| 152 | + * the string UNKNOWN will be returned. |
|---|
| 153 | + */ |
|---|
| 77 | 154 | const char *usb_state_string(enum usb_device_state state) |
|---|
| 78 | 155 | { |
|---|
| 79 | 156 | static const char *const names[] = { |
|---|
| .. | .. |
|---|
| 100 | 177 | [USB_DR_MODE_HOST] = "host", |
|---|
| 101 | 178 | [USB_DR_MODE_PERIPHERAL] = "peripheral", |
|---|
| 102 | 179 | [USB_DR_MODE_OTG] = "otg", |
|---|
| 103 | | - [USB_DR_MODE_DRD] = "drd", |
|---|
| 104 | 180 | }; |
|---|
| 105 | 181 | |
|---|
| 106 | 182 | static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str) |
|---|
| .. | .. |
|---|
| 123 | 199 | return usb_get_dr_mode_from_string(dr_mode); |
|---|
| 124 | 200 | } |
|---|
| 125 | 201 | EXPORT_SYMBOL_GPL(usb_get_dr_mode); |
|---|
| 202 | + |
|---|
| 203 | +/** |
|---|
| 204 | + * usb_decode_interval - Decode bInterval into the time expressed in 1us unit |
|---|
| 205 | + * @epd: The descriptor of the endpoint |
|---|
| 206 | + * @speed: The speed that the endpoint works as |
|---|
| 207 | + * |
|---|
| 208 | + * Function returns the interval expressed in 1us unit for servicing |
|---|
| 209 | + * endpoint for data transfers. |
|---|
| 210 | + */ |
|---|
| 211 | +unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd, |
|---|
| 212 | + enum usb_device_speed speed) |
|---|
| 213 | +{ |
|---|
| 214 | + unsigned int interval = 0; |
|---|
| 215 | + |
|---|
| 216 | + switch (usb_endpoint_type(epd)) { |
|---|
| 217 | + case USB_ENDPOINT_XFER_CONTROL: |
|---|
| 218 | + /* uframes per NAK */ |
|---|
| 219 | + if (speed == USB_SPEED_HIGH) |
|---|
| 220 | + interval = epd->bInterval; |
|---|
| 221 | + break; |
|---|
| 222 | + case USB_ENDPOINT_XFER_ISOC: |
|---|
| 223 | + interval = 1 << (epd->bInterval - 1); |
|---|
| 224 | + break; |
|---|
| 225 | + case USB_ENDPOINT_XFER_BULK: |
|---|
| 226 | + /* uframes per NAK */ |
|---|
| 227 | + if (speed == USB_SPEED_HIGH && usb_endpoint_dir_out(epd)) |
|---|
| 228 | + interval = epd->bInterval; |
|---|
| 229 | + break; |
|---|
| 230 | + case USB_ENDPOINT_XFER_INT: |
|---|
| 231 | + if (speed >= USB_SPEED_HIGH) |
|---|
| 232 | + interval = 1 << (epd->bInterval - 1); |
|---|
| 233 | + else |
|---|
| 234 | + interval = epd->bInterval; |
|---|
| 235 | + break; |
|---|
| 236 | + } |
|---|
| 237 | + |
|---|
| 238 | + interval *= (speed >= USB_SPEED_HIGH) ? 125 : 1000; |
|---|
| 239 | + |
|---|
| 240 | + return interval; |
|---|
| 241 | +} |
|---|
| 242 | +EXPORT_SYMBOL_GPL(usb_decode_interval); |
|---|
| 126 | 243 | |
|---|
| 127 | 244 | #ifdef CONFIG_OF |
|---|
| 128 | 245 | /** |
|---|
| .. | .. |
|---|
| 276 | 393 | EXPORT_SYMBOL_GPL(usb_of_get_companion_dev); |
|---|
| 277 | 394 | #endif |
|---|
| 278 | 395 | |
|---|
| 396 | +struct dentry *usb_debug_root; |
|---|
| 397 | +EXPORT_SYMBOL_GPL(usb_debug_root); |
|---|
| 398 | + |
|---|
| 399 | +static int __init usb_common_init(void) |
|---|
| 400 | +{ |
|---|
| 401 | + usb_debug_root = debugfs_create_dir("usb", NULL); |
|---|
| 402 | + ledtrig_usb_init(); |
|---|
| 403 | + return 0; |
|---|
| 404 | +} |
|---|
| 405 | + |
|---|
| 406 | +static void __exit usb_common_exit(void) |
|---|
| 407 | +{ |
|---|
| 408 | + ledtrig_usb_exit(); |
|---|
| 409 | + debugfs_remove_recursive(usb_debug_root); |
|---|
| 410 | +} |
|---|
| 411 | + |
|---|
| 412 | +subsys_initcall(usb_common_init); |
|---|
| 413 | +module_exit(usb_common_exit); |
|---|
| 414 | + |
|---|
| 279 | 415 | MODULE_LICENSE("GPL"); |
|---|