Allow mv_udc to work when cache is enabled by adding flushing and invalidating calls.
Signed-off-by: Troy Kisky <troy.ki...@boundarydevices.com> --- drivers/usb/gadget/mv_udc.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/mv_udc.c b/drivers/usb/gadget/mv_udc.c index b9ff306..324a8d1 100644 --- a/drivers/usb/gadget/mv_udc.c +++ b/drivers/usb/gadget/mv_udc.c @@ -131,10 +131,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 = controller.udc; unsigned n; - head = epts + 2*num + in; n = readl(&udc->epctrl[num]); if (in) @@ -142,8 +140,12 @@ static void ep_enable(int num, int in, int maxpacket) else n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); - if (num != 0) + if (num != 0) { + struct ept_queue_head *head = epts + 2*num + in; + head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT; + flush_cache((unsigned long)head, sizeof(struct ept_queue_head)); + } writel(n, &udc->epctrl[num]); } @@ -192,25 +194,26 @@ static int mv_ep_queue(struct usb_ep *ep, head = epts + 2 * num + in; phys = (unsigned)req->buf; len = req->length; + flush_cache(phys, len); item->next = TERMINATE; item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE; item->page0 = phys; item->page1 = (phys & 0xfffff000) + 0x1000; + flush_cache((unsigned long)item, sizeof(struct ept_queue_item)); head->next = (unsigned) item; head->info = 0; DBG("ept%d %s queue len %x, buffer %x\n", num, in ? "in" : "out", len, phys); + flush_cache((unsigned long)head, sizeof(struct ept_queue_head)); if (in) bit = EPT_TX(num); else bit = EPT_RX(num); - flush_cache(phys, len); - flush_cache((unsigned long)item, sizeof(struct ept_queue_item)); writel(bit, &udc->epprime); return 0; @@ -234,6 +237,13 @@ static void handle_ep_complete(struct mv_ep *ep) ep->req.length -= len; DBG("ept%d %s complete %x\n", num, in ? "in" : "out", len); + if (ep->req.length && !in) { + unsigned start = (unsigned)ep->req.buf & ~0x3f; + unsigned end = ((unsigned)ep->req.buf + ep->req.length + + 0x3f) & ~0x3f; + + invalidate_dcache_range(start, end); + } ep->req.complete(&ep->ep, &ep->req); if (num == 0) { ep->req.length = 0; @@ -255,7 +265,8 @@ static void handle_setup(void) char *buf; head = epts; - flush_cache((unsigned long)head, sizeof(struct ept_queue_head)); + invalidate_dcache_range((unsigned long)head, (unsigned long)head + + sizeof(struct ept_queue_head)); memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); writel(EPT_RX(0), &udc->epstat); DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest), @@ -335,6 +346,8 @@ static void stop_activity(void) in = (ep[i].desc->bEndpointAddress & USB_DIR_IN) != 0; head = epts + (num * 2) + (in); head->info = INFO_ACTIVE; + flush_cache((unsigned long)head, + sizeof(struct ept_queue_head)); } } } @@ -458,9 +471,11 @@ static int mvudc_probe(void) { struct ept_queue_head *head; int i; + const int qh_size = QH_MAXNUM * sizeof(struct ept_queue_head); + const int item_size = sizeof(struct ept_queue_item); - epts = memalign(PAGE_SIZE, QH_MAXNUM * sizeof(struct ept_queue_head)); - memset(epts, 0, QH_MAXNUM * sizeof(struct ept_queue_head)); + epts = memalign(PAGE_SIZE, qh_size); + memset(epts, 0, qh_size); for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { /* * For item0 and item1, they are served as ep0 @@ -476,8 +491,11 @@ static int mvudc_probe(void) head->next = TERMINATE; head->info = 0; - items[i] = memalign(PAGE_SIZE, sizeof(struct ept_queue_item)); + items[i] = memalign(PAGE_SIZE, item_size); + memset(items[i], 0, item_size); + flush_cache((unsigned long)items[i], item_size); } + flush_cache((unsigned long)epts, qh_size); INIT_LIST_HEAD(&controller.gadget.ep_list); ep[0].ep.maxpacket = 64; -- 1.8.1.2 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot