#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
buf_bsize = 0;
break;
case R8A66597_BULK:
- bufnum = r8a66597->bi_bufnum +
- (info->pipe - R8A66597_BASE_PIPENUM_BULK) * 16;
- r8a66597->bi_bufnum += 16;
+ /* isochronous pipes may be used as bulk pipes */
+ if (info->pipe > R8A66597_BASE_PIPENUM_BULK)
+ bufnum = info->pipe - R8A66597_BASE_PIPENUM_BULK;
+ else
+ bufnum = info->pipe - R8A66597_BASE_PIPENUM_ISOC;
+
+ bufnum = R8A66597_BASE_BUFNUM + (bufnum * 16);
buf_bsize = 7;
pipecfg |= R8A66597_DBLB;
if (!info->dir_in)
pipecfg |= R8A66597_SHTNAK;
break;
case R8A66597_ISO:
- bufnum = r8a66597->bi_bufnum +
+ bufnum = R8A66597_BASE_BUFNUM +
(info->pipe - R8A66597_BASE_PIPENUM_ISOC) * 16;
- r8a66597->bi_bufnum += 16;
buf_bsize = 7;
break;
}
- if (r8a66597->bi_bufnum > R8A66597_MAX_BUFNUM) {
- printk(KERN_ERR "r8a66597 pipe memory is insufficient(%d)\n",
- r8a66597->bi_bufnum);
+
+ if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
+ pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n");
return -ENOMEM;
}
if (info->pipe == 0)
return;
- switch (info->type) {
- case R8A66597_BULK:
- if (is_bulk_pipe(info->pipe))
- r8a66597->bi_bufnum -= 16;
- break;
- case R8A66597_ISO:
- if (is_isoc_pipe(info->pipe))
- r8a66597->bi_bufnum -= 16;
- break;
- }
-
if (is_bulk_pipe(info->pipe))
r8a66597->bulk--;
else if (is_interrupt_pipe(info->pipe))
if (r8a66597->pdata->on_chip) {
r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+ /* disable interrupts */
r8a66597_write(r8a66597, 0, INTENB0);
r8a66597_write(r8a66597, 0, INTENB1);
+ r8a66597_write(r8a66597, 0, BRDYENB);
+ r8a66597_write(r8a66597, 0, BEMPENB);
+ r8a66597_write(r8a66597, 0, NRDYENB);
+
+ /* clear status */
+ r8a66597_write(r8a66597, 0, BRDYSTS);
+ r8a66597_write(r8a66597, 0, NRDYSTS);
+ r8a66597_write(r8a66597, 0, BEMPSTS);
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
u16 w_index = le16_to_cpu(ctrl->wIndex);
ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
- pipe_stop(r8a66597, ep->pipenum);
- control_reg_sqclr(r8a66597, ep->pipenum);
+ if (!ep->wedge) {
+ pipe_stop(r8a66597, ep->pipenum);
+ control_reg_sqclr(r8a66597, ep->pipenum);
+ spin_unlock(&r8a66597->lock);
+ usb_ep_clear_halt(&ep->ep);
+ spin_lock(&r8a66597->lock);
+ }
control_end(r8a66597, 1);
pipe_stall(ep->r8a66597, ep->pipenum);
} else {
ep->busy = 0;
+ ep->wedge = 0;
pipe_stop(ep->r8a66597, ep->pipenum);
}
return ret;
}
+static int r8a66597_set_wedge(struct usb_ep *_ep)
+{
+ struct r8a66597_ep *ep;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct r8a66597_ep, ep);
+
+ if (!ep || !ep->desc)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->r8a66597->lock, flags);
+ ep->wedge = 1;
+ spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+ return usb_ep_set_halt(_ep);
+}
+
static void r8a66597_fifo_flush(struct usb_ep *_ep)
{
struct r8a66597_ep *ep;
.dequeue = r8a66597_dequeue,
.set_halt = r8a66597_set_halt,
+ .set_wedge = r8a66597_set_wedge,
.fifo_flush = r8a66597_fifo_flush,
};
iounmap((void *)r8a66597->reg);
free_irq(platform_get_irq(pdev, 0), r8a66597);
r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
+#ifdef CONFIG_HAVE_CLK
+ if (r8a66597->pdata->on_chip) {
+ clk_disable(r8a66597->clk);
+ clk_put(r8a66597->clk);
+ }
+#endif
kfree(r8a66597);
return 0;
}
static int __init r8a66597_probe(struct platform_device *pdev)
{
+#ifdef CONFIG_HAVE_CLK
+ char clk_name[8];
+#endif
struct resource *res, *ires;
int irq;
void __iomem *reg = NULL;
r8a66597->timer.data = (unsigned long)r8a66597;
r8a66597->reg = (unsigned long)reg;
- r8a66597->bi_bufnum = R8A66597_BASE_BUFNUM;
+#ifdef CONFIG_HAVE_CLK
+ if (r8a66597->pdata->on_chip) {
+ snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
+ r8a66597->clk = clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(r8a66597->clk)) {
+ dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+ clk_name);
+ ret = PTR_ERR(r8a66597->clk);
+ goto clean_up;
+ }
+ clk_enable(r8a66597->clk);
+ }
+#endif
disable_controller(r8a66597); /* make sure controller is disabled */
udc_name, r8a66597);
if (ret < 0) {
printk(KERN_ERR "request_irq error (%d)\n", ret);
- goto clean_up;
+ goto clean_up2;
}
INIT_LIST_HEAD(&r8a66597->gadget.ep_list);
r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep,
GFP_KERNEL);
if (r8a66597->ep0_req == NULL)
- goto clean_up2;
+ goto clean_up3;
r8a66597->ep0_req->complete = nop_completion;
init_controller(r8a66597);
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
-clean_up2:
+clean_up3:
free_irq(irq, r8a66597);
+clean_up2:
+#ifdef CONFIG_HAVE_CLK
+ if (r8a66597->pdata->on_chip) {
+ clk_disable(r8a66597->clk);
+ clk_put(r8a66597->clk);
+ }
+#endif
clean_up:
if (r8a66597) {
if (r8a66597->ep0_req)