Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 18:17:39 +0000 (11:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 18:17:39 +0000 (11:17 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (97 commits)
  USB: qcserial: add device id for HP devices
  USB: isp1760: Add a delay before reading the SKIPMAP registers in isp1760-hcd.c
  USB: allow malformed LANGID descriptors
  USB: pxa27x_udc: typo fixes and code cleanups
  USB: gadget: gadget zero uses new suspend/resume hooks
  USB: gadget: composite device-level suspend/resume hooks
  USB: r8a66597-hcd: suspend/resume support
  USB: more u32 conversion after transfer_buffer_length and actual_length
  USB: Fix cp2101 USB serial device driver termios functions for console use
  USB: CP2101 New Device ID
  USB: ipaq: handle 4 endpoint devices
  USB: S3C: Move usb-control.h to platform include
  USB: ohci-hcd: Add ARCH_S3C24XX to the ohci-s3c2410.c glue
  USB: pedantic: spelling correction in comment for ch9.h
  USB: host: fix sparse warning: Using plain integer as NULL pointer
  USB: ohci-s3c2410: fix name of bus clock
  USB: ohci-s3c2410: remove <mach/hardware.h> include
  USB: serial: rename cp2101 driver to cp210x
  USB: CP2101 Reduce Error Logging
  USB: CP2101 Support AN205 baud rates
  ...

1  2 
drivers/usb/gadget/ci13xxx_udc.c
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/imx_udc.c
drivers/usb/host/ohci-hcd.c

index 7f4e5eb1dc805904e31ff21d72227e57a6faf51a,0e310b9aa7af4c8654b2c1a9775c6fca9da74ab3..22c65960c42971c4d94bb3ff83bd09dbfa6cbd94
@@@ -56,7 -56,6 +56,6 @@@
  #include <linux/dma-mapping.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
- #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/irq.h>
  #include <linux/kernel.h>
@@@ -2626,7 -2625,7 +2625,7 @@@ static int udc_probe(struct device *dev
        INIT_LIST_HEAD(&udc->gadget.ep_list);
        udc->gadget.ep0 = NULL;
  
 -      strcpy(udc->gadget.dev.bus_id, "gadget");
 +      dev_set_name(&udc->gadget.dev, "gadget");
        udc->gadget.dev.dma_mask = dev->dma_mask;
        udc->gadget.dev.parent   = dev;
        udc->gadget.dev.release  = udc_release;
index 14e09abbddfcb0463e701a08cc3ec48702686875,bb738bc96d4a0aa7f777047f47b6415fcf8571de..b9312dc6e04151f60c4dea4dce27b36c74e3ae87
@@@ -199,10 -199,10 +199,10 @@@ DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1)
  static struct usb_device_descriptor device_desc = {
        .bLength =              USB_DT_DEVICE_SIZE,
        .bDescriptorType =      USB_DT_DEVICE,
-       .bcdUSB =               __constant_cpu_to_le16(0x0200),
+       .bcdUSB =               cpu_to_le16(0x0200),
        .bDeviceClass =         USB_CLASS_PER_INTERFACE,
-       .idVendor =             __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
-       .idProduct =            __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+       .idVendor =             cpu_to_le16(DRIVER_VENDOR_NUM),
+       .idProduct =            cpu_to_le16(DRIVER_PRODUCT_NUM),
        .iManufacturer =        STRING_MANUFACTURER,
        .iProduct =             STRING_PRODUCT,
        .bNumConfigurations =   1,
@@@ -241,8 -241,8 +241,8 @@@ static const struct usb_ac_header_descr
        .bLength =              USB_DT_AC_HEADER_SIZE(1),
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubtype =   USB_MS_HEADER,
-       .bcdADC =               __constant_cpu_to_le16(0x0100),
-       .wTotalLength =         __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
+       .bcdADC =               cpu_to_le16(0x0100),
+       .wTotalLength =         cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
        .bInCollection =        1,
        .baInterfaceNr = {
                [0] =           GMIDI_MS_INTERFACE,
@@@ -265,8 -265,8 +265,8 @@@ static const struct usb_ms_header_descr
        .bLength =              USB_DT_MS_HEADER_SIZE,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubtype =   USB_MS_HEADER,
-       .bcdMSC =               __constant_cpu_to_le16(0x0100),
-       .wTotalLength =         __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE
+       .bcdMSC =               cpu_to_le16(0x0100),
+       .wTotalLength =         cpu_to_le16(USB_DT_MS_HEADER_SIZE
                                + 2*USB_DT_MIDI_IN_SIZE
                                + 2*USB_DT_MIDI_OUT_SIZE(1)),
  };
@@@ -1099,9 -1099,10 +1099,9 @@@ static int gmidi_register_card(struct g
                .dev_free = gmidi_snd_free,
        };
  
 -      card = snd_card_new(index, id, THIS_MODULE, 0);
 -      if (!card) {
 -              ERROR(dev, "snd_card_new failed\n");
 -              err = -ENOMEM;
 +      err = snd_card_create(index, id, THIS_MODULE, 0, &card);
 +      if (err < 0) {
 +              ERROR(dev, "snd_card_create failed\n");
                goto fail;
        }
        dev->card = card;
@@@ -1226,7 -1227,7 +1226,7 @@@ autoconf_fail
                 */
                pr_warning("%s: controller '%s' not recognized\n",
                        shortname, gadget->name);
-               device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+               device_desc.bcdDevice = cpu_to_le16(0x9999);
        }
  
  
index cd67ac75e6241097796399a415449084885b63eb,8d3c6a960988e06082adc3c81d74225455ed3cd5..168658b4b4e26d2bc7b2614cf5b8cb891a3614e5
@@@ -1,7 -1,7 +1,7 @@@
  /*
   *    driver/usb/gadget/imx_udc.c
   *
-  *    Copyright (C) 2005 Mike Lee(eemike@gmail.com)
+  *    Copyright (C) 2005 Mike Lee <eemike@gmail.com>
   *    Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>
   *
   *    This program is free software; you can redistribute it and/or modify
@@@ -28,6 -28,7 +28,7 @@@
  #include <linux/dma-mapping.h>
  #include <linux/clk.h>
  #include <linux/delay.h>
+ #include <linux/timer.h>
  
  #include <linux/usb/ch9.h>
  #include <linux/usb/gadget.h>
@@@ -51,7 -52,8 +52,8 @@@ void ep0_chg_stat(const char *label, st
  void imx_udc_enable(struct imx_udc_struct *imx_usb)
  {
        int temp = __raw_readl(imx_usb->base + USB_CTRL);
-       __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL);
+       __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA,
+                                               imx_usb->base + USB_CTRL);
        imx_usb->gadget.speed = USB_SPEED_FULL;
  }
  
@@@ -126,7 -128,8 +128,8 @@@ void imx_udc_config(struct imx_udc_stru
                        for (j = 0; j < 5; j++) {
                                __raw_writeb(ep_conf[j],
                                        imx_usb->base + USB_DDAT);
-                               do {} while (__raw_readl(imx_usb->base + USB_DADR)
+                               do {} while (__raw_readl(imx_usb->base
+                                                               + USB_DADR)
                                        & DADR_BSY);
                        }
                }
@@@ -183,7 -186,8 +186,8 @@@ void imx_udc_init_ep(struct imx_udc_str
                temp = (EP_DIR(imx_ep) << 7) | (max << 5)
                        | (imx_ep->bmAttributes << 3);
                __raw_writel(temp, imx_usb->base + USB_EP_STAT(i));
-               __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i));
+               __raw_writel(temp | EPSTAT_FLUSH,
+                                               imx_usb->base + USB_EP_STAT(i));
                D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
                        __raw_readl(imx_usb->base + USB_EP_STAT(i)));
        }
@@@ -278,15 -282,18 +282,18 @@@ void imx_ep_stall(struct imx_ep_struct 
        struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
        int temp, i;
  
-       D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
+       D_ERR(imx_usb->dev,
+               "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
  
        imx_flush(imx_ep);
  
        /* Special care for ep0 */
-       if (EP_NO(imx_ep)) {
+       if (!EP_NO(imx_ep)) {
                temp = __raw_readl(imx_usb->base + USB_CTRL);
-               __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL);
-               do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER);
+               __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR,
+                                               imx_usb->base + USB_CTRL);
+               do { } while (__raw_readl(imx_usb->base + USB_CTRL)
+                                               & CTRL_CMDOVER);
                temp = __raw_readl(imx_usb->base + USB_CTRL);
                __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
        }
                        imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
  
                for (i = 0; i < 100; i ++) {
-                       temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
+                       temp = __raw_readl(imx_usb->base
+                                               + USB_EP_STAT(EP_NO(imx_ep)));
                        if (!(temp & EPSTAT_STALL))
                                break;
                        udelay(20);
                }
-               if (i == 50)
+               if (i == 100)
                        D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
                                __func__, imx_ep->ep.name);
        }
@@@ -325,7 -333,8 +333,8 @@@ static int imx_udc_wakeup(struct usb_ga
   *******************************************************************************
   */
  
- static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
+ static void ep_add_request(struct imx_ep_struct *imx_ep,
+                                                       struct imx_request *req)
  {
        if (unlikely(!req))
                return;
        list_add_tail(&req->queue, &imx_ep->queue);
  }
  
- static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
+ static void ep_del_request(struct imx_ep_struct *imx_ep,
+                                                       struct imx_request *req)
  {
        if (unlikely(!req))
                return;
        req->in_use = 0;
  }
  
- static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status)
+ static void done(struct imx_ep_struct *imx_ep,
+                                       struct imx_request *req, int status)
  {
        ep_del_request(imx_ep, req);
  
@@@ -494,7 -505,8 +505,8 @@@ static int write_fifo(struct imx_ep_str
                                __func__, imx_ep->ep.name, req,
                                completed ? "completed" : "not completed");
                        if (!EP_NO(imx_ep))
-                               ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE);
+                               ep0_chg_stat(__func__,
+                                               imx_ep->imx_usb, EP0_IDLE);
                }
        }
  
@@@ -539,10 -551,9 +551,9 @@@ static int handle_ep0(struct imx_ep_str
        struct imx_request *req = NULL;
        int ret = 0;
  
-       if (!list_empty(&imx_ep->queue))
+       if (!list_empty(&imx_ep->queue)) {
                req = list_entry(imx_ep->queue.next, struct imx_request, queue);
  
-       if (req) {
                switch (imx_ep->imx_usb->ep0state) {
  
                case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR */
                }
        }
  
+       else
+               D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
+                                               __func__, imx_ep->ep.name);
        return ret;
  }
  
@@@ -583,7 -598,8 +598,8 @@@ static void handle_ep0_devreq(struct im
                                "<%s> no setup packet received\n", __func__);
                        goto stall;
                }
-               u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep)));
+               u.word[i] = __raw_readl(imx_usb->base
+                                               + USB_EP_FDAT(EP_NO(imx_ep)));
        }
  
        temp = imx_ep_empty(imx_ep);
@@@ -759,7 -775,7 +775,7 @@@ static int imx_ep_queu
        */
        if (imx_usb->set_config && !EP_NO(imx_ep)) {
                imx_usb->set_config = 0;
-               D_EPX(imx_usb->dev,
+               D_ERR(imx_usb->dev,
                        "<%s> gadget reply set config\n", __func__);
                return 0;
        }
                return -ESHUTDOWN;
        }
  
-       local_irq_save(flags);
        /* Debug */
        D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
                __func__, EP_NO(imx_ep),
-               ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
-               || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length);
+               ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
+                                                       == EP0_IN_DATA_PHASE)
+               || (EP_NO(imx_ep) && EP_DIR(imx_ep)))
+                                       ? "IN" : "OUT", usb_req->length);
        dump_req(__func__, imx_ep, usb_req);
  
        if (imx_ep->stopped) {
                usb_req->status = -ESHUTDOWN;
-               ret = -ESHUTDOWN;
-               goto out;
+               return -ESHUTDOWN;
        }
  
        if (req->in_use) {
                D_ERR(imx_usb->dev,
                        "<%s> refusing to queue req %p (already queued)\n",
                        __func__, req);
-               goto out;
+               return 0;
        }
  
