12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2001 32e192b24SSimon Glass * Denis Peter, MPL AG Switzerland 42e192b24SSimon Glass * 52e192b24SSimon Glass * Adapted for U-Boot driver model 62e192b24SSimon Glass * (C) Copyright 2015 Google, Inc 72e192b24SSimon Glass * 82e192b24SSimon Glass * Most of this source has been derived from the Linux USB 92e192b24SSimon Glass * project. 102e192b24SSimon Glass * 112e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 122e192b24SSimon Glass */ 132e192b24SSimon Glass 142e192b24SSimon Glass #include <common.h> 152e192b24SSimon Glass #include <command.h> 162e192b24SSimon Glass #include <console.h> 172e192b24SSimon Glass #include <dm.h> 18192eab93SHans de Goede #include <dm/uclass-internal.h> 192e192b24SSimon Glass #include <memalign.h> 202e192b24SSimon Glass #include <asm/byteorder.h> 212e192b24SSimon Glass #include <asm/unaligned.h> 222e192b24SSimon Glass #include <part.h> 232e192b24SSimon Glass #include <usb.h> 242e192b24SSimon Glass 252e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 262e192b24SSimon Glass static int usb_stor_curr_dev = -1; /* current device */ 272e192b24SSimon Glass #endif 282e192b24SSimon Glass #if defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH) 292e192b24SSimon Glass static int __maybe_unused usb_ether_curr_dev = -1; /* current ethernet device */ 302e192b24SSimon Glass #endif 312e192b24SSimon Glass 322e192b24SSimon Glass /* some display routines (info command) */ 332e192b24SSimon Glass static char *usb_get_class_desc(unsigned char dclass) 342e192b24SSimon Glass { 352e192b24SSimon Glass switch (dclass) { 362e192b24SSimon Glass case USB_CLASS_PER_INTERFACE: 372e192b24SSimon Glass return "See Interface"; 382e192b24SSimon Glass case USB_CLASS_AUDIO: 392e192b24SSimon Glass return "Audio"; 402e192b24SSimon Glass case USB_CLASS_COMM: 412e192b24SSimon Glass return "Communication"; 422e192b24SSimon Glass case USB_CLASS_HID: 432e192b24SSimon Glass return "Human Interface"; 442e192b24SSimon Glass case USB_CLASS_PRINTER: 452e192b24SSimon Glass return "Printer"; 462e192b24SSimon Glass case USB_CLASS_MASS_STORAGE: 472e192b24SSimon Glass return "Mass Storage"; 482e192b24SSimon Glass case USB_CLASS_HUB: 492e192b24SSimon Glass return "Hub"; 502e192b24SSimon Glass case USB_CLASS_DATA: 512e192b24SSimon Glass return "CDC Data"; 522e192b24SSimon Glass case USB_CLASS_VENDOR_SPEC: 532e192b24SSimon Glass return "Vendor specific"; 542e192b24SSimon Glass default: 552e192b24SSimon Glass return ""; 562e192b24SSimon Glass } 572e192b24SSimon Glass } 582e192b24SSimon Glass 592e192b24SSimon Glass static void usb_display_class_sub(unsigned char dclass, unsigned char subclass, 602e192b24SSimon Glass unsigned char proto) 612e192b24SSimon Glass { 622e192b24SSimon Glass switch (dclass) { 632e192b24SSimon Glass case USB_CLASS_PER_INTERFACE: 642e192b24SSimon Glass printf("See Interface"); 652e192b24SSimon Glass break; 662e192b24SSimon Glass case USB_CLASS_HID: 672e192b24SSimon Glass printf("Human Interface, Subclass: "); 682e192b24SSimon Glass switch (subclass) { 692e192b24SSimon Glass case USB_SUB_HID_NONE: 702e192b24SSimon Glass printf("None"); 712e192b24SSimon Glass break; 722e192b24SSimon Glass case USB_SUB_HID_BOOT: 732e192b24SSimon Glass printf("Boot "); 742e192b24SSimon Glass switch (proto) { 752e192b24SSimon Glass case USB_PROT_HID_NONE: 762e192b24SSimon Glass printf("None"); 772e192b24SSimon Glass break; 782e192b24SSimon Glass case USB_PROT_HID_KEYBOARD: 792e192b24SSimon Glass printf("Keyboard"); 802e192b24SSimon Glass break; 812e192b24SSimon Glass case USB_PROT_HID_MOUSE: 822e192b24SSimon Glass printf("Mouse"); 832e192b24SSimon Glass break; 842e192b24SSimon Glass default: 852e192b24SSimon Glass printf("reserved"); 862e192b24SSimon Glass break; 872e192b24SSimon Glass } 882e192b24SSimon Glass break; 892e192b24SSimon Glass default: 902e192b24SSimon Glass printf("reserved"); 912e192b24SSimon Glass break; 922e192b24SSimon Glass } 932e192b24SSimon Glass break; 942e192b24SSimon Glass case USB_CLASS_MASS_STORAGE: 952e192b24SSimon Glass printf("Mass Storage, "); 962e192b24SSimon Glass switch (subclass) { 972e192b24SSimon Glass case US_SC_RBC: 982e192b24SSimon Glass printf("RBC "); 992e192b24SSimon Glass break; 1002e192b24SSimon Glass case US_SC_8020: 1012e192b24SSimon Glass printf("SFF-8020i (ATAPI)"); 1022e192b24SSimon Glass break; 1032e192b24SSimon Glass case US_SC_QIC: 1042e192b24SSimon Glass printf("QIC-157 (Tape)"); 1052e192b24SSimon Glass break; 1062e192b24SSimon Glass case US_SC_UFI: 1072e192b24SSimon Glass printf("UFI"); 1082e192b24SSimon Glass break; 1092e192b24SSimon Glass case US_SC_8070: 1102e192b24SSimon Glass printf("SFF-8070"); 1112e192b24SSimon Glass break; 1122e192b24SSimon Glass case US_SC_SCSI: 1132e192b24SSimon Glass printf("Transp. SCSI"); 1142e192b24SSimon Glass break; 1152e192b24SSimon Glass default: 1162e192b24SSimon Glass printf("reserved"); 1172e192b24SSimon Glass break; 1182e192b24SSimon Glass } 1192e192b24SSimon Glass printf(", "); 1202e192b24SSimon Glass switch (proto) { 1212e192b24SSimon Glass case US_PR_CB: 1222e192b24SSimon Glass printf("Command/Bulk"); 1232e192b24SSimon Glass break; 1242e192b24SSimon Glass case US_PR_CBI: 1252e192b24SSimon Glass printf("Command/Bulk/Int"); 1262e192b24SSimon Glass break; 1272e192b24SSimon Glass case US_PR_BULK: 1282e192b24SSimon Glass printf("Bulk only"); 1292e192b24SSimon Glass break; 1302e192b24SSimon Glass default: 1312e192b24SSimon Glass printf("reserved"); 1322e192b24SSimon Glass break; 1332e192b24SSimon Glass } 1342e192b24SSimon Glass break; 1352e192b24SSimon Glass default: 1362e192b24SSimon Glass printf("%s", usb_get_class_desc(dclass)); 1372e192b24SSimon Glass break; 1382e192b24SSimon Glass } 1392e192b24SSimon Glass } 1402e192b24SSimon Glass 1412e192b24SSimon Glass static void usb_display_string(struct usb_device *dev, int index) 1422e192b24SSimon Glass { 1432e192b24SSimon Glass ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256); 1442e192b24SSimon Glass 1452e192b24SSimon Glass if (index != 0) { 1462e192b24SSimon Glass if (usb_string(dev, index, &buffer[0], 256) > 0) 1472e192b24SSimon Glass printf("String: \"%s\"", buffer); 1482e192b24SSimon Glass } 1492e192b24SSimon Glass } 1502e192b24SSimon Glass 1512e192b24SSimon Glass static void usb_display_desc(struct usb_device *dev) 1522e192b24SSimon Glass { 1532e192b24SSimon Glass if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { 1542e192b24SSimon Glass printf("%d: %s, USB Revision %x.%x\n", dev->devnum, 1552e192b24SSimon Glass usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass), 1562e192b24SSimon Glass (dev->descriptor.bcdUSB>>8) & 0xff, 1572e192b24SSimon Glass dev->descriptor.bcdUSB & 0xff); 1582e192b24SSimon Glass 1592e192b24SSimon Glass if (strlen(dev->mf) || strlen(dev->prod) || 1602e192b24SSimon Glass strlen(dev->serial)) 1612e192b24SSimon Glass printf(" - %s %s %s\n", dev->mf, dev->prod, 1622e192b24SSimon Glass dev->serial); 1632e192b24SSimon Glass if (dev->descriptor.bDeviceClass) { 1642e192b24SSimon Glass printf(" - Class: "); 1652e192b24SSimon Glass usb_display_class_sub(dev->descriptor.bDeviceClass, 1662e192b24SSimon Glass dev->descriptor.bDeviceSubClass, 1672e192b24SSimon Glass dev->descriptor.bDeviceProtocol); 1682e192b24SSimon Glass printf("\n"); 1692e192b24SSimon Glass } else { 1702e192b24SSimon Glass printf(" - Class: (from Interface) %s\n", 1712e192b24SSimon Glass usb_get_class_desc( 1722e192b24SSimon Glass dev->config.if_desc[0].desc.bInterfaceClass)); 1732e192b24SSimon Glass } 1742e192b24SSimon Glass printf(" - PacketSize: %d Configurations: %d\n", 1752e192b24SSimon Glass dev->descriptor.bMaxPacketSize0, 1762e192b24SSimon Glass dev->descriptor.bNumConfigurations); 1772e192b24SSimon Glass printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n", 1782e192b24SSimon Glass dev->descriptor.idVendor, dev->descriptor.idProduct, 1792e192b24SSimon Glass (dev->descriptor.bcdDevice>>8) & 0xff, 1802e192b24SSimon Glass dev->descriptor.bcdDevice & 0xff); 1812e192b24SSimon Glass } 1822e192b24SSimon Glass 1832e192b24SSimon Glass } 1842e192b24SSimon Glass 1852e192b24SSimon Glass static void usb_display_conf_desc(struct usb_config_descriptor *config, 1862e192b24SSimon Glass struct usb_device *dev) 1872e192b24SSimon Glass { 1882e192b24SSimon Glass printf(" Configuration: %d\n", config->bConfigurationValue); 1892e192b24SSimon Glass printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces, 1902e192b24SSimon Glass (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ", 1912e192b24SSimon Glass (config->bmAttributes & 0x20) ? "Remote Wakeup " : "", 1922e192b24SSimon Glass config->bMaxPower*2); 1932e192b24SSimon Glass if (config->iConfiguration) { 1942e192b24SSimon Glass printf(" - "); 1952e192b24SSimon Glass usb_display_string(dev, config->iConfiguration); 1962e192b24SSimon Glass printf("\n"); 1972e192b24SSimon Glass } 1982e192b24SSimon Glass } 1992e192b24SSimon Glass 2002e192b24SSimon Glass static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, 2012e192b24SSimon Glass struct usb_device *dev) 2022e192b24SSimon Glass { 2032e192b24SSimon Glass printf(" Interface: %d\n", ifdesc->bInterfaceNumber); 2042e192b24SSimon Glass printf(" - Alternate Setting %d, Endpoints: %d\n", 2052e192b24SSimon Glass ifdesc->bAlternateSetting, ifdesc->bNumEndpoints); 2062e192b24SSimon Glass printf(" - Class "); 2072e192b24SSimon Glass usb_display_class_sub(ifdesc->bInterfaceClass, 2082e192b24SSimon Glass ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol); 2092e192b24SSimon Glass printf("\n"); 2102e192b24SSimon Glass if (ifdesc->iInterface) { 2112e192b24SSimon Glass printf(" - "); 2122e192b24SSimon Glass usb_display_string(dev, ifdesc->iInterface); 2132e192b24SSimon Glass printf("\n"); 2142e192b24SSimon Glass } 2152e192b24SSimon Glass } 2162e192b24SSimon Glass 2172e192b24SSimon Glass static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) 2182e192b24SSimon Glass { 2192e192b24SSimon Glass printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf, 2202e192b24SSimon Glass (epdesc->bEndpointAddress & 0x80) ? "In" : "Out"); 2212e192b24SSimon Glass switch ((epdesc->bmAttributes & 0x03)) { 2222e192b24SSimon Glass case 0: 2232e192b24SSimon Glass printf("Control"); 2242e192b24SSimon Glass break; 2252e192b24SSimon Glass case 1: 2262e192b24SSimon Glass printf("Isochronous"); 2272e192b24SSimon Glass break; 2282e192b24SSimon Glass case 2: 2292e192b24SSimon Glass printf("Bulk"); 2302e192b24SSimon Glass break; 2312e192b24SSimon Glass case 3: 2322e192b24SSimon Glass printf("Interrupt"); 2332e192b24SSimon Glass break; 2342e192b24SSimon Glass } 2352e192b24SSimon Glass printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize)); 2362e192b24SSimon Glass if ((epdesc->bmAttributes & 0x03) == 0x3) 2372e192b24SSimon Glass printf(" Interval %dms", epdesc->bInterval); 2382e192b24SSimon Glass printf("\n"); 2392e192b24SSimon Glass } 2402e192b24SSimon Glass 2412e192b24SSimon Glass /* main routine to diasplay the configs, interfaces and endpoints */ 2422e192b24SSimon Glass static void usb_display_config(struct usb_device *dev) 2432e192b24SSimon Glass { 2442e192b24SSimon Glass struct usb_config *config; 2452e192b24SSimon Glass struct usb_interface *ifdesc; 2462e192b24SSimon Glass struct usb_endpoint_descriptor *epdesc; 2472e192b24SSimon Glass int i, ii; 2482e192b24SSimon Glass 2492e192b24SSimon Glass config = &dev->config; 2502e192b24SSimon Glass usb_display_conf_desc(&config->desc, dev); 2512e192b24SSimon Glass for (i = 0; i < config->no_of_if; i++) { 2522e192b24SSimon Glass ifdesc = &config->if_desc[i]; 2532e192b24SSimon Glass usb_display_if_desc(&ifdesc->desc, dev); 2542e192b24SSimon Glass for (ii = 0; ii < ifdesc->no_of_ep; ii++) { 2552e192b24SSimon Glass epdesc = &ifdesc->ep_desc[ii]; 2562e192b24SSimon Glass usb_display_ep_desc(epdesc); 2572e192b24SSimon Glass } 2582e192b24SSimon Glass } 2592e192b24SSimon Glass printf("\n"); 2602e192b24SSimon Glass } 2612e192b24SSimon Glass 2622e192b24SSimon Glass /* 2632e192b24SSimon Glass * With driver model this isn't right since we can have multiple controllers 2642e192b24SSimon Glass * and the device numbering starts at 1 on each bus. 2652e192b24SSimon Glass * TODO(sjg@chromium.org): Add a way to specify the controller/bus. 2662e192b24SSimon Glass */ 2672e192b24SSimon Glass static struct usb_device *usb_find_device(int devnum) 2682e192b24SSimon Glass { 2692e192b24SSimon Glass #ifdef CONFIG_DM_USB 2702e192b24SSimon Glass struct usb_device *udev; 2712e192b24SSimon Glass struct udevice *hub; 2722e192b24SSimon Glass struct uclass *uc; 2732e192b24SSimon Glass int ret; 2742e192b24SSimon Glass 2752e192b24SSimon Glass /* Device addresses start at 1 */ 2762e192b24SSimon Glass devnum++; 2772e192b24SSimon Glass ret = uclass_get(UCLASS_USB_HUB, &uc); 2782e192b24SSimon Glass if (ret) 2792e192b24SSimon Glass return NULL; 2802e192b24SSimon Glass 2812e192b24SSimon Glass uclass_foreach_dev(hub, uc) { 2822e192b24SSimon Glass struct udevice *dev; 2832e192b24SSimon Glass 2842e192b24SSimon Glass if (!device_active(hub)) 2852e192b24SSimon Glass continue; 2862e192b24SSimon Glass udev = dev_get_parent_priv(hub); 2872e192b24SSimon Glass if (udev->devnum == devnum) 2882e192b24SSimon Glass return udev; 2892e192b24SSimon Glass 2902e192b24SSimon Glass for (device_find_first_child(hub, &dev); 2912e192b24SSimon Glass dev; 2922e192b24SSimon Glass device_find_next_child(&dev)) { 2932e192b24SSimon Glass if (!device_active(hub)) 2942e192b24SSimon Glass continue; 2952e192b24SSimon Glass 2962e192b24SSimon Glass udev = dev_get_parent_priv(dev); 2972e192b24SSimon Glass if (udev->devnum == devnum) 2982e192b24SSimon Glass return udev; 2992e192b24SSimon Glass } 3002e192b24SSimon Glass } 3012e192b24SSimon Glass #else 3022e192b24SSimon Glass struct usb_device *udev; 3032e192b24SSimon Glass int d; 3042e192b24SSimon Glass 3052e192b24SSimon Glass for (d = 0; d < USB_MAX_DEVICE; d++) { 3062e192b24SSimon Glass udev = usb_get_dev_index(d); 3072e192b24SSimon Glass if (udev == NULL) 3082e192b24SSimon Glass return NULL; 3092e192b24SSimon Glass if (udev->devnum == devnum) 3102e192b24SSimon Glass return udev; 3112e192b24SSimon Glass } 3122e192b24SSimon Glass #endif 3132e192b24SSimon Glass 3142e192b24SSimon Glass return NULL; 3152e192b24SSimon Glass } 3162e192b24SSimon Glass 3172e192b24SSimon Glass static inline char *portspeed(int speed) 3182e192b24SSimon Glass { 3192e192b24SSimon Glass char *speed_str; 3202e192b24SSimon Glass 3212e192b24SSimon Glass switch (speed) { 3222e192b24SSimon Glass case USB_SPEED_SUPER: 3232e192b24SSimon Glass speed_str = "5 Gb/s"; 3242e192b24SSimon Glass break; 3252e192b24SSimon Glass case USB_SPEED_HIGH: 3262e192b24SSimon Glass speed_str = "480 Mb/s"; 3272e192b24SSimon Glass break; 3282e192b24SSimon Glass case USB_SPEED_LOW: 3292e192b24SSimon Glass speed_str = "1.5 Mb/s"; 3302e192b24SSimon Glass break; 3312e192b24SSimon Glass default: 3322e192b24SSimon Glass speed_str = "12 Mb/s"; 3332e192b24SSimon Glass break; 3342e192b24SSimon Glass } 3352e192b24SSimon Glass 3362e192b24SSimon Glass return speed_str; 3372e192b24SSimon Glass } 3382e192b24SSimon Glass 3392e192b24SSimon Glass /* shows the device tree recursively */ 3402e192b24SSimon Glass static void usb_show_tree_graph(struct usb_device *dev, char *pre) 3412e192b24SSimon Glass { 3422e192b24SSimon Glass int index; 3432e192b24SSimon Glass int has_child, last_child; 3442e192b24SSimon Glass 3452e192b24SSimon Glass index = strlen(pre); 3462e192b24SSimon Glass printf(" %s", pre); 3472e192b24SSimon Glass #ifdef CONFIG_DM_USB 3482e192b24SSimon Glass has_child = device_has_active_children(dev->dev); 3492e192b24SSimon Glass #else 3502e192b24SSimon Glass /* check if the device has connected children */ 3512e192b24SSimon Glass int i; 3522e192b24SSimon Glass 3532e192b24SSimon Glass has_child = 0; 3542e192b24SSimon Glass for (i = 0; i < dev->maxchild; i++) { 3552e192b24SSimon Glass if (dev->children[i] != NULL) 3562e192b24SSimon Glass has_child = 1; 3572e192b24SSimon Glass } 3582e192b24SSimon Glass #endif 3592e192b24SSimon Glass /* check if we are the last one */ 3602e192b24SSimon Glass #ifdef CONFIG_DM_USB 3612e192b24SSimon Glass /* Not the root of the usb tree? */ 3622e192b24SSimon Glass if (device_get_uclass_id(dev->dev->parent) != UCLASS_USB) { 3632e192b24SSimon Glass last_child = device_is_last_sibling(dev->dev); 3642e192b24SSimon Glass #else 3652e192b24SSimon Glass if (dev->parent != NULL) { /* not root? */ 3662e192b24SSimon Glass last_child = 1; 3672e192b24SSimon Glass for (i = 0; i < dev->parent->maxchild; i++) { 3682e192b24SSimon Glass /* search for children */ 3692e192b24SSimon Glass if (dev->parent->children[i] == dev) { 3702e192b24SSimon Glass /* found our pointer, see if we have a 3712e192b24SSimon Glass * little sister 3722e192b24SSimon Glass */ 3732e192b24SSimon Glass while (i++ < dev->parent->maxchild) { 3742e192b24SSimon Glass if (dev->parent->children[i] != NULL) { 3752e192b24SSimon Glass /* found a sister */ 3762e192b24SSimon Glass last_child = 0; 3772e192b24SSimon Glass break; 3782e192b24SSimon Glass } /* if */ 3792e192b24SSimon Glass } /* while */ 3802e192b24SSimon Glass } /* device found */ 3812e192b24SSimon Glass } /* for all children of the parent */ 3822e192b24SSimon Glass #endif 3832e192b24SSimon Glass printf("\b+-"); 3842e192b24SSimon Glass /* correct last child */ 3852e192b24SSimon Glass if (last_child && index) 3862e192b24SSimon Glass pre[index-1] = ' '; 3872e192b24SSimon Glass } /* if not root hub */ 3882e192b24SSimon Glass else 3892e192b24SSimon Glass printf(" "); 3902e192b24SSimon Glass printf("%d ", dev->devnum); 3912e192b24SSimon Glass pre[index++] = ' '; 3922e192b24SSimon Glass pre[index++] = has_child ? '|' : ' '; 3932e192b24SSimon Glass pre[index] = 0; 3942e192b24SSimon Glass printf(" %s (%s, %dmA)\n", usb_get_class_desc( 3952e192b24SSimon Glass dev->config.if_desc[0].desc.bInterfaceClass), 3962e192b24SSimon Glass portspeed(dev->speed), 3972e192b24SSimon Glass dev->config.desc.bMaxPower * 2); 3982e192b24SSimon Glass if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) 3992e192b24SSimon Glass printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial); 4002e192b24SSimon Glass printf(" %s\n", pre); 4012e192b24SSimon Glass #ifdef CONFIG_DM_USB 4022e192b24SSimon Glass struct udevice *child; 4032e192b24SSimon Glass 4042e192b24SSimon Glass for (device_find_first_child(dev->dev, &child); 4052e192b24SSimon Glass child; 4062e192b24SSimon Glass device_find_next_child(&child)) { 4072e192b24SSimon Glass struct usb_device *udev; 4082e192b24SSimon Glass 4092e192b24SSimon Glass if (!device_active(child)) 4102e192b24SSimon Glass continue; 4112e192b24SSimon Glass 4122e192b24SSimon Glass udev = dev_get_parent_priv(child); 4132e192b24SSimon Glass 4142e192b24SSimon Glass /* Ignore emulators, we only want real devices */ 4152e192b24SSimon Glass if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { 4162e192b24SSimon Glass usb_show_tree_graph(udev, pre); 4172e192b24SSimon Glass pre[index] = 0; 4182e192b24SSimon Glass } 4192e192b24SSimon Glass } 4202e192b24SSimon Glass #else 4212e192b24SSimon Glass if (dev->maxchild > 0) { 4222e192b24SSimon Glass for (i = 0; i < dev->maxchild; i++) { 4232e192b24SSimon Glass if (dev->children[i] != NULL) { 4242e192b24SSimon Glass usb_show_tree_graph(dev->children[i], pre); 4252e192b24SSimon Glass pre[index] = 0; 4262e192b24SSimon Glass } 4272e192b24SSimon Glass } 4282e192b24SSimon Glass } 4292e192b24SSimon Glass #endif 4302e192b24SSimon Glass } 4312e192b24SSimon Glass 4322e192b24SSimon Glass /* main routine for the tree command */ 4332e192b24SSimon Glass static void usb_show_subtree(struct usb_device *dev) 4342e192b24SSimon Glass { 4352e192b24SSimon Glass char preamble[32]; 4362e192b24SSimon Glass 4372e192b24SSimon Glass memset(preamble, '\0', sizeof(preamble)); 4382e192b24SSimon Glass usb_show_tree_graph(dev, &preamble[0]); 4392e192b24SSimon Glass } 4402e192b24SSimon Glass 4412e192b24SSimon Glass #ifdef CONFIG_DM_USB 442*2138fd6dSHans de Goede typedef void (*usb_dev_func_t)(struct usb_device *udev); 443*2138fd6dSHans de Goede 444*2138fd6dSHans de Goede static void usb_for_each_root_dev(usb_dev_func_t func) 445*2138fd6dSHans de Goede { 4462e192b24SSimon Glass struct udevice *bus; 4472e192b24SSimon Glass 448192eab93SHans de Goede for (uclass_find_first_device(UCLASS_USB, &bus); 4492e192b24SSimon Glass bus; 450192eab93SHans de Goede uclass_find_next_device(&bus)) { 4512e192b24SSimon Glass struct usb_device *udev; 4522e192b24SSimon Glass struct udevice *dev; 4532e192b24SSimon Glass 454192eab93SHans de Goede if (!device_active(bus)) 455192eab93SHans de Goede continue; 456192eab93SHans de Goede 4572e192b24SSimon Glass device_find_first_child(bus, &dev); 4582e192b24SSimon Glass if (dev && device_active(dev)) { 4592e192b24SSimon Glass udev = dev_get_parent_priv(dev); 460*2138fd6dSHans de Goede func(udev); 4612e192b24SSimon Glass } 4622e192b24SSimon Glass } 463*2138fd6dSHans de Goede } 464*2138fd6dSHans de Goede #endif 465*2138fd6dSHans de Goede 466*2138fd6dSHans de Goede void usb_show_tree(void) 467*2138fd6dSHans de Goede { 468*2138fd6dSHans de Goede #ifdef CONFIG_DM_USB 469*2138fd6dSHans de Goede usb_for_each_root_dev(usb_show_subtree); 4702e192b24SSimon Glass #else 4712e192b24SSimon Glass struct usb_device *udev; 4722e192b24SSimon Glass int i; 4732e192b24SSimon Glass 4742e192b24SSimon Glass for (i = 0; i < USB_MAX_DEVICE; i++) { 4752e192b24SSimon Glass udev = usb_get_dev_index(i); 4762e192b24SSimon Glass if (udev == NULL) 4772e192b24SSimon Glass break; 4782e192b24SSimon Glass if (udev->parent == NULL) 4792e192b24SSimon Glass usb_show_subtree(udev); 4802e192b24SSimon Glass } 4812e192b24SSimon Glass #endif 4822e192b24SSimon Glass } 4832e192b24SSimon Glass 4842e192b24SSimon Glass static int usb_test(struct usb_device *dev, int port, char* arg) 4852e192b24SSimon Glass { 4862e192b24SSimon Glass int mode; 4872e192b24SSimon Glass 4882e192b24SSimon Glass if (port > dev->maxchild) { 4892e192b24SSimon Glass printf("Device is no hub or does not have %d ports.\n", port); 4902e192b24SSimon Glass return 1; 4912e192b24SSimon Glass } 4922e192b24SSimon Glass 4932e192b24SSimon Glass switch (arg[0]) { 4942e192b24SSimon Glass case 'J': 4952e192b24SSimon Glass case 'j': 4962e192b24SSimon Glass printf("Setting Test_J mode"); 4972e192b24SSimon Glass mode = USB_TEST_MODE_J; 4982e192b24SSimon Glass break; 4992e192b24SSimon Glass case 'K': 5002e192b24SSimon Glass case 'k': 5012e192b24SSimon Glass printf("Setting Test_K mode"); 5022e192b24SSimon Glass mode = USB_TEST_MODE_K; 5032e192b24SSimon Glass break; 5042e192b24SSimon Glass case 'S': 5052e192b24SSimon Glass case 's': 5062e192b24SSimon Glass printf("Setting Test_SE0_NAK mode"); 5072e192b24SSimon Glass mode = USB_TEST_MODE_SE0_NAK; 5082e192b24SSimon Glass break; 5092e192b24SSimon Glass case 'P': 5102e192b24SSimon Glass case 'p': 5112e192b24SSimon Glass printf("Setting Test_Packet mode"); 5122e192b24SSimon Glass mode = USB_TEST_MODE_PACKET; 5132e192b24SSimon Glass break; 5142e192b24SSimon Glass case 'F': 5152e192b24SSimon Glass case 'f': 5162e192b24SSimon Glass printf("Setting Test_Force_Enable mode"); 5172e192b24SSimon Glass mode = USB_TEST_MODE_FORCE_ENABLE; 5182e192b24SSimon Glass break; 5192e192b24SSimon Glass default: 5202e192b24SSimon Glass printf("Unrecognized test mode: %s\nAvailable modes: " 5212e192b24SSimon Glass "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg); 5222e192b24SSimon Glass return 1; 5232e192b24SSimon Glass } 5242e192b24SSimon Glass 5252e192b24SSimon Glass if (port) 5262e192b24SSimon Glass printf(" on downstream facing port %d...\n", port); 5272e192b24SSimon Glass else 5282e192b24SSimon Glass printf(" on upstream facing port...\n"); 5292e192b24SSimon Glass 5302e192b24SSimon Glass if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE, 5312e192b24SSimon Glass port ? USB_RT_PORT : USB_RECIP_DEVICE, 5322e192b24SSimon Glass port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST, 5332e192b24SSimon Glass (mode << 8) | port, 5342e192b24SSimon Glass NULL, 0, USB_CNTL_TIMEOUT) == -1) { 5352e192b24SSimon Glass printf("Error during SET_FEATURE.\n"); 5362e192b24SSimon Glass return 1; 5372e192b24SSimon Glass } else { 5382e192b24SSimon Glass printf("Test mode successfully set. Use 'usb start' " 5392e192b24SSimon Glass "to return to normal operation.\n"); 5402e192b24SSimon Glass return 0; 5412e192b24SSimon Glass } 5422e192b24SSimon Glass } 5432e192b24SSimon Glass 5442e192b24SSimon Glass 5452e192b24SSimon Glass /****************************************************************************** 5462e192b24SSimon Glass * usb boot command intepreter. Derived from diskboot 5472e192b24SSimon Glass */ 5482e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 5492e192b24SSimon Glass static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5502e192b24SSimon Glass { 5512e192b24SSimon Glass return common_diskboot(cmdtp, "usb", argc, argv); 5522e192b24SSimon Glass } 5532e192b24SSimon Glass #endif /* CONFIG_USB_STORAGE */ 5542e192b24SSimon Glass 5552e192b24SSimon Glass static int do_usb_stop_keyboard(int force) 5562e192b24SSimon Glass { 5579a80e714SHans de Goede #if !defined CONFIG_DM_USB && defined CONFIG_USB_KEYBOARD 5582e192b24SSimon Glass if (usb_kbd_deregister(force) != 0) { 5592e192b24SSimon Glass printf("USB not stopped: usbkbd still using USB\n"); 5602e192b24SSimon Glass return 1; 5612e192b24SSimon Glass } 5622e192b24SSimon Glass #endif 5632e192b24SSimon Glass return 0; 5642e192b24SSimon Glass } 5652e192b24SSimon Glass 5662e192b24SSimon Glass static void do_usb_start(void) 5672e192b24SSimon Glass { 5682e192b24SSimon Glass bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start"); 5692e192b24SSimon Glass 5702e192b24SSimon Glass if (usb_init() < 0) 5712e192b24SSimon Glass return; 5722e192b24SSimon Glass 5732e192b24SSimon Glass /* Driver model will probe the devices as they are found */ 5742e192b24SSimon Glass #ifndef CONFIG_DM_USB 5752e192b24SSimon Glass # ifdef CONFIG_USB_STORAGE 5762e192b24SSimon Glass /* try to recognize storage devices immediately */ 5772e192b24SSimon Glass usb_stor_curr_dev = usb_stor_scan(1); 5782e192b24SSimon Glass # endif 5792e192b24SSimon Glass # ifdef CONFIG_USB_KEYBOARD 5802e192b24SSimon Glass drv_usb_kbd_init(); 5812e192b24SSimon Glass # endif 5822e192b24SSimon Glass #endif /* !CONFIG_DM_USB */ 5832e192b24SSimon Glass #ifdef CONFIG_USB_HOST_ETHER 5842e192b24SSimon Glass # ifdef CONFIG_DM_ETH 5852e192b24SSimon Glass # ifndef CONFIG_DM_USB 5862e192b24SSimon Glass # error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH" 5872e192b24SSimon Glass # endif 5882e192b24SSimon Glass # else 5892e192b24SSimon Glass /* try to recognize ethernet devices immediately */ 5902e192b24SSimon Glass usb_ether_curr_dev = usb_host_eth_scan(1); 5912e192b24SSimon Glass # endif 5922e192b24SSimon Glass #endif 5932e192b24SSimon Glass } 5942e192b24SSimon Glass 5952e192b24SSimon Glass #ifdef CONFIG_DM_USB 5962e192b24SSimon Glass static void show_info(struct udevice *dev) 5972e192b24SSimon Glass { 5982e192b24SSimon Glass struct udevice *child; 5992e192b24SSimon Glass struct usb_device *udev; 6002e192b24SSimon Glass 6012e192b24SSimon Glass udev = dev_get_parent_priv(dev); 6022e192b24SSimon Glass usb_display_desc(udev); 6032e192b24SSimon Glass usb_display_config(udev); 6042e192b24SSimon Glass for (device_find_first_child(dev, &child); 6052e192b24SSimon Glass child; 6062e192b24SSimon Glass device_find_next_child(&child)) { 6072e192b24SSimon Glass if (device_active(child)) 6082e192b24SSimon Glass show_info(child); 6092e192b24SSimon Glass } 6102e192b24SSimon Glass } 6112e192b24SSimon Glass 6122e192b24SSimon Glass static int usb_device_info(void) 6132e192b24SSimon Glass { 6142e192b24SSimon Glass struct udevice *bus; 6152e192b24SSimon Glass 6162e192b24SSimon Glass for (uclass_first_device(UCLASS_USB, &bus); 6172e192b24SSimon Glass bus; 6182e192b24SSimon Glass uclass_next_device(&bus)) { 6192e192b24SSimon Glass struct udevice *hub; 6202e192b24SSimon Glass 6212e192b24SSimon Glass device_find_first_child(bus, &hub); 6222e192b24SSimon Glass if (device_get_uclass_id(hub) == UCLASS_USB_HUB && 6232e192b24SSimon Glass device_active(hub)) { 6242e192b24SSimon Glass show_info(hub); 6252e192b24SSimon Glass } 6262e192b24SSimon Glass } 6272e192b24SSimon Glass 6282e192b24SSimon Glass return 0; 6292e192b24SSimon Glass } 6302e192b24SSimon Glass #endif 6312e192b24SSimon Glass 6322e192b24SSimon Glass /****************************************************************************** 6332e192b24SSimon Glass * usb command intepreter 6342e192b24SSimon Glass */ 6352e192b24SSimon Glass static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 6362e192b24SSimon Glass { 6372e192b24SSimon Glass struct usb_device *udev = NULL; 6382e192b24SSimon Glass int i; 6392e192b24SSimon Glass extern char usb_started; 6402e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 6414101f687SSimon Glass struct blk_desc *stor_dev; 6422e192b24SSimon Glass #endif 6432e192b24SSimon Glass 6442e192b24SSimon Glass if (argc < 2) 6452e192b24SSimon Glass return CMD_RET_USAGE; 6462e192b24SSimon Glass 6472e192b24SSimon Glass if (strncmp(argv[1], "start", 5) == 0) { 6482e192b24SSimon Glass if (usb_started) 6492e192b24SSimon Glass return 0; /* Already started */ 6502e192b24SSimon Glass printf("starting USB...\n"); 6512e192b24SSimon Glass do_usb_start(); 6522e192b24SSimon Glass return 0; 6532e192b24SSimon Glass } 6542e192b24SSimon Glass 6552e192b24SSimon Glass if (strncmp(argv[1], "reset", 5) == 0) { 6562e192b24SSimon Glass printf("resetting USB...\n"); 6572e192b24SSimon Glass if (do_usb_stop_keyboard(1) != 0) 6582e192b24SSimon Glass return 1; 6592e192b24SSimon Glass usb_stop(); 6602e192b24SSimon Glass do_usb_start(); 6612e192b24SSimon Glass return 0; 6622e192b24SSimon Glass } 6632e192b24SSimon Glass if (strncmp(argv[1], "stop", 4) == 0) { 6642e192b24SSimon Glass if (argc != 2) 6652e192b24SSimon Glass console_assign(stdin, "serial"); 6662e192b24SSimon Glass if (do_usb_stop_keyboard(0) != 0) 6672e192b24SSimon Glass return 1; 6682e192b24SSimon Glass printf("stopping USB..\n"); 6692e192b24SSimon Glass usb_stop(); 6702e192b24SSimon Glass return 0; 6712e192b24SSimon Glass } 6722e192b24SSimon Glass if (!usb_started) { 6732e192b24SSimon Glass printf("USB is stopped. Please issue 'usb start' first.\n"); 6742e192b24SSimon Glass return 1; 6752e192b24SSimon Glass } 6762e192b24SSimon Glass if (strncmp(argv[1], "tree", 4) == 0) { 6772e192b24SSimon Glass puts("USB device tree:\n"); 6782e192b24SSimon Glass usb_show_tree(); 6792e192b24SSimon Glass return 0; 6802e192b24SSimon Glass } 6812e192b24SSimon Glass if (strncmp(argv[1], "inf", 3) == 0) { 6822e192b24SSimon Glass if (argc == 2) { 6832e192b24SSimon Glass #ifdef CONFIG_DM_USB 6842e192b24SSimon Glass usb_device_info(); 6852e192b24SSimon Glass #else 6862e192b24SSimon Glass int d; 6872e192b24SSimon Glass for (d = 0; d < USB_MAX_DEVICE; d++) { 6882e192b24SSimon Glass udev = usb_get_dev_index(d); 6892e192b24SSimon Glass if (udev == NULL) 6902e192b24SSimon Glass break; 6912e192b24SSimon Glass usb_display_desc(udev); 6922e192b24SSimon Glass usb_display_config(udev); 6932e192b24SSimon Glass } 6942e192b24SSimon Glass #endif 6952e192b24SSimon Glass return 0; 6962e192b24SSimon Glass } else { 6972e192b24SSimon Glass /* 6982e192b24SSimon Glass * With driver model this isn't right since we can 6992e192b24SSimon Glass * have multiple controllers and the device numbering 7002e192b24SSimon Glass * starts at 1 on each bus. 7012e192b24SSimon Glass */ 7022e192b24SSimon Glass i = simple_strtoul(argv[2], NULL, 10); 7032e192b24SSimon Glass printf("config for device %d\n", i); 7042e192b24SSimon Glass udev = usb_find_device(i); 7052e192b24SSimon Glass if (udev == NULL) { 7062e192b24SSimon Glass printf("*** No device available ***\n"); 7072e192b24SSimon Glass return 0; 7082e192b24SSimon Glass } else { 7092e192b24SSimon Glass usb_display_desc(udev); 7102e192b24SSimon Glass usb_display_config(udev); 7112e192b24SSimon Glass } 7122e192b24SSimon Glass } 7132e192b24SSimon Glass return 0; 7142e192b24SSimon Glass } 7152e192b24SSimon Glass if (strncmp(argv[1], "test", 4) == 0) { 7162e192b24SSimon Glass if (argc < 5) 7172e192b24SSimon Glass return CMD_RET_USAGE; 7182e192b24SSimon Glass i = simple_strtoul(argv[2], NULL, 10); 7192e192b24SSimon Glass udev = usb_find_device(i); 7202e192b24SSimon Glass if (udev == NULL) { 7212e192b24SSimon Glass printf("Device %d does not exist.\n", i); 7222e192b24SSimon Glass return 1; 7232e192b24SSimon Glass } 7242e192b24SSimon Glass i = simple_strtoul(argv[3], NULL, 10); 7252e192b24SSimon Glass return usb_test(udev, i, argv[4]); 7262e192b24SSimon Glass } 7272e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 7282e192b24SSimon Glass if (strncmp(argv[1], "stor", 4) == 0) 7292e192b24SSimon Glass return usb_stor_info(); 7302e192b24SSimon Glass 7312e192b24SSimon Glass if (strncmp(argv[1], "part", 4) == 0) { 7322e192b24SSimon Glass int devno, ok = 0; 7332e192b24SSimon Glass if (argc == 2) { 7342e192b24SSimon Glass for (devno = 0; ; ++devno) { 73557ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, 73657ebf67bSSimon Glass devno); 7372e192b24SSimon Glass if (stor_dev == NULL) 7382e192b24SSimon Glass break; 7392e192b24SSimon Glass if (stor_dev->type != DEV_TYPE_UNKNOWN) { 7402e192b24SSimon Glass ok++; 7412e192b24SSimon Glass if (devno) 7422e192b24SSimon Glass printf("\n"); 7432e192b24SSimon Glass debug("print_part of %x\n", devno); 7443e8bd469SSimon Glass part_print(stor_dev); 7452e192b24SSimon Glass } 7462e192b24SSimon Glass } 7472e192b24SSimon Glass } else { 7482e192b24SSimon Glass devno = simple_strtoul(argv[2], NULL, 16); 74957ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); 7502e192b24SSimon Glass if (stor_dev != NULL && 7512e192b24SSimon Glass stor_dev->type != DEV_TYPE_UNKNOWN) { 7522e192b24SSimon Glass ok++; 7532e192b24SSimon Glass debug("print_part of %x\n", devno); 7543e8bd469SSimon Glass part_print(stor_dev); 7552e192b24SSimon Glass } 7562e192b24SSimon Glass } 7572e192b24SSimon Glass if (!ok) { 7582e192b24SSimon Glass printf("\nno USB devices available\n"); 7592e192b24SSimon Glass return 1; 7602e192b24SSimon Glass } 7612e192b24SSimon Glass return 0; 7622e192b24SSimon Glass } 7632e192b24SSimon Glass if (strcmp(argv[1], "read") == 0) { 7642e192b24SSimon Glass if (usb_stor_curr_dev < 0) { 7652e192b24SSimon Glass printf("no current device selected\n"); 7662e192b24SSimon Glass return 1; 7672e192b24SSimon Glass } 7682e192b24SSimon Glass if (argc == 5) { 7692e192b24SSimon Glass unsigned long addr = simple_strtoul(argv[2], NULL, 16); 7702e192b24SSimon Glass unsigned long blk = simple_strtoul(argv[3], NULL, 16); 7712e192b24SSimon Glass unsigned long cnt = simple_strtoul(argv[4], NULL, 16); 7722e192b24SSimon Glass unsigned long n; 7732e192b24SSimon Glass printf("\nUSB read: device %d block # %ld, count %ld" 7742e192b24SSimon Glass " ... ", usb_stor_curr_dev, blk, cnt); 77557ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, 77657ebf67bSSimon Glass usb_stor_curr_dev); 7772a981dc2SSimon Glass n = blk_dread(stor_dev, blk, cnt, (ulong *)addr); 7782e192b24SSimon Glass printf("%ld blocks read: %s\n", n, 7792e192b24SSimon Glass (n == cnt) ? "OK" : "ERROR"); 7802e192b24SSimon Glass if (n == cnt) 7812e192b24SSimon Glass return 0; 7822e192b24SSimon Glass return 1; 7832e192b24SSimon Glass } 7842e192b24SSimon Glass } 7852e192b24SSimon Glass if (strcmp(argv[1], "write") == 0) { 7862e192b24SSimon Glass if (usb_stor_curr_dev < 0) { 7872e192b24SSimon Glass printf("no current device selected\n"); 7882e192b24SSimon Glass return 1; 7892e192b24SSimon Glass } 7902e192b24SSimon Glass if (argc == 5) { 7912e192b24SSimon Glass unsigned long addr = simple_strtoul(argv[2], NULL, 16); 7922e192b24SSimon Glass unsigned long blk = simple_strtoul(argv[3], NULL, 16); 7932e192b24SSimon Glass unsigned long cnt = simple_strtoul(argv[4], NULL, 16); 7942e192b24SSimon Glass unsigned long n; 7952e192b24SSimon Glass printf("\nUSB write: device %d block # %ld, count %ld" 7962e192b24SSimon Glass " ... ", usb_stor_curr_dev, blk, cnt); 79757ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, 79857ebf67bSSimon Glass usb_stor_curr_dev); 7992a981dc2SSimon Glass n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr); 8002e192b24SSimon Glass printf("%ld blocks write: %s\n", n, 8012e192b24SSimon Glass (n == cnt) ? "OK" : "ERROR"); 8022e192b24SSimon Glass if (n == cnt) 8032e192b24SSimon Glass return 0; 8042e192b24SSimon Glass return 1; 8052e192b24SSimon Glass } 8062e192b24SSimon Glass } 8072e192b24SSimon Glass if (strncmp(argv[1], "dev", 3) == 0) { 8082e192b24SSimon Glass if (argc == 3) { 8092e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 8102e192b24SSimon Glass printf("\nUSB device %d: ", dev); 81157ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev); 8127839f5f8SPeng Fan if ((stor_dev == NULL) || 8137839f5f8SPeng Fan (stor_dev->if_type == IF_TYPE_UNKNOWN)) { 8142e192b24SSimon Glass printf("unknown device\n"); 8152e192b24SSimon Glass return 1; 8162e192b24SSimon Glass } 8172e192b24SSimon Glass printf("\n Device %d: ", dev); 8182e192b24SSimon Glass dev_print(stor_dev); 8192e192b24SSimon Glass if (stor_dev->type == DEV_TYPE_UNKNOWN) 8202e192b24SSimon Glass return 1; 8212e192b24SSimon Glass usb_stor_curr_dev = dev; 8222e192b24SSimon Glass printf("... is now current device\n"); 8232e192b24SSimon Glass return 0; 8242e192b24SSimon Glass } else { 8252e192b24SSimon Glass printf("\nUSB device %d: ", usb_stor_curr_dev); 82657ebf67bSSimon Glass stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, 82757ebf67bSSimon Glass usb_stor_curr_dev); 8282e192b24SSimon Glass dev_print(stor_dev); 8292e192b24SSimon Glass if (stor_dev->type == DEV_TYPE_UNKNOWN) 8302e192b24SSimon Glass return 1; 8312e192b24SSimon Glass return 0; 8322e192b24SSimon Glass } 8332e192b24SSimon Glass return 0; 8342e192b24SSimon Glass } 8352e192b24SSimon Glass #endif /* CONFIG_USB_STORAGE */ 8362e192b24SSimon Glass return CMD_RET_USAGE; 8372e192b24SSimon Glass } 8382e192b24SSimon Glass 8392e192b24SSimon Glass U_BOOT_CMD( 8402e192b24SSimon Glass usb, 5, 1, do_usb, 8412e192b24SSimon Glass "USB sub-system", 8422e192b24SSimon Glass "start - start (scan) USB controller\n" 8432e192b24SSimon Glass "usb reset - reset (rescan) USB controller\n" 8442e192b24SSimon Glass "usb stop [f] - stop USB [f]=force stop\n" 8452e192b24SSimon Glass "usb tree - show USB device tree\n" 8462e192b24SSimon Glass "usb info [dev] - show available USB devices\n" 8472e192b24SSimon Glass "usb test [dev] [port] [mode] - set USB 2.0 test mode\n" 8482e192b24SSimon Glass " (specify port 0 to indicate the device's upstream port)\n" 8492e192b24SSimon Glass " Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n" 8502e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 8512e192b24SSimon Glass "usb storage - show details of USB storage devices\n" 8522e192b24SSimon Glass "usb dev [dev] - show or set current USB storage device\n" 8532e192b24SSimon Glass "usb part [dev] - print partition table of one or all USB storage" 8542e192b24SSimon Glass " devices\n" 8552e192b24SSimon Glass "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" 8562e192b24SSimon Glass " to memory address `addr'\n" 8572e192b24SSimon Glass "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n" 8582e192b24SSimon Glass " from memory address `addr'" 8592e192b24SSimon Glass #endif /* CONFIG_USB_STORAGE */ 8602e192b24SSimon Glass ); 8612e192b24SSimon Glass 8622e192b24SSimon Glass 8632e192b24SSimon Glass #ifdef CONFIG_USB_STORAGE 8642e192b24SSimon Glass U_BOOT_CMD( 8652e192b24SSimon Glass usbboot, 3, 1, do_usbboot, 8662e192b24SSimon Glass "boot from USB device", 8672e192b24SSimon Glass "loadAddr dev:part" 8682e192b24SSimon Glass ); 8692e192b24SSimon Glass #endif /* CONFIG_USB_STORAGE */ 870