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