On 04/07/2016 03:14 PM, George Broz wrote: > On 6 April 2016 at 19:05, Marek Vasut <ma...@denx.de> wrote: >> On 04/07/2016 03:42 AM, George Broz wrote: >> >> Hi, >> >>>>> U-Boot SPL 2016.03 (Apr 05 2016 - 17:57:23) >>>>> drivers/ddr/altera/sequencer.c: Preparing to start memory calibration >>>>> drivers/ddr/altera/sequencer.c: CALIBRATION PASSED >>>>> drivers/ddr/altera/sequencer.c: Calibration complete >>>>> Trying to boot from MMC1 >>>>> >>>>> First time that an SPL built from a recent version has run successfully >>>>> on that board. >>>>> >>>>> Will try it out on de0 tomorrow morning... >>>> >>>> This is great news, thanks! >>> >>> This patch also fixes the intermittent SDRAM calibration failures on my >>> de0_nano_soc board. Thanks so much! >> >> Great >> >>> Now with up-to-date versions of SPL and image... I have some >>> USB questions/news/observations: >>> >>> When using an OTG cable between USB port and mass storage >>> device, the de0_nano_soc board is able to detect and access some USB >>> sticks. The detection with these is almost immediate from when 'usb start' >>> is entered. If the same (working) USB stick is used with a non-OTG cable, >>> I get the timeout messages from before: >>> >>> dwc_otg_core_host_init: Timeout! >>> dwc_otg_core_host_init: Timeout! >>> >>> and this is true even if I add 'dr_mode = "host" ' >> >> I don't think the driver supports the dr_mode property yet. Patch is >> welcome. >> >>> to the dts for usb1 >>> of the de0 >>> (and rebuild/reload). The older SPL/image that ships from the Terasic >>> factory >>> detects USB sticks with a non-OTG cable, (the cable that ships with the >>> unit). >>> What is the correct "expected" behavior here?? Is an OTG cable required or >>> not? >> >> The DWC2 driver tests the value of the OTG ID pin, so if you don't use >> OTG cable with correct ID pin setup, the host won't work. >> >>> Even with the OTG cable, some USB sticks "fail" in a not-so-great way. >>> I have a Kingston stick and the sequence goes like this: >>> >>> => usb reset >>> resetting USB... >>> USB0: Core Release: 2.93a >>> scanning bus 0 for devices... >>> >>> <<< 1 minute, 41 seconds pass before >>> >>> ... Device NOT ready >>> Request Sense returned 00 00 00 >>> >>> <<< then another 24 seconds pass before >>> >>> >>> 2 USB Device(s) found >>> >>> It was able to read some information about the stick: >>> >>> => usb info >>> : >>> 2: Mass Storage, USB Revision 2.0 >>> - Kingston DataTraveler SE9 0014857749E5ECB0173000D3 >>> - Class: (from Interface) Mass Storage >>> - PacketSize: 64 Configurations: 1 >>> - Vendor: 0x0930 Product 0x6545 Version 1.0 >>> Configuration: 1 >>> - Interfaces: 1 Bus Powered 200mA >>> Interface: 0 >>> - Alternate Setting 0, Endpoints: 2 >>> - Class Mass Storage, Transp. SCSI, Bulk only >>> - Endpoint 1 In Bulk MaxPacket 512 >>> - Endpoint 2 Out Bulk MaxPacket 512 >>> >>> BUT, the stick cannot be accessed otherwise, for example: >>> >>> => usb part 0 >>> ## Unknown partition table type 0 >>> >>> >>> Is there any feature of the USB stick that would indicate >>> whether or not it is "compatible" with u-boot? >> >> Can you do "dcache off" before you do "usb reset" and see if that fixes >> the problem ? > > The behavior is unchanged if "dcache off" done before "usb reset".
Try with the attached patch (and probably with dcache off) Best regards, Marek Vasut
>From 1d9326d5db29f2dca8639e8929eac780e1bd29a3 Mon Sep 17 00:00:00 2001 From: Marek Vasut <ma...@denx.de> Date: Sat, 2 Apr 2016 00:20:37 +0200 Subject: [PATCH] Revert "usb: Change power-on / scanning timeout handling" This reverts commit c998da0d67091f800933e59b8693913764a9e8f4. --- common/usb_hub.c | 317 +++++++++++++++++-------------------------------------- include/usb.h | 4 - 2 files changed, 94 insertions(+), 227 deletions(-) diff --git a/common/usb_hub.c b/common/usb_hub.c index e6a2cdb..d621f50 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -30,7 +30,6 @@ #include <asm/processor.h> #include <asm/unaligned.h> #include <linux/ctype.h> -#include <linux/list.h> #include <asm/byteorder.h> #ifdef CONFIG_SANDBOX #include <asm/state.h> @@ -50,19 +49,9 @@ DECLARE_GLOBAL_DATA_PTR; #define HUB_SHORT_RESET_TIME 20 #define HUB_LONG_RESET_TIME 200 -#define PORT_OVERCURRENT_MAX_SCAN_COUNT 3 - -struct usb_device_scan { - struct usb_device *dev; /* USB hub device to scan */ - struct usb_hub_device *hub; /* USB hub struct */ - int port; /* USB port to scan */ - struct list_head list; -}; - /* TODO(s...@chromium.org): Remove this when CONFIG_DM_USB is defined */ static struct usb_hub_device hub_dev[USB_MAX_HUB]; static int usb_hub_index; -static LIST_HEAD(usb_scan_list); __weak void usb_hub_reset_devices(int port) { @@ -120,15 +109,6 @@ static void usb_hub_power_on(struct usb_hub_device *hub) debug("port %d returns %lX\n", i + 1, dev->status); } -#ifdef CONFIG_SANDBOX - /* - * Don't set timeout / delay values here. This results - * in these values still being reset to 0. - */ - if (state_get_skip_delays()) - return; -#endif - /* * Wait for power to become stable, * plus spec-defined max time for device to connect @@ -140,30 +120,12 @@ static void usb_hub_power_on(struct usb_hub_device *hub) pgood_delay = max(pgood_delay, (unsigned)simple_strtol(env, NULL, 0)); debug("pgood_delay=%dms\n", pgood_delay); - - /* - * Do a minimum delay of the larger value of 100ms or pgood_delay - * so that the power can stablize before the devices are queried - */ - hub->query_delay = get_timer(0) + max(100, (int)pgood_delay); - - /* - * Record the power-on timeout here. The max. delay (timeout) - * will be done based on this value in the USB port loop in - * usb_hub_configure() later. - */ - hub->connect_timeout = hub->query_delay + 1000; - debug("devnum=%d poweron: query_delay=%d connect_timeout=%d\n", - dev->devnum, max(100, (int)pgood_delay), - max(100, (int)pgood_delay) + 1000); + mdelay(pgood_delay + 1000); } void usb_hub_reset(void) { usb_hub_index = 0; - - /* Zero out global hub_dev in case its re-used again */ - memset(hub_dev, 0, sizeof(hub_dev)); } static struct usb_hub_device *usb_hub_allocate(void) @@ -370,168 +332,6 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port) return ret; } -static int usb_scan_port(struct usb_device_scan *usb_scan) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); - unsigned short portstatus; - unsigned short portchange; - struct usb_device *dev; - struct usb_hub_device *hub; - int ret = 0; - int i; - - dev = usb_scan->dev; - hub = usb_scan->hub; - i = usb_scan->port; - - /* - * Don't talk to the device before the query delay is expired. - * This is needed for voltages to stabalize. - */ - if (get_timer(0) < hub->query_delay) - return 0; - - ret = usb_get_port_status(dev, i + 1, portsts); - if (ret < 0) { - debug("get_port_status failed\n"); - if (get_timer(0) >= hub->connect_timeout) { - debug("devnum=%d port=%d: timeout\n", - dev->devnum, i + 1); - /* Remove this device from scanning list */ - list_del(&usb_scan->list); - free(usb_scan); - return 0; - } - } - - portstatus = le16_to_cpu(portsts->wPortStatus); - portchange = le16_to_cpu(portsts->wPortChange); - debug("Port %d Status %X Change %X\n", i + 1, portstatus, portchange); - - /* No connection change happened, wait a bit more. */ - if (!(portchange & USB_PORT_STAT_C_CONNECTION)) { - if (get_timer(0) >= hub->connect_timeout) { - debug("devnum=%d port=%d: timeout\n", - dev->devnum, i + 1); - /* Remove this device from scanning list */ - list_del(&usb_scan->list); - free(usb_scan); - return 0; - } - return 0; - } - - /* Test if the connection came up, and if not exit */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return 0; - - /* A new USB device is ready at this point */ - debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); - - usb_hub_port_connect_change(dev, i); - - if (portchange & USB_PORT_STAT_C_ENABLE) { - debug("port %d enable change, status %x\n", i + 1, portstatus); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); - /* - * The following hack causes a ghost device problem - * to Faraday EHCI - */ -#ifndef CONFIG_USB_EHCI_FARADAY - /* - * EM interference sometimes causes bad shielded USB - * devices to be shutdown by the hub, this hack enables - * them again. Works at least with mouse driver - */ - if (!(portstatus & USB_PORT_STAT_ENABLE) && - (portstatus & USB_PORT_STAT_CONNECTION) && - usb_device_has_child_on_port(dev, i)) { - debug("already running port %i disabled by hub (EMI?), re-enabling...\n", - i + 1); - usb_hub_port_connect_change(dev, i); - } -#endif - } - - if (portstatus & USB_PORT_STAT_SUSPEND) { - debug("port %d suspend change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); - } - - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - debug("port %d over-current change\n", i + 1); - usb_clear_port_feature(dev, i + 1, - USB_PORT_FEAT_C_OVER_CURRENT); - /* Only power-on this one port */ - usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); - hub->overcurrent_count[i]++; - - /* - * If the max-scan-count is not reached, return without removing - * the device from scan-list. This will re-issue a new scan. - */ - if (hub->overcurrent_count[i] <= - PORT_OVERCURRENT_MAX_SCAN_COUNT) - return 0; - - /* Otherwise the device will get removed */ - printf("Port %d over-current occured %d times\n", i + 1, - hub->overcurrent_count[i]); - } - - if (portchange & USB_PORT_STAT_C_RESET) { - debug("port %d reset change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); - } - - /* - * We're done with this device, so let's remove this device from - * scanning list - */ - list_del(&usb_scan->list); - free(usb_scan); - - return 0; -} - -static int usb_device_list_scan(void) -{ - struct usb_device_scan *usb_scan; - struct usb_device_scan *tmp; - static int running; - int ret = 0; - - /* Only run this loop once for each controller */ - if (running) - return 0; - - running = 1; - - while (1) { - /* We're done, once the list is empty again */ - if (list_empty(&usb_scan_list)) - goto out; - - list_for_each_entry_safe(usb_scan, tmp, &usb_scan_list, list) { - int ret; - - /* Scan this port */ - ret = usb_scan_port(usb_scan); - if (ret) - goto out; - } - } - -out: - /* - * This USB controller has finished scanning all its connected - * USB devices. Set "running" back to 0, so that other USB controllers - * will scan their devices too. - */ - running = 0; - - return ret; -} static int usb_hub_configure(struct usb_device *dev) { @@ -666,33 +466,104 @@ static int usb_hub_configure(struct usb_device *dev) for (i = 0; i < dev->maxchild; i++) usb_hub_reset_devices(i + 1); - /* - * Only add the connected USB devices, including potential hubs, - * to a scanning list. This list will get scanned and devices that - * are detected (either via port connected or via port timeout) - * will get removed from this list. Scanning of the devices on this - * list will continue until all devices are removed. - */ for (i = 0; i < dev->maxchild; i++) { - struct usb_device_scan *usb_scan; + ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); + unsigned short portstatus, portchange; + int ret; + ulong start = get_timer(0); + uint delay = CONFIG_SYS_HZ; + +#ifdef CONFIG_SANDBOX + if (state_get_skip_delays()) + delay = 0; +#endif +#ifdef CONFIG_DM_USB + debug("\n\nScanning '%s' port %d\n", dev->dev->name, i + 1); +#else + debug("\n\nScanning port %d\n", i + 1); +#endif + /* + * Wait for (whichever finishes first) + * - A maximum of 10 seconds + * This is a purely observational value driven by connecting + * a few broken pen drives and taking the max * 1.5 approach + * - connection_change and connection state to report same + * state + */ + do { + ret = usb_get_port_status(dev, i + 1, portsts); + if (ret < 0) { + debug("get_port_status failed\n"); + break; + } + + portstatus = le16_to_cpu(portsts->wPortStatus); + portchange = le16_to_cpu(portsts->wPortChange); + + /* No connection change happened, wait a bit more. */ + if (!(portchange & USB_PORT_STAT_C_CONNECTION)) + continue; + + /* Test if the connection came up, and if so, exit. */ + if (portstatus & USB_PORT_STAT_CONNECTION) + break; + + } while (get_timer(start) < delay); + + if (ret < 0) + continue; - usb_scan = calloc(1, sizeof(*usb_scan)); - if (!usb_scan) { - printf("Can't allocate memory for USB device!\n"); - return -ENOMEM; + debug("Port %d Status %X Change %X\n", + i + 1, portstatus, portchange); + + if (portchange & USB_PORT_STAT_C_CONNECTION) { + debug("port %d connection change\n", i + 1); + usb_hub_port_connect_change(dev, i); + } + if (portchange & USB_PORT_STAT_C_ENABLE) { + debug("port %d enable change, status %x\n", + i + 1, portstatus); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_ENABLE); + /* + * The following hack causes a ghost device problem + * to Faraday EHCI + */ +#ifndef CONFIG_USB_EHCI_FARADAY + /* EM interference sometimes causes bad shielded USB + * devices to be shutdown by the hub, this hack enables + * them again. Works at least with mouse driver */ + if (!(portstatus & USB_PORT_STAT_ENABLE) && + (portstatus & USB_PORT_STAT_CONNECTION) && + usb_device_has_child_on_port(dev, i)) { + debug("already running port %i " \ + "disabled by hub (EMI?), " \ + "re-enabling...\n", i + 1); + usb_hub_port_connect_change(dev, i); + } +#endif + } + if (portstatus & USB_PORT_STAT_SUSPEND) { + debug("port %d suspend change\n", i + 1); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_SUSPEND); } - usb_scan->dev = dev; - usb_scan->hub = hub; - usb_scan->port = i; - list_add_tail(&usb_scan->list, &usb_scan_list); - } - /* - * And now call the scanning code which loops over the generated list - */ - ret = usb_device_list_scan(); + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + debug("port %d over-current change\n", i + 1); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_OVER_CURRENT); + usb_hub_power_on(hub); + } - return ret; + if (portchange & USB_PORT_STAT_C_RESET) { + debug("port %d reset change\n", i + 1); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_RESET); + } + } /* end for i all ports */ + + return 0; } static int usb_hub_check(struct usb_device *dev, int ifnum) diff --git a/include/usb.h b/include/usb.h index 5adad36..ed2336b 100644 --- a/include/usb.h +++ b/include/usb.h @@ -556,10 +556,6 @@ struct usb_hub_descriptor { struct usb_hub_device { struct usb_device *pusb_dev; struct usb_hub_descriptor desc; - - ulong connect_timeout; /* Device connection timeout in ms */ - ulong query_delay; /* Device query delay in ms */ - int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */ }; #ifdef CONFIG_DM_USB -- 2.7.0
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot