Merge branch 'master' of git://git.denx.de/u-boot-usb
diff --git a/board/davinci/dvevm/dvevm.c b/board/davinci/dvevm/dvevm.c
index abf60b3..bf36f73 100644
--- a/board/davinci/dvevm/dvevm.c
+++ b/board/davinci/dvevm/dvevm.c
@@ -52,6 +52,7 @@
 	lpsc_on(DAVINCI_LPSC_UART0);
 	lpsc_on(DAVINCI_LPSC_TIMER1);
 	lpsc_on(DAVINCI_LPSC_GPIO);
+	lpsc_on(DAVINCI_LPSC_USB);
 
 #if !defined(CONFIG_SYS_USE_DSPLINK)
 	/* Powerup the DSP */
@@ -101,3 +102,26 @@
 
 	return(0);
 }
+
+#ifdef CONFIG_USB_DAVINCI
+
+/* IO Expander I2C address and USB VBUS enable mask */
+#define IOEXP_I2C_ADDR 0x3A
+#define IOEXP_VBUSEN_MASK 1
+
+/*
+ * This function enables USB VBUS by writting to IO expander using I2C.
+ * Note that the I2C is already initialized at this stage. This
+ * function is used by davinci specific USB wrapper code.
+ */
+void enable_vbus(void)
+{
+	uchar data;  /* IO Expander data to enable VBUS */
+
+	/* Write to IO expander to enable VBUS */
+	i2c_read(IOEXP_I2C_ADDR, 0, 0, &data, 1);
+	data &= ~IOEXP_VBUSEN_MASK;
+	i2c_write(IOEXP_I2C_ADDR, 0, 0, &data, 1);
+}
+#endif
+
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 423a29f..a18e16e 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -264,6 +264,16 @@
 	printf("\n");
 }
 
+static inline char *portspeed(int speed)
+{
+	if (speed == USB_SPEED_HIGH)
+		return "480 Mb/s";
+	else if (speed == USB_SPEED_LOW)
+		return "1.5 Mb/s";
+	else
+		return "12 Mb/s";
+}
+
 /* shows the device tree recursively */
 void usb_show_tree_graph(struct usb_device *dev, char *pre)
 {
@@ -310,7 +320,7 @@
 	pre[index] = 0;
 	printf(" %s (%s, %dmA)\n", usb_get_class_desc(
 					dev->config.if_desc[0].bInterfaceClass),
-					dev->slow ? "1.5MBit/s" : "12MBit/s",
+					portspeed(dev->speed),
 					dev->config.MaxPower * 2);
 	if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
 		printf(" %s  %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
diff --git a/common/usb.c b/common/usb.c
index ee18152..87fca70 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -681,7 +681,7 @@
 		err = usb_string_sub(dev, 0, 0, tbuf);
 		if (err < 0) {
 			USB_PRINTF("error getting string descriptor 0 " \
-				   "(error=%x)\n", dev->status);
+				   "(error=%lx)\n", dev->status);
 			return -1;
 		} else if (tbuf[0] < 4) {
 			USB_PRINTF("string descriptor 0 too short\n");
@@ -939,8 +939,10 @@
 	dev_index = 0;
 	/* device 0 is always present (root hub, so let it analyze) */
 	dev = usb_alloc_new_device();
-	usb_new_device(dev);
-	printf("%d USB Device(s) found\n", dev_index);
+	if (usb_new_device(dev))
+		printf("No USB Device found\n");
+	else
+		printf("%d USB Device(s) found\n", dev_index);
 	/* insert "driver" if possible */
 #ifdef CONFIG_USB_KEYBOARD
 	drv_usb_kbd_init();
@@ -1041,6 +1043,16 @@
 
 #define MAX_TRIES 5
 
+static inline char *portspeed(int portstatus)
+{
+	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
+		return "480 Mb/s";
+	else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
+		return "1.5 Mb/s";
+	else
+		return "12 Mb/s";
+}
+
 static int hub_port_reset(struct usb_device *dev, int port,
 			unsigned short *portstat)
 {
@@ -1061,10 +1073,11 @@
 		}
 		portstatus = le16_to_cpu(portsts.wPortStatus);
 		portchange = le16_to_cpu(portsts.wPortChange);
+
 		USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
 				portstatus, portchange,
-				portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? \
-						"Low Speed" : "High Speed");
+				portspeed(portstatus));
+
 		USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d" \
 			       "  USB_PORT_STAT_ENABLE %d\n",
 			(portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
@@ -1109,9 +1122,7 @@
 	portstatus = le16_to_cpu(portsts.wPortStatus);
 	portchange = le16_to_cpu(portsts.wPortChange);
 	USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
-			portstatus, portchange,
-			portstatus&(1 << USB_PORT_FEAT_LOWSPEED) ? \
-						"Low Speed" : "High Speed");
+			portstatus, portchange, portspeed(portstatus));
 
 	/* Clear the connection change status */
 	usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
@@ -1136,7 +1147,13 @@
 
 	/* Allocate a new device struct for it */
 	usb = usb_alloc_new_device();
-	usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
+
+	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+		usb->speed = USB_SPEED_HIGH;
+	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+		usb->speed = USB_SPEED_LOW;
+	else
+		usb->speed = USB_SPEED_FULL;
 
 	dev->children[port] = usb;
 	usb->parent = dev;
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 89e6ee7..e0d006c 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -183,6 +183,7 @@
 				usb_kbd_dev.puts = NULL;
 				usb_kbd_dev.getc = usb_kbd_getc;
 				usb_kbd_dev.tstc = usb_kbd_testc;
+				usb_kbd_dev.priv = (void *)dev;
 				error = device_register (&usb_kbd_dev);
 				if(error==0) {
 					/* check if this is the standard input device */
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 94f659f..51f0789 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -45,8 +45,6 @@
  * New Note:
  * Support for USB Mass Storage Devices (BBB) has been added. It has
  * only been tested with USB memory sticks.
- * Nota bene: if you are using the BBB support with a little-endian
- * CPU then you MUST define LITTLEENDIAN in the configuration file!
  */
 
 
@@ -63,9 +61,9 @@
 #undef BBB_XPORT_TRACE
 
 #ifdef	USB_STOR_DEBUG
-#define USB_STOR_PRINTF(fmt,args...)	printf (fmt ,##args)
+#define USB_STOR_PRINTF(fmt, args...)	printf(fmt , ##args)
 #else
-#define USB_STOR_PRINTF(fmt,args...)
+#define USB_STOR_PRINTF(fmt, args...)
 #endif
 
 #include <scsi.h>
@@ -110,7 +108,7 @@
 	__u8		CBWCDB[CBWCDBLENGTH];
 } umass_bbb_cbw_t;
 #define UMASS_BBB_CBW_SIZE	31
-static __u32 CBWTag = 0;
+static __u32 CBWTag;
 
 /* Command Status Wrapper */
 typedef struct {
@@ -126,34 +124,35 @@
 #define UMASS_BBB_CSW_SIZE	13
 
 #define USB_MAX_STOR_DEV 5
-static int usb_max_devs = 0; /* number of highest available usb device */
+static int usb_max_devs; /* number of highest available usb device */
 
 static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
 
 struct us_data;
-typedef int (*trans_cmnd)(ccb*, struct us_data*);
-typedef int (*trans_reset)(struct us_data*);
+typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
+typedef int (*trans_reset)(struct us_data *data);
 
 struct us_data {
-	struct usb_device	*pusb_dev;	 /* this usb_device */
-	unsigned int		flags;		 /* from filter initially */
-	unsigned char		ifnum;		 /* interface number */
-	unsigned char		ep_in;		 /* in endpoint */
-	unsigned char		ep_out;		 /* out ....... */
-	unsigned char		ep_int;		 /* interrupt . */
-	unsigned char		subclass;	 /* as in overview */
-	unsigned char		protocol;	 /* .............. */
-	unsigned char		attention_done;	 /* force attn on first cmd */
-	unsigned short	ip_data;	 /* interrupt data */
-	int							action;		 /* what to do */
-	int							ip_wanted; /* needed */
-	int							*irq_handle;	 /* for USB int requests */
-	unsigned int		irqpipe;	 /* pipe for release_irq */
-	unsigned char		irqmaxp;	/* max packed for irq Pipe */
-	unsigned char	irqinterval; /* Intervall for IRQ Pipe */
-	ccb							*srb;		 /* current srb */
-	trans_reset			transport_reset; /* reset routine */
-	trans_cmnd			transport; /* transport routine */
+	struct usb_device *pusb_dev;	 /* this usb_device */
+
+	unsigned int	flags;			/* from filter initially */
+	unsigned char	ifnum;			/* interface number */
+	unsigned char	ep_in;			/* in endpoint */
+	unsigned char	ep_out;			/* out ....... */
+	unsigned char	ep_int;			/* interrupt . */
+	unsigned char	subclass;		/* as in overview */
+	unsigned char	protocol;		/* .............. */
+	unsigned char	attention_done;		/* force attn on first cmd */
+	unsigned short	ip_data;		/* interrupt data */
+	int		action;			/* what to do */
+	int		ip_wanted;		/* needed */
+	int		*irq_handle;		/* for USB int requests */
+	unsigned int	irqpipe;	 	/* pipe for release_irq */
+	unsigned char	irqmaxp;		/* max packed for irq Pipe */
+	unsigned char	irqinterval;		/* Intervall for IRQ Pipe */
+	ccb		*srb;			/* current srb */
+	trans_reset	transport_reset;	/* reset routine */
+	trans_cmnd	transport;		/* transport routine */
 };
 
 static struct us_data usb_stor[USB_MAX_STOR_DEV];
@@ -163,10 +162,12 @@
 #define USB_STOR_TRANSPORT_FAILED -1
 #define USB_STOR_TRANSPORT_ERROR  -2
 
-
-int usb_stor_get_info(struct usb_device *dev, struct us_data *us, block_dev_desc_t *dev_desc);
-int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss);
-unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer);
+int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
+		      block_dev_desc_t *dev_desc);
+int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
+		      struct us_data *ss);
+unsigned long usb_stor_read(int device, unsigned long blknr,
+			    unsigned long blkcnt, void *buffer);
 struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
 
@@ -181,7 +182,7 @@
 	printf(".");
 }
 
-/*********************************************************************************
+/*******************************************************************************
  * show info on storage devices; 'usb start/init' must be invoked earlier
  * as we only retrieve structures populated during devices initialization
  */
@@ -191,7 +192,7 @@
 
 	if (usb_max_devs > 0) {
 		for (i = 0; i < usb_max_devs; i++) {
-			printf ("  Device %d: ", i);
+			printf("  Device %d: ", i);
 			dev_print(&usb_dev_desc[i]);
 		}
 		return 0;
@@ -201,7 +202,7 @@
 	return 1;
 }
 
-/*********************************************************************************
+/*******************************************************************************
  * scan the usb and reports device info
  * to the user if mode = 1
  * returns current device or -1 if no
@@ -214,67 +215,69 @@
 	/* GJ */
 	memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
 
-	if(mode==1) {
+	if (mode == 1)
 		printf("       scanning bus for storage devices... ");
-	}
+
 	usb_disable_asynch(1); /* asynch transfer not allowed */
 
-	for(i=0;i<USB_MAX_STOR_DEV;i++) {
-		memset(&usb_dev_desc[i],0,sizeof(block_dev_desc_t));
-		usb_dev_desc[i].target=0xff;
-		usb_dev_desc[i].if_type=IF_TYPE_USB;
-		usb_dev_desc[i].dev=i;
-		usb_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
-		usb_dev_desc[i].block_read=usb_stor_read;
+	for (i = 0; i < USB_MAX_STOR_DEV; i++) {
+		memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
+		usb_dev_desc[i].target = 0xff;
+		usb_dev_desc[i].if_type = IF_TYPE_USB;
+		usb_dev_desc[i].dev = i;
+		usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
+		usb_dev_desc[i].block_read = usb_stor_read;
 	}
 
-	usb_max_devs=0;
-	for(i=0;i<USB_MAX_DEVICE;i++) {
-		dev=usb_get_dev_index(i); /* get device */
-		USB_STOR_PRINTF("i=%d\n",i);
-		if(dev==NULL) {
+	usb_max_devs = 0;
+	for (i = 0; i < USB_MAX_DEVICE; i++) {
+		dev = usb_get_dev_index(i); /* get device */
+		USB_STOR_PRINTF("i=%d\n", i);
+		if (dev == NULL)
 			break; /* no more devices avaiable */
-		}
-		if(usb_storage_probe(dev,0,&usb_stor[usb_max_devs])) { /* ok, it is a storage devices */
-			/* get info and fill it in */
-			if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs]))
+
+		if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
+			/* ok, it is a storage devices
+			 * get info and fill it in
+			 */
+			if (usb_stor_get_info(dev, &usb_stor[usb_max_devs],
+						&usb_dev_desc[usb_max_devs]))
 				usb_max_devs++;
-		} /* if storage device */
-		if(usb_max_devs==USB_MAX_STOR_DEV) {
-			printf("max USB Storage Device reached: %d stopping\n",usb_max_devs);
+		}
+		/* if storage device */
+		if (usb_max_devs == USB_MAX_STOR_DEV) {
+			printf("max USB Storage Device reached: %d stopping\n",
+				usb_max_devs);
 			break;
 		}
 	} /* for */
 
 	usb_disable_asynch(0); /* asynch transfer allowed */
 	printf("%d Storage Device(s) found\n", usb_max_devs);
-	if(usb_max_devs>0)
+	if (usb_max_devs > 0)
 		return 0;
-	else
-		return-1;
+	return -1;
 }
 
 static int usb_stor_irq(struct usb_device *dev)
 {
 	struct us_data *us;
-	us=(struct us_data *)dev->privptr;
+	us = (struct us_data *)dev->privptr;
 
-	if(us->ip_wanted) {
-		us->ip_wanted=0;
-	}
+	if (us->ip_wanted)
+		us->ip_wanted = 0;
 	return 0;
 }
 
 
 #ifdef	USB_STOR_DEBUG
 
-static void usb_show_srb(ccb * pccb)
+static void usb_show_srb(ccb *pccb)
 {
 	int i;
-	printf("SRB: len %d datalen 0x%lX\n ",pccb->cmdlen,pccb->datalen);
-	for(i=0;i<12;i++) {
-		printf("%02X ",pccb->cmd[i]);
-	}
+	printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
+	for (i = 0; i < 12; i++)
+		printf("%02X ", pccb->cmd[i]);
 	printf("\n");
 }
 
@@ -322,11 +325,14 @@
 			USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
 				  (unsigned int)buf, this_xfer, 11 - maxtry);
 			result = usb_bulk_msg(us->pusb_dev, pipe, buf,
-					      this_xfer, &partial, USB_CNTL_TIMEOUT*5);
+					      this_xfer, &partial,
+					      USB_CNTL_TIMEOUT * 5);
 			USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
 				  result, partial, this_xfer);
-			if(us->pusb_dev->status!=0) {
-				/* if we stall, we need to clear it before we go on */
+			if (us->pusb_dev->status != 0) {
+				/* if we stall, we need to clear it before
+				 * we go on
+				 */
 #ifdef USB_STOR_DEBUG
 				display_int_status(us->pusb_dev->status);
 #endif
@@ -334,9 +340,9 @@
 					USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
 					stat = us->pusb_dev->status;
 					usb_clear_halt(us->pusb_dev, pipe);
-					us->pusb_dev->status=stat;
-					if(this_xfer == partial) {
-						USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n",us->pusb_dev->status);
+					us->pusb_dev->status = stat;
+					if (this_xfer == partial) {
+						USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n", us->pusb_dev->status);
 						return 0;
 					}
 					else
@@ -346,12 +352,15 @@
 					USB_STOR_PRINTF("Device NAKed bulk_msg\n");
 					return result;
 				}
-				if(this_xfer == partial) {
-					USB_STOR_PRINTF("bulk transferred with error %d, but data ok\n",us->pusb_dev->status);
+				USB_STOR_PRINTF("bulk transferred with error");
+				if (this_xfer == partial) {
+					USB_STOR_PRINTF(" %d, but data ok\n",
+							us->pusb_dev->status);
 					return 0;
 				}
 				/* if our try counter reaches 0, bail out */
-				USB_STOR_PRINTF("bulk transferred with error %d, data %d\n",us->pusb_dev->status,partial);
+					USB_STOR_PRINTF(" %d, data %d\n",
+						us->pusb_dev->status, partial);
 				if (!maxtry--)
 						return result;
 			}
@@ -359,7 +368,7 @@
 			this_xfer -= partial;
 			buf += partial;
 			/* continue until this transfer is done */
-		} while ( this_xfer );
+		} while (this_xfer);
 	}
 
 	/* if we get here, we're done and successful */
@@ -386,29 +395,33 @@
 	 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
 	 */
 	USB_STOR_PRINTF("BBB_reset\n");
-	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-				 US_BBB_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT*5);
+	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
+				 US_BBB_RESET,
+				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
 
-	if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED))
-	{
+	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
 		USB_STOR_PRINTF("RESET:stall\n");
 		return -1;
 	}
 
 	/* long wait for reset */
 	wait_ms(150);
-	USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n",result,us->pusb_dev->status);
+	USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n", result,
+			us->pusb_dev->status);
 	pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
 	result = usb_clear_halt(us->pusb_dev, pipe);
 	/* long wait for reset */
 	wait_ms(150);
-	USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",result,us->pusb_dev->status);
+	USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",
+			result, us->pusb_dev->status);
 	/* long wait for reset */
 	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
 	result = usb_clear_halt(us->pusb_dev, pipe);
 	wait_ms(150);
-	USB_STOR_PRINTF("BBB_reset result %d: status %X clearing OUT endpoint\n",result,us->pusb_dev->status);
+	USB_STOR_PRINTF("BBB_reset result %d: status %X"
+			" clearing OUT endpoint\n", result,
+			us->pusb_dev->status);
 	USB_STOR_PRINTF("BBB_reset done\n");
 	return 0;
 }
@@ -423,16 +436,20 @@
 	int result;
 
 	USB_STOR_PRINTF("CB_reset\n");
-	memset(cmd, 0xFF, sizeof(cmd));
+	memset(cmd, 0xff, sizeof(cmd));
 	cmd[0] = SCSI_SEND_DIAG;
 	cmd[1] = 4;
-	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-				 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, cmd, sizeof(cmd), USB_CNTL_TIMEOUT*5);
+	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
+				 US_CBI_ADSC,
+				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				 0, us->ifnum, cmd, sizeof(cmd),
+				 USB_CNTL_TIMEOUT * 5);
 
 	/* long wait for reset */
 	wait_ms(1500);
-	USB_STOR_PRINTF("CB_reset result %d: status %X clearing endpoint halt\n",result,us->pusb_dev->status);
+	USB_STOR_PRINTF("CB_reset result %d: status %X"
+			" clearing endpoint halt\n", result,
+			us->pusb_dev->status);
 	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
 	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
 
@@ -455,9 +472,11 @@
 	dir_in = US_DIRECTION(srb->cmd[0]);
 
 #ifdef BBB_COMDAT_TRACE
-	printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n", dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen, srb->pdata);
+	printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
+		dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
+		srb->pdata);
 	if (srb->cmdlen) {
-		for(result = 0;result < srb->cmdlen;result++)
+		for (result = 0; result < srb->cmdlen; result++)
 			printf("cmd[%d] %#x ", result, srb->cmd[result]);
 		printf("\n");
 	}
@@ -474,13 +493,14 @@
 	cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
 	cbw.dCBWTag = cpu_to_le32(CBWTag++);
 	cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
-	cbw.bCBWFlags = (dir_in? CBWFLAGS_IN : CBWFLAGS_OUT);
+	cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
 	cbw.bCBWLUN = srb->lun;
 	cbw.bCDBLength = srb->cmdlen;
 	/* copy the command data into the CBW command data buffer */
 	/* DST SRC LEN!!! */
 	memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
-	result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);
+	result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
+			      &actlen, USB_CNTL_TIMEOUT * 5);
 	if (result < 0)
 		USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
 	return result;
@@ -492,46 +512,61 @@
 int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
 {
 	int result = 0;
-	int dir_in,retry;
+	int dir_in, retry;
 	unsigned int pipe;
 	unsigned long status;
 
-	retry=5;
-		dir_in=US_DIRECTION(srb->cmd[0]);
+	retry = 5;
+	dir_in = US_DIRECTION(srb->cmd[0]);
 
-		if(dir_in)
-			pipe=usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-		else
-			pipe=usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-	while(retry--) {
-		USB_STOR_PRINTF("CBI gets a command: Try %d\n",5-retry);
+	if (dir_in)
+		pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+	else
+		pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+
+	while (retry--) {
+		USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
 #ifdef USB_STOR_DEBUG
 		usb_show_srb(srb);
 #endif
 		/* let's send the command via the control pipe */
-		result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-					 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		result = usb_control_msg(us->pusb_dev,
+					 usb_sndctrlpipe(us->pusb_dev , 0),
+					 US_CBI_ADSC,
+					 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 					 0, us->ifnum,
-					 srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);
-		USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status);
+					 srb->cmd, srb->cmdlen,
+					 USB_CNTL_TIMEOUT * 5);
+		USB_STOR_PRINTF("CB_transport: control msg returned %d,"
+				" status %X\n", result, us->pusb_dev->status);
 		/* check the return code for the command */
 		if (result < 0) {
-			if(us->pusb_dev->status & USB_ST_STALLED) {
-				status=us->pusb_dev->status;
-				USB_STOR_PRINTF(" stall during command found, clear pipe\n");
-				usb_clear_halt(us->pusb_dev,  usb_sndctrlpipe(us->pusb_dev,0));
-				us->pusb_dev->status=status;
+			if (us->pusb_dev->status & USB_ST_STALLED) {
+				status = us->pusb_dev->status;
+				USB_STOR_PRINTF(" stall during command found,"
+						" clear pipe\n");
+				usb_clear_halt(us->pusb_dev,
+					      usb_sndctrlpipe(us->pusb_dev, 0));
+				us->pusb_dev->status = status;
 			}
-			USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status);
+			USB_STOR_PRINTF(" error during command %02X"
+					" Stat = %X\n", srb->cmd[0],
+					us->pusb_dev->status);
 			return result;
 		}
 		/* transfer the data payload for this command, if one exists*/
 
-		USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen);
+		USB_STOR_PRINTF("CB_transport: control msg returned %d,"
+				" direction is %s to go 0x%lx\n", result,
+				dir_in ? "IN" : "OUT", srb->datalen);
 		if (srb->datalen) {
-			result = us_one_transfer(us, pipe, (char *)srb->pdata,srb->datalen);
-			USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len);
-			if(!(us->pusb_dev->status & USB_ST_NAK_REC))
+			result = us_one_transfer(us, pipe, (char *)srb->pdata,
+						 srb->datalen);
+			USB_STOR_PRINTF("CBI attempted to transfer data,"
+					" result is %d status %lX, len %d\n",
+					result, us->pusb_dev->status,
+					us->pusb_dev->act_len);
+			if (!(us->pusb_dev->status & USB_ST_NAK_REC))
 				break;
 		} /* if (srb->datalen) */
 		else
@@ -543,21 +578,21 @@
 }
 
 
-int usb_stor_CBI_get_status (ccb * srb, struct us_data *us)
+int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
 {
 	int timeout;
 
 	us->ip_wanted = 1;
-	submit_int_msg (us->pusb_dev, us->irqpipe,
+	submit_int_msg(us->pusb_dev, us->irqpipe,
 			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
 	timeout = 1000;
 	while (timeout--) {
 		if ((volatile int *) us->ip_wanted == 0)
 			break;
-		wait_ms (10);
+		wait_ms(10);
 	}
 	if (us->ip_wanted) {
-		printf ("	Did not get interrupt on CBI\n");
+		printf("	Did not get interrupt on CBI\n");
 		us->ip_wanted = 0;
 		return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -596,9 +631,9 @@
 	int result;
 
 	/* ENDPOINT_HALT = 0, so set value to 0 */
-	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
 				USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
-				0, endpt, 0, 0, USB_CNTL_TIMEOUT*5);
+				0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
 	return result;
 }
 
@@ -638,12 +673,14 @@
 		pipe = pipein;
 	else
 		pipe = pipeout;
-	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);
+	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
+			      &data_actlen, USB_CNTL_TIMEOUT * 5);
 	/* special handling of STALL in DATA phase */
-	if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
+	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
 		USB_STOR_PRINTF("DATA:stall\n");
 		/* clear the STALL on the endpoint */
-		result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);
+		result = usb_stor_BBB_clear_endpt_stall(us,
+					dir_in ? us->ep_in : us->ep_out);
 		if (result >= 0)
 			/* continue on to STATUS phase */
 			goto st;
@@ -660,15 +697,16 @@
 	printf("\n");
 #endif
 	/* STATUS phase + error handling */
-   st:
+st:
 	retry = 0;
-   again:
+again:
 	USB_STOR_PRINTF("STATUS phase\n");
 	result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
 				&actlen, USB_CNTL_TIMEOUT*5);
 
 	/* special handling of STALL in STATUS phase */
-	if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {
+	if ((result < 0) && (retry < 1) &&
+	    (us->pusb_dev->status & USB_ST_STALLED)) {
 		USB_STOR_PRINTF("STATUS:stall\n");
 		/* clear the STALL on the endpoint */
 		result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
@@ -722,32 +760,33 @@
 
 int usb_stor_CB_transport(ccb *srb, struct us_data *us)
 {
-	int result,status;
+	int result, status;
 	ccb *psrb;
 	ccb reqsrb;
-	int retry,notready;
+	int retry, notready;
 
 	psrb = &reqsrb;
-	status=USB_STOR_TRANSPORT_GOOD;
-	retry=0;
-	notready=0;
+	status = USB_STOR_TRANSPORT_GOOD;
+	retry = 0;
+	notready = 0;
 	/* issue the command */
 do_retry:
-	result=usb_stor_CB_comdat(srb,us);
-	USB_STOR_PRINTF("command / Data returned %d, status %X\n",result,us->pusb_dev->status);
+	result = usb_stor_CB_comdat(srb, us);
+	USB_STOR_PRINTF("command / Data returned %d, status %X\n",
+			result, us->pusb_dev->status);
 	/* if this is an CBI Protocol, get IRQ */
-	if(us->protocol==US_PR_CBI) {
-		status=usb_stor_CBI_get_status(srb,us);
+	if (us->protocol == US_PR_CBI) {
+		status = usb_stor_CBI_get_status(srb, us);
 		/* if the status is error, report it */
-		if(status==USB_STOR_TRANSPORT_ERROR) {
+		if (status == USB_STOR_TRANSPORT_ERROR) {
 			USB_STOR_PRINTF(" USB CBI Command Error\n");
 			return status;
 		}
-		srb->sense_buf[12]=(unsigned char)(us->ip_data>>8);
-		srb->sense_buf[13]=(unsigned char)(us->ip_data&0xff);
-		if(!us->ip_data) {
-		/* if the status is good, report it */
-			if(status==USB_STOR_TRANSPORT_GOOD) {
+		srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
+		srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
+		if (!us->ip_data) {
+			/* if the status is good, report it */
+			if (status == USB_STOR_TRANSPORT_GOOD) {
 				USB_STOR_PRINTF(" USB CBI Command Good\n");
 				return status;
 			}
@@ -755,51 +794,62 @@
 	}
 	/* do we have to issue an auto request? */
 	/* HERE we have to check the result */
-	if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
-		USB_STOR_PRINTF("ERROR %X\n",us->pusb_dev->status);
+	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
+		USB_STOR_PRINTF("ERROR %X\n", us->pusb_dev->status);
 		us->transport_reset(us);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
-	if((us->protocol==US_PR_CBI) &&
-			((srb->cmd[0]==SCSI_REQ_SENSE) ||
-			(srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */
+	if ((us->protocol == US_PR_CBI) &&
+	    ((srb->cmd[0] == SCSI_REQ_SENSE) ||
+	    (srb->cmd[0] == SCSI_INQUIRY))) {
+		/* do not issue an autorequest after request sense */
 		USB_STOR_PRINTF("No auto request and good\n");
 		return USB_STOR_TRANSPORT_GOOD;
 	}
 	/* issue an request_sense */
-	memset(&psrb->cmd[0],0,12);
-	psrb->cmd[0]=SCSI_REQ_SENSE;
-	psrb->cmd[1]=srb->lun<<5;
-	psrb->cmd[4]=18;
-	psrb->datalen=18;
+	memset(&psrb->cmd[0], 0, 12);
+	psrb->cmd[0] = SCSI_REQ_SENSE;
+	psrb->cmd[1] = srb->lun << 5;
+	psrb->cmd[4] = 18;
+	psrb->datalen = 18;
 	psrb->pdata = &srb->sense_buf[0];
-	psrb->cmdlen=12;
+	psrb->cmdlen = 12;
 	/* issue the command */
-	result=usb_stor_CB_comdat(psrb,us);
-	USB_STOR_PRINTF("auto request returned %d\n",result);
+	result = usb_stor_CB_comdat(psrb, us);
+	USB_STOR_PRINTF("auto request returned %d\n", result);
 	/* if this is an CBI Protocol, get IRQ */
-	if(us->protocol==US_PR_CBI) {
-		status=usb_stor_CBI_get_status(psrb,us);
-	}
-	if((result<0)&&!(us->pusb_dev->status & USB_ST_STALLED)) {
-		USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status);
+	if (us->protocol == US_PR_CBI)
+		status = usb_stor_CBI_get_status(psrb, us);
+
+	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
+		USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",
+				us->pusb_dev->status);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
-	USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+	USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
+			srb->sense_buf[0], srb->sense_buf[2],
+			srb->sense_buf[12], srb->sense_buf[13]);
 	/* Check the auto request result */
-	if((srb->sense_buf[2]==0) &&
-		 (srb->sense_buf[12]==0) &&
-		 (srb->sense_buf[13]==0)) /* ok, no sense */
+	if ((srb->sense_buf[2] == 0) &&
+	    (srb->sense_buf[12] == 0) &&
+	    (srb->sense_buf[13] == 0)) {
+		/* ok, no sense */
 		return USB_STOR_TRANSPORT_GOOD;
+	}
+
 	/* Check the auto request result */
-	switch(srb->sense_buf[2]) {
-	case 0x01: /* Recovered Error */
+	switch (srb->sense_buf[2]) {
+	case 0x01:
+		/* Recovered Error */
 		return USB_STOR_TRANSPORT_GOOD;
 		break;
-	case 0x02: /* Not Ready */
-		if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
-			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n",
-				srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+	case 0x02:
+		/* Not Ready */
+		if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
+			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
+			       " 0x%02X (NOT READY)\n", srb->cmd[0],
+				srb->sense_buf[0], srb->sense_buf[2],
+				srb->sense_buf[12], srb->sense_buf[13]);
 			return USB_STOR_TRANSPORT_FAILED;
 		} else {
 			wait_ms(100);
@@ -807,113 +857,116 @@
 		}
 		break;
 	default:
-		if(retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
-			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
-				srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+		if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
+			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
+			       " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
+				srb->sense_buf[2], srb->sense_buf[12],
+				srb->sense_buf[13]);
 			return USB_STOR_TRANSPORT_FAILED;
-		} else {
+		} else
 			goto do_retry;
-		}
 		break;
 	}
 	return USB_STOR_TRANSPORT_FAILED;
 }
 
 
-static int usb_inquiry(ccb *srb,struct us_data *ss)
+static int usb_inquiry(ccb *srb, struct us_data *ss)
 {
-	int retry,i;
-	retry=5;
+	int retry, i;
+	retry = 5;
 	do {
-		memset(&srb->cmd[0],0,12);
-		srb->cmd[0]=SCSI_INQUIRY;
-		srb->cmd[1]=srb->lun<<5;
-		srb->cmd[4]=36;
-		srb->datalen=36;
-		srb->cmdlen=12;
-		i=ss->transport(srb,ss);
-		USB_STOR_PRINTF("inquiry returns %d\n",i);
-		if(i==0)
+		memset(&srb->cmd[0], 0, 12);
+		srb->cmd[0] = SCSI_INQUIRY;
+		srb->cmd[1] = srb->lun<<5;
+		srb->cmd[4] = 36;
+		srb->datalen = 36;
+		srb->cmdlen = 12;
+		i = ss->transport(srb, ss);
+		USB_STOR_PRINTF("inquiry returns %d\n", i);
+		if (i == 0)
 			break;
-	} while(retry--);
+	} while (retry--);
 
-	if(!retry) {
+	if (!retry) {
 		printf("error in inquiry\n");
 		return -1;
 	}
 	return 0;
 }
 
-static int usb_request_sense(ccb *srb,struct us_data *ss)
+static int usb_request_sense(ccb *srb, struct us_data *ss)
 {
 	char *ptr;
 
-	ptr=(char *)srb->pdata;
-	memset(&srb->cmd[0],0,12);
-	srb->cmd[0]=SCSI_REQ_SENSE;
-	srb->cmd[1]=srb->lun<<5;
-	srb->cmd[4]=18;
-	srb->datalen=18;
+	ptr = (char *)srb->pdata;
+	memset(&srb->cmd[0], 0, 12);
+	srb->cmd[0] = SCSI_REQ_SENSE;
+	srb->cmd[1] = srb->lun << 5;
+	srb->cmd[4] = 18;
+	srb->datalen = 18;
 	srb->pdata = &srb->sense_buf[0];
-	srb->cmdlen=12;
-	ss->transport(srb,ss);
-	USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
-	srb->pdata=(uchar *)ptr;
+	srb->cmdlen = 12;
+	ss->transport(srb, ss);
+	USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
+			srb->sense_buf[2], srb->sense_buf[12],
+			srb->sense_buf[13]);
+	srb->pdata = (uchar *)ptr;
 	return 0;
 }
 
-static int usb_test_unit_ready(ccb *srb,struct us_data *ss)
+static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
 {
 	int retries = 10;
 
 	do {
-		memset(&srb->cmd[0],0,12);
-		srb->cmd[0]=SCSI_TST_U_RDY;
-		srb->cmd[1]=srb->lun<<5;
-		srb->datalen=0;
-		srb->cmdlen=12;
-		if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) {
+		memset(&srb->cmd[0], 0, 12);
+		srb->cmd[0] = SCSI_TST_U_RDY;
+		srb->cmd[1] = srb->lun << 5;
+		srb->datalen = 0;
+		srb->cmdlen = 12;
+		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
 			return 0;
-		}
-		usb_request_sense (srb, ss);
-		wait_ms (100);
-	} while(retries--);
+		usb_request_sense(srb, ss);
+		wait_ms(100);
+	} while (retries--);
 
 	return -1;
 }
 
-static int usb_read_capacity(ccb *srb,struct us_data *ss)
+static int usb_read_capacity(ccb *srb, struct us_data *ss)
 {
 	int retry;
-	retry = 3; /* retries */
+	/* XXX retries */
+	retry = 3;
 	do {
-		memset(&srb->cmd[0],0,12);
-		srb->cmd[0]=SCSI_RD_CAPAC;
-		srb->cmd[1]=srb->lun<<5;
-		srb->datalen=8;
-		srb->cmdlen=12;
-		if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) {
+		memset(&srb->cmd[0], 0, 12);
+		srb->cmd[0] = SCSI_RD_CAPAC;
+		srb->cmd[1] = srb->lun << 5;
+		srb->datalen = 8;
+		srb->cmdlen = 12;
+		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
 			return 0;
-		}
-	} while(retry--);
+	} while (retry--);
 
 	return -1;
 }
 
-static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigned short blocks)
+static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
+		       unsigned short blocks)
 {
-	memset(&srb->cmd[0],0,12);
-	srb->cmd[0]=SCSI_READ10;
-	srb->cmd[1]=srb->lun<<5;
-	srb->cmd[2]=((unsigned char) (start>>24))&0xff;
-	srb->cmd[3]=((unsigned char) (start>>16))&0xff;
-	srb->cmd[4]=((unsigned char) (start>>8))&0xff;
-	srb->cmd[5]=((unsigned char) (start))&0xff;
-	srb->cmd[7]=((unsigned char) (blocks>>8))&0xff;
-	srb->cmd[8]=(unsigned char) blocks & 0xff;
-	srb->cmdlen=12;
-	USB_STOR_PRINTF("read10: start %lx blocks %x\n",start,blocks);
-	return ss->transport(srb,ss);
+	memset(&srb->cmd[0], 0, 12);
+	srb->cmd[0] = SCSI_READ10;
+	srb->cmd[1] = srb->lun << 5;
+	srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
+	srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
+	srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
+	srb->cmd[5] = ((unsigned char) (start)) & 0xff;
+	srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
+	srb->cmd[8] = (unsigned char) blocks & 0xff;
+	srb->cmdlen = 12;
+	USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
+	return ss->transport(srb, ss);
 }
 
 
@@ -933,85 +986,94 @@
 	const unsigned char max_vendor_len = 40;
 	const unsigned char max_product_len = 20;
 	if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
-		strncpy ((char *)vendor, "SMSC", max_vendor_len);
-		strncpy ((char *)product, "Flash Media Cntrller", max_product_len);
+		strncpy((char *)vendor, "SMSC", max_vendor_len);
+		strncpy((char *)product, "Flash Media Cntrller",
+			max_product_len);
 	}
 }
 #endif /* CONFIG_USB_BIN_FIXUP */
 
 #define USB_MAX_READ_BLK 20
 
-unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer)
+unsigned long usb_stor_read(int device, unsigned long blknr,
+			    unsigned long blkcnt, void *buffer)
 {
-	unsigned long start,blks, buf_addr;
+	unsigned long start, blks, buf_addr;
 	unsigned short smallblks;
 	struct usb_device *dev;
-	int retry,i;
+	int retry, i;
 	ccb *srb = &usb_ccb;
 
 	if (blkcnt == 0)
 		return 0;
 
 	device &= 0xff;
-	/* Setup  device
-	 */
-	USB_STOR_PRINTF("\nusb_read: dev %d \n",device);
-	dev=NULL;
-	for(i=0;i<USB_MAX_DEVICE;i++) {
-		dev=usb_get_dev_index(i);
-		if(dev==NULL) {
+	/* Setup  device */
+	USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
+	dev = NULL;
+	for (i = 0; i < USB_MAX_DEVICE; i++) {
+		dev = usb_get_dev_index(i);
+		if (dev == NULL)
 			return 0;
-		}
-		if(dev->devnum==usb_dev_desc[device].target)
+		if (dev->devnum == usb_dev_desc[device].target)
 			break;
 	}
 
 	usb_disable_asynch(1); /* asynch transfer not allowed */
-	srb->lun=usb_dev_desc[device].lun;
-	buf_addr=(unsigned long)buffer;
-	start=blknr;
-	blks=blkcnt;
-	if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr)) {
-		printf("Device NOT ready\n   Request Sense returned %02X %02X %02X\n",
-			srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+	srb->lun = usb_dev_desc[device].lun;
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
+		printf("Device NOT ready\n   Request Sense returned %02X %02X"
+		       " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
+		       srb->sense_buf[13]);
 		return 0;
 	}
-	USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks, buf_addr);
+
+	USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
+			" buffer %lx\n", device, start, blks, buf_addr);
+
 	do {
-		retry=2;
-		srb->pdata=(unsigned char *)buf_addr;
-		if(blks>USB_MAX_READ_BLK) {
-			smallblks=USB_MAX_READ_BLK;
-		} else {
-			smallblks=(unsigned short) blks;
-		}
+		/* XXX need some comment here */
+		retry = 2;
+		srb->pdata = (unsigned char *)buf_addr;
+		if (blks > USB_MAX_READ_BLK)
+			smallblks = USB_MAX_READ_BLK;
+		else
+			smallblks = (unsigned short) blks;
 retry_it:
-		if(smallblks==USB_MAX_READ_BLK)
+		if (smallblks == USB_MAX_READ_BLK)
 			usb_show_progress();
-		srb->datalen=usb_dev_desc[device].blksz * smallblks;
-		srb->pdata=(unsigned char *)buf_addr;
-		if(usb_read_10(srb,(struct us_data *)dev->privptr, start, smallblks)) {
+		srb->datalen = usb_dev_desc[device].blksz * smallblks;
+		srb->pdata = (unsigned char *)buf_addr;
+		if (usb_read_10(srb, (struct us_data *)dev->privptr, start,
+		    smallblks)) {
 			USB_STOR_PRINTF("Read ERROR\n");
-			usb_request_sense(srb,(struct us_data *)dev->privptr);
-			if(retry--)
+			usb_request_sense(srb, (struct us_data *)dev->privptr);
+			if (retry--)
 				goto retry_it;
-			blkcnt-=blks;
+			blkcnt -= blks;
 			break;
 		}
-		start+=smallblks;
-		blks-=smallblks;
-		buf_addr+=srb->datalen;
-	} while(blks!=0);
-	USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
+		start += smallblks;
+		blks -= smallblks;
+		buf_addr += srb->datalen;
+	} while (blks != 0);
+
+	USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
+			start, smallblks, buf_addr);
+
 	usb_disable_asynch(0); /* asynch transfer allowed */
-	if(blkcnt>=USB_MAX_READ_BLK)
+	if (blkcnt >= USB_MAX_READ_BLK)
 		printf("\n");
-	return(blkcnt);
+	return blkcnt;
 }
 
 
 /* Probe to see if a new device is actually a Storage device */
-int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss)
+int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
+		      struct us_data *ss)
 {
 	struct usb_interface_descriptor *iface;
 	int i;
@@ -1025,8 +1087,11 @@
 
 #if 0
 	/* this is the place to patch some storage devices */
-	USB_STOR_PRINTF("iVendor %X iProduct %X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
-	if ((dev->descriptor.idVendor) == 0x066b && (dev->descriptor.idProduct) == 0x0103) {
+	USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
+			dev->descriptor.idProduct);
+
+	if ((dev->descriptor.idVendor) == 0x066b &&
+	    (dev->descriptor.idProduct) == 0x0103) {
 		USB_STOR_PRINTF("patched for E-USB\n");
 		protocol = US_PR_CB;
 		subclass = US_SC_UFI;	    /* an assumption */
@@ -1095,19 +1160,20 @@
 	 */
 	for (i = 0; i < iface->bNumEndpoints; i++) {
 		/* is it an BULK endpoint? */
-		if ((iface->ep_desc[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK)
-		    == USB_ENDPOINT_XFER_BULK) {
+		if ((iface->ep_desc[i].bmAttributes &
+		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
 			if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
 				ss->ep_in = iface->ep_desc[i].bEndpointAddress &
 					USB_ENDPOINT_NUMBER_MASK;
 			else
-				ss->ep_out = iface->ep_desc[i].bEndpointAddress &
+				ss->ep_out =
+					iface->ep_desc[i].bEndpointAddress &
 					USB_ENDPOINT_NUMBER_MASK;
 		}
 
 		/* is it an interrupt endpoint? */
-		if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		    == USB_ENDPOINT_XFER_INT) {
+		if ((iface->ep_desc[i].bmAttributes &
+		    USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
 			ss->ep_int = iface->ep_desc[i].bEndpointAddress &
 				USB_ENDPOINT_NUMBER_MASK;
 			ss->irqinterval = iface->ep_desc[i].bInterval;
@@ -1130,26 +1196,28 @@
 	 */
 	if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
 	    ss->subclass != US_SC_8070) {
-		printf("Sorry, protocol %d not yet supported.\n",ss->subclass);
+		printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
 		return 0;
 	}
-	if(ss->ep_int) { /* we had found an interrupt endpoint, prepare irq pipe */
-		/* set up the IRQ pipe and handler */
-
+	if (ss->ep_int) {
+		/* we had found an interrupt endpoint, prepare irq pipe
+		 * set up the IRQ pipe and handler
+		 */
 		ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
 		ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
 		ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
-		dev->irq_handle=usb_stor_irq;
+		dev->irq_handle = usb_stor_irq;
 	}
-	dev->privptr=(void *)ss;
+	dev->privptr = (void *)ss;
 	return 1;
 }
 
-int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t *dev_desc)
+int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
+		      block_dev_desc_t *dev_desc)
 {
-	unsigned char perq,modi;
+	unsigned char perq, modi;
 	unsigned long cap[2];
-	unsigned long *capacity,*blksz;
+	unsigned long *capacity, *blksz;
 	ccb *pccb = &usb_ccb;
 
 	/* for some reasons a couple of devices would not survive this reset */
@@ -1157,7 +1225,6 @@
 	    /* Sony USM256E */
 	    (dev->descriptor.idVendor == 0x054c &&
 	     dev->descriptor.idProduct == 0x019e)
-
 	    ||
 	    /* USB007 Mini-USB2 Flash Drive */
 	    (dev->descriptor.idVendor == 0x066f &&
@@ -1166,6 +1233,13 @@
 	    /* SanDisk Corporation Cruzer Micro 20044318410546613953 */
 	    (dev->descriptor.idVendor == 0x0781 &&
 	     dev->descriptor.idProduct == 0x5151)
+	    ||
+	    /*
+	     * SanDisk Corporation U3 Cruzer Micro 1/4GB
+	     * Flash Drive 000016244373FFB4
+	     */
+	    (dev->descriptor.idVendor == 0x0781 &&
+	     dev->descriptor.idProduct == 0x5406)
 	    )
 		USB_STOR_PRINTF("usb_stor_get_info: skipping RESET..\n");
 	else
@@ -1175,17 +1249,20 @@
 
 	dev_desc->target = dev->devnum;
 	pccb->lun = dev_desc->lun;
-	USB_STOR_PRINTF(" address %d\n",dev_desc->target);
+	USB_STOR_PRINTF(" address %d\n", dev_desc->target);
 
-	if(usb_inquiry(pccb,ss))
+	if (usb_inquiry(pccb, ss))
 		return -1;
 
 	perq = usb_stor_buf[0];
 	modi = usb_stor_buf[1];
-	if((perq & 0x1f) == 0x1f) {
-		return 0; /* skip unknown devices */
+
+	if ((perq & 0x1f) == 0x1f) {
+		/* skip unknown devices */
+		return 0;
 	}
-	if((modi&0x80) == 0x80) {/* drive is removable */
+	if ((modi&0x80) == 0x80) {
+		/* drive is removable */
 		dev_desc->removable = 1;
 	}
 	memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
@@ -1195,29 +1272,34 @@
 	dev_desc->product[16] = 0;
 	dev_desc->revision[4] = 0;
 #ifdef CONFIG_USB_BIN_FIXUP
-	usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor, (uchar *)dev_desc->product);
+	usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
+		      (uchar *)dev_desc->product);
 #endif /* CONFIG_USB_BIN_FIXUP */
-	USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]);
-	if(usb_test_unit_ready(pccb,ss)) {
-		printf("Device NOT ready\n   Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]);
-		if(dev_desc->removable == 1) {
+	USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
+			usb_stor_buf[3]);
+	if (usb_test_unit_ready(pccb, ss)) {
+		printf("Device NOT ready\n"
+		       "   Request Sense returned %02X %02X %02X\n",
+		       pccb->sense_buf[2], pccb->sense_buf[12],
+		       pccb->sense_buf[13]);
+		if (dev_desc->removable == 1) {
 			dev_desc->type = perq;
 			return 1;
 		}
-		else
-			return 0;
+		return 0;
 	}
 	pccb->pdata = (unsigned char *)&cap[0];
-	memset(pccb->pdata,0,8);
-	if(usb_read_capacity(pccb,ss) != 0) {
+	memset(pccb->pdata, 0, 8);
+	if (usb_read_capacity(pccb, ss) != 0) {
 		printf("READ_CAP ERROR\n");
 		cap[0] = 2880;
 		cap[1] = 0x200;
 	}
-	USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]);
+	USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
+			cap[1]);
 #if 0
-	if(cap[0]>(0x200000 * 10)) /* greater than 10 GByte */
-		cap[0]>>=16;
+	if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
+		cap[0] >>= 16;
 #endif
 	cap[0] = cpu_to_be32(cap[0]);
 	cap[1] = cpu_to_be32(cap[1]);
@@ -1226,15 +1308,16 @@
 	cap[0] += 1;
 	capacity = &cap[0];
 	blksz = &cap[1];
-	USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz);
+	USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
+			*capacity, *blksz);
 	dev_desc->lba = *capacity;
 	dev_desc->blksz = *blksz;
 	dev_desc->type = perq;
-	USB_STOR_PRINTF(" address %d\n",dev_desc->target);
-	USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);
+	USB_STOR_PRINTF(" address %d\n", dev_desc->target);
+	USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
 
 	init_part(dev_desc);
 
-	USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);
+	USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
 	return 1;
 }
diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c
index 641f270..9cbd477 100644
--- a/cpu/arm920t/s3c24x0/usb_ohci.c
+++ b/cpu/arm920t/s3c24x0/usb_ohci.c
@@ -29,9 +29,7 @@
  */
 /*
  * IMPORTANT NOTES
- * 1 - you MUST define LITTLEENDIAN in the configuration file for the
- *     board or this driver will NOT work!
- * 2 - this driver is intended for use with USB Mass Storage Devices
+ * 1 - this driver is intended for use with USB Mass Storage Devices
  *     (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
  */
 
diff --git a/cpu/mips/au1x00_usb_ohci.c b/cpu/mips/au1x00_usb_ohci.c
index 17489da..ea02efb 100644
--- a/cpu/mips/au1x00_usb_ohci.c
+++ b/cpu/mips/au1x00_usb_ohci.c
@@ -27,9 +27,7 @@
  */
 /*
  * IMPORTANT NOTES
- * 1 - you MUST define LITTLEENDIAN in the configuration file for the
- *     board or this driver will NOT work!
- * 2 - this driver is intended for use with USB Mass Storage Devices
+ * 1 - this driver is intended for use with USB Mass Storage Devices
  *     (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
  */
 
@@ -56,7 +54,7 @@
 #define USBH_ENABLE_CE (1<<3)
 #define USBH_ENABLE_RD (1<<4)
 
-#ifdef LITTLEENDIAN
+#ifdef __LITTLE_ENDIAN
 #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C)
 #else
 #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE)
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 856f51a..b306a65 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -28,11 +28,18 @@
 # core
 COBJS-y += usbdcore.o
 COBJS-$(CONFIG_USB_OHCI_NEW) += usb_ohci.o
+COBJS-$(CONFIG_USB_EHCI) += usb_ehci_core.o
 
 # host
 COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
 COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
 COBJS-$(CONFIG_USB_SL811HS) += sl811_usb.o
+COBJS-$(CONFIG_USB_EHCI_FSL) += usb_ehci_fsl.o
+COBJS-$(CONFIG_USB_EHCI_PCI) += usb_ehci_pci.o
+COBJS-$(CONFIG_USB_EHCI_IXP4XX) += usb_ehci_ixp.o
+COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
+COBJS-$(CONFIG_USB_DAVINCI) += davinci_usb.o
+COBJS-$(CONFIG_USB_EHCI_VCT) += usb_ehci_vct.o
 
 # device
 ifdef CONFIG_USB_DEVICE
