Merge branch 'master' of git://git.denx.de/u-boot-usb
diff --git a/board/cm_t35/cm_t35.c b/board/cm_t35/cm_t35.c
index 6c2e95b..edbb941 100644
--- a/board/cm_t35/cm_t35.c
+++ b/board/cm_t35/cm_t35.c
@@ -32,6 +32,7 @@
 #include <netdev.h>
 #include <net.h>
 #include <i2c.h>
+#include <usb.h>
 #include <twl4030.h>
 #include <linux/compiler.h>
 
@@ -41,6 +42,8 @@
 #include <asm/arch/mmc_host_def.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-types.h>
+#include <asm/ehci-omap.h>
+#include <asm/gpio.h>
 
 #include "eeprom.h"
 
@@ -260,6 +263,36 @@
 	MUX_VAL(CP(HSUSB0_DATA6),	(IEN  | PTD | DIS | M0)); /*HSUSB0_DATA6*/
 	MUX_VAL(CP(HSUSB0_DATA7),	(IEN  | PTD | DIS | M0)); /*HSUSB0_DATA7*/
 
+	/* USB EHCI */
+	MUX_VAL(CP(ETK_D0_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT0*/
+	MUX_VAL(CP(ETK_D1_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT1*/
+	MUX_VAL(CP(ETK_D2_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT2*/
+	MUX_VAL(CP(ETK_D7_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT3*/
+	MUX_VAL(CP(ETK_D4_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT4*/
+	MUX_VAL(CP(ETK_D5_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT5*/
+	MUX_VAL(CP(ETK_D6_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT6*/
+	MUX_VAL(CP(ETK_D3_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DT7*/
+	MUX_VAL(CP(ETK_D8_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_DIR*/
+	MUX_VAL(CP(ETK_D9_ES2),		(IEN  | PTD | EN  | M3)); /*HSUSB1_NXT*/
+	MUX_VAL(CP(ETK_CTL_ES2),	(IDIS | PTD | DIS | M3)); /*HSUSB1_CLK*/
+	MUX_VAL(CP(ETK_CLK_ES2),	(IDIS | PTU | DIS | M3)); /*HSUSB1_STP*/
+
+	MUX_VAL(CP(ETK_D14_ES2),	(IEN  | PTD | EN  | M3)); /*HSUSB2_DT0*/
+	MUX_VAL(CP(ETK_D15_ES2),	(IEN  | PTD | EN  | M3)); /*HSUSB2_DT1*/
+	MUX_VAL(CP(MCSPI1_CS3),		(IEN  | PTD | EN  | M3)); /*HSUSB2_DT2*/
+	MUX_VAL(CP(MCSPI2_CS1),		(IEN  | PTD | EN  | M3)); /*HSUSB2_DT3*/
+	MUX_VAL(CP(MCSPI2_SIMO),	(IEN  | PTD | EN  | M3)); /*HSUSB2_DT4*/
+	MUX_VAL(CP(MCSPI2_SOMI),	(IEN  | PTD | EN  | M3)); /*HSUSB2_DT5*/
+	MUX_VAL(CP(MCSPI2_CS0),		(IEN  | PTD | EN  | M3)); /*HSUSB2_DT6*/
+	MUX_VAL(CP(MCSPI2_CLK),		(IEN  | PTD | EN  | M3)); /*HSUSB2_DT7*/
+	MUX_VAL(CP(ETK_D12_ES2),	(IEN  | PTD | EN  | M3)); /*HSUSB2_DIR*/
+	MUX_VAL(CP(ETK_D13_ES2),	(IEN  | PTD | EN  | M3)); /*HSUSB2_NXT*/
+	MUX_VAL(CP(ETK_D10_ES2),	(IDIS | PTD | DIS | M3)); /*HSUSB2_CLK*/
+	MUX_VAL(CP(ETK_D11_ES2),	(IDIS | PTU | DIS | M3)); /*HSUSB2_STP*/
+
+	/* SB_T35_USB_HUB_RESET_GPIO */
+	MUX_VAL(CP(CAM_WEN),		(IDIS | PTD | DIS | M4)); /*GPIO_167*/
+
 	/* I2C1 */
 	MUX_VAL(CP(I2C1_SCL),		(IEN  | PTU | EN  | M0)); /*I2C1_SCL*/
 	MUX_VAL(CP(I2C1_SDA),		(IEN  | PTU | EN  | M0)); /*I2C1_SDA*/
@@ -461,3 +494,47 @@
 	serialnr->low = 0;
 	serialnr->high = 0;
 };
+
+#ifdef CONFIG_USB_EHCI_OMAP
+struct omap_usbhs_board_data usbhs_bdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
+};
+
+#define SB_T35_USB_HUB_RESET_GPIO	167
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+{
+	u8 val;
+	int offset;
+
+	if (gpio_request(SB_T35_USB_HUB_RESET_GPIO, "SB-T35 usb hub reset")) {
+		printf("Error: can't obtain GPIO %d for SB-T35 usb hub reset",
+				SB_T35_USB_HUB_RESET_GPIO);
+		return -1;
+	}
+
+	gpio_direction_output(SB_T35_USB_HUB_RESET_GPIO, 0);
+	udelay(10);
+	gpio_set_value(SB_T35_USB_HUB_RESET_GPIO, 1);
+	udelay(1000);
+
+	offset = TWL4030_BASEADD_GPIO + TWL4030_GPIO_GPIODATADIR1;
+	twl4030_i2c_read_u8(TWL4030_CHIP_GPIO, &val, offset);
+	/* Set GPIO6 and GPIO7 of TPS65930 as output */
+	val |= 0xC0;
+	twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, val, offset);
+	offset = TWL4030_BASEADD_GPIO + TWL4030_GPIO_SETGPIODATAOUT1;
+	/* Take both PHYs out of reset */
+	twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, 0xC0, offset);
+	udelay(1);
+
+	return omap_ehci_hcd_init(&usbhs_bdata, hccr, hcor);
+}
+
+int ehci_hcd_stop(void)
+{
+	return omap_ehci_hcd_stop();
+}
+
+#endif /* CONFIG_USB_EHCI_OMAP */
diff --git a/board/h2200/h2200.c b/board/h2200/h2200.c
index 3076306..720b06e 100644
--- a/board/h2200/h2200.c
+++ b/board/h2200/h2200.c
@@ -22,9 +22,16 @@
 #include <asm/arch/pxa.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/io.h>
+#include <usb.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int board_eth_init(bd_t *bis)
+{
+	usb_eth_initialize(bis);
+	return 0;
+}
+
 int board_init(void)
 {
 	/* We have RAM, disable cache */
@@ -36,6 +43,10 @@
 	/* adress of boot parameters */
 	gd->bd->bi_boot_params = 0xa0000100;
 
+	/* Let host see that device is disconnected */
+	udc_disconnect();
+	mdelay(500);
+
 	return 0;
 }
 
diff --git a/common/usb.c b/common/usb.c
index ac9b4ca..6fc0fc1 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -805,6 +805,18 @@
 	return &usb_dev[dev_index - 1];
 }
 
+/*
+ * Free the newly created device node.
+ * Called in error cases where configuring a newly attached
+ * device fails for some reason.
+ */
+void usb_free_device(void)
+{
+	dev_index--;
+	USB_PRINTF("Freeing device node: %d\n", dev_index);
+	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
+	usb_dev[dev_index].devnum = -1;
+}
 
 /*
  * By the time we get here, the device has gotten a new device ID
diff --git a/common/usb_hub.c b/common/usb_hub.c
index e4a1201..b5eeb62 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -259,6 +259,8 @@
 	/* Run it through the hoops (find a driver, etc) */
 	if (usb_new_device(usb)) {
 		/* Woops, disable the port */
+		usb_free_device();
+		dev->children[port] = NULL;
 		USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
 		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
 	}
@@ -396,14 +398,37 @@
 	for (i = 0; i < dev->maxchild; i++) {
 		ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
 		unsigned short portstatus, portchange;
+		int ret;
+		ulong start = get_timer(0);
 
-		if (usb_get_port_status(dev, i + 1, portsts) < 0) {
-			USB_HUB_PRINTF("get_port_status failed\n");
+		/*
+		 * 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) {
+				USB_HUB_PRINTF("get_port_status failed\n");
+				break;
+			}
+
+			portstatus = le16_to_cpu(portsts->wPortStatus);
+			portchange = le16_to_cpu(portsts->wPortChange);
+
+			if ((portchange & USB_PORT_STAT_C_CONNECTION) ==
+				(portstatus & USB_PORT_STAT_CONNECTION))
+				break;
+
+			mdelay(100);
+		} while (get_timer(start) < CONFIG_SYS_HZ * 10);
+
+		if (ret < 0)
 			continue;
-		}
 
-		portstatus = le16_to_cpu(portsts->wPortStatus);
-		portchange = le16_to_cpu(portsts->wPortChange);
 		USB_HUB_PRINTF("Port %d Status %X Change %X\n",
 				i + 1, portstatus, portchange);
 
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 2d92ee1..fb322b4 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -970,6 +970,16 @@
 			return 0;
 		}
 		usb_request_sense(srb, ss);
+		/*
+		 * Check the Key Code Qualifier, if it matches
+		 * "Not Ready - medium not present"
+		 * (the sense Key equals 0x2 and the ASC is 0x3a)
+		 * return immediately as the medium being absent won't change
+		 * unless there is a user action.
+		 */
+		if ((srb->sense_buf[2] == 0x02) &&
+		    (srb->sense_buf[12] == 0x3a))
+			return -1;
 		mdelay(100);
 	} while (retries--);
 
diff --git a/doc/README.usb b/doc/README.usb
index ef1d6ba..b4c3ef5 100644
--- a/doc/README.usb
+++ b/doc/README.usb
@@ -63,7 +63,7 @@
 Storage USB Commands:
 - usb scan:	    scans the USB for storage devices.The USB must be
 		    running for this command (usb start)
-- usb device [dev]: show or set current USB staorage device
+- usb device [dev]: show or set current USB storage device
 - usb part [dev]:   print partition table of one or all USB storage
 		    devices
 - usb read addr blk# cnt:
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 7d87050..a5a4c1f 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -69,6 +69,7 @@
 static struct usb_string g_dnl_string_defs[] = {
 	{ 0, manufacturer, },
 	{ 1, product, },
+	{  }		/* end of list */
 };
 
 static struct usb_gadget_strings g_dnl_string_tab = {
@@ -83,7 +84,12 @@
 
 static int g_dnl_unbind(struct usb_composite_dev *cdev)
 {
-	debug("%s\n", __func__);
+	struct usb_gadget *gadget = cdev->gadget;
+
+	debug("%s: calling usb_gadget_disconnect for "
+			"controller '%s'\n", shortname, gadget->name);
+	usb_gadget_disconnect(gadget);
+
 	return 0;
 }
 
@@ -153,6 +159,10 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 
+	debug("%s: calling usb_gadget_connect for "
+			"controller '%s'\n", shortname, gadget->name);
+	usb_gadget_connect(gadget);
+
 	return 0;
 
  error:
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index dd74143..9ce98f0 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/arch/pxa.h>
 
-#include <usbdescriptors.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <usb/lin_gadget_compat.h>
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h
index 568ae8e..8db3a61 100644
--- a/include/configs/cm_t35.h
+++ b/include/configs/cm_t35.h
@@ -114,9 +114,15 @@
 #define CONFIG_DOS_PARTITION
 
 /* USB */
-#define CONFIG_MUSB_UDC
 #define CONFIG_USB_OMAP3
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_OMAP
+#define CONFIG_USB_ULPI
+#define CONFIG_USB_ULPI_VIEWPORT_OMAP
+#define CONFIG_USB_STORAGE
+#define CONFIG_MUSB_UDC
 #define CONFIG_TWL4030_USB
+#define CONFIG_CMD_USB
 
 /* USB device configuration */
 #define CONFIG_USB_DEVICE
diff --git a/include/configs/h2200.h b/include/configs/h2200.h
index ef14dd3..516a26e 100644
--- a/include/configs/h2200.h
+++ b/include/configs/h2200.h
@@ -154,4 +154,29 @@
 
 #define CONFIG_BOOTARGS "root=/dev/ram0 ro console=ttyS0,115200n8"
 
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_USB_DEV_PULLUP_GPIO	33
+/* USB VBUS GPIO 3 */
+
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+
+#define CONFIG_BOOTDELAY		2
+#define CONFIG_BOOTCOMMAND		\
+	"setenv downloaded 0 ; while test $downloaded -eq 0 ; do " \
+	"if bootp ; then setenv downloaded 1 ; fi ; done ; " \
+	"source :script ; " \
+	"bootm ; "
+
+#define CONFIG_USB_GADGET_PXA2XX
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_SUBSET
+
+#define CONFIG_USBNET_DEV_ADDR		"de:ad:be:ef:00:01"
+#define CONFIG_USBNET_HOST_ADDR	"de:ad:be:ef:00:02"
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"stdin=serial\0" \
+	"stdout=serial\0" \
+	"stderr=serial\0"
+
 #endif /* __CONFIG_H */
diff --git a/include/twl4030.h b/include/twl4030.h
index 0c17f59..5aa1841 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -580,6 +580,50 @@
 #define TWL4030_USB_PHY_CLK_CTRL			0xFE
 #define TWL4030_USB_PHY_CLK_CTRL_STS			0xFF
 
+/* GPIO */
+#define TWL4030_GPIO_GPIODATAIN1			0x00
+#define TWL4030_GPIO_GPIODATAIN2			0x01
+#define TWL4030_GPIO_GPIODATAIN3			0x02
+#define TWL4030_GPIO_GPIODATADIR1			0x03
+#define TWL4030_GPIO_GPIODATADIR2			0x04
+#define TWL4030_GPIO_GPIODATADIR3			0x05
+#define TWL4030_GPIO_GPIODATAOUT1			0x06
+#define TWL4030_GPIO_GPIODATAOUT2			0x07
+#define TWL4030_GPIO_GPIODATAOUT3			0x08
+#define TWL4030_GPIO_CLEARGPIODATAOUT1			0x09
+#define TWL4030_GPIO_CLEARGPIODATAOUT2			0x0A
+#define TWL4030_GPIO_CLEARGPIODATAOUT3			0x0B
+#define TWL4030_GPIO_SETGPIODATAOUT1			0x0C
+#define TWL4030_GPIO_SETGPIODATAOUT2			0x0D
+#define TWL4030_GPIO_SETGPIODATAOUT3			0x0E
+#define TWL4030_GPIO_GPIO_DEBEN1			0x0F
+#define TWL4030_GPIO_GPIO_DEBEN2			0x10
+#define TWL4030_GPIO_GPIO_DEBEN3			0x11
+#define TWL4030_GPIO_GPIO_CTRL				0x12
+#define TWL4030_GPIO_GPIOPUPDCTR1			0x13
+#define TWL4030_GPIO_GPIOPUPDCTR2			0x14
+#define TWL4030_GPIO_GPIOPUPDCTR3			0x15
+#define TWL4030_GPIO_GPIOPUPDCTR4			0x16
+#define TWL4030_GPIO_GPIOPUPDCTR5			0x17
+#define TWL4030_GPIO_GPIO_ISR1A				0x19
+#define TWL4030_GPIO_GPIO_ISR2A				0x1A
+#define TWL4030_GPIO_GPIO_ISR3A				0x1B
+#define TWL4030_GPIO_GPIO_IMR1A				0x1C
+#define TWL4030_GPIO_GPIO_IMR2A				0x1D
+#define TWL4030_GPIO_GPIO_IMR3A				0x1E
+#define TWL4030_GPIO_GPIO_ISR1B				0x1F
+#define TWL4030_GPIO_GPIO_ISR2B				0x20
+#define TWL4030_GPIO_GPIO_ISR3B				0x21
+#define TWL4030_GPIO_GPIO_IMR1B				0x22
+#define TWL4030_GPIO_GPIO_IMR2B				0x23
+#define TWL4030_GPIO_GPIO_IMR3B				0x24
+#define TWL4030_GPIO_GPIO_EDR1				0x28
+#define TWL4030_GPIO_GPIO_EDR2				0x29
+#define TWL4030_GPIO_GPIO_EDR3				0x2A
+#define TWL4030_GPIO_GPIO_EDR4				0x2B
+#define TWL4030_GPIO_GPIO_EDR5				0x2C
+#define TWL4030_GPIO_GPIO_SIH_CTRL			0x2D
+
 /*
  * Convience functions to read and write from TWL4030
  *
diff --git a/include/usb.h b/include/usb.h
index 8d8a2c9..d79c865 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -392,5 +392,6 @@
 struct usb_device *usb_alloc_new_device(void *controller);
 
 int usb_new_device(struct usb_device *dev);
+void usb_free_device(void);
 
 #endif /*_USB_H_ */