Merge branch 'master' of git://git.denx.de/u-boot-usb
authorWolfgang Denk <wd@denx.de>
Wed, 28 Jan 2009 20:09:46 +0000 (21:09 +0100)
committerWolfgang Denk <wd@denx.de>
Wed, 28 Jan 2009 20:09:46 +0000 (21:09 +0100)
36 files changed:
board/davinci/dvevm/dvevm.c
common/cmd_usb.c
common/usb.c
common/usb_kbd.c
common/usb_storage.c
cpu/arm920t/s3c24x0/usb_ohci.c
cpu/mips/au1x00_usb_ohci.c
drivers/usb/Makefile
drivers/usb/davinci_usb.c [new file with mode: 0644]
drivers/usb/davinci_usb.h [new file with mode: 0644]
drivers/usb/musb_core.c [new file with mode: 0644]
drivers/usb/musb_core.h [new file with mode: 0644]
drivers/usb/musb_hcd.c [new file with mode: 0644]
drivers/usb/musb_hcd.h [new file with mode: 0644]
drivers/usb/usb_ehci.h [new file with mode: 0644]
drivers/usb/usb_ehci_core.c [new file with mode: 0644]
drivers/usb/usb_ehci_core.h [new file with mode: 0644]
drivers/usb/usb_ehci_fsl.c [new file with mode: 0644]
drivers/usb/usb_ehci_fsl.h [new file with mode: 0644]
drivers/usb/usb_ehci_ixp.c [new file with mode: 0644]
drivers/usb/usb_ehci_pci.c [new file with mode: 0644]
include/configs/VCMA9.h
include/configs/afeb9260.h
include/configs/at91cap9adk.h
include/configs/at91sam9260ek.h
include/configs/at91sam9261ek.h
include/configs/at91sam9263ek.h
include/configs/davinci_dvevm.h
include/configs/delta.h
include/configs/mp2usb.h
include/configs/sh7785lcr.h
include/configs/smdk6400.h
include/configs/trab.h
include/configs/trizepsiv.h
include/usb.h
include/usb_defs.h

index abf60b3..bf36f73 100644 (file)
@@ -52,6 +52,7 @@ int board_init(void)
        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 @@ int misc_init_r(void)
 
        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
+
index 423a29f..a18e16e 100644 (file)
@@ -264,6 +264,16 @@ void usb_display_config(struct usb_device *dev)
        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 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre)
        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);
index ee18152..87fca70 100644 (file)
@@ -681,7 +681,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
                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 @@ void usb_scan_devices(void)
        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 @@ struct usb_hub_device *usb_hub_allocate(void)
 
 #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 @@ static int hub_port_reset(struct usb_device *dev, int port,
                }
                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 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
        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 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 
        /* 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;
index 89e6ee7..e0d006c 100644 (file)
@@ -183,6 +183,7 @@ int drv_usb_kbd_init(void)
                                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 */
index 94f659f..51f0789 100644 (file)
@@ -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 @@ typedef struct {
        __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 @@ typedef struct {
 #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 @@ static struct us_data usb_stor[USB_MAX_STOR_DEV];
 #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 @@ void usb_show_progress(void)
        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 @@ int usb_stor_info(void)
 
        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 @@ int usb_stor_info(void)
        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 @@ int usb_stor_scan(int mode)
        /* 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 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
                        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 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
                                        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 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
                                        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 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
                        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 @@ static int usb_stor_BBB_reset(struct us_data *us)
         * 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 @@ static int usb_stor_CB_reset(struct us_data *us)
        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 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
        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 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
        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_BBB_comdat(ccb *srb, struct us_data *us)
 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_CB_comdat(ccb *srb, struct us_data *us)
 }
 
 
-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 usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
        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 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
                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 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
        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_BBB_transport(ccb *srb, struct us_data *us)
 
 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_retry:
        }
        /* 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 @@ do_retry:
                }
                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 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
        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 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
 
 #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 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
         */
        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 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
         */
        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 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
            /* Sony USM256E */
            (dev->descriptor.idVendor == 0x054c &&
             dev->descriptor.idProduct == 0x019e)
-
            ||
            /* USB007 Mini-USB2 Flash Drive */
            (dev->descriptor.idVendor == 0x066f &&
@@ -1166,6 +1233,13 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
            /* 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 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
 
        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 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
        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 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
        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;
 }
index 641f270..9cbd477 100644 (file)
@@ -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!
  */
 
index 17489da..ea02efb 100644 (file)
@@ -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)
index 856f51a..b306a65 100644 (file)
@@ -28,11 +28,18 @@ LIB := $(obj)libusb.a
 # 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 (file)
index 0000000..e66f660
--- /dev/null
@@ -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 (file)
index 0000000..d270861
--- /dev/null
@@ -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 (file)
index 0000000..ec57fc8
--- /dev/null
@@ -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 (file)
index 0000000..9f5ebe7
--- /dev/null
@@ -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 (file)
index 0000000..352a0d4
--- /dev/null
@@ -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 (file)
index 0000000..bb83311
--- /dev/null
@@ -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 (file)
index 0000000..b3c1d5d
--- /dev/null
@@ -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 (file)
index 0000000..813f64a
--- /dev/null
@@ -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 (file)
index 0000000..39e5c5e
--- /dev/null
@@ -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 (file)
index 0000000..81d5d21
--- /dev/null
@@ -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 (file)
index 0000000..c429af1
--- /dev/null
@@ -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 (file)
index 0000000..25c18c1
--- /dev/null
@@ -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 (file)
index 0000000..3e7143c
--- /dev/null
@@ -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;
+}
index 83d0d56..d9bcf6b 100644 (file)
@@ -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  */
index e996bbd..9eed342 100644 (file)
 
 /* 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 */
index f1c5526..01da99b 100644 (file)
 
 /* 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 */
index 4501cae..2f1a41f 100644 (file)
 
 /* 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 */
index 668fe3b..ebecfa4 100644 (file)
 
 /* 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 */
index c6603ff..09b871a 100644 (file)
 
 /* 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 */
index a727f56..667c0d8 100644 (file)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
+#define CONFIG_MUSB_HCD
+#define CONFIG_USB_DAVINCI
 /*===================*/
 /* Linux Information */
 /*===================*/
 #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) */
 /*=======================*/
index fd97b74..abb2676 100644 (file)
 #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
index fb10616..9ac7e9a 100644 (file)
 #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 */
index 1b59059..ebca448 100644 (file)
 #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 */
index 57c82d1..c61667f 100644 (file)
 #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
index 562cd60..0a7a73d 100644 (file)
@@ -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
index b2065ee..0a8e994 100644 (file)
@@ -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
 
index 510df95..7c47098 100644 (file)
@@ -138,7 +138,7 @@ enum {
 
 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 @@ struct usb_device {
        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 @@ struct usb_device {
  */
 
 #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 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
                ((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 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
  *  - 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 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
  *  - 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 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
 /* 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 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
 #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)
index 353019f..8032e57 100644 (file)
 #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
 #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
 #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