[U-Boot] [PATCH RFC V1 17/18] usb: gadget: mv_udc: fix cache issues

Troy Kisky troy.kisky at boundarydevices.com
Tue Jul 16 22:47:45 CEST 2013


Allow mv_udc to work when cache is enabled by
adding flushing and invalidating calls.

Signed-off-by: Troy Kisky <troy.kisky at 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



More information about the U-Boot mailing list