]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/gadget/mv_udc.c
Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
[u-boot] / drivers / usb / gadget / mv_udc.c
index 24c3e4f118f61870fea47936121d384025359a73..da41738653eb13efac685c7ca74d7672a081eb56 100644 (file)
 #include <config.h>
 #include <net.h>
 #include <malloc.h>
+#include <asm/byteorder.h>
+#include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
 #include <linux/types.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
 #include <usb/mv_udc.h>
+#include "../host/ehci.h"
+#include "mv_udc.h"
 
 /*
  * Check if the system has too long cachelines. If the cachelines are
@@ -210,10 +216,8 @@ static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req)
 
 static void ep_enable(int num, int in, int maxpacket)
 {
-       struct ept_queue_head *head;
        struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
        unsigned n;
-       head = mv_get_qh(num, in);
 
        n = readl(&udc->epctrl[num]);
        if (in)
@@ -222,6 +226,8 @@ static void ep_enable(int num, int in, int maxpacket)
                n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK);
 
        if (num != 0) {
+               struct ept_queue_head *head = mv_get_qh(num, in);
+
                head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT;
                mv_flush_qh(num);
        }
@@ -261,7 +267,7 @@ static int mv_ep_disable(struct usb_ep *ep)
        return 0;
 }
 
-static int mv_bounce(struct mv_ep *ep)
+static int mv_bounce(struct mv_ep *ep, int in)
 {
        uint32_t addr = (uint32_t)ep->req.buf;
        uint32_t ba;
@@ -290,8 +296,8 @@ align:
                if (!ep->b_buf)
                        return -ENOMEM;
        }
-
-       memcpy(ep->b_buf, ep->req.buf, ep->req.length);
+       if (in)
+               memcpy(ep->b_buf, ep->req.buf, ep->req.length);
 
 flush:
        ba = (uint32_t)ep->b_buf;
@@ -300,29 +306,25 @@ flush:
        return 0;
 }
 
-static void mv_debounce(struct mv_ep *ep)
+static void mv_debounce(struct mv_ep *ep, int in)
 {
        uint32_t addr = (uint32_t)ep->req.buf;
        uint32_t ba = (uint32_t)ep->b_buf;
 
+       if (in) {
+               if (addr == ba)
+                       return;         /* not a bounce */
+               goto free;
+       }
        invalidate_dcache_range(ba, ba + ep->b_len);
 
-       /* Input buffer address is not aligned. */
-       if (addr & (ARCH_DMA_MINALIGN - 1))
-               goto copy;
+       if (addr == ba)
+               return;         /* not a bounce */
 
-       /* Input buffer length is not aligned. */
-       if (ep->req.length & (ARCH_DMA_MINALIGN - 1))
-               goto copy;
-
-       /* The buffer is well aligned, only invalidate cache. */
-       return;
-
-copy:
        memcpy(ep->req.buf, ep->b_buf, ep->req.length);
-
+free:
        /* Large payloads use allocated buffer, free it. */
-       if (ep->req.length > 64)
+       if (ep->b_buf != ep->b_fast)
                free(ep->b_buf);
 }
 
@@ -340,7 +342,7 @@ static int mv_ep_queue(struct usb_ep *ep,
        head = mv_get_qh(num, in);
        len = req->length;
 
-       ret = mv_bounce(mv_ep);
+       ret = mv_bounce(mv_ep, in);
        if (ret)
                return ret;
 
@@ -383,10 +385,9 @@ static void handle_ep_complete(struct mv_ep *ep)
                       num, in ? "in" : "out", item->info, item->page0);
 
        len = (item->info >> 16) & 0x7fff;
-
-       mv_debounce(ep);
-
        ep->req.length -= len;
+       mv_debounce(ep, in);
+
        DBG("ept%d %s complete %x\n",
                        num, in ? "in" : "out", len);
        ep->req.complete(&ep->ep, &ep->req);