+       local_irq_save(flags);
        usb_req->status = -EINPROGRESS;
        usb_req->actual = 0;
  
                ret = handle_ep0(imx_ep);
        else
                ret = handle_ep(imx_ep);
- out:
        local_irq_restore(flags);
        return ret;
  }
@@@ -997,71 -1014,32 +1014,32 @@@ static void udc_stop_activity(struct im
   *******************************************************************************
   */
  
- static irqreturn_t imx_udc_irq(int irq, void *dev)
+ /*
+  * Called when timer expires.
+  * Timer is started when CFG_CHG is received.
+  */
+ static void handle_config(unsigned long data)
  {
-       struct imx_udc_struct *imx_usb = dev;
+       struct imx_udc_struct *imx_usb = (void *)data;
        struct usb_ctrlrequest u;
        int temp, cfg, intf, alt;
-       int intr = __raw_readl(imx_usb->base + USB_INTR);
-       if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
-                       | INTR_RESET_STOP | INTR_CFG_CHG)) {
-                               dump_intr(__func__, intr, imx_usb->dev);
-                               dump_usb_stat(__func__, imx_usb);
-       }
-       if (!imx_usb->driver) {
-               /*imx_udc_disable(imx_usb);*/
-               goto end_irq;
-       }
-       if (intr & INTR_WAKEUP) {
-               if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
-                       && imx_usb->driver && imx_usb->driver->resume)
-                               imx_usb->driver->resume(&imx_usb->gadget);
-               imx_usb->set_config = 0;
-               imx_usb->gadget.speed = USB_SPEED_FULL;
-       }
-       if (intr & INTR_SUSPEND) {
-               if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
-                       && imx_usb->driver && imx_usb->driver->suspend)
-                               imx_usb->driver->suspend(&imx_usb->gadget);
-               imx_usb->set_config = 0;
-               imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-       }
  
-       if (intr & INTR_RESET_START) {
-               __raw_writel(intr, imx_usb->base + USB_INTR);
-               udc_stop_activity(imx_usb, imx_usb->driver);
-               imx_usb->set_config = 0;
-               imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-       }
-       if (intr & INTR_RESET_STOP)
-               imx_usb->gadget.speed = USB_SPEED_FULL;
+       local_irq_disable();
  
-       if (intr & INTR_CFG_CHG) {
-               __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
-               temp = __raw_readl(imx_usb->base + USB_STAT);
-               cfg  = (temp & STAT_CFG) >> 5;
-               intf = (temp & STAT_INTF) >> 3;
-               alt  =  temp & STAT_ALTSET;
+       temp = __raw_readl(imx_usb->base + USB_STAT);
+       cfg  = (temp & STAT_CFG) >> 5;
+       intf = (temp & STAT_INTF) >> 3;
+       alt  =  temp & STAT_ALTSET;
  
-               D_REQ(imx_usb->dev,
-                       "<%s> orig config C=%d, I=%d, A=%d / "
-                       "req config C=%d, I=%d, A=%d\n",
-                       __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
-                       cfg, intf, alt);
+       D_REQ(imx_usb->dev,
+               "<%s> orig config C=%d, I=%d, A=%d / "
+               "req config C=%d, I=%d, A=%d\n",
+               __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
+               cfg, intf, alt);
  
-               if (cfg != 1 && cfg != 2)
-                       goto end_irq;
+       if (cfg == 1 || cfg == 2) {
  
-               imx_usb->set_config = 0;
-               /* Config setup */
                if (imx_usb->cfg != cfg) {
-                       D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__);
                        u.bRequest = USB_REQ_SET_CONFIGURATION;
                        u.bRequestType = USB_DIR_OUT |
                                        USB_TYPE_STANDARD |
                        u.wIndex = 0;
                        u.wLength = 0;
                        imx_usb->cfg = cfg;
-                       imx_usb->set_config = 1;
                        imx_usb->driver->setup(&imx_usb->gadget, &u);
-                       imx_usb->set_config = 0;
-                       D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__);
  
                }
                if (imx_usb->intf != intf || imx_usb->alt != alt) {
-                       D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__);
                        u.bRequest = USB_REQ_SET_INTERFACE;
                        u.bRequestType = USB_DIR_OUT |
                                          USB_TYPE_STANDARD |
                        u.wLength = 0;
                        imx_usb->intf = intf;
                        imx_usb->alt = alt;