diff --git a/drivers/usb/davinci_usb.c b/drivers/usb/davinci_usb.c
new file mode 100644
index 0000000..e66f660
--- /dev/null
+++ b/drivers/usb/davinci_usb.c
@@ -0,0 +1,106 @@
+/*
+ * TI's Davinci platform specific USB wrapper functions.
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "davinci_usb.h"
+
+/* MUSB platform configuration */
+struct musb_config musb_cfg = {
+	(struct	musb_regs *)MENTOR_USB0_BASE,
+	DAVINCI_USB_TIMEOUT,
+	0
+};
+
+/* MUSB module register overlay */
+struct davinci_usb_regs *dregs;
+
+/*
+ * Enable the USB phy
+ */
+static u8 phy_on(void)
+{
+	u32 timeout;
+
+	/* Wait until the USB phy is turned on */
+	writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN, USBPHY_CTL_PADDR);
+	timeout = musb_cfg.timeout;
+	while (timeout--)
+		if (readl(USBPHY_CTL_PADDR) & USBPHY_PHYCLKGD)
+			return 1;
+
+	/* USB phy was not turned on */
+	return 0;
+}
+
+/*
+ * Disable the USB phy
+ */
+static void phy_off(void)
+{
+	/* powerdown the on-chip PHY and its oscillator */
+	writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, USBPHY_CTL_PADDR);
+}
+
+/*
+ * This function performs Davinci platform specific initialization for usb0.
+ */
+int musb_platform_init(void)
+{
+	u32  revision;
+
+	/* enable USB VBUS */
+	enable_vbus();
+
+	/* start the on-chip USB phy and its pll */
+	if (!phy_on())
+		return -1;
+
+	/* reset the controller */
+	dregs = (struct davinci_usb_regs *)DAVINCI_USB0_BASE;
+	writel(1, &dregs->ctrlr);
+	udelay(5000);
+
+	/* Returns zero if e.g. not clocked */
+	revision = readl(&dregs->version);
+	if (!revision)
+		return -1;
+
+	/* Disable all interrupts */
+	writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_RXINT_MASK |
+			DAVINCI_USB_TXINT_MASK , &dregs->intmsksetr);
+	return 0;
+}
+
+/*
+ * This function performs Davinci platform specific deinitialization for usb0.
+ */
+void musb_platform_deinit(void)
+{
+	/* Turn of the phy */
+	phy_off();
+
+	/* flush any interrupts */
+	writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_TXINT_MASK |
+			DAVINCI_USB_RXINT_MASK , &dregs->intclrr);
+}
diff --git a/drivers/usb/davinci_usb.h b/drivers/usb/davinci_usb.h
new file mode 100644
index 0000000..d270861
--- /dev/null
+++ b/drivers/usb/davinci_usb.h
@@ -0,0 +1,87 @@
+/*
+ * TI's Davinci platform specific USB wrapper functions.
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#ifndef __DAVINCI_USB_H__
+#define __DAVINCI_USB_H__
+
+#include <asm/arch/hardware.h>
+#include "musb_core.h"
+
+/* Base address of DAVINCI usb0 wrapper */
+#define DAVINCI_USB0_BASE 0x01C64000
+
+/* Base address of DAVINCI musb core */
+#define MENTOR_USB0_BASE (DAVINCI_USB0_BASE+0x400)
+
+/*
+ * Davinci platform USB wrapper register overlay. Note: Only the required
+ * registers are included in this structure. It can be expanded as required.
+ */
+struct davinci_usb_regs {
+	u32	version;
+	u32	ctrlr;
+	u32	reserved[0x20];
+	u32	intclrr;
+	u32 	intmskr;
+	u32 	intmsksetr;
+};
+
+#define DAVINCI_USB_TX_ENDPTS_MASK	0x1f /* ep0 + 4 tx */
+#define DAVINCI_USB_RX_ENDPTS_MASK	0x1e /* 4 rx */
+#define DAVINCI_USB_USBINT_SHIFT	16
+#define DAVINCI_USB_TXINT_SHIFT 	0
+#define DAVINCI_USB_RXINT_SHIFT 	8
+#define DAVINCI_INTR_DRVVBUS		0x0100
+
+#define DAVINCI_USB_USBINT_MASK 	0x01ff0000	/* 8 Mentor, DRVVBUS */
+#define DAVINCI_USB_TXINT_MASK \
+		(DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT)
+#define DAVINCI_USB_RXINT_MASK \
+		(DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT)
+#define MGC_BUSCTL_OFFSET(_bEnd, _bOffset) \
+		(0x80 + (8*(_bEnd)) + (_bOffset))
+
+/* Integrated highspeed/otg PHY */
+#define USBPHY_CTL_PADDR	(DAVINCI_SYSTEM_MODULE_BASE + 0x34)
+#define USBPHY_PHYCLKGD 	(1 << 8)
+#define USBPHY_SESNDEN		(1 << 7)	/* v(sess_end) comparator */
+#define USBPHY_VBDTCTEN 	(1 << 6)	/* v(bus) comparator */
+#define USBPHY_PHYPLLON 	(1 << 4)	/* override pll suspend */
+#define USBPHY_CLKO1SEL 	(1 << 3)
+#define USBPHY_OSCPDWN		(1 << 2)
+#define USBPHY_PHYPDWN		(1 << 0)
+
+/* Timeout for Davinci USB module */
+#define DAVINCI_USB_TIMEOUT 0x3FFFFFF
+
+/* IO Expander I2C address and VBUS enable mask */
+#define IOEXP_I2C_ADDR 0x3A
+#define IOEXP_VBUSEN_MASK 1
+
+/* extern functions */
+extern void lpsc_on(unsigned int id);
+extern int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
+extern int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len);
+extern void enable_vbus(void);
+#endif	/* __DAVINCI_USB_H__ */
+
diff --git a/drivers/usb/musb_core.c b/drivers/usb/musb_core.c
new file mode 100644
index 0000000..ec57fc8
--- /dev/null
+++ b/drivers/usb/musb_core.c
@@ -0,0 +1,141 @@
+/*
+ * Mentor USB OTG Core functionality common for both Host and Device
+ * functionality.
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+
+#include "musb_core.h"
+struct musb_regs *musbr;
+
+/*
+ * program the mentor core to start (enable interrupts, dma, etc.)
+ */
+void musb_start(void)
+{
+	u8 devctl;
+
+	/* disable all interrupts */
+	writew(0, &musbr->intrtxe);
+	writew(0, &musbr->intrrxe);
+	writeb(0, &musbr->intrusbe);
+	writeb(0, &musbr->testmode);
+
+	/* put into basic highspeed mode and start session */
+	writeb(MUSB_POWER_HSENAB, &musbr->power);
+#if defined(CONFIG_MUSB_HCD)
+	devctl = readb(&musbr->devctl);
+	writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl);
+#endif
+}
+
+/*
+ * This function configures the endpoint configuration. The musb hcd or musb
+ * device implementation can use this function to configure the endpoints
+ * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints
+ * should not be more than the available FIFO size.
+ *
+ * epinfo	- Pointer to EP configuration table
+ * cnt		- Number of entries in the EP conf table.
+ */
+void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
+{
+	u16 csr;
+	u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */
+	u32 fifosize;
+	u8  idx;
+
+	while (cnt--) {
+		/* prepare fifosize to write to register */
+		fifosize = epinfo->epsize >> 3;
+		idx = ffs(fifosize) - 1;
+
+		writeb(epinfo->epnum, &musbr->index);
+		if (epinfo->epdir) {
+			/* Configure fifo size and fifo base address */
+			writeb(idx, &musbr->txfifosz);
+			writew(fifoaddr >> 3, &musbr->txfifoadd);
+#if defined(CONFIG_MUSB_HCD)
+			/* clear the data toggle bit */
+			csr = readw(&musbr->txcsr);
+			writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
+#endif
+			/* Flush fifo if required */
+			if (csr & MUSB_TXCSR_TXPKTRDY)
+				writew(csr | MUSB_TXCSR_FLUSHFIFO,
+					&musbr->txcsr);
+		} else {
+			/* Configure fifo size and fifo base address */
+			writeb(idx, &musbr->rxfifosz);
+			writew(fifoaddr >> 3, &musbr->rxfifoadd);
+#if defined(CONFIG_MUSB_HCD)
+			/* clear the data toggle bit */
+			csr = readw(&musbr->rxcsr);
+			writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
+#endif
+			/* Flush fifo if required */
+			if (csr & MUSB_RXCSR_RXPKTRDY)
+				writew(csr | MUSB_RXCSR_FLUSHFIFO,
+					&musbr->rxcsr);
+		}
+		fifoaddr += epinfo->epsize;
+		epinfo++;
+	}
+}
+
+/*
+ * This function writes data to endpoint fifo
+ *
+ * ep		- endpoint number
+ * length	- number of bytes to write to FIFO
+ * fifo_data	- Pointer to data buffer that contains the data to write
+ */
+void write_fifo(u8 ep, u32 length, void *fifo_data)
+{
+	u8  *data = (u8 *)fifo_data;
+
+	/* select the endpoint index */
+	writeb(ep, &musbr->index);
+
+	/* write the data to the fifo */
+	while (length--)
+		writeb(*data++, &musbr->fifox[ep]);
+}
+
+/*
+ * This function reads data from endpoint fifo
+ *
+ * ep           - endpoint number
+ * length       - number of bytes to read from FIFO
+ * fifo_data    - pointer to data buffer into which data is read
+ */
+void read_fifo(u8 ep, u32 length, void *fifo_data)
+{
+	u8  *data = (u8 *)fifo_data;
+
+	/* select the endpoint index */
+	writeb(ep, &musbr->index);
+
+	/* read the data to the fifo */
+	while (length--)
+		*data++ = readb(&musbr->fifox[ep]);
+}
diff --git a/drivers/usb/musb_core.h b/drivers/usb/musb_core.h
new file mode 100644
index 0000000..9f5ebe7
--- /dev/null
+++ b/drivers/usb/musb_core.h
@@ -0,0 +1,317 @@
+/******************************************************************
+ * Copyright 2008 Mentor Graphics Corporation
+ * Copyright (C) 2008 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
+ * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
+ * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
+ * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
+ * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
+ * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
+ * GRAPHICS SUPPORT CUSTOMER.
+ ******************************************************************/
+
+#ifndef __MUSB_HDRC_DEFS_H__
+#define __MUSB_HDRC_DEFS_H__
+
+#include <usb.h>
+#include <usb_defs.h>
+#include <asm/io.h>
+
+#define MUSB_EP0_FIFOSIZE	64	/* This is non-configurable */
+
+/* Mentor USB core register overlay structure */
+struct musb_regs {
+	/* common registers */
+	u8	faddr;
+	u8	power;
+	u16	intrtx;
+	u16	intrrx;
+	u16	intrtxe;
+	u16	intrrxe;
+	u8	intrusb;
+	u8	intrusbe;
+	u16	frame;
+	u8	index;
+	u8	testmode;
+	/* indexed registers */
+	u16	txmaxp;
+	u16	txcsr;
+	u16	rxmaxp;
+	u16	rxcsr;
+	u16	rxcount;
+	u8	txtype;
+	u8	txinterval;
+	u8	rxtype;
+	u8	rxinterval;
+	u8	reserved0;
+	u8	fifosize;
+	/* fifo */
+	u32	fifox[16];
+	/* OTG, dynamic FIFO, version & vendor registers */
+	u8	devctl;
+	u8	reserved1;
+	u8	txfifosz;
+	u8	rxfifosz;
+	u16	txfifoadd;
+	u16	rxfifoadd;
+	u32	vcontrol;
+	u16	hwvers;
+	u16	reserved2[5];
+	u8	epinfo;
+	u8	raminfo;
+	u8	linkinfo;
+	u8	vplen;
+	u8	hseof1;
+	u8	fseof1;
+	u8	lseof1;
+	u8	reserved3;
+	/* target address registers */
+	struct musb_tar_regs {
+		u8	txfuncaddr;
+		u8	reserved0;
+		u8	txhubaddr;
+		u8	txhubport;
+		u8	rxfuncaddr;
+		u8	reserved1;
+		u8	rxhubaddr;
+		u8	rxhubport;
+	} tar[16];
+} __attribute((aligned(32)));
+
+/*
+ * MUSB Register bits
+ */
+
+/* POWER */
+#define MUSB_POWER_ISOUPDATE	0x80
+#define MUSB_POWER_SOFTCONN	0x40
+#define MUSB_POWER_HSENAB	0x20
+#define MUSB_POWER_HSMODE	0x10
+#define MUSB_POWER_RESET	0x08
+#define MUSB_POWER_RESUME	0x04
+#define MUSB_POWER_SUSPENDM	0x02
+#define MUSB_POWER_ENSUSPEND	0x01
+#define MUSB_POWER_HSMODE_SHIFT	4
+
+/* INTRUSB */
+#define MUSB_INTR_SUSPEND	0x01
+#define MUSB_INTR_RESUME	0x02
+#define MUSB_INTR_RESET		0x04
+#define MUSB_INTR_BABBLE	0x04
+#define MUSB_INTR_SOF		0x08
+#define MUSB_INTR_CONNECT	0x10
+#define MUSB_INTR_DISCONNECT	0x20
+#define MUSB_INTR_SESSREQ	0x40
+#define MUSB_INTR_VBUSERROR	0x80	/* For SESSION end */
+
+/* DEVCTL */
+#define MUSB_DEVCTL_BDEVICE	0x80
+#define MUSB_DEVCTL_FSDEV	0x40
+#define MUSB_DEVCTL_LSDEV	0x20
+#define MUSB_DEVCTL_VBUS	0x18
+#define MUSB_DEVCTL_VBUS_SHIFT	3
+#define MUSB_DEVCTL_HM		0x04
+#define MUSB_DEVCTL_HR		0x02
+#define MUSB_DEVCTL_SESSION	0x01
+
+/* TESTMODE */
+#define MUSB_TEST_FORCE_HOST	0x80
+#define MUSB_TEST_FIFO_ACCESS	0x40
+#define MUSB_TEST_FORCE_FS	0x20
+#define MUSB_TEST_FORCE_HS	0x10
+#define MUSB_TEST_PACKET	0x08
+#define MUSB_TEST_K		0x04
+#define MUSB_TEST_J		0x02
+#define MUSB_TEST_SE0_NAK	0x01
+
+/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
+#define MUSB_FIFOSZ_DPB		0x10
+/* Allocation size (8, 16, 32, ... 4096) */
+#define MUSB_FIFOSZ_SIZE	0x0f
+
+/* CSR0 */
+#define MUSB_CSR0_FLUSHFIFO	0x0100
+#define MUSB_CSR0_TXPKTRDY	0x0002
+#define MUSB_CSR0_RXPKTRDY	0x0001
+
+/* CSR0 in Peripheral mode */
+#define MUSB_CSR0_P_SVDSETUPEND	0x0080
+#define MUSB_CSR0_P_SVDRXPKTRDY	0x0040
+#define MUSB_CSR0_P_SENDSTALL	0x0020
+#define MUSB_CSR0_P_SETUPEND	0x0010
+#define MUSB_CSR0_P_DATAEND	0x0008
+#define MUSB_CSR0_P_SENTSTALL	0x0004
+
+/* CSR0 in Host mode */
+#define MUSB_CSR0_H_DIS_PING		0x0800
+#define MUSB_CSR0_H_WR_DATATOGGLE	0x0400	/* Set to allow setting: */
+#define MUSB_CSR0_H_DATATOGGLE		0x0200	/* Data toggle control */
+#define MUSB_CSR0_H_NAKTIMEOUT		0x0080
+#define MUSB_CSR0_H_STATUSPKT		0x0040
+#define MUSB_CSR0_H_REQPKT		0x0020
+#define MUSB_CSR0_H_ERROR		0x0010
+#define MUSB_CSR0_H_SETUPPKT		0x0008
+#define MUSB_CSR0_H_RXSTALL		0x0004
+
+/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_CSR0_P_WZC_BITS	\
+	(MUSB_CSR0_P_SENTSTALL)
+#define MUSB_CSR0_H_WZC_BITS	\
+	(MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
+	| MUSB_CSR0_RXPKTRDY)
+
+/* TxType/RxType */
+#define MUSB_TYPE_SPEED		0xc0
+#define MUSB_TYPE_SPEED_SHIFT	6
+#define MUSB_TYPE_SPEED_HIGH 	1
+#define MUSB_TYPE_SPEED_FULL 	2
+#define MUSB_TYPE_SPEED_LOW	3
+#define MUSB_TYPE_PROTO		0x30	/* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_SHIFT	4
+#define MUSB_TYPE_REMOTE_END	0xf	/* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_BULK 	2
+#define MUSB_TYPE_PROTO_INTR 	3
+
+/* CONFIGDATA */
+#define MUSB_CONFIGDATA_MPRXE		0x80	/* Auto bulk pkt combining */
+#define MUSB_CONFIGDATA_MPTXE		0x40	/* Auto bulk pkt splitting */
+#define MUSB_CONFIGDATA_BIGENDIAN	0x20
+#define MUSB_CONFIGDATA_HBRXE		0x10	/* HB-ISO for RX */
+#define MUSB_CONFIGDATA_HBTXE		0x08	/* HB-ISO for TX */
+#define MUSB_CONFIGDATA_DYNFIFO		0x04	/* Dynamic FIFO sizing */
+#define MUSB_CONFIGDATA_SOFTCONE	0x02	/* SoftConnect */
+#define MUSB_CONFIGDATA_UTMIDW		0x01	/* Data width 0/1 => 8/16bits */
+
+/* TXCSR in Peripheral and Host mode */
+#define MUSB_TXCSR_AUTOSET		0x8000
+#define MUSB_TXCSR_MODE			0x2000
+#define MUSB_TXCSR_DMAENAB		0x1000
+#define MUSB_TXCSR_FRCDATATOG		0x0800
+#define MUSB_TXCSR_DMAMODE		0x0400
+#define MUSB_TXCSR_CLRDATATOG		0x0040
+#define MUSB_TXCSR_FLUSHFIFO		0x0008
+#define MUSB_TXCSR_FIFONOTEMPTY		0x0002
+#define MUSB_TXCSR_TXPKTRDY		0x0001
+
+/* TXCSR in Peripheral mode */
+#define MUSB_TXCSR_P_ISO		0x4000
+#define MUSB_TXCSR_P_INCOMPTX		0x0080
+#define MUSB_TXCSR_P_SENTSTALL		0x0020
+#define MUSB_TXCSR_P_SENDSTALL		0x0010
+#define MUSB_TXCSR_P_UNDERRUN		0x0004
+
+/* TXCSR in Host mode */
+#define MUSB_TXCSR_H_WR_DATATOGGLE	0x0200
+#define MUSB_TXCSR_H_DATATOGGLE		0x0100
+#define MUSB_TXCSR_H_NAKTIMEOUT		0x0080
+#define MUSB_TXCSR_H_RXSTALL		0x0020
+#define MUSB_TXCSR_H_ERROR		0x0004
+#define MUSB_TXCSR_H_DATATOGGLE_SHIFT	8
+
+/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_TXCSR_P_WZC_BITS	\
+	(MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
+	| MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
+#define MUSB_TXCSR_H_WZC_BITS	\
+	(MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
+	| MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
+
+/* RXCSR in Peripheral and Host mode */
+#define MUSB_RXCSR_AUTOCLEAR		0x8000
+#define MUSB_RXCSR_DMAENAB		0x2000
+#define MUSB_RXCSR_DISNYET		0x1000
+#define MUSB_RXCSR_PID_ERR		0x1000
+#define MUSB_RXCSR_DMAMODE		0x0800
+#define MUSB_RXCSR_INCOMPRX		0x0100
+#define MUSB_RXCSR_CLRDATATOG		0x0080
+#define MUSB_RXCSR_FLUSHFIFO		0x0010
+#define MUSB_RXCSR_DATAERROR		0x0008
+#define MUSB_RXCSR_FIFOFULL		0x0002
+#define MUSB_RXCSR_RXPKTRDY		0x0001
+
+/* RXCSR in Peripheral mode */
+#define MUSB_RXCSR_P_ISO		0x4000
+#define MUSB_RXCSR_P_SENTSTALL		0x0040
+#define MUSB_RXCSR_P_SENDSTALL		0x0020
+#define MUSB_RXCSR_P_OVERRUN		0x0004
+
+/* RXCSR in Host mode */
+#define MUSB_RXCSR_H_AUTOREQ		0x4000
+#define MUSB_RXCSR_H_WR_DATATOGGLE	0x0400
+#define MUSB_RXCSR_H_DATATOGGLE		0x0200
+#define MUSB_RXCSR_H_RXSTALL		0x0040
+#define MUSB_RXCSR_H_REQPKT		0x0020
+#define MUSB_RXCSR_H_ERROR		0x0004
+#define MUSB_S_RXCSR_H_DATATOGGLE	9
+
+/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_RXCSR_P_WZC_BITS	\
+	(MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
+	| MUSB_RXCSR_RXPKTRDY)
+#define MUSB_RXCSR_H_WZC_BITS	\
+	(MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
+	| MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
+
+/* HUBADDR */
+#define MUSB_HUBADDR_MULTI_TT		0x80
+
+/* Endpoint configuration information. Note: The value of endpoint fifo size
+ * element should be either 8,16,32,64,128,256,512,1024,2048 or 4096. Other
+ * values are not supported
+ */
+struct musb_epinfo {
+	u8	epnum;	/* endpoint number 	*/
+	u8	epdir;	/* endpoint direction	*/
+	u16	epsize;	/* endpoint FIFO size	*/
+};
+
+/*
+ * Platform specific MUSB configuration. Any platform using the musb
+ * functionality should create one instance of this structure in the
+ * platform specific file.
+ */
+struct musb_config {
+	struct	musb_regs	*regs;
+	u32			timeout;
+	u8			musb_speed;
+};
+
+/* externally defined data */
+extern struct musb_config	musb_cfg;
+extern struct musb_regs		*musbr;
+
+/* exported functions */
+extern void musb_start(void);
+extern void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt);
+extern void write_fifo(u8 ep, u32 length, void *fifo_data);
+extern void read_fifo(u8 ep, u32 length, void *fifo_data);
+
+/* extern functions */
+extern inline void musb_writew(u32 offset, u16 value);
+extern inline void musb_writeb(u32 offset, u8 value);
+extern inline u16 musb_readw(u32 offset);
+extern inline u8 musb_readb(u32 offset);
+
+#endif	/* __MUSB_HDRC_DEFS_H__ */
+
diff --git a/drivers/usb/musb_hcd.c b/drivers/usb/musb_hcd.c
new file mode 100644
index 0000000..352a0d4
--- /dev/null
+++ b/drivers/usb/musb_hcd.c
@@ -0,0 +1,792 @@
+/*
+ * Mentor USB OTG Core host controller driver.
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+#include "musb_hcd.h"
+
+/* MSC control transfers */
+#define USB_MSC_BBB_RESET 	0xFF
+#define USB_MSC_BBB_GET_MAX_LUN	0xFE
+
+/* Endpoint configuration information */
+static struct musb_epinfo epinfo[3] = {
+	{MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */
+	{MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In  - 512 Bytes */
+	{MUSB_INTR_EP, 0, 64}   /* EP2 - Interrupt IN - 64 Bytes */
+};
+
+/*
+ * This function writes the data toggle value.
+ */
+static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
+{
+	u16 toggle = usb_gettoggle(dev, ep, dir_out);
+	u16 csr;
+
+	if (dir_out) {
+		if (!toggle)
+			writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
+		else {
+			csr = readw(&musbr->txcsr);
+			csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
+			writew(csr, &musbr->txcsr);
+			csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
+			writew(csr, &musbr->txcsr);
+		}
+	} else {
+		if (!toggle)
+			writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
+		else {
+			csr = readw(&musbr->rxcsr);
+			csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
+			writew(csr, &musbr->rxcsr);
+			csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE);
+			writew(csr, &musbr->rxcsr);
+		}
+	}
+}
+
+/*
+ * This function checks if RxStall has occured on the endpoint. If a RxStall
+ * has occured, the RxStall is cleared and 1 is returned. If RxStall has
+ * not occured, 0 is returned.
+ */
+static u8 check_stall(u8 ep, u8 dir_out)
+{
+	u16 csr;
+
+	/* For endpoint 0 */
+	if (!ep) {
+		csr = readw(&musbr->txcsr);
+		if (csr & MUSB_CSR0_H_RXSTALL) {
+			csr &= ~MUSB_CSR0_H_RXSTALL;
+			writew(csr, &musbr->txcsr);
+			return 1;
+		}
+	} else { /* For non-ep0 */
+		if (dir_out) { /* is it tx ep */
+			csr = readw(&musbr->txcsr);
+			if (csr & MUSB_TXCSR_H_RXSTALL) {
+				csr &= ~MUSB_TXCSR_H_RXSTALL;
+				writew(csr, &musbr->txcsr);
+				return 1;
+			}
+		} else { /* is it rx ep */
+			csr = readw(&musbr->rxcsr);
+			if (csr & MUSB_RXCSR_H_RXSTALL) {
+				csr &= ~MUSB_RXCSR_H_RXSTALL;
+				writew(csr, &musbr->rxcsr);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout
+ * error and -2 for stall.
+ */
+static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
+{
+	u16 csr;
+	int result = 1;
+
+	while (result > 0) {
+		csr = readw(&musbr->txcsr);
+		if (csr & MUSB_CSR0_H_ERROR) {
+			csr &= ~MUSB_CSR0_H_ERROR;
+			writew(csr, &musbr->txcsr);
+			dev->status = USB_ST_CRC_ERR;
+			result = -1;
+			break;
+		}
+
+		switch (bit_mask) {
+		case MUSB_CSR0_TXPKTRDY:
+			if (!(csr & MUSB_CSR0_TXPKTRDY)) {
+				if (check_stall(MUSB_CONTROL_EP, 0)) {
+					dev->status = USB_ST_STALLED;
+					result = -2;
+				} else
+					result = 0;
+			}
+			break;
+
+		case MUSB_CSR0_RXPKTRDY:
+			if (check_stall(MUSB_CONTROL_EP, 0)) {
+				dev->status = USB_ST_STALLED;
+				result = -2;
+			} else
+				if (csr & MUSB_CSR0_RXPKTRDY)
+					result = 0;
+			break;
+
+		case MUSB_CSR0_H_REQPKT:
+			if (!(csr & MUSB_CSR0_H_REQPKT)) {
+				if (check_stall(MUSB_CONTROL_EP, 0)) {
+					dev->status = USB_ST_STALLED;
+					result = -2;
+				} else
+					result = 0;
+			}
+			break;
+		}
+	}
+	return result;
+}
+
+/*
+ * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error.
+ */
+static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
+{
+	u16 csr;
+
+	do {
+		if (check_stall(ep, 1)) {
+			dev->status = USB_ST_STALLED;
+			return 0;
+		}
+
+		csr = readw(&musbr->txcsr);
+		if (csr & MUSB_TXCSR_H_ERROR) {
+			dev->status = USB_ST_CRC_ERR;
+			return 0;
+		}
+	} while (csr & MUSB_TXCSR_TXPKTRDY);
+	return 1;
+}
+
+/*
+ * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error.
+ */
+static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
+{
+	u16 csr;
+
+	do {
+		if (check_stall(ep, 0)) {
+			dev->status = USB_ST_STALLED;
+			return 0;
+		}
+
+		csr = readw(&musbr->rxcsr);
+		if (csr & MUSB_RXCSR_H_ERROR) {
+			dev->status = USB_ST_CRC_ERR;
+			return 0;
+		}
+	} while (!(csr & MUSB_RXCSR_RXPKTRDY));
+	return 1;
+}
+
+/*
+ * This function performs the setup phase of the control transfer
+ */
+static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup)
+{
+	int result;
+	u16 csr;
+
+	/* write the control request to ep0 fifo */
+	write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup);
+
+	/* enable transfer of setup packet */
+	csr = readw(&musbr->txcsr);
+	csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT);
+	writew(csr, &musbr->txcsr);
+
+	/* wait until the setup packet is transmitted */
+	result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+	dev->act_len = 0;
+	return result;
+}
+
+/*
+ * This function handles the control transfer in data phase
+ */
+static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer)
+{
+	u16 csr;
+	u32 rxlen = 0;
+	u32 nextlen = 0;
+	u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
+	u8  *rxbuff = (u8 *)buffer;
+	u8  rxedlength;
+	int result;
+
+	while (rxlen < len) {
+		/* Determine the next read length */
+		nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen);
+
+		/* Set the ReqPkt bit */
+		csr = readw(&musbr->txcsr);
+		writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr);
+		result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY);
+		if (result < 0)
+			return result;
+
+		/* Actual number of bytes received by usb */
+		rxedlength = readb(&musbr->rxcount);
+
+		/* Read the data from the RxFIFO */
+		read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]);
+
+		/* Clear the RxPktRdy Bit */
+		csr = readw(&musbr->txcsr);
+		csr &= ~MUSB_CSR0_RXPKTRDY;
+		writew(csr, &musbr->txcsr);
+
+		/* short packet? */
+		if (rxedlength != nextlen) {
+			dev->act_len += rxedlength;
+			break;
+		}
+		rxlen += nextlen;
+		dev->act_len = rxlen;
+	}
+	return 0;
+}
+
+/*
+ * This function handles the control transfer out data phase
+ */
+static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
+{
+	u16 csr;
+	u32 txlen = 0;
+	u32 nextlen = 0;
+	u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
+	u8  *txbuff = (u8 *)buffer;
+	int result = 0;
+
+	while (txlen < len) {
+		/* Determine the next write length */
+		nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen);
+
+		/* Load the data to send in FIFO */
+		write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]);
+
+		/* Set TXPKTRDY bit */
+		csr = readw(&musbr->txcsr);
+		writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY,
+					&musbr->txcsr);
+		result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+		if (result < 0)
+			break;
+
+		txlen += nextlen;
+		dev->act_len = txlen;
+	}
+	return result;
+}
+
+/*
+ * This function handles the control transfer out status phase
+ */
+static int ctrlreq_out_status_phase(struct usb_device *dev)
+{
+	u16 csr;
+	int result;
+
+	/* Set the StatusPkt bit */
+	csr = readw(&musbr->txcsr);
+	csr |= (MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY |
+			MUSB_CSR0_H_STATUSPKT);
+	writew(csr, &musbr->txcsr);
+
+	/* Wait until TXPKTRDY bit is cleared */
+	result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
+	return result;
+}
+
+/*
+ * This function handles the control transfer in status phase
+ */
+static int ctrlreq_in_status_phase(struct usb_device *dev)
+{
+	u16 csr;
+	int result;
+
+	/* Set the StatusPkt bit and ReqPkt bit */
+	csr = MUSB_CSR0_H_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
+	writew(csr, &musbr->txcsr);
+	result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);
+
+	/* clear StatusPkt bit and RxPktRdy bit */
+	csr = readw(&musbr->txcsr);
+	csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT);
+	writew(csr, &musbr->txcsr);
+	return result;
+}
+
+/*
+ * determines the speed of the device (High/Full/Slow)
+ */
+static u8 get_dev_speed(struct usb_device *dev)
+{
+	return (dev->speed & USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
+		((dev->speed & USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
+						MUSB_TYPE_SPEED_FULL);
+}
+
+/*
+ * configure the hub address and the port address.
+ */
+static void config_hub_port(struct usb_device *dev, u8 ep)
+{
+	u8 chid;
+	u8 hub;
+
+	/* Find out the nearest parent which is high speed */
+	while (dev->parent->parent != NULL)
+		if (get_dev_speed(dev->parent) !=  MUSB_TYPE_SPEED_HIGH)
+			dev = dev->parent;
+		else
+			break;
+
+	/* determine the port address at that hub */
+	hub = dev->parent->devnum;
+	for (chid = 0; chid < USB_MAXCHILDREN; chid++)
+		if (dev->parent->children[chid] == dev)
+			break;
+
+	/* configure the hub address and the port address */
+	writeb(hub, &musbr->tar[ep].txhubaddr);
+	writeb((chid + 1), &musbr->tar[ep].txhubport);
+	writeb(hub, &musbr->tar[ep].rxhubaddr);
+	writeb((chid + 1), &musbr->tar[ep].rxhubport);
+}
+
+/*
+ * do a control transfer
+ */
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int len, struct devrequest *setup)
+{
+	int devnum = usb_pipedevice(pipe);
+	u16 csr;
+	u8  devspeed;
+
+	/* select control endpoint */
+	writeb(MUSB_CONTROL_EP, &musbr->index);
+	csr = readw(&musbr->txcsr);
+
+	/* target addr and (for multipoint) hub addr/port */
+	writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr);
+	writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr);
+
+	/* configure the hub address and the port number as required */
+	devspeed = get_dev_speed(dev);
+	if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+		(devspeed != MUSB_TYPE_SPEED_HIGH)) {
+		config_hub_port(dev, MUSB_CONTROL_EP);
+		writeb(devspeed << 6, &musbr->txtype);
+	} else {
+		writeb(musb_cfg.musb_speed << 6, &musbr->txtype);
+		writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr);
+		writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport);
+		writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr);
+		writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport);
+	}
+
+	/* Control transfer setup phase */
+	if (ctrlreq_setup_phase(dev, setup) < 0)
+		return 0;
+
+	switch (setup->request) {
+	case USB_REQ_GET_DESCRIPTOR:
+	case USB_REQ_GET_CONFIGURATION:
+	case USB_REQ_GET_INTERFACE:
+	case USB_REQ_GET_STATUS:
+	case USB_MSC_BBB_GET_MAX_LUN:
+		/* control transfer in-data-phase */
+		if (ctrlreq_in_data_phase(dev, len, buffer) < 0)
+			return 0;
+		/* control transfer out-status-phase */
+		if (ctrlreq_out_status_phase(dev) < 0)
+			return 0;
+		break;
+
+	case USB_REQ_SET_ADDRESS:
+	case USB_REQ_SET_CONFIGURATION:
+	case USB_REQ_SET_FEATURE:
+	case USB_REQ_SET_INTERFACE:
+	case USB_REQ_CLEAR_FEATURE:
+	case USB_MSC_BBB_RESET:
+		/* control transfer in status phase */
+		if (ctrlreq_in_status_phase(dev) < 0)
+			return 0;
+		break;
+
+	case USB_REQ_SET_DESCRIPTOR:
+		/* control transfer out data phase */
+		if (ctrlreq_out_data_phase(dev, len, buffer) < 0)
+			return 0;
+		/* control transfer in status phase */
+		if (ctrlreq_in_status_phase(dev) < 0)
+			return 0;
+		break;
+
+	default:
+		/* unhandled control transfer */
+		return -1;
+	}
+
+	dev->status = 0;
+	dev->act_len = len;
+	return len;
+}
+
+/*
+ * do a bulk transfer
+ */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+					void *buffer, int len)
+{
+	int dir_out = usb_pipeout(pipe);
+	int ep = usb_pipeendpoint(pipe);
+	int devnum = usb_pipedevice(pipe);
+	u8  type;
+	u16 csr;
+	u32 txlen = 0;
+	u32 nextlen = 0;
+	u8  devspeed;
+
+	/* select bulk endpoint */
+	writeb(MUSB_BULK_EP, &musbr->index);
+
+	/* write the address of the device */
+	if (dir_out)
+		writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr);
+	else
+		writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr);
+
+	/* configure the hub address and the port number as required */
+	devspeed = get_dev_speed(dev);
+	if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+		(devspeed != MUSB_TYPE_SPEED_HIGH)) {
+		/*
+		 * MUSB is in high speed and the destination device is full
+		 * speed device. So configure the hub address and port
+		 * address registers.
+		 */
+		config_hub_port(dev, MUSB_BULK_EP);
+	} else {
+		if (dir_out) {
+			writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr);
+			writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport);
+		} else {
+			writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr);
+			writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport);
+		}
+		devspeed = musb_cfg.musb_speed;
+	}
+
+	/* Write the saved toggle bit value */
+	write_toggle(dev, ep, dir_out);
+
+	if (dir_out) { /* bulk-out transfer */
+		/* Program the TxType register */
+		type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+			   (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
+			   (ep & MUSB_TYPE_REMOTE_END);
+		writeb(type, &musbr->txtype);
+
+		/* Write maximum packet size to the TxMaxp register */
+		writew(dev->epmaxpacketout[ep], &musbr->txmaxp);
+		while (txlen < len) {
+			nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ?
+					(len-txlen) : dev->epmaxpacketout[ep];
+
+			/* Write the data to the FIFO */
+			write_fifo(MUSB_BULK_EP, nextlen,
+					(void *)(((u8 *)buffer) + txlen));
+
+			/* Set the TxPktRdy bit */
+			csr = readw(&musbr->txcsr);
+			writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr);
+
+			/* Wait until the TxPktRdy bit is cleared */
+			if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) {
+				readw(&musbr->txcsr);
+				usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
+				dev->act_len = txlen;
+				return 0;
+			}
+			txlen += nextlen;
+		}
+
+		/* Keep a copy of the data toggle bit */
+		csr = readw(&musbr->txcsr);
+		usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
+	} else { /* bulk-in transfer */
+		/* Write the saved toggle bit value */
+		write_toggle(dev, ep, dir_out);
+
+		/* Program the RxType register */
+		type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+			   (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
+			   (ep & MUSB_TYPE_REMOTE_END);
+		writeb(type, &musbr->rxtype);
+
+		/* Write the maximum packet size to the RxMaxp register */
+		writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
+		while (txlen < len) {
+			nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
+					(len-txlen) : dev->epmaxpacketin[ep];
+
+			/* Set the ReqPkt bit */
+			writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
+
+			/* Wait until the RxPktRdy bit is set */
+			if (!wait_until_rxep_ready(dev, MUSB_BULK_EP)) {
+				csr = readw(&musbr->rxcsr);
+				usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+				csr &= ~MUSB_RXCSR_RXPKTRDY;
+				writew(csr, &musbr->rxcsr);
+				dev->act_len = txlen;
+				return 0;
+			}
+
+			/* Read the data from the FIFO */
+			read_fifo(MUSB_BULK_EP, nextlen,
+					(void *)(((u8 *)buffer) + txlen));
+
+			/* Clear the RxPktRdy bit */
+			csr =  readw(&musbr->rxcsr);
+			csr &= ~MUSB_RXCSR_RXPKTRDY;
+			writew(csr, &musbr->rxcsr);
+			txlen += nextlen;
+		}
+
+		/* Keep a copy of the data toggle bit */
+		csr = readw(&musbr->rxcsr);
+		usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+	}
+
+	/* bulk transfer is complete */
+	dev->status = 0;
+	dev->act_len = len;
+	return 0;
+}
+
+/*
+ * This function initializes the usb controller module.
+ */
+int usb_lowlevel_init(void)
+{
+	u8  power;
+	u32 timeout;
+
+	if (musb_platform_init() == -1)
+		return -1;
+
+	/* Configure all the endpoint FIFO's and start usb controller */
+	musbr = musb_cfg.regs;
+	musb_configure_ep(&epinfo[0],
+			sizeof(epinfo) / sizeof(struct musb_epinfo));
+	musb_start();
+
+	/*
+	 * Wait until musb is enabled in host mode with a timeout. There
+	 * should be a usb device connected.
+	 */
+	timeout = musb_cfg.timeout;
+	while (timeout--)
+		if (readb(&musbr->devctl) & MUSB_DEVCTL_HM)
+			break;
+
+	/* if musb core is not in host mode, then return */
+	if (!timeout)
+		return -1;
+
+	/* start usb bus reset */
+	power = readb(&musbr->power);
+	writeb(power | MUSB_POWER_RESET, &musbr->power);
+
+	/* After initiating a usb reset, wait for about 20ms to 30ms */
+	udelay(30000);
+
+	/* stop usb bus reset */
+	power = readb(&musbr->power);
+	power &= ~MUSB_POWER_RESET;
+	writeb(power, &musbr->power);
+
+	/* Determine if the connected device is a high/full/low speed device */
+	musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
+			MUSB_TYPE_SPEED_HIGH :
+			((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ?
+			MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW);
+	return 0;
+}
+
+/*
+ * This function stops the operation of the davinci usb module.
+ */
+int usb_lowlevel_stop(void)
+{
+	/* Reset the USB module */
+	musb_platform_deinit();
+	writeb(0, &musbr->devctl);
+	return 0;
+}
+
+/*
+ * This function supports usb interrupt transfers. Currently, usb interrupt
+ * transfers are not supported.
+ */
+int submit_int_msg(struct usb_device *dev, unsigned long pipe,
+				void *buffer, int len, int interval)
+{
+	int dir_out = usb_pipeout(pipe);
+	int ep = usb_pipeendpoint(pipe);
+	int devnum = usb_pipedevice(pipe);
+	u8  type;
+	u16 csr;
+	u32 txlen = 0;
+	u32 nextlen = 0;
+	u8  devspeed;
+
+	/* select interrupt endpoint */
+	writeb(MUSB_INTR_EP, &musbr->index);
+
+	/* write the address of the device */
+	if (dir_out)
+		writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr);
+	else
+		writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr);
+
+	/* configure the hub address and the port number as required */
+	devspeed = get_dev_speed(dev);
+	if ((musb_ishighspeed()) && (dev->parent != NULL) &&
+		(devspeed != MUSB_TYPE_SPEED_HIGH)) {
+		/*
+		 * MUSB is in high speed and the destination device is full
+		 * speed device. So configure the hub address and port
+		 * address registers.
+		 */
+		config_hub_port(dev, MUSB_INTR_EP);
+	} else {
+		if (dir_out) {
+			writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr);
+			writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport);
+		} else {
+			writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr);
+			writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport);
+		}
+		devspeed = musb_cfg.musb_speed;
+	}
+
+	/* Write the saved toggle bit value */
+	write_toggle(dev, ep, dir_out);
+
+	if (!dir_out) { /* intrrupt-in transfer */
+		/* Write the saved toggle bit value */
+		write_toggle(dev, ep, dir_out);
+		writeb(interval, &musbr->rxinterval);
+
+		/* Program the RxType register */
+		type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
+			   (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) |
+			   (ep & MUSB_TYPE_REMOTE_END);
+		writeb(type, &musbr->rxtype);
+
+		/* Write the maximum packet size to the RxMaxp register */
+		writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
+
+		while (txlen < len) {
+			nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
+					(len-txlen) : dev->epmaxpacketin[ep];
+
+			/* Set the ReqPkt bit */
+			writew(MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
+
+			/* Wait until the RxPktRdy bit is set */
+			if (!wait_until_rxep_ready(dev, MUSB_INTR_EP)) {
+				csr = readw(&musbr->rxcsr);
+				usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+				csr &= ~MUSB_RXCSR_RXPKTRDY;
+				writew(csr, &musbr->rxcsr);
+				dev->act_len = txlen;
+				return 0;
+			}
+
+			/* Read the data from the FIFO */
+			read_fifo(MUSB_INTR_EP, nextlen,
+					(void *)(((u8 *)buffer) + txlen));
+
+			/* Clear the RxPktRdy bit */
+			csr =  readw(&musbr->rxcsr);
+			csr &= ~MUSB_RXCSR_RXPKTRDY;
+			writew(csr, &musbr->rxcsr);
+			txlen += nextlen;
+		}
+
+		/* Keep a copy of the data toggle bit */
+		csr = readw(&musbr->rxcsr);
+		usb_settoggle(dev, ep, dir_out,
+				(csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
+	}
+
+	/* interrupt transfer is complete */
+	dev->irq_status = 0;
+	dev->irq_act_len = len;
+	dev->irq_handle(dev);
+	dev->status = 0;
+	dev->act_len = len;
+	return 0;
+}
+
+
+#ifdef CONFIG_SYS_USB_EVENT_POLL
+/*
+ * This function polls for USB keyboard data.
+ */
+void usb_event_poll()
+{
+	device_t *dev;
+	struct usb_device *usb_kbd_dev;
+	struct usb_interface_descriptor *iface;
+	struct usb_endpoint_descriptor *ep;
+	int pipe;
+	int maxp;
+
+	/* Get the pointer to USB Keyboard device pointer */
+	dev = device_get_by_name("usbkbd");
+	usb_kbd_dev = (struct usb_device *)dev->priv;
+	iface = &usb_kbd_dev->config.if_desc[0];
+	ep = &iface->ep_desc[0];
+	pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress);
+
+	/* Submit a interrupt transfer request */
+	maxp = usb_maxpacket(usb_kbd_dev, pipe);
+	usb_submit_int_msg(usb_kbd_dev, pipe, &new[0],
+			maxp > 8 ? 8 : maxp, ep->bInterval);
+}
+#endif /* CONFIG_SYS_USB_EVENT_POLL */
diff --git a/drivers/usb/musb_hcd.h b/drivers/usb/musb_hcd.h
new file mode 100644
index 0000000..bb83311
--- /dev/null
+++ b/drivers/usb/musb_hcd.h
@@ -0,0 +1,51 @@
+/*
+ * Mentor USB OTG Core host controller driver.
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
+ */
+
+#ifndef __MUSB_HCD_H__
+#define __MUSB_HCD_H__
+
+#include "musb_core.h"
+#ifdef CONFIG_USB_KEYBOARD
+#include <devices.h>
+extern unsigned char new[];
+#endif
+
+/* This defines the endpoint number used for control transfers */
+#define MUSB_CONTROL_EP 0
+
+/* This defines the endpoint number used for bulk transfer */
+#define MUSB_BULK_EP 1
+
+/* This defines the endpoint number used for interrupt transfer */
+#define MUSB_INTR_EP 2
+
+/* Determine the operating speed of MUSB core */
+#define musb_ishighspeed() \
+	((readb(&musbr->power) & MUSB_POWER_HSMODE) \
+		>> MUSB_POWER_HSMODE_SHIFT)
+
+/* extern functions */
+extern int musb_platform_init(void);
+extern void musb_platform_deinit(void);
+
+#endif	/* __MUSB_HCD_H__ */
diff --git a/drivers/usb/usb_ehci.h b/drivers/usb/usb_ehci.h
new file mode 100644
index 0000000..b3c1d5d
--- /dev/null
+++ b/drivers/usb/usb_ehci.h
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef USB_EHCI_H
+#define USB_EHCI_H
+
+#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS	2
+#endif
+
+/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
+#define DeviceRequest \
+	((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
+
+#define DeviceOutRequest \
+	((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8)
+
+#define InterfaceRequest \
+	((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+#define EndpointRequest \
+	((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+#define EndpointOutRequest \
+	((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
+
+/*
+ * Register Space.
+ */
+struct ehci_hccr {
+	uint32_t cr_capbase;
+#define HC_LENGTH(p)		(((p) >> 0) & 0x00ff)
+#define HC_VERSION(p)		(((p) >> 16) & 0xffff)
+	uint32_t cr_hcsparams;
+#define HCS_PPC(p)		((p) & (1 << 4))
+#define HCS_INDICATOR(p)	((p) & (1 << 16)) /* Port indicators */
+#define HCS_N_PORTS(p)		(((p) >> 0) & 0xf)
+	uint32_t cr_hccparams;
+	uint8_t cr_hcsp_portrt[8];
+} __attribute__ ((packed));
+
+struct ehci_hcor {
+	uint32_t or_usbcmd;
+#define CMD_PARK	(1 << 11)		/* enable "park" */
+#define CMD_PARK_CNT(c)	(((c) >> 8) & 3)	/* how many transfers to park */
+#define CMD_ASE		(1 << 5)		/* async schedule enable */
+#define CMD_LRESET	(1 << 7)		/* partial reset */
+#define CMD_IAAD	(1 << 5)		/* "doorbell" interrupt */
+#define CMD_PSE		(1 << 4)		/* periodic schedule enable */
+#define CMD_RESET	(1 << 1)		/* reset HC not bus */
+#define CMD_RUN		(1 << 0)		/* start/stop HC */
+	uint32_t or_usbsts;
+#define	STD_ASS		(1 << 15)
+#define STS_HALT	(1 << 12)
+	uint32_t or_usbintr;
+	uint32_t or_frindex;
+	uint32_t or_ctrldssegment;
+	uint32_t or_periodiclistbase;
+	uint32_t or_asynclistaddr;
+	uint32_t _reserved_[9];
+	uint32_t or_configflag;
+#define FLAG_CF		(1 << 0)	/* true:  we'll support "high speed" */
+	uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
+	uint32_t or_systune;
+} __attribute__ ((packed));
+
+#define USBMODE		0x68		/* USB Device mode */
+#define USBMODE_SDIS	(1 << 3)	/* Stream disable */
+#define USBMODE_BE	(1 << 2)	/* BE/LE endiannes select */
+#define USBMODE_CM_HC	(3 << 0)	/* host controller mode */
+#define USBMODE_CM_IDLE	(0 << 0)	/* idle state */
+
+/* Interface descriptor */
+struct usb_linux_interface_descriptor {
+	unsigned char	bLength;
+	unsigned char	bDescriptorType;
+	unsigned char	bInterfaceNumber;
+	unsigned char	bAlternateSetting;
+	unsigned char	bNumEndpoints;
+	unsigned char	bInterfaceClass;
+	unsigned char	bInterfaceSubClass;
+	unsigned char	bInterfaceProtocol;
+	unsigned char	iInterface;
+} __attribute__ ((packed));
+
+/* Configuration descriptor information.. */
+struct usb_linux_config_descriptor {
+	unsigned char	bLength;
+	unsigned char	bDescriptorType;
+	unsigned short	wTotalLength;
+	unsigned char	bNumInterfaces;
+	unsigned char	bConfigurationValue;
+	unsigned char	iConfiguration;
+	unsigned char	bmAttributes;
+	unsigned char	MaxPower;
+} __attribute__ ((packed));
+
+#if defined CONFIG_EHCI_DESC_BIG_ENDIAN
+#define	ehci_readl(x)		(*((volatile u32 *)(x)))
+#define ehci_writel(a, b)	(*((volatile u32 *)(a)) = ((volatile u32)b))
+#else
+#define ehci_readl(x)		cpu_to_le32((*((volatile u32 *)(x))))
+#define ehci_writel(a, b)	(*((volatile u32 *)(a)) = \
+					cpu_to_le32(((volatile u32)b)))
+#endif
+
+#if defined CONFIG_EHCI_MMIO_BIG_ENDIAN
+#define hc32_to_cpu(x)		be32_to_cpu((x))
+#define cpu_to_hc32(x)		cpu_to_be32((x))
+#else
+#define hc32_to_cpu(x)		le32_to_cpu((x))
+#define cpu_to_hc32(x)		cpu_to_le32((x))
+#endif
+
+#define EHCI_PS_WKOC_E		(1 << 22)	/* RW wake on over current */
+#define EHCI_PS_WKDSCNNT_E	(1 << 21)	/* RW wake on disconnect */
+#define EHCI_PS_WKCNNT_E	(1 << 20)	/* RW wake on connect */
+#define EHCI_PS_PO		(1 << 13)	/* RW port owner */
+#define EHCI_PS_PP		(1 << 12)	/* RW,RO port power */
+#define EHCI_PS_LS		(3 << 10)	/* RO line status */
+#define EHCI_PS_PR		(1 << 8)	/* RW port reset */
+#define EHCI_PS_SUSP		(1 << 7)	/* RW suspend */
+#define EHCI_PS_FPR		(1 << 6)	/* RW force port resume */
+#define EHCI_PS_OCC		(1 << 5)	/* RWC over current change */
+#define EHCI_PS_OCA		(1 << 4)	/* RO over current active */
+#define EHCI_PS_PEC		(1 << 3)	/* RWC port enable change */
+#define EHCI_PS_PE		(1 << 2)	/* RW port enable */
+#define EHCI_PS_CSC		(1 << 1)	/* RWC connect status change */
+#define EHCI_PS_CS		(1 << 0)	/* RO connect status */
+#define EHCI_PS_CLEAR		(EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
+
+#define EHCI_PS_IS_LOWSPEED(x)	(((x) & EHCI_PS_LS) == (1 << 10))
+
+/*
+ * Schedule Interface Space.
+ *
+ * IMPORTANT: Software must ensure that no interface data structure
+ * reachable by the EHCI host controller spans a 4K page boundary!
+ *
+ * Periodic transfers (i.e. isochronous and interrupt transfers) are
+ * not supported.
+ */
+
+/* Queue Element Transfer Descriptor (qTD). */
+struct qTD {
+	uint32_t qt_next;
+#define	QT_NEXT_TERMINATE	1
+	uint32_t qt_altnext;
+	uint32_t qt_token;
+	uint32_t qt_buffer[5];
+};
+
+/* Queue Head (QH). */
+struct QH {
+	uint32_t qh_link;
+#define	QH_LINK_TERMINATE	1
+#define	QH_LINK_TYPE_ITD	0
+#define	QH_LINK_TYPE_QH		2
+#define	QH_LINK_TYPE_SITD	4
+#define	QH_LINK_TYPE_FSTN	6
+	uint32_t qh_endpt1;
+	uint32_t qh_endpt2;
+	uint32_t qh_curtd;
+	struct qTD qh_overlay;
+	/*
+	 * Add dummy fill value to make the size of this struct
+	 * aligned to 32 bytes
+	 */
+	uint8_t fill[16];
+};
+
+/* Low level init functions */
+int ehci_hcd_init(void);
+int ehci_hcd_stop(void);
+
+#endif /* USB_EHCI_H */
diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c
new file mode 100644
index 0000000..813f64a
--- /dev/null
+++ b/drivers/usb/usb_ehci_core.c
@@ -0,0 +1,880 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Excito Elektronik i Skåne AB
+ * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <asm/byteorder.h>
+#include <usb.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include "usb_ehci.h"
+
+int rootdev;
+struct ehci_hccr *hccr;	/* R/O registers, not need for volatile */
+volatile struct ehci_hcor *hcor;
+
+static uint16_t portreset;
+static struct QH qh_list __attribute__((aligned(32)));
+
+static struct descriptor {
+	struct usb_hub_descriptor hub;
+	struct usb_device_descriptor device;
+	struct usb_linux_config_descriptor config;
+	struct usb_linux_interface_descriptor interface;
+	struct usb_endpoint_descriptor endpoint;
+}  __attribute__ ((packed)) descriptor = {
+	{
+		0x8,		/* bDescLength */
+		0x29,		/* bDescriptorType: hub descriptor */
+		2,		/* bNrPorts -- runtime modified */
+		0,		/* wHubCharacteristics */
+		0xff,		/* bPwrOn2PwrGood */
+		0,		/* bHubCntrCurrent */
+		{},		/* Device removable */
+		{}		/* at most 7 ports! XXX */
+	},
+	{
+		0x12,		/* bLength */
+		1,		/* bDescriptorType: UDESC_DEVICE */
+		0x0002,		/* bcdUSB: v2.0 */
+		9,		/* bDeviceClass: UDCLASS_HUB */
+		0,		/* bDeviceSubClass: UDSUBCLASS_HUB */
+		1,		/* bDeviceProtocol: UDPROTO_HSHUBSTT */
+		64,		/* bMaxPacketSize: 64 bytes */
+		0x0000,		/* idVendor */
+		0x0000,		/* idProduct */
+		0x0001,		/* bcdDevice */
+		1,		/* iManufacturer */
+		2,		/* iProduct */
+		0,		/* iSerialNumber */
+		1		/* bNumConfigurations: 1 */
+	},
+	{
+		0x9,
+		2,		/* bDescriptorType: UDESC_CONFIG */
+		cpu_to_le16(0x19),
+		1,		/* bNumInterface */
+		1,		/* bConfigurationValue */
+		0,		/* iConfiguration */
+		0x40,		/* bmAttributes: UC_SELF_POWER */
+		0		/* bMaxPower */
+	},
+	{
+		0x9,		/* bLength */
+		4,		/* bDescriptorType: UDESC_INTERFACE */
+		0,		/* bInterfaceNumber */
+		0,		/* bAlternateSetting */
+		1,		/* bNumEndpoints */
+		9,		/* bInterfaceClass: UICLASS_HUB */
+		0,		/* bInterfaceSubClass: UISUBCLASS_HUB */
+		0,		/* bInterfaceProtocol: UIPROTO_HSHUBSTT */
+		0		/* iInterface */
+	},
+	{
+		0x7,		/* bLength */
+		5,		/* bDescriptorType: UDESC_ENDPOINT */
+		0x81,		/* bEndpointAddress:
+				 * UE_DIR_IN | EHCI_INTR_ENDPT
+				 */
+		3,		/* bmAttributes: UE_INTERRUPT */
+		8, 0,		/* wMaxPacketSize */
+		255		/* bInterval */
+	},
+};
+
+#if defined(CONFIG_EHCI_IS_TDI)
+#define ehci_is_TDI()	(1)
+#else
+#define ehci_is_TDI()	(0)
+#endif
+
+#if defined(CONFIG_EHCI_DCACHE)
+/*
+ * Routines to handle (flush/invalidate) the dcache for the QH and qTD
+ * structures and data buffers. This is needed on platforms using this
+ * EHCI support with dcache enabled.
+ */
+static void flush_invalidate(u32 addr, int size, int flush)
+{
+	if (flush)
+		flush_dcache_range(addr, addr + size);
+	else
+		invalidate_dcache_range(addr, addr + size);
+}
+
+static void cache_qtd(struct qTD *qtd, int flush)
+{
+	u32 *ptr = (u32 *)qtd->qt_buffer[0];
+	int len = (qtd->qt_token & 0x7fff0000) >> 16;
+
+	flush_invalidate((u32)qtd, sizeof(struct qTD), flush);
+	if (ptr && len)
+		flush_invalidate((u32)ptr, len, flush);
+}
+
+
+static inline struct QH *qh_addr(struct QH *qh)
+{
+	return (struct QH *)((u32)qh & 0xffffffe0);
+}
+
+static void cache_qh(struct QH *qh, int flush)
+{
+	struct qTD *qtd;
+	struct qTD *next;
+	static struct qTD *first_qtd;
+
+	/*
+	 * Walk the QH list and flush/invalidate all entries
+	 */
+	while (1) {
+		flush_invalidate((u32)qh_addr(qh), sizeof(struct QH), flush);
+		if ((u32)qh & QH_LINK_TYPE_QH)
+			break;
+		qh = qh_addr(qh);
+		qh = (struct QH *)qh->qh_link;
+	}
+	qh = qh_addr(qh);
+
+	/*
+	 * Save first qTD pointer, needed for invalidating pass on this QH
+	 */
+	if (flush)
+		first_qtd = qtd = (struct qTD *)(*(u32 *)&qh->qh_overlay &
+						 0xffffffe0);
+	else
+		qtd = first_qtd;
+
+	/*
+	 * Walk the qTD list and flush/invalidate all entries
+	 */
+	while (1) {
+		if (qtd == NULL)
+			break;
+		cache_qtd(qtd, flush);
+		next = (struct qTD *)((u32)qtd->qt_next & 0xffffffe0);
+		if (next == qtd)
+			break;
+		qtd = next;
+	}
+}
+
+static inline void ehci_flush_dcache(struct QH *qh)
+{
+	cache_qh(qh, 1);
+}
+
+static inline void ehci_invalidate_dcache(struct QH *qh)
+{
+	cache_qh(qh, 0);
+}
+#else /* CONFIG_EHCI_DCACHE */
+/*
+ *
+ */
+static inline void ehci_flush_dcache(struct QH *qh)
+{
+}
+
+static inline void ehci_invalidate_dcache(struct QH *qh)
+{
+}
+#endif /* CONFIG_EHCI_DCACHE */
+
+static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
+{
+	uint32_t result;
+	do {
+		result = ehci_readl(ptr);
+		if (result == ~(uint32_t)0)
+			return -1;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -1;
+}
+
+static void ehci_free(void *p, size_t sz)
+{
+
+}
+
+static int ehci_reset(void)
+{
+	uint32_t cmd;
+	uint32_t tmp;
+	uint32_t *reg_ptr;
+	int ret = 0;
+
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd |= CMD_RESET;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+	ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
+	if (ret < 0) {
+		printf("EHCI fail to reset\n");
+		goto out;
+	}
+
+	if (ehci_is_TDI()) {
+		reg_ptr = (uint32_t *)((u8 *)hcor + USBMODE);
+		tmp = ehci_readl(reg_ptr);
+		tmp |= USBMODE_CM_HC;
+#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
+		tmp |= USBMODE_BE;
+#endif
+		ehci_writel(reg_ptr, tmp);
+	}
+out:
+	return ret;
+}
+
+static void *ehci_alloc(size_t sz, size_t align)
+{
+	static struct QH qh __attribute__((aligned(32)));
+	static struct qTD td[3] __attribute__((aligned (32)));
+	static int ntds;
+	void *p;
+
+	switch (sz) {
+	case sizeof(struct QH):
+		p = &qh;
+		ntds = 0;
+		break;
+	case sizeof(struct qTD):
+		if (ntds == 3) {
+			debug("out of TDs\n");
+			return NULL;
+		}
+		p = &td[ntds];
+		ntds++;
+		break;
+	default:
+		debug("unknown allocation size\n");
+		return NULL;
+	}
+
+	memset(p, sz, 0);
+	return p;
+}
+
+static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
+{
+	uint32_t addr, delta, next;
+	int idx;
+
+	addr = (uint32_t) buf;
+	idx = 0;
+	while (idx < 5) {
+		td->qt_buffer[idx] = cpu_to_hc32(addr);
+		next = (addr + 4096) & ~4095;
+		delta = next - addr;
+		if (delta >= sz)
+			break;
+		sz -= delta;
+		addr = next;
+		idx++;
+	}
+
+	if (idx == 5) {
+		debug("out of buffer pointers (%u bytes left)\n", sz);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
+		   int length, struct devrequest *req)
+{
+	struct QH *qh;
+	struct qTD *td;
+	volatile struct qTD *vtd;
+	unsigned long ts;
+	uint32_t *tdp;
+	uint32_t endpt, token, usbsts;
+	uint32_t c, toggle;
+	uint32_t cmd;
+	int ret = 0;
+
+	debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
+	      buffer, length, req);
+	if (req != NULL)
+		debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
+		      req->request, req->request,
+		      req->requesttype, req->requesttype,
+		      le16_to_cpu(req->value), le16_to_cpu(req->value),
+		      le16_to_cpu(req->index));
+
+	qh = ehci_alloc(sizeof(struct QH), 32);
+	if (qh == NULL) {
+		debug("unable to allocate QH\n");
+		return -1;
+	}
+	qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+	c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
+	     usb_pipeendpoint(pipe) == 0) ? 1 : 0;
+	endpt = (8 << 28) |
+	    (c << 27) |
+	    (usb_maxpacket(dev, pipe) << 16) |
+	    (0 << 15) |
+	    (1 << 14) |
+	    (usb_pipespeed(pipe) << 12) |
+	    (usb_pipeendpoint(pipe) << 8) |
+	    (0 << 7) | (usb_pipedevice(pipe) << 0);
+	qh->qh_endpt1 = cpu_to_hc32(endpt);
+	endpt = (1 << 30) |
+	    (dev->portnr << 23) |
+	    (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
+	qh->qh_endpt2 = cpu_to_hc32(endpt);
+	qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+
+	td = NULL;
+	tdp = &qh->qh_overlay.qt_next;
+
+	toggle =
+	    usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+	if (req != NULL) {
+		td = ehci_alloc(sizeof(struct qTD), 32);
+		if (td == NULL) {
+			debug("unable to allocate SETUP td\n");
+			goto fail;
+		}
+		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		token = (0 << 31) |
+		    (sizeof(*req) << 16) |
+		    (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
+		td->qt_token = cpu_to_hc32(token);
+		if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
+			debug("unable construct SETUP td\n");
+			ehci_free(td, sizeof(*td));
+			goto fail;
+		}
+		*tdp = cpu_to_hc32((uint32_t) td);
+		tdp = &td->qt_next;
+		toggle = 1;
+	}
+
+	if (length > 0 || req == NULL) {
+		td = ehci_alloc(sizeof(struct qTD), 32);
+		if (td == NULL) {
+			debug("unable to allocate DATA td\n");
+			goto fail;
+		}
+		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		token = (toggle << 31) |
+		    (length << 16) |
+		    ((req == NULL ? 1 : 0) << 15) |
+		    (0 << 12) |
+		    (3 << 10) |
+		    ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
+		td->qt_token = cpu_to_hc32(token);
+		if (ehci_td_buffer(td, buffer, length) != 0) {
+			debug("unable construct DATA td\n");
+			ehci_free(td, sizeof(*td));
+			goto fail;
+		}
+		*tdp = cpu_to_hc32((uint32_t) td);
+		tdp = &td->qt_next;
+	}
+
+	if (req != NULL) {
+		td = ehci_alloc(sizeof(struct qTD), 32);
+		if (td == NULL) {
+			debug("unable to allocate ACK td\n");
+			goto fail;
+		}
+		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		token = (toggle << 31) |
+		    (0 << 16) |
+		    (1 << 15) |
+		    (0 << 12) |
+		    (3 << 10) |
+		    ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
+		td->qt_token = cpu_to_hc32(token);
+		*tdp = cpu_to_hc32((uint32_t) td);
+		tdp = &td->qt_next;
+	}
+
+	qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
+
+	/* Flush dcache */
+	ehci_flush_dcache(&qh_list);
+
+	usbsts = ehci_readl(&hcor->or_usbsts);
+	ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
+
+	/* Enable async. schedule. */
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd |= CMD_ASE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS,
+			100 * 1000);
+	if (ret < 0) {
+		printf("EHCI fail timeout STD_ASS set\n");
+		goto fail;
+	}
+
+	/* Wait for TDs to be processed. */
+	ts = get_timer(0);
+	vtd = td;
+	do {
+		/* Invalidate dcache */
+		ehci_invalidate_dcache(&qh_list);
+		token = hc32_to_cpu(vtd->qt_token);
+		if (!(token & 0x80))
+			break;
+	} while (get_timer(ts) < CONFIG_SYS_HZ);
+
+	/* Disable async schedule. */
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd &= ~CMD_ASE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0,
+			100 * 1000);
+	if (ret < 0) {
+		printf("EHCI fail timeout STD_ASS reset\n");
+		goto fail;
+	}
+
+	qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+
+	token = hc32_to_cpu(qh->qh_overlay.qt_token);
+	if (!(token & 0x80)) {
+		debug("TOKEN=%#x\n", token);
+		switch (token & 0xfc) {
+		case 0:
+			toggle = token >> 31;
+			usb_settoggle(dev, usb_pipeendpoint(pipe),
+				       usb_pipeout(pipe), toggle);
+			dev->status = 0;
+			break;
+		case 0x40:
+			dev->status = USB_ST_STALLED;
+			break;
+		case 0xa0:
+		case 0x20:
+			dev->status = USB_ST_BUF_ERR;
+			break;
+		case 0x50:
+		case 0x10:
+			dev->status = USB_ST_BABBLE_DET;
+			break;
+		default:
+			dev->status = USB_ST_CRC_ERR;
+			break;
+		}
+		dev->act_len = length - ((token >> 16) & 0x7fff);
+	} else {
+		dev->act_len = 0;
+		debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
+		      dev->devnum, ehci_readl(&hcor->or_usbsts),
+		      ehci_readl(&hcor->or_portsc[0]),
+		      ehci_readl(&hcor->or_portsc[1]));
+	}
+
+	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
+
+fail:
+	td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
+	while (td != (void *)QT_NEXT_TERMINATE) {
+		qh->qh_overlay.qt_next = td->qt_next;
+		ehci_free(td, sizeof(*td));
+		td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
+	}
+	ehci_free(qh, sizeof(*qh));
+	return -1;
+}
+
+static inline int min3(int a, int b, int c)
+{
+
+	if (b < a)
+		a = b;
+	if (c < a)
+		a = c;
+	return a;
+}
+
+int
+ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
+		 int length, struct devrequest *req)
+{
+	uint8_t tmpbuf[4];
+	u16 typeReq;
+	void *srcptr = NULL;
+	int len, srclen;
+	uint32_t reg;
+	uint32_t *status_reg;
+
+	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);
+		return -1;
+	}
+	status_reg = (uint32_t *)&hcor->or_portsc[
+						le16_to_cpu(req->index) - 1];
+	srclen = 0;
+
+	debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
+	      req->request, req->request,
+	      req->requesttype, req->requesttype,
+	      le16_to_cpu(req->value), le16_to_cpu(req->index));
+
+	typeReq = req->request << 8 | req->requesttype;
+
+	switch (le16_to_cpu(typeReq)) {
+	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+		switch (le16_to_cpu(req->value) >> 8) {
+		case USB_DT_DEVICE:
+			debug("USB_DT_DEVICE request\n");
+			srcptr = &descriptor.device;
+			srclen = 0x12;
+			break;
+		case USB_DT_CONFIG:
+			debug("USB_DT_CONFIG config\n");
+			srcptr = &descriptor.config;
+			srclen = 0x19;
+			break;
+		case USB_DT_STRING:
+			debug("USB_DT_STRING config\n");
+			switch (le16_to_cpu(req->value) & 0xff) {
+			case 0:	/* Language */
+				srcptr = "\4\3\1\0";
+				srclen = 4;
+				break;
+			case 1:	/* Vendor */
+				srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
+				srclen = 14;
+				break;
+			case 2:	/* Product */
+				srcptr = "\52\3E\0H\0C\0I\0 "
+					 "\0H\0o\0s\0t\0 "
+					 "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
+				srclen = 42;
+				break;
+			default:
+				debug("unknown value DT_STRING %x\n",
+					le16_to_cpu(req->value));
+				goto unknown;
+			}
+			break;
+		default:
+			debug("unknown value %x\n", le16_to_cpu(req->value));
+			goto unknown;
+		}
+		break;
+	case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
+		switch (le16_to_cpu(req->value) >> 8) {
+		case USB_DT_HUB:
+			debug("USB_DT_HUB config\n");
+			srcptr = &descriptor.hub;
+			srclen = 0x8;
+			break;
+		default:
+			debug("unknown value %x\n", le16_to_cpu(req->value));
+			goto unknown;
+		}
+		break;
+	case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
+		debug("USB_REQ_SET_ADDRESS\n");
+		rootdev = le16_to_cpu(req->value);
+		break;
+	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+		debug("USB_REQ_SET_CONFIGURATION\n");
+		/* Nothing to do */
+		break;
+	case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
+		tmpbuf[0] = 1;	/* USB_STATUS_SELFPOWERED */
+		tmpbuf[1] = 0;
+		srcptr = tmpbuf;
+		srclen = 2;
+		break;
+	case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
+		memset(tmpbuf, 0, 4);
+		reg = ehci_readl(status_reg);
+		if (reg & EHCI_PS_CS)
+			tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
+		if (reg & EHCI_PS_PE)
+			tmpbuf[0] |= USB_PORT_STAT_ENABLE;
+		if (reg & EHCI_PS_SUSP)
+			tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
+		if (reg & EHCI_PS_OCA)
+			tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
+		if (reg & EHCI_PS_PR &&
+		    (portreset & (1 << le16_to_cpu(req->index)))) {
+			int ret;
+			/* force reset to complete */
+			reg = reg & ~(EHCI_PS_PR | EHCI_PS_CLEAR);
+			ehci_writel(status_reg, reg);
+			ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000);
+			if (!ret)
+				tmpbuf[0] |= USB_PORT_STAT_RESET;
+			else
+				printf("port(%d) reset error\n",
+					le16_to_cpu(req->index) - 1);
+		}
+		if (reg & EHCI_PS_PP)
+			tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
+
+		if (ehci_is_TDI()) {
+			switch ((reg >> 26) & 3) {
+			case 0:
+				break;
+			case 1:
+				tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
+				break;
+			case 2:
+			default:
+				tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
+				break;
+			}
+		} else {
+			tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
+		}
+
+		if (reg & EHCI_PS_CSC)
+			tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
+		if (reg & EHCI_PS_PEC)
+			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
+		if (reg & EHCI_PS_OCC)
+			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
+		if (portreset & (1 << le16_to_cpu(req->index)))
+			tmpbuf[2] |= USB_PORT_STAT_C_RESET;
+
+		srcptr = tmpbuf;
+		srclen = 4;
+		break;
+	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
+		reg = ehci_readl(status_reg);
+		reg &= ~EHCI_PS_CLEAR;
+		switch (le16_to_cpu(req->value)) {
+		case USB_PORT_FEAT_ENABLE:
+			reg |= EHCI_PS_PE;
+			ehci_writel(status_reg, reg);
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) {
+				reg |= EHCI_PS_PP;
+				ehci_writel(status_reg, reg);
+			}
+			break;
+		case USB_PORT_FEAT_RESET:
+			if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
+			    !ehci_is_TDI() &&
+			    EHCI_PS_IS_LOWSPEED(reg)) {
+				/* Low speed device, give up ownership. */
+				debug("port %d low speed --> companion\n",
+				      req->index - 1);
+				reg |= EHCI_PS_PO;
+				ehci_writel(status_reg, reg);
+				break;
+			} else {
+				reg |= EHCI_PS_PR;
+				reg &= ~EHCI_PS_PE;
+				ehci_writel(status_reg, reg);
+				/*
+				 * caller must wait, then call GetPortStatus
+				 * usb 2.0 specification say 50 ms resets on
+				 * root
+				 */
+				wait_ms(50);
+				portreset |= 1 << le16_to_cpu(req->index);
+			}
+			break;
+		default:
+			debug("unknown feature %x\n", le16_to_cpu(req->value));
+			goto unknown;
+		}
+		/* unblock posted writes */
+		ehci_readl(&hcor->or_usbcmd);
+		break;
+	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
+		reg = ehci_readl(status_reg);
+		switch (le16_to_cpu(req->value)) {
+		case USB_PORT_FEAT_ENABLE:
+			reg &= ~EHCI_PS_PE;
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams)))
+				reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
+		case USB_PORT_FEAT_C_CONNECTION:
+			reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
+			break;
+		case USB_PORT_FEAT_OVER_CURRENT:
+			reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			portreset &= ~(1 << le16_to_cpu(req->index));
+			break;
+		default:
+			debug("unknown feature %x\n", le16_to_cpu(req->value));
+			goto unknown;
+		}
+		ehci_writel(status_reg, reg);
+		/* unblock posted write */
+		ehci_readl(&hcor->or_usbcmd);
+		break;
+	default:
+		debug("Unknown request\n");
+		goto unknown;
+	}
+
+	wait_ms(1);
+	len = min3(srclen, le16_to_cpu(req->length), length);
+	if (srcptr != NULL && len > 0)
+		memcpy(buffer, srcptr, len);
+	else
+		debug("Len is 0\n");
+
+	dev->act_len = len;
+	dev->status = 0;
+	return 0;
+
+unknown:
+	debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n",
+	      req->requesttype, req->request, le16_to_cpu(req->value),
+	      le16_to_cpu(req->index), le16_to_cpu(req->length));
+
+	dev->act_len = 0;
+	dev->status = USB_ST_STALLED;
+	return -1;
+}
+
+int usb_lowlevel_stop(void)
+{
+	return ehci_hcd_stop();
+}
+
+int usb_lowlevel_init(void)
+{
+	uint32_t reg;
+	uint32_t cmd;
+
+	if (ehci_hcd_init() != 0)
+		return -1;
+
+	/* EHCI spec section 4.1 */
+	if (ehci_reset() != 0)
+		return -1;
+
+#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
+	if (ehci_hcd_init() != 0)
+		return -1;
+#endif
+
+	/* Set head of reclaim list */
+	memset(&qh_list, 0, sizeof(qh_list));
+	qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+	qh_list.qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
+	qh_list.qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
+	qh_list.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	qh_list.qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+	qh_list.qh_overlay.qt_token = cpu_to_hc32(0x40);
+
+	/* Set async. queue head pointer. */
+	ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list);
+
+	reg = ehci_readl(&hccr->cr_hcsparams);
+	descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
+	printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
+	/* Port Indicators */
+	if (HCS_INDICATOR(reg))
+		descriptor.hub.wHubCharacteristics |= 0x80;
+	/* Port Power Control */
+	if (HCS_PPC(reg))
+		descriptor.hub.wHubCharacteristics |= 0x01;
+
+	/* Start the host controller. */
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	/* Philips, Intel, and maybe others need CMD_RUN before the
+         * root hub will detect new devices (why?); NEC doesn't */
+	cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+	cmd |= CMD_RUN;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	/* take control over the ports */
+	cmd = ehci_readl(&hcor->or_configflag);
+	cmd |= FLAG_CF;
+	ehci_writel(&hcor->or_configflag, cmd);
+	/* unblock posted write */
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	wait_ms(5);
+	reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
+	printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
+
+	rootdev = 0;
+
+	return 0;
+}
+
+int
+submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int length)
+{
+
+	if (usb_pipetype(pipe) != PIPE_BULK) {
+		debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe));
+		return -1;
+	}
+	return ehci_submit_async(dev, pipe, buffer, length, NULL);
+}
+
+int
+submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		   int length, struct devrequest *setup)
+{
+
+	if (usb_pipetype(pipe) != PIPE_CONTROL) {
+		debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
+		return -1;
+	}
+
+	if (usb_pipedevice(pipe) == rootdev) {
+		if (rootdev == 0)
+			dev->speed = USB_SPEED_HIGH;
+		return ehci_submit_root(dev, pipe, buffer, length, setup);
+	}
+	return ehci_submit_async(dev, pipe, buffer, length, setup);
+}
+
+int
+submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+	       int length, int interval)
+{
+
+	debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
+	      dev, pipe, buffer, length, interval);
+	return -1;
+}
diff --git a/drivers/usb/usb_ehci_core.h b/drivers/usb/usb_ehci_core.h
new file mode 100644
index 0000000..39e5c5e
--- /dev/null
+++ b/drivers/usb/usb_ehci_core.h
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008, Excito Elektronik i Skåne AB
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef USB_EHCI_CORE_H
+#define USB_EHCI_CORE_H
+
+extern int rootdev;
+extern struct ehci_hccr *hccr;
+extern volatile struct ehci_hcor *hcor;
+
+#endif
diff --git a/drivers/usb/usb_ehci_fsl.c b/drivers/usb/usb_ehci_fsl.c
new file mode 100644
index 0000000..81d5d21
--- /dev/null
+++ b/drivers/usb/usb_ehci_fsl.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
+ *
+ * Author: Tor Krill tor@excito.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <usb.h>
+#include <mpc83xx.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+#include "usb_ehci.h"
+#include "usb_ehci_fsl.h"
+#include "usb_ehci_core.h"
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ *
+ * Excerpts from linux ehci fsl driver.
+ */
+int ehci_hcd_init(void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	uint32_t addr, temp;
+
+	addr = (uint32_t)&(im->usb[0]);
+	hccr = (struct ehci_hccr *)(addr + FSL_SKIP_PCI);
+	hcor = (struct ehci_hcor *)((uint32_t) hccr +
+			HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	/* Configure clock */
+	clrsetbits_be32(&(im->clk.sccr), MPC83XX_SCCR_USB_MASK,
+			MPC83XX_SCCR_USB_DRCM_11);
+
+	/* Confgure interface. */
+	temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+	out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp
+		 | REFSEL_16MHZ | UTMI_PHY_EN);
+
+	/* Wait for clock to stabilize */
+	do {
+		temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+		udelay(1000);
+	} while (!(temp & PHY_CLK_VALID));
+
+	/* Set to Host mode */
+	temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
+	out_le32((void *)(addr + FSL_SOC_USB_USBMODE), temp | CM_HOST);
+
+	out_be32((void *)(addr + FSL_SOC_USB_SNOOP1), SNOOP_SIZE_2GB);
+	out_be32((void *)(addr + FSL_SOC_USB_SNOOP2),
+		 0x80000000 | SNOOP_SIZE_2GB);
+
+	/* Init phy */
+	/* TODO: handle different phys? */
+	out_le32(&(hcor->or_portsc[0]), PORT_PTS_UTMI);
+
+	/* Enable interface. */
+	temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+	out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
+
+	out_be32((void *)(addr + FSL_SOC_USB_PRICTRL), 0x0000000c);
+	out_be32((void *)(addr + FSL_SOC_USB_AGECNTTHRSH), 0x00000040);
+	out_be32((void *)(addr + FSL_SOC_USB_SICTRL), 0x00000001);
+
+	/* Enable interface. */
+	temp = in_be32((void *)(addr + FSL_SOC_USB_CTRL));
+	out_be32((void *)(addr + FSL_SOC_USB_CTRL), temp | USB_EN);
+
+	temp = in_le32((void *)(addr + FSL_SOC_USB_USBMODE));
+
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+	return 0;
+}
diff --git a/drivers/usb/usb_ehci_fsl.h b/drivers/usb/usb_ehci_fsl.h
new file mode 100644
index 0000000..c429af1
--- /dev/null
+++ b/drivers/usb/usb_ehci_fsl.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2005 freescale semiconductor
+ * Copyright (c) 2005 MontaVista Software
+ * Copyright (c) 2008 Excito Elektronik i Sk=E5ne AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _EHCI_FSL_H
+#define _EHCI_FSL_H
+
+/* Global offsets */
+#define FSL_SKIP_PCI		0x100
+
+/* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ULPIVP	0x170
+#define FSL_SOC_USB_PORTSC1	0x184
+#define PORT_PTS_MSK		(3 << 30)
+#define PORT_PTS_UTMI		(0 << 30)
+#define PORT_PTS_ULPI		(2 << 30)
+#define PORT_PTS_SERIAL		(3 << 30)
+#define PORT_PTS_PTW		(1 << 28)
+
+/* USBMODE Register bits */
+#define CM_IDLE			(0 << 0)
+#define CM_RESERVED		(1 << 0)
+#define CM_DEVICE		(2 << 0)
+#define CM_HOST			(3 << 0)
+#define USBMODE_RESERVED_2	(0 << 2)
+#define SLOM			(1 << 3)
+#define SDIS			(1 << 4)
+
+/* CONTROL Register bits */
+#define ULPI_INT_EN		(1 << 0)
+#define WU_INT_EN		(1 << 1)
+#define USB_EN			(1 << 2)
+#define LSF_EN			(1 << 3)
+#define KEEP_OTG_ON		(1 << 4)
+#define OTG_PORT		(1 << 5)
+#define REFSEL_12MHZ		(0 << 6)
+#define REFSEL_16MHZ		(1 << 6)
+#define REFSEL_48MHZ		(2 << 6)
+#define PLL_RESET		(1 << 8)
+#define UTMI_PHY_EN		(1 << 9)
+#define PHY_CLK_SEL_UTMI	(0 << 10)
+#define PHY_CLK_SEL_ULPI	(1 << 10)
+#define CLKIN_SEL_USB_CLK	(0 << 11)
+#define CLKIN_SEL_USB_CLK2	(1 << 11)
+#define CLKIN_SEL_SYS_CLK	(2 << 11)
+#define CLKIN_SEL_SYS_CLK2	(3 << 11)
+#define RESERVED_18		(0 << 13)
+#define RESERVED_17		(0 << 14)
+#define RESERVED_16		(0 << 15)
+#define WU_INT			(1 << 16)
+#define PHY_CLK_VALID		(1 << 17)
+
+#define FSL_SOC_USB_PORTSC2	0x188
+#define FSL_SOC_USB_USBMODE	0x1a8
+#define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
+#define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
+#define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
+#define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
+#define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
+#define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
+#define SNOOP_SIZE_2GB		0x1e
+
+/* System Clock Control Register */
+#define MPC83XX_SCCR_USB_MASK		0x00f00000
+#define MPC83XX_SCCR_USB_DRCM_11	0x00300000
+#define MPC83XX_SCCR_USB_DRCM_01	0x00100000
+#define MPC83XX_SCCR_USB_DRCM_10	0x00200000
+
+#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/usb_ehci_ixp.c b/drivers/usb/usb_ehci_ixp.c
new file mode 100644
index 0000000..25c18c1
--- /dev/null
+++ b/drivers/usb/usb_ehci_ixp.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
+ *
+ * Author: Michael Trimarchi <trimarchimichael@yahoo.it>
+ * This code is based on ehci freescale driver
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <usb.h>
+#include "usb_ehci.h"
+#include "usb_ehci_core.h"
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+	hccr = (struct ehci_hccr *)(0xcd000100);
+	hcor = (struct ehci_hcor *)((uint32_t) hccr
+			+ HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	printf("IXP4XX init hccr %x and hcor %x hc_length %d\n",
+		(uint32_t)hccr, (uint32_t)hcor,
+		(uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+	return 0;
+}
diff --git a/drivers/usb/usb_ehci_pci.c b/drivers/usb/usb_ehci_pci.c
new file mode 100644
index 0000000..3e7143c
--- /dev/null
+++ b/drivers/usb/usb_ehci_pci.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2007-2008, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <usb.h>
+#include "usb_ehci.h"
+#include "usb_ehci_core.h"
+
+#ifdef CONFIG_PCI_EHCI_DEVICE
+static struct pci_device_id ehci_pci_ids[] = {
+	/* Please add supported PCI EHCI controller ids here */
+	{0, 0}
+};
+#endif
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+	pci_dev_t pdev;
+	uint32_t addr;
+
+	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
+	if (pdev == -1) {
+		printf("EHCI host controller not found\n");
+		return -1;
+	}
+
+	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr);
+	hccr = (struct ehci_hccr *)addr;
+	hcor = (struct ehci_hcor *)((uint32_t) hccr +
+			HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+	return 0;
+}
diff --git a/include/configs/VCMA9.h b/include/configs/VCMA9.h
index 83d0d56..d9bcf6b 100644
--- a/include/configs/VCMA9.h
+++ b/include/configs/VCMA9.h
@@ -36,7 +36,6 @@
 #define CONFIG_ARM920T		1	/* This is an ARM920T Core	*/
 #define	CONFIG_S3C2410		1	/* in a SAMSUNG S3C2410 SoC     */
 #define CONFIG_VCMA9		1	/* on a MPL VCMA9 Board  */
-#define LITTLEENDIAN		1	/* used by usb_ohci.c		*/
 
 /* input clock of PLL */
 #define CONFIG_SYS_CLK_FREQ	12000000/* VCMA9 has 12MHz input clock	*/
diff --git a/include/configs/afeb9260.h b/include/configs/afeb9260.h
index e996bbd..9eed342 100644
--- a/include/configs/afeb9260.h
+++ b/include/configs/afeb9260.h
@@ -114,7 +114,6 @@
 
 /* USB */
 #define CONFIG_USB_OHCI_NEW		1
-#define LITTLEENDIAN			1
 #define CONFIG_DOS_PARTITION		1
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
 #define CONFIG_SYS_USB_OHCI_REGS_BASE		0x00500000	/* AT91SAM9260_UHP_BASE */
diff --git a/include/configs/at91cap9adk.h b/include/configs/at91cap9adk.h
index f1c5526..01da99b 100644
--- a/include/configs/at91cap9adk.h
+++ b/include/configs/at91cap9adk.h
@@ -131,7 +131,6 @@
 
 /* USB */
 #define CONFIG_USB_OHCI_NEW		1
-#define LITTLEENDIAN			1
 #define CONFIG_DOS_PARTITION		1
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
 #define CONFIG_SYS_USB_OHCI_REGS_BASE		0x00700000	/* AT91_BASE_UHP */
diff --git a/include/configs/at91sam9260ek.h b/include/configs/at91sam9260ek.h
index 4501cae..2f1a41f 100644
--- a/include/configs/at91sam9260ek.h
+++ b/include/configs/at91sam9260ek.h
@@ -116,7 +116,6 @@
 
 /* USB */
 #define CONFIG_USB_OHCI_NEW		1
-#define LITTLEENDIAN			1
 #define CONFIG_DOS_PARTITION		1
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
 #define CONFIG_SYS_USB_OHCI_REGS_BASE		0x00500000	/* AT91SAM9260_UHP_BASE */
diff --git a/include/configs/at91sam9261ek.h b/include/configs/at91sam9261ek.h
index 668fe3b..ebecfa4 100644
--- a/include/configs/at91sam9261ek.h
+++ b/include/configs/at91sam9261ek.h
@@ -129,7 +129,6 @@
 
 /* USB */
 #define CONFIG_USB_OHCI_NEW		1
-#define LITTLEENDIAN			1
 #define CONFIG_DOS_PARTITION		1
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
 #define CONFIG_SYS_USB_OHCI_REGS_BASE		0x00500000	/* AT91SAM9261_UHP_BASE */
diff --git a/include/configs/at91sam9263ek.h b/include/configs/at91sam9263ek.h
index c6603ff..09b871a 100644
--- a/include/configs/at91sam9263ek.h
+++ b/include/configs/at91sam9263ek.h
@@ -136,7 +136,6 @@
 
 /* USB */
 #define CONFIG_USB_OHCI_NEW		1
-#define LITTLEENDIAN			1
 #define CONFIG_DOS_PARTITION		1
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
 #define CONFIG_SYS_USB_OHCI_REGS_BASE		0x00a00000	/* AT91SAM9263_UHP_BASE */
diff --git a/include/configs/davinci_dvevm.h b/include/configs/davinci_dvevm.h
index a727f56..667c0d8 100644
--- a/include/configs/davinci_dvevm.h
+++ b/include/configs/davinci_dvevm.h
@@ -171,6 +171,8 @@
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
+#define CONFIG_MUSB_HCD
+#define CONFIG_USB_DAVINCI
 /*===================*/
 /* Linux Information */
 /*===================*/
@@ -203,6 +205,22 @@
 #else
 #error "Either CONFIG_SYS_USE_NAND or CONFIG_SYS_USE_NOR _MUST_ be defined !!!"
 #endif
+/*==========================*/
+/* USB MSC support (if any) */
+/*==========================*/
+#ifdef CONFIG_USB_DAVINCI
+#define CONFIG_CMD_USB
+#ifdef CONFIG_MUSB_HCD
+#define CONFIG_USB_STORAGE
+#define CONFIG_CMD_STORAGE
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#endif
+#ifdef CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL
+#define CONFIG_PREBOOT "usb start"
+#endif
+#endif
 /*=======================*/
 /* KGDB support (if any) */
 /*=======================*/
diff --git a/include/configs/delta.h b/include/configs/delta.h
index fd97b74..abb2676 100644
--- a/include/configs/delta.h
+++ b/include/configs/delta.h
@@ -131,8 +131,6 @@
 #define CONFIG_SYS_USB_OHCI_SLOT_NAME	"delta"
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	3
 
-#define LITTLEENDIAN            1       /* used by usb_ohci.c  */
-
 #define CONFIG_BOOTDELAY	-1
 #define CONFIG_ETHADDR		08:00:3e:26:0a:5b
 #define CONFIG_NETMASK		255.255.0.0
diff --git a/include/configs/mp2usb.h b/include/configs/mp2usb.h
index fb10616..9ac7e9a 100644
--- a/include/configs/mp2usb.h
+++ b/include/configs/mp2usb.h
@@ -216,7 +216,6 @@
 #define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
 
 #define CONFIG_SYS_DEVICE_DEREGISTER           /* needs device_deregister */
-#define LITTLEENDIAN            1       /* used by usb_ohci.c  */
 
 #define CONFIG_SYS_HZ 1000
 #define CONFIG_SYS_HZ_CLOCK (AT91C_MASTER_CLOCK/2)	/* AT91C_TC0_CMR is implicitly set to */
diff --git a/include/configs/sh7785lcr.h b/include/configs/sh7785lcr.h
index 1b59059..ebca448 100644
--- a/include/configs/sh7785lcr.h
+++ b/include/configs/sh7785lcr.h
@@ -123,7 +123,6 @@
 #undef	CONFIG_SYS_DIRECT_FLASH_TFTP
 
 /* R8A66597 */
-#define LITTLEENDIAN			/* for include/usb.h */
 #define CONFIG_USB_R8A66597_HCD
 #define CONFIG_R8A66597_BASE_ADDR	SH7785LCR_USB_BASE
 #define CONFIG_R8A66597_XTAL		0x0000	/* 12MHz */
diff --git a/include/configs/smdk6400.h b/include/configs/smdk6400.h
index 57c82d1..c61667f 100644
--- a/include/configs/smdk6400.h
+++ b/include/configs/smdk6400.h
@@ -293,7 +293,6 @@
 #define CONFIG_SYS_USB_OHCI_SLOT_NAME		"s3c6400"
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	3
 #define CONFIG_SYS_USB_OHCI_CPU_INIT		1
-#define LITTLEENDIAN			1	/* used by usb_ohci.c	*/
 
 #define CONFIG_USB_STORAGE	1
 #endif
diff --git a/include/configs/trab.h b/include/configs/trab.h
index 562cd60..0a7a73d 100644
--- a/include/configs/trab.h
+++ b/include/configs/trab.h
@@ -44,7 +44,6 @@
 #define CONFIG_S3C2400		1	/* in a SAMSUNG S3C2400 SoC	*/
 #define CONFIG_TRAB		1	/* on a TRAB Board		*/
 #undef CONFIG_TRAB_50MHZ		/* run the CPU at 50 MHz	*/
-#define LITTLEENDIAN		1	/* used by usb_ohci.c		*/
 
 /* automatic software updates (see board/trab/auto_update.c) */
 #define CONFIG_AUTO_UPDATE	1
diff --git a/include/configs/trizepsiv.h b/include/configs/trizepsiv.h
index b2065ee..0a8e994 100644
--- a/include/configs/trizepsiv.h
+++ b/include/configs/trizepsiv.h
@@ -42,8 +42,6 @@
  */
 #define CONFIG_PXA27X		1	/* This is an PXA27x CPU    */
 
-#define LITTLEENDIAN		1	/* used by usb_ohci.c		*/
-
 #define CONFIG_MMC		1
 #define BOARD_LATE_INIT		1
 
diff --git a/include/usb.h b/include/usb.h
index 510df95..7c47098 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -138,7 +138,7 @@
 
 struct usb_device {
 	int	devnum;			/* Device number on USB bus */
-	int	slow;			/* Slow device? */
+	int	speed;			/* full/low/high */
 	char	mf[32];			/* manufacturer */
 	char	prod[32];		/* product */
 	char	serial[32];		/* serial number */
@@ -171,6 +171,7 @@
 	unsigned long status;
 	int act_len;			/* transfered bytes */
 	int maxchild;			/* Number of ports if hub */
+	int portnr;
 	struct usb_device *parent;
 	struct usb_device *children[USB_MAXCHILDREN];
 };
@@ -180,8 +181,9 @@
  */
 
 #if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
-	defined(CONFIG_USB_OHCI_NEW) || defined(CONFIG_USB_SL811HS) || \
-	defined(CONFIG_USB_ISP116X_HCD) || defined(CONFIG_USB_R8A66597_HCD)
+	defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \
+	defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
+	defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI)
 
 int usb_lowlevel_init(void);
 int usb_lowlevel_stop(void);
@@ -263,13 +265,13 @@
 		((x_ & 0xFF000000UL) >> 24)); \
 	})
 
-#ifdef LITTLEENDIAN
+#ifdef __LITTLE_ENDIAN
 # define swap_16(x) (x)
 # define swap_32(x) (x)
 #else
 # define swap_16(x) __swap_16(x)
 # define swap_32(x) __swap_32(x)
-#endif /* LITTLEENDIAN */
+#endif
 
 /*
  * Calling this entity a "pipe" is glorifying it. A USB pipe
@@ -279,7 +281,7 @@
  *  - endpoint number (4 bits)
  *  - current Data0/1 state (1 bit)
  *  - direction (1 bit)
- *  - speed (1 bit)
+ *  - speed (2 bits)
  *  - max packet size (2 bits: 8, 16, 32 or 64)
  *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
  *
@@ -296,7 +298,7 @@
  *  - device:		bits 8-14
  *  - endpoint:		bits 15-18
  *  - Data0/1:		bit 19
- *  - speed:		bit 26		(0 = Full, 1 = Low Speed)
+ *  - speed:		bit 26		(0 = Full, 1 = Low Speed, 2 = High)
  *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt,
  *					 10 = control, 11 = bulk)
  *
@@ -308,8 +310,8 @@
 /* Create various pipes... */
 #define create_pipe(dev,endpoint) \
 		(((dev)->devnum << 8) | (endpoint << 15) | \
-		((dev)->slow << 26) | (dev)->maxpacketsize)
-#define default_pipe(dev) ((dev)->slow << 26)
+		((dev)->speed << 26) | (dev)->maxpacketsize)
+#define default_pipe(dev) ((dev)->speed << 26)
 
 #define usb_sndctrlpipe(dev, endpoint)	((PIPE_CONTROL << 30) | \
 					 create_pipe(dev, endpoint))
@@ -359,7 +361,8 @@
 #define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff)
 #define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)
 #define usb_pipedata(pipe)	(((pipe) >> 19) & 1)
-#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
+#define usb_pipespeed(pipe)	(((pipe) >> 26) & 3)
+#define usb_pipeslow(pipe)	(usb_pipespeed(pipe) == USB_SPEED_LOW)
 #define usb_pipetype(pipe)	(((pipe) >> 30) & 3)
 #define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
 #define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT)
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 353019f..8032e57 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -80,6 +80,12 @@
 #define USB_DIR_OUT           0
 #define USB_DIR_IN            0x80
 
+/* USB device speeds */
+#define USB_SPEED_FULL		0x0	/* 12Mbps */
+#define USB_SPEED_LOW		0x1	/* 1.5Mbps */
+#define USB_SPEED_HIGH		0x2	/* 480Mbps */
+#define USB_SPEED_RESERVED	0x3
+
 /* Descriptor types */
 #define USB_DT_DEVICE        0x01
 #define USB_DT_CONFIG        0x02
@@ -202,6 +208,7 @@
 #define USB_PORT_FEAT_RESET          4
 #define USB_PORT_FEAT_POWER          8
 #define USB_PORT_FEAT_LOWSPEED       9
+#define USB_PORT_FEAT_HIGHSPEED      10
 #define USB_PORT_FEAT_C_CONNECTION   16
 #define USB_PORT_FEAT_C_ENABLE       17
 #define USB_PORT_FEAT_C_SUSPEND      18
@@ -216,6 +223,9 @@
 #define USB_PORT_STAT_RESET         0x0010
 #define USB_PORT_STAT_POWER         0x0100
 #define USB_PORT_STAT_LOW_SPEED     0x0200
+#define USB_PORT_STAT_HIGH_SPEED    0x0400	/* support for EHCI */
+#define USB_PORT_STAT_SPEED	\
+	(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
 
 /* wPortChange bits */
 #define USB_PORT_STAT_C_CONNECTION  0x0001