Merge git://git.infradead.org/mtd-2.6
[safe/jmp/linux-2.6] / drivers / usb / gadget / m66592-udc.c
index 611130c..43dcf9e 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/list.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb_gadget.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
 
 #include "m66592-udc.h"
 
-MODULE_DESCRIPTION("M66592 USB gadget driiver");
+
+MODULE_DESCRIPTION("M66592 USB gadget driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:m66592_udc");
 
-#define DRIVER_VERSION "9 May 2007"
+#define DRIVER_VERSION "18 Oct 2007"
 
 /* module parameters */
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static unsigned short endian = M66592_LITTLE;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
+#else
 static unsigned short clock = M66592_XTAL24;
 module_param(clock, ushort, 0644);
-MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)");
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
+               "(default=16384)");
+
 static unsigned short vif = M66592_LDRV;
 module_param(vif, ushort, 0644);
-MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
-static unsigned short endian = 0;
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)");
+
+static unsigned short endian;
 module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
+
 static unsigned short irq_sense = M66592_INTL;
 module_param(irq_sense, ushort, 0644);
-MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)");
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
+               "(default=2)");
+#endif
 
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
@@ -72,8 +76,8 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
                        gfp_t gfp_flags);
 
 static void transfer_complete(struct m66592_ep *ep,
-                             struct m66592_request *req,
-                             int status);
+               struct m66592_request *req, int status);
+
 /*-------------------------------------------------------------------------*/
 static inline u16 get_usb_speed(struct m66592 *m66592)
 {
@@ -81,25 +85,25 @@ static inline u16 get_usb_speed(struct m66592 *m66592)
 }
 
 static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-                           unsigned long reg)
+               unsigned long reg)
 {
        u16 tmp;
 
        tmp = m66592_read(m66592, M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bset(m66592, (1 << pipenum), reg);
        m66592_write(m66592, tmp, M66592_INTENB0);
 }
 
 static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-                            unsigned long reg)
+               unsigned long reg)
 {
        u16 tmp;
 
        tmp = m66592_read(m66592, M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bclr(m66592, (1 << pipenum), reg);
        m66592_write(m66592, tmp, M66592_INTENB0);
 }
@@ -108,17 +112,19 @@ static void m66592_usb_connect(struct m66592 *m66592)
 {
        m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
        m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
 
        m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
 }
 
 static void m66592_usb_disconnect(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
        m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
        m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
 
@@ -142,13 +148,13 @@ static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
                offset = get_pipectr_addr(pipenum);
                pid = m66592_read(m66592, offset) & M66592_PID;
        } else
-               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+               pr_err("unexpect pipe num (%d)\n", pipenum);
 
        return pid;
 }
 
 static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
-                                      u16 pid)
+               u16 pid)
 {
        unsigned long offset;
 
@@ -158,7 +164,7 @@ static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
                offset = get_pipectr_addr(pipenum);
                m66592_mdfy(m66592, pid, M66592_PID, offset);
        } else
-               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+               pr_err("unexpect pipe num (%d)\n", pipenum);
 }
 
 static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
@@ -187,7 +193,7 @@ static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
                offset = get_pipectr_addr(pipenum);
                ret = m66592_read(m66592, offset);
        } else
-               printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+               pr_err("unexpect pipe num (%d)\n", pipenum);
 
        return ret;
 }
@@ -204,7 +210,7 @@ static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
                offset = get_pipectr_addr(pipenum);
                m66592_bset(m66592, M66592_SQCLR, offset);
        } else
-               printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+               pr_err("unexpect pipe num(%d)\n", pipenum);
 }
 
 static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
@@ -250,7 +256,7 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 }
 
 static int pipe_buffer_setting(struct m66592 *m66592,
-                              struct m66592_pipe_info *info)
+               struct m66592_pipe_info *info)
 {
        u16 bufnum = 0, buf_bsize = 0;
        u16 pipecfg = 0;
@@ -286,8 +292,8 @@ static int pipe_buffer_setting(struct m66592 *m66592,
                break;
        }
        if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
-               printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
-                      m66592->bi_bufnum);
+               pr_err("m66592 pipe memory is insufficient(%d)\n",
+                               m66592->bi_bufnum);
                return -ENOMEM;
        }
 
@@ -327,8 +333,8 @@ static void pipe_buffer_release(struct m66592 *m66592,
                if (info->type == M66592_BULK)
                        m66592->bulk--;
        } else
-               printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
-                      info->pipe);
+               pr_err("ep_release: unexpect pipenum (%d)\n",
+                               info->pipe);
 }
 
 static void pipe_initialize(struct m66592_ep *ep)
@@ -350,8 +356,8 @@ static void pipe_initialize(struct m66592_ep *ep)
 }
 
 static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
-                             const struct usb_endpoint_descriptor *desc,
-                             u16 pipenum, int dma)
+               const struct usb_endpoint_descriptor *desc,
+               u16 pipenum, int dma)
 {
        if ((pipenum != 0) && dma) {
                if (m66592->num_dma == 0) {
@@ -361,6 +367,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
                        ep->fifosel = M66592_D0FIFOSEL;
                        ep->fifoctr = M66592_D0FIFOCTR;
                        ep->fifotrn = M66592_D0FIFOTRN;
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
                } else if (m66592->num_dma == 1) {
                        m66592->num_dma++;
                        ep->use_dma = 1;
@@ -368,6 +375,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
                        ep->fifosel = M66592_D1FIFOSEL;
                        ep->fifoctr = M66592_D1FIFOCTR;
                        ep->fifotrn = M66592_D1FIFOTRN;
+#endif
                } else {
                        ep->use_dma = 0;
                        ep->fifoaddr = M66592_CFIFO;
@@ -385,7 +393,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
 
        ep->pipectr = get_pipectr_addr(pipenum);
        ep->pipenum = pipenum;
-       ep->ep.maxpacket = desc->wMaxPacketSize;
+       ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
        m66592->pipenum2ep[pipenum] = ep;
        m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
        INIT_LIST_HEAD(&ep->queue);
@@ -407,7 +415,7 @@ static void m66592_ep_release(struct m66592_ep *ep)
 }
 
 static int alloc_pipe_config(struct m66592_ep *ep,
-                            const struct usb_endpoint_descriptor *desc)
+               const struct usb_endpoint_descriptor *desc)
 {
        struct m66592 *m66592 = ep->m66592;
        struct m66592_pipe_info info;
@@ -419,15 +427,15 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 
        BUG_ON(ep->pipenum);
 
-       switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
        case USB_ENDPOINT_XFER_BULK:
                if (m66592->bulk >= M66592_MAX_NUM_BULK) {
                        if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-                               printk(KERN_ERR "bulk pipe is insufficient\n");
+                               pr_err("bulk pipe is insufficient\n");
                                return -ENODEV;
                        } else {
-                               info.pipe = M66592_BASE_PIPENUM_ISOC +
-                                           m66592->isochronous;
+                               info.pipe = M66592_BASE_PIPENUM_ISOC
+                                               + m66592->isochronous;
                                counter = &m66592->isochronous;
                        }
                } else {
@@ -439,7 +447,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
                break;
        case USB_ENDPOINT_XFER_INT:
                if (m66592->interrupt >= M66592_MAX_NUM_INT) {
-                       printk(KERN_ERR "interrupt pipe is insufficient\n");
+                       pr_err("interrupt pipe is insufficient\n");
                        return -ENODEV;
                }
                info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
@@ -448,7 +456,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
                break;
        case USB_ENDPOINT_XFER_ISOC:
                if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-                       printk(KERN_ERR "isochronous pipe is insufficient\n");
+                       pr_err("isochronous pipe is insufficient\n");
                        return -ENODEV;
                }
                info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
@@ -456,13 +464,13 @@ static int alloc_pipe_config(struct m66592_ep *ep,
                counter = &m66592->isochronous;
                break;
        default:
-               printk(KERN_ERR "unexpect xfer type\n");
+               pr_err("unexpect xfer type\n");
                return -EINVAL;
        }
        ep->type = info.type;
 
        info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-       info.maxpacket = desc->wMaxPacketSize;
+       info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
        info.interval = desc->bInterval;
        if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                info.dir_in = 1;
@@ -471,7 +479,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 
        ret = pipe_buffer_setting(m66592, &info);
        if (ret < 0) {
-               printk(KERN_ERR "pipe_buffer_setting fail\n");
+               pr_err("pipe_buffer_setting fail\n");
                return ret;
        }
 
@@ -525,8 +533,8 @@ static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 
        pipe_change(m66592, ep->pipenum);
        m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
-                   (M66592_ISEL | M66592_CURPIPE),
-                   M66592_CFIFOSEL);
+                       (M66592_ISEL | M66592_CURPIPE),
+                       M66592_CFIFOSEL);
        m66592_write(m66592, M66592_BCLR, ep->fifoctr);
        if (req->req.length == 0) {
                m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
@@ -561,8 +569,8 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
 
        if (ep->pipenum == 0) {
                m66592_mdfy(m66592, M66592_PIPE0,
-                           (M66592_ISEL | M66592_CURPIPE),
-                           M66592_CFIFOSEL);
+                               (M66592_ISEL | M66592_CURPIPE),
+                               M66592_CFIFOSEL);
                m66592_write(m66592, M66592_BCLR, ep->fifoctr);
                pipe_start(m66592, pipenum);
                pipe_irq_enable(m66592, pipenum);
@@ -572,8 +580,9 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
                        pipe_change(m66592, pipenum);
                        m66592_bset(m66592, M66592_TRENB, ep->fifosel);
                        m66592_write(m66592,
-                                    (req->req.length + ep->ep.maxpacket - 1) /
-                                    ep->ep.maxpacket, ep->fifotrn);
+                               (req->req.length + ep->ep.maxpacket - 1)
+                                       / ep->ep.maxpacket,
+                               ep->fifotrn);
                }
                pipe_start(m66592, pipenum);    /* trigger once */
                pipe_irq_enable(m66592, pipenum);
@@ -606,15 +615,36 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
                control_end(ep->m66592, 0);
                break;
        default:
-               printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+               pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
                break;
        }
 }
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static void init_controller(struct m66592 *m66592)
+{
+       m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
+       m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+       m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+       /* This is a workaound for SH7722 2nd cut */
+       m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+       m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+       m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+
+       m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+       m66592_write(m66592, 0, M66592_CFBCFG);
+       m66592_write(m66592, 0, M66592_D0FBCFG);
+       m66592_bset(m66592, endian, M66592_CFBCFG);
+       m66592_bset(m66592, endian, M66592_D0FBCFG);
+}
+#else  /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 static void init_controller(struct m66592 *m66592)
 {
        m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
-                   M66592_PINCFG);
+                       M66592_PINCFG);
        m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
        m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
 
@@ -634,11 +664,13 @@ static void init_controller(struct m66592 *m66592)
 
        m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
        m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
-                    M66592_DMA0CFG);
+                       M66592_DMA0CFG);
 }
+#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 static void disable_controller(struct m66592 *m66592)
 {
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
        m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
        udelay(1);
        m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
@@ -646,21 +678,25 @@ static void disable_controller(struct m66592 *m66592)
        m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
        udelay(1);
        m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 
 static void m66592_start_xclock(struct m66592 *m66592)
 {
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
        u16 tmp;
 
        tmp = m66592_read(m66592, M66592_SYSCFG);
        if (!(tmp & M66592_XCKE))
                m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 
 /*-------------------------------------------------------------------------*/
 static void transfer_complete(struct m66592_ep *ep,
-                             struct m66592_request *req,
-                             int status)
+               struct m66592_request *req, int status)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        int restart = 0;
 
@@ -680,8 +716,9 @@ static void transfer_complete(struct m66592_ep *ep,
        if (!list_empty(&ep->queue))
                restart = 1;
 
-       if (likely(req->req.complete))
-               req->req.complete(&ep->ep, &req->req);
+       spin_unlock(&ep->m66592->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->m66592->lock);
 
        if (restart) {
                req = list_entry(ep->queue.next, struct m66592_request, queue);
@@ -693,7 +730,7 @@ static void transfer_complete(struct m66592_ep *ep,
 static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 {
        int i;
-       volatile u16 tmp;
+       u16 tmp;
        unsigned bufsize;
        size_t size;
        void *buf;
@@ -707,7 +744,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
        do {
                tmp = m66592_read(m66592, ep->fifoctr);
                if (i++ > 100000) {
-                       printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+                       pr_err("pipe0 is busy. maybe cpu i/o bus "
                                "conflict. please power off this controller.");
                        return;
                }
@@ -731,8 +768,9 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
        req->req.actual += size;
 
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                disable_irq_ready(m66592, pipenum);
                disable_irq_empty(m66592, pipenum);
        } else {
@@ -756,7 +794,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
        if (unlikely((tmp & M66592_FRDY) == 0)) {
                pipe_stop(m66592, pipenum);
                pipe_irq_disable(m66592, pipenum);
-               printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+               pr_err("write fifo not ready. pipnum=%d\n", pipenum);
                return;
        }
 
@@ -768,16 +806,19 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
        /* write fifo */
        if (req->req.buf) {
                m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
-               if ((size == 0) || ((size % ep->ep.maxpacket) != 0) ||
-                   ((bufsize != ep->ep.maxpacket) && (bufsize > size)))
+               if ((size == 0)
+                               || ((size % ep->ep.maxpacket) != 0)
+                               || ((bufsize != ep->ep.maxpacket)
+                                       && (bufsize > size)))
                        m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
        }
 
        /* update parameters */
        req->req.actual += size;
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                disable_irq_ready(m66592, pipenum);
                enable_irq_empty(m66592, pipenum);
        } else {
@@ -802,7 +843,7 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
                req->req.status = -EPIPE;
                pipe_stop(m66592, pipenum);
                pipe_irq_disable(m66592, pipenum);
-               printk(KERN_ERR "read fifo not ready");
+               pr_err("read fifo not ready");
                return;
        }
 
@@ -821,8 +862,9 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
        req->req.actual += size;
 
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                pipe_stop(m66592, pipenum);
                pipe_irq_disable(m66592, pipenum);
                finish = 1;
@@ -850,7 +892,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
        if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
                m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
                m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
-                           M66592_CFIFOSEL);
+                               M66592_CFIFOSEL);
 
                ep = &m66592->ep[0];
                req = list_entry(ep->queue.next, struct m66592_request, queue);
@@ -909,23 +951,26 @@ static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
 }
 
 static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        struct m66592_ep *ep;
        u16 pid;
        u16 status = 0;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
 
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
        case USB_RECIP_DEVICE:
-               status = 1;     /* selfpower */
+               status = 1 << USB_DEVICE_SELF_POWERED;
                break;
        case USB_RECIP_INTERFACE:
                status = 0;
                break;
        case USB_RECIP_ENDPOINT:
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pid = control_reg_get_pid(m66592, ep->pipenum);
                if (pid == M66592_PID_STALL)
-                       status = 1;
+                       status = 1 << USB_ENDPOINT_HALT;
                else
                        status = 0;
                break;
@@ -934,10 +979,13 @@ static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                return;         /* exit */
        }
 
-       *m66592->ep0_buf = status;
-       m66592->ep0_req->buf = m66592->ep0_buf;
+       m66592->ep0_data = cpu_to_le16(status);
+       m66592->ep0_req->buf = &m66592->ep0_data;
        m66592->ep0_req->length = 2;
+       /* AV: what happens if we get called again before that gets through? */
+       spin_unlock(&m66592->lock);
        m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+       spin_lock(&m66592->lock);
 }
 
 static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
@@ -952,8 +1000,9 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
        case USB_RECIP_ENDPOINT: {
                struct m66592_ep *ep;
                struct m66592_request *req;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
 
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pipe_stop(m66592, ep->pipenum);
                control_reg_sqclr(m66592, ep->pipenum);
 
@@ -988,8 +1037,9 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                break;
        case USB_RECIP_ENDPOINT: {
                struct m66592_ep *ep;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
 
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pipe_stall(m66592, ep->pipenum);
 
                control_end(m66592, 1);
@@ -1048,7 +1098,7 @@ static void m66592_update_usb_speed(struct m66592 *m66592)
                break;
        default:
                m66592->gadget.speed = USB_SPEED_UNKNOWN;
-               printk(KERN_ERR "USB speed unknown\n");
+               pr_err("USB speed unknown\n");
        }
 }
 
@@ -1065,14 +1115,16 @@ static void irq_device_state(struct m66592 *m66592)
        }
        if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
                m66592_update_usb_speed(m66592);
-       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) &&
-           m66592->gadget.speed == USB_SPEED_UNKNOWN)
+       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
+                       && m66592->gadget.speed == USB_SPEED_UNKNOWN)
                m66592_update_usb_speed(m66592);
 
        m66592->old_dvsq = dvsq;
 }
 
 static void irq_control_stage(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        struct usb_ctrlrequest ctrl;
        u16 ctsq;
@@ -1094,8 +1146,10 @@ static void irq_control_stage(struct m66592 *m66592)
        case M66592_CS_WRDS:
        case M66592_CS_WRND:
                if (setup_packet(m66592, &ctrl)) {
+                       spin_unlock(&m66592->lock);
                        if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
                                pipe_stall(m66592, 0);
+                       spin_lock(&m66592->lock);
                }
                break;
        case M66592_CS_RDSS:
@@ -1103,7 +1157,7 @@ static void irq_control_stage(struct m66592 *m66592)
                control_end(m66592, 0);
                break;
        default:
-               printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+               pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
                break;
        }
 }
@@ -1118,9 +1172,24 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
        u16 savepipe;
        u16 mask0;
 
+       spin_lock(&m66592->lock);
+
        intsts0 = m66592_read(m66592, M66592_INTSTS0);
        intenb0 = m66592_read(m66592, M66592_INTENB0);
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+       if (!intsts0 && !intenb0) {
+               /*
+                * When USB clock stops, it cannot read register. Even if a
+                * clock stops, the interrupt occurs. So this driver turn on
+                * a clock by this timing and do re-reading of register.
+                */
+               m66592_start_xclock(m66592);
+               intsts0 = m66592_read(m66592, M66592_INTSTS0);
+               intenb0 = m66592_read(m66592, M66592_INTENB0);
+       }
+#endif
+
        savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 
        mask0 = intsts0 & intenb0;
@@ -1133,27 +1202,27 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
                bempenb = m66592_read(m66592, M66592_BEMPENB);
 
                if (mask0 & M66592_VBINT) {
-                       m66592_write(m66592, (u16)~M66592_VBINT,
-                                    M66592_INTSTS0);
+                       m66592_write(m66592,  0xffff & ~M66592_VBINT,
+                                       M66592_INTSTS0);
                        m66592_start_xclock(m66592);
 
                        /* start vbus sampling */
                        m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
-                                          & M66592_VBSTS;
+                                       & M66592_VBSTS;
                        m66592->scount = M66592_MAX_SAMPLING;
 
                        mod_timer(&m66592->timer,
-                                 jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                }
                if (intsts0 & M66592_DVSQ)
                        irq_device_state(m66592);
 
-               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) &&
-                   (brdysts & brdyenb)) {
+               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
+                               && (brdysts & brdyenb)) {
                        irq_pipe_ready(m66592, brdysts, brdyenb);
                }
-               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) &&
-                   (bempsts & bempenb)) {
+               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
+                               && (bempsts & bempenb)) {
                        irq_pipe_empty(m66592, bempsts, bempenb);
                }
 
@@ -1163,6 +1232,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
 
        m66592_write(m66592, savepipe, M66592_CFIFOSEL);
 
+       spin_unlock(&m66592->lock);
        return IRQ_HANDLED;
 }
 
@@ -1190,13 +1260,13 @@ static void m66592_timer(unsigned long _m66592)
                                        m66592_usb_disconnect(m66592);
                        } else {
                                mod_timer(&m66592->timer,
-                                         jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                        }
                } else {
                        m66592->scount = M66592_MAX_SAMPLING;
                        m66592->old_vbus = tmp;
                        mod_timer(&m66592->timer,
-                                 jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                }
        }
        spin_unlock_irqrestore(&m66592->lock, flags);
@@ -1254,24 +1324,6 @@ static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
        kfree(req);
 }
 
-static void *m66592_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-                                dma_addr_t *dma, gfp_t gfp_flags)
-{
-       void *buf;
-
-       buf = kzalloc(bytes, gfp_flags);
-       if (dma)
-               *dma = virt_to_bus(buf);
-
-       return buf;
-}
-
-static void m66592_free_buffer(struct usb_ep *_ep, void *buf,
-                              dma_addr_t dma, unsigned bytes)
-{
-       kfree(buf);
-}
-
 static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
                        gfp_t gfp_flags)
 {
@@ -1295,7 +1347,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
        req->req.actual = 0;
        req->req.status = -EINPROGRESS;
 
-       if (ep->desc == 0)      /* control */
+       if (ep->desc == NULL)   /* control */
                start_ep0(ep, req);
        else {
                if (request && !ep->busy)
@@ -1352,11 +1404,6 @@ out:
        return ret;
 }
 
-static int m66592_fifo_status(struct usb_ep *_ep)
-{
-       return -EOPNOTSUPP;
-}
-
 static void m66592_fifo_flush(struct usb_ep *_ep)
 {
        struct m66592_ep *ep;
@@ -1378,14 +1425,10 @@ static struct usb_ep_ops m66592_ep_ops = {
        .alloc_request  = m66592_alloc_request,
        .free_request   = m66592_free_request,
 
-       .alloc_buffer   = m66592_alloc_buffer,
-       .free_buffer    = m66592_free_buffer,
-
        .queue          = m66592_queue,
        .dequeue        = m66592_dequeue,
 
        .set_halt       = m66592_set_halt,
-       .fifo_status    = m66592_fifo_status,
        .fifo_flush     = m66592_fifo_flush,
 };
 
@@ -1397,11 +1440,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
        struct m66592 *m66592 = the_controller;
        int retval;
 
-       if (!driver ||
-           driver->speed != USB_SPEED_HIGH ||
-           !driver->bind ||
-           !driver->unbind ||
-           !driver->setup)
+       if (!driver
+                       || driver->speed != USB_SPEED_HIGH
+                       || !driver->bind
+                       || !driver->setup)
                return -EINVAL;
        if (!m66592)
                return -ENODEV;
@@ -1415,13 +1457,13 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 
        retval = device_add(&m66592->gadget.dev);
        if (retval) {
-               printk(KERN_ERR "device_add error (%d)\n", retval);
+               pr_err("device_add error (%d)\n", retval);
                goto error;
        }
 
        retval = driver->bind (&m66592->gadget);
        if (retval) {
-               printk(KERN_ERR "bind to driver error (%d)\n", retval);
+               pr_err("bind to driver error (%d)\n", retval);
                device_del(&m66592->gadget.dev);
                goto error;
        }
@@ -1433,8 +1475,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
                m66592->old_vbus = m66592_read(m66592,
                                         M66592_INTSTS0) & M66592_VBSTS;
                m66592->scount = M66592_MAX_SAMPLING;
-               mod_timer(&m66592->timer,
-                         jiffies + msecs_to_jiffies(50));
+               mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
        }
 
        return 0;
@@ -1452,6 +1493,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        struct m66592 *m66592 = the_controller;
        unsigned long flags;
 
+       if (driver != m66592->driver || !driver->unbind)
+               return -EINVAL;
+
        spin_lock_irqsave(&m66592->lock, flags);
        if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
                m66592_usb_disconnect(m66592);
@@ -1460,6 +1504,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
        driver->unbind(&m66592->gadget);
+       m66592->gadget.dev.driver = NULL;
 
        init_controller(m66592);
        disable_controller(m66592);
@@ -1481,70 +1526,63 @@ static struct usb_gadget_ops m66592_gadget_ops = {
        .get_frame              = m66592_get_frame,
 };
 
-#if defined(CONFIG_PM)
-static int m66592_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       pdev->dev.power.power_state = state;
-       return 0;
-}
-
-static int m66592_resume(struct platform_device *pdev)
-{
-       pdev->dev.power.power_state = PMSG_ON;
-       return 0;
-}
-#else  /* if defined(CONFIG_PM) */
-#define m66592_suspend         NULL
-#define m66592_resume          NULL
-#endif
-
-static int __init_or_module m66592_remove(struct platform_device *pdev)
+static int __exit m66592_remove(struct platform_device *pdev)
 {
        struct m66592           *m66592 = dev_get_drvdata(&pdev->dev);
 
        del_timer_sync(&m66592->timer);
        iounmap(m66592->reg);
        free_irq(platform_get_irq(pdev, 0), m66592);
+       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+       clk_disable(m66592->clk);
+       clk_put(m66592->clk);
+#endif
        kfree(m66592);
        return 0;
 }
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
+static void nop_completion(struct usb_ep *ep, struct usb_request *r)
+{
+}
+
 static int __init m66592_probe(struct platform_device *pdev)
 {
-       struct resource *res = NULL;
-       int irq = -1;
+       struct resource *res;
+       int irq;
        void __iomem *reg = NULL;
        struct m66592 *m66592 = NULL;
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+       char clk_name[8];
+#endif
        int ret = 0;
        int i;
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                          (char *)udc_name);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                ret = -ENODEV;
-               printk(KERN_ERR "platform_get_resource_byname error.\n");
+               pr_err("platform_get_resource error.\n");
                goto clean_up;
        }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = -ENODEV;
-               printk(KERN_ERR "platform_get_irq error.\n");
+               pr_err("platform_get_irq error.\n");
                goto clean_up;
        }
 
-       reg = ioremap(res->start, resource_len(res));
+       reg = ioremap(res->start, resource_size(res));
        if (reg == NULL) {
                ret = -ENOMEM;
-               printk(KERN_ERR "ioremap error.\n");
+               pr_err("ioremap error.\n");
                goto clean_up;
        }
 
        /* initialize ucd */
        m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
        if (m66592 == NULL) {
-               printk(KERN_ERR "kzalloc error\n");
+               pr_err("kzalloc error\n");
                goto clean_up;
        }
 
@@ -1553,7 +1591,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 
        m66592->gadget.ops = &m66592_gadget_ops;
        device_initialize(&m66592->gadget.dev);
-       strcpy(m66592->gadget.dev.bus_id, "gadget");
+       dev_set_name(&m66592->gadget.dev, "gadget");
        m66592->gadget.is_dualspeed = 1;
        m66592->gadget.dev.parent = &pdev->dev;
        m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
@@ -1567,13 +1605,23 @@ static int __init m66592_probe(struct platform_device *pdev)
 
        m66592->bi_bufnum = M66592_BASE_BUFNUM;
 
-       ret = request_irq(irq, m66592_irq, SA_INTERRUPT | SA_SHIRQ,
-                         udc_name, m66592);
+       ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+                       udc_name, m66592);
        if (ret < 0) {
-               printk(KERN_ERR "request_irq error (%d)\n", ret);
+               pr_err("request_irq error (%d)\n", ret);
                goto clean_up;
        }
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+       snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
+       m66592->clk = clk_get(&pdev->dev, clk_name);
+       if (IS_ERR(m66592->clk)) {
+               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+               ret = PTR_ERR(m66592->clk);
+               goto clean_up2;
+       }
+       clk_enable(m66592->clk);
+#endif
        INIT_LIST_HEAD(&m66592->gadget.ep_list);
        m66592->gadget.ep0 = &m66592->ep[0].ep;
        INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
@@ -1583,7 +1631,7 @@ static int __init m66592_probe(struct platform_device *pdev)
                if (i != 0) {
                        INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
                        list_add_tail(&m66592->ep[i].ep.ep_list,
-                                     &m66592->gadget.ep_list);
+                                       &m66592->gadget.ep_list);
                }
                ep->m66592 = m66592;
                INIT_LIST_HEAD(&ep->queue);
@@ -1605,17 +1653,21 @@ static int __init m66592_probe(struct platform_device *pdev)
 
        m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
        if (m66592->ep0_req == NULL)
-               goto clean_up;
-       m66592->ep0_buf = m66592_alloc_buffer(&m66592->ep[0].ep, 2, NULL,
-                                             GFP_KERNEL);
-       if (m66592->ep0_buf == NULL)
-               goto clean_up;
+               goto clean_up3;
+       m66592->ep0_req->complete = nop_completion;
 
        init_controller(m66592);
 
-       printk("driver %s, %s\n", udc_name, DRIVER_VERSION);
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
        return 0;
 
+clean_up3:
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+       clk_disable(m66592->clk);
+       clk_put(m66592->clk);
+clean_up2:
+#endif
+       free_irq(irq, m66592);
 clean_up:
        if (m66592) {
                if (m66592->ep0_req)
@@ -1630,18 +1682,16 @@ clean_up:
 
 /*-------------------------------------------------------------------------*/
 static struct platform_driver m66592_driver = {
-       .probe =        m66592_probe,
-       .remove =       m66592_remove,
-       .suspend =      m66592_suspend,
-       .resume =       m66592_resume,
+       .remove =       __exit_p(m66592_remove),
        .driver         = {
                .name = (char *) udc_name,
+               .owner  = THIS_MODULE,
        },
 };
 
 static int __init m66592_udc_init(void)
 {
-       return platform_driver_register(&m66592_driver);
+       return platform_driver_probe(&m66592_driver, m66592_probe);
 }
 module_init(m66592_udc_init);
 
@@ -1650,4 +1700,3 @@ static void __exit m66592_udc_cleanup(void)
        platform_driver_unregister(&m66592_driver);
 }
 module_exit(m66592_udc_cleanup);
-