X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fusb%2Fgadget%2Fm66592-udc.c;h=43dcf9e1af6b06bc46379ccfe1bcfb05aa25f524;hb=389623fef0e8b088f293c437d3b7094fe82349fd;hp=611130c8983b21d5695ee62a6cf628cb2444bf50;hpb=4cf2503c6801a69fee25030475eceeefb36d1b56;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 611130c..43dcf9e 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -21,44 +21,48 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include -#include -#include -#include -#include -#include +#include +#include #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); -