diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index dacdc2d..adc5f02 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -269,6 +269,22 @@ static void usb_display_config(struct usb_device *dev)
 	printf("\n");
 }
 
+static struct usb_device *usb_find_device(int devnum)
+{
+	struct usb_device *dev;
+	int d;
+
+	for (d = 0; d < USB_MAX_DEVICE; d++) {
+		dev = usb_get_dev_index(d);
+		if (dev == NULL)
+			return NULL;
+		if (dev->devnum == devnum)
+			return dev;
+	}
+
+	return NULL;
+}
+
 static inline char *portspeed(int speed)
 {
 	if (speed == USB_SPEED_HIGH)
@@ -348,6 +364,66 @@ static void usb_show_tree(struct usb_device *dev)
 	usb_show_tree_graph(dev, &preamble[0]);
 }
 
+static int usb_test(struct usb_device *dev, int port, char* arg)
+{
+	int mode;
+
+	if (port > dev->maxchild) {
+		printf("Device is no hub or does not have %d ports.\n", port);
+		return 1;
+	}
+
+	switch (arg[0]) {
+	case 'J':
+	case 'j':
+		printf("Setting Test_J mode");
+		mode = USB_TEST_MODE_J;
+		break;
+	case 'K':
+	case 'k':
+		printf("Setting Test_K mode");
+		mode = USB_TEST_MODE_K;
+		break;
+	case 'S':
+	case 's':
+		printf("Setting Test_SE0_NAK mode");
+		mode = USB_TEST_MODE_SE0_NAK;
+		break;
+	case 'P':
+	case 'p':
+		printf("Setting Test_Packet mode");
+		mode = USB_TEST_MODE_PACKET;
+		break;
+	case 'F':
+	case 'f':
+		printf("Setting Test_Force_Enable mode");
+		mode = USB_TEST_MODE_FORCE_ENABLE;
+		break;
+	default:
+		printf("Unrecognized test mode: %s\nAvailable modes: "
+		       "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg);
+		return 1;
+	}
+
+	if (port)
+		printf(" on downstream facing port %d...\n", port);
+	else
+		printf(" on upstream facing port...\n");
+
+	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE,
+			    port ? USB_RT_PORT : USB_RECIP_DEVICE,
+			    port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST,
+			    (mode << 8) | port,
+			    NULL, 0, USB_CNTL_TIMEOUT) == -1) {
+		printf("Error during SET_FEATURE.\n");
+		return 1;
+	} else {
+		printf("Test mode successfully set. Use 'usb start' "
+		       "to return to normal operation.\n");
+		return 0;
+	}
+}
+
 
 /******************************************************************************
  * usb boot command intepreter. Derived from diskboot
@@ -441,17 +517,9 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			}
 			return 0;
 		} else {
-			int d;
-
-			i = simple_strtoul(argv[2], NULL, 16);
+			i = simple_strtoul(argv[2], NULL, 10);
 			printf("config for device %d\n", i);
-			for (d = 0; d < USB_MAX_DEVICE; d++) {
-				dev = usb_get_dev_index(d);
-				if (dev == NULL)
-					break;
-				if (dev->devnum == i)
-					break;
-			}
+			dev = usb_find_device(i);
 			if (dev == NULL) {
 				printf("*** No device available ***\n");
 				return 0;
@@ -462,6 +530,18 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		}
 		return 0;
 	}
+	if (strncmp(argv[1], "test", 4) == 0) {
+		if (argc < 5)
+			return CMD_RET_USAGE;
+		i = simple_strtoul(argv[2], NULL, 10);
+		dev = usb_find_device(i);
+		if (dev == NULL) {
+			printf("Device %d does not exist.\n", i);
+			return 1;
+		}
+		i = simple_strtoul(argv[3], NULL, 10);
+		return usb_test(dev, i, argv[4]);
+	}
 #ifdef CONFIG_USB_STORAGE
 	if (strncmp(argv[1], "stor", 4) == 0)
 		return usb_stor_info();
@@ -571,7 +651,6 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_USB_STORAGE
 U_BOOT_CMD(
 	usb,	5,	1,	do_usb,
 	"USB sub-system",
@@ -580,30 +659,26 @@ U_BOOT_CMD(
 	"usb stop [f] - stop USB [f]=force stop\n"
 	"usb tree - show USB device tree\n"
 	"usb info [dev] - show available USB devices\n"
+	"usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
+	"    (specify port 0 to indicate the device's upstream port)\n"
+	"    Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
+#ifdef CONFIG_USB_STORAGE
 	"usb storage - show details of USB storage devices\n"
 	"usb dev [dev] - show or set current USB storage device\n"
 	"usb part [dev] - print partition table of one or all USB storage"
-	" devices\n"
+	"    devices\n"
 	"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
 	"    to memory address `addr'\n"
 	"usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
 	"    from memory address `addr'"
+#endif /* CONFIG_USB_STORAGE */
 );
 
 
+#ifdef CONFIG_USB_STORAGE
 U_BOOT_CMD(
 	usbboot,	3,	1,	do_usbboot,
 	"boot from USB device",
 	"loadAddr dev:part"
 );
-
-#else
-U_BOOT_CMD(
-	usb,	5,	1,	do_usb,
-	"USB sub-system",
-	"start - start (scan) USB controller\n"
-	"usb reset - reset (rescan) USB controller\n"
-	"usb tree - show USB device tree\n"
-	"usb info [dev] - show available USB devices"
-);
-#endif
+#endif /* CONFIG_USB_STORAGE */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7f98a63..32c7c1d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -602,15 +602,19 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 	int len, srclen;
 	uint32_t reg;
 	uint32_t *status_reg;
+	int port = le16_to_cpu(req->index) & 0xff;
 	struct ehci_ctrl *ctrl = dev->controller;
 
-	if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
-		printf("The request port(%d) is not configured\n",
-			le16_to_cpu(req->index) - 1);
+	if (port > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
+		printf("The request port(%d) is not configured\n", port - 1);
 		return -1;
 	}
-	status_reg = (uint32_t *)&ctrl->hcor->or_portsc[
-						le16_to_cpu(req->index) - 1];
+	if (port && !(ctrl->port_enable_mask &
+			(1 << (port - 1)))) {
+		debug("skip request on disabled port%d\n", port - 1);
+		return 0;
+	}
+	status_reg = (uint32_t *)&hcor->or_portsc[port - 1];
 	srclen = 0;
 
 	debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
@@ -727,7 +731,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
 		if (reg & EHCI_PS_OCC)
 			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
-		if (ctrl->portreset & (1 << le16_to_cpu(req->index)))
+		if (ctrl->portreset & (1 << port))
 			tmpbuf[2] |= USB_PORT_STAT_C_RESET;
 
 		srcptr = tmpbuf;
@@ -753,7 +757,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 			    EHCI_PS_IS_LOWSPEED(reg)) {
 				/* Low speed device, give up ownership. */
 				debug("port %d low speed --> companion\n",
-				      req->index - 1);
+				      port - 1);
 				reg |= EHCI_PS_PO;
 				ehci_writel(status_reg, reg);
 				break;
@@ -779,13 +783,17 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 				ret = handshake(status_reg, EHCI_PS_PR, 0,
 						2 * 1000);
 				if (!ret)
-					ctrl->portreset |=
-						1 << le16_to_cpu(req->index);
+					ctrl->portreset |= 1 << port;
 				else
 					printf("port(%d) reset error\n",
-					le16_to_cpu(req->index) - 1);
+					       port - 1);
 			}
 			break;
+		case USB_PORT_FEAT_TEST:
+			reg &= ~(0xf << 16);
+			reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
+			ehci_writel(status_reg, reg);
+			break;
 		default:
 			debug("unknown feature %x\n", le16_to_cpu(req->value));
 			goto unknown;
@@ -812,7 +820,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 			reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
 			break;
 		case USB_PORT_FEAT_C_RESET:
-			ctrl->portreset &= ~(1 << le16_to_cpu(req->index));
+			ctrl->portreset &= ~(1 << port);
 			break;
 		default:
 			debug("unknown feature %x\n", le16_to_cpu(req->value));
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 9502544..5c5478f 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -150,6 +150,18 @@
 #define USB_REQ_SET_IDLE            0x0A
 #define USB_REQ_SET_PROTOCOL        0x0B
 
+/* Device features */
+#define USB_FEAT_HALT               0x00
+#define USB_FEAT_WAKEUP             0x01
+#define USB_FEAT_TEST               0x02
+
+/* Test modes */
+#define USB_TEST_MODE_J             0x01
+#define USB_TEST_MODE_K             0x02
+#define USB_TEST_MODE_SE0_NAK       0x03
+#define USB_TEST_MODE_PACKET        0x04
+#define USB_TEST_MODE_FORCE_ENABLE  0x05
+
 
 /* "pipe" definitions */
 
@@ -208,6 +220,7 @@
 #define USB_PORT_FEAT_C_SUSPEND      18
 #define USB_PORT_FEAT_C_OVER_CURRENT 19
 #define USB_PORT_FEAT_C_RESET        20
+#define USB_PORT_FEAT_TEST           21
 
 /* wPortStatus bits */
 #define USB_PORT_STAT_CONNECTION    0x0001