-                       imx_usb->set_config = 1;
                        imx_usb->driver->setup(&imx_usb->gadget, &u);
-                       imx_usb->set_config = 0;
-                       D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__);
                }
        }
  
+       imx_usb->set_config = 0;
+       local_irq_enable();
+ }
+ static irqreturn_t imx_udc_irq(int irq, void *dev)
+ {
+       struct imx_udc_struct *imx_usb = dev;
+       int intr = __raw_readl(imx_usb->base + USB_INTR);
+       int temp;
+       if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
+                       | INTR_RESET_STOP | INTR_CFG_CHG)) {
+                               dump_intr(__func__, intr, imx_usb->dev);
+                               dump_usb_stat(__func__, imx_usb);
+       }
+       if (!imx_usb->driver)
+               goto end_irq;
        if (intr & INTR_SOF) {
+               /* Copy from Freescale BSP.
+                  We must enable SOF intr and set CMDOVER.
+                  Datasheet don't specifiy this action, but it
+                  is done in Freescale BSP, so just copy it.
+               */
                if (imx_usb->ep0state == EP0_IDLE) {
                        temp = __raw_readl(imx_usb->base + USB_CTRL);
-                       __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
+                       __raw_writel(temp | CTRL_CMDOVER,
+                                               imx_usb->base + USB_CTRL);
                }
        }
  
+       if (intr & INTR_CFG_CHG) {
+               /* A workaround of serious IMX UDC bug.
+                  Handling of CFG_CHG should be delayed for some time, because
+                  IMX does not NACK the host when CFG_CHG interrupt is pending.
+                  There is no time to handle current CFG_CHG
+                  if next CFG_CHG or SETUP packed is send immediately.
+                  We have to clear CFG_CHG, start the timer and
+                  NACK the host by setting CTRL_CMDOVER
+                  if it sends any SETUP packet.
+                  When timer expires, handler is called to handle configuration
+                  changes. While CFG_CHG is not handled (set_config=1),
+                  we must NACK the host to every SETUP packed.
+                  This delay prevents from going out of sync with host.
+                */
+               __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
+               imx_usb->set_config = 1;
+               mod_timer(&imx_usb->timer, jiffies + 5);
+               goto end_irq;
+       }
+       if (intr & INTR_WAKEUP) {
+               if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
+                       && imx_usb->driver && imx_usb->driver->resume)
+                               imx_usb->driver->resume(&imx_usb->gadget);
+               imx_usb->set_config = 0;
+               del_timer(&imx_usb->timer);
+               imx_usb->gadget.speed = USB_SPEED_FULL;
+       }
+       if (intr & INTR_SUSPEND) {
+               if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
+                       && imx_usb->driver && imx_usb->driver->suspend)
+                               imx_usb->driver->suspend(&imx_usb->gadget);
+               imx_usb->set_config = 0;
+               del_timer(&imx_usb->timer);
+               imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+       }
+       if (intr & INTR_RESET_START) {
+               __raw_writel(intr, imx_usb->base + USB_INTR);
+               udc_stop_activity(imx_usb, imx_usb->driver);
+               imx_usb->set_config = 0;
+               del_timer(&imx_usb->timer);
+               imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+       }
+       if (intr & INTR_RESET_STOP)
+               imx_usb->gadget.speed = USB_SPEED_FULL;
  end_irq:
        __raw_writel(intr, imx_usb->base + USB_INTR);
        return IRQ_HANDLED;
  static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
  {
        struct imx_udc_struct *imx_usb = dev;
+       struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
        int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0));
  
        dump_ep_intr(__func__, 0, intr, imx_usb->dev);
                return IRQ_HANDLED;
        }
  
-       /* DEVREQ IRQ has highest priority */
+       /* DEVREQ has highest priority */
        if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ))
                handle_ep0_devreq(imx_usb);
        /* Seem i.MX is missing EOF interrupt sometimes.
-        * Therefore we monitor both EOF and FIFO_EMPTY interrups
-        * when transmiting, and both EOF and FIFO_FULL when
-        * receiving data.
+        * Therefore we don't monitor EOF.
+        * We call handle_ep0() only if a request is queued for ep0.
         */
-       else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL))
-               handle_ep0(&imx_usb->imx_ep[0]);
+       else if (!list_empty(&imx_ep->queue))
+               handle_ep0(imx_ep);
  
        __raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
  
@@@ -1186,8 -1232,8 +1232,8 @@@ static struct imx_udc_struct controlle
                .ep0            = &controller.imx_ep[0].ep,
                .name           = driver_name,
                .dev = {
 -                       .bus_id        = "gadget",
 -               },
 +                      .init_name      = "gadget",
 +              },
        },
  
        .imx_ep[0] = {
@@@ -1318,6 -1364,7 +1364,7 @@@ int usb_gadget_unregister_driver(struc
  
        udc_stop_activity(imx_usb, driver);
        imx_udc_disable(imx_usb);
+       del_timer(&imx_usb->timer);
  
        driver->unbind(&imx_usb->gadget);
        imx_usb->gadget.dev.driver = NULL;
@@@ -1435,6 -1482,10 +1482,10 @@@ static int __init imx_udc_probe(struct 
        usb_init_data(imx_usb);
        imx_udc_init(imx_usb);
  
+       init_timer(&imx_usb->timer);
+       imx_usb->timer.function = handle_config;
+       imx_usb->timer.data = (unsigned long)imx_usb;
        return 0;
  
  fail3:
@@@ -1457,6 -1508,7 +1508,7 @@@ static int __exit imx_udc_remove(struc
        int i;
  
        imx_udc_disable(imx_usb);
+       del_timer(&imx_usb->timer);
  
        for (i = 0; i < IMX_USB_NB_EP + 1; i++)
                free_irq(imx_usb->usbd_int[i], imx_usb);
index 7658589edb1c289007f124fa07ebf44512f0244b,d052955439c32628e920bce428c52e8683bf5e66..25db704f3a2aa8c7d60ae1c48eab54270abab45e
@@@ -997,7 -997,7 +997,7 @@@ MODULE_LICENSE ("GPL")
  #define SA1111_DRIVER         ohci_hcd_sa1111_driver
  #endif
  
- #ifdef CONFIG_ARCH_S3C2410
+ #if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX)
  #include "ohci-s3c2410.c"
  #define PLATFORM_DRIVER               ohci_hcd_s3c2410_driver
  #endif
  
  #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
 -    defined(CONFIG_CPU_SUBTYPE_SH7763)
 +    defined(CONFIG_CPU_SUBTYPE_SH7763) || \
 +    defined(CONFIG_CPU_SUBTYPE_SH7786)
  #include "ohci-sh.c"
  #define PLATFORM_DRIVER               ohci_hcd_sh_driver
  #endif