[U-Boot] [PATCH] usb: ehci: add missing cache managment

Stephen Warren swarren at wwwdotorg.org
Fri May 24 23:03:17 CEST 2013


From: Stephen Warren <swarren at nvidia.com>

Commit 8f62ca6 "usb: ehci: Support interrupt transfers via periodic list"
didn't include any cache management in the new interrupt transfer path.
It also added an extra write to or_asynclistaddr in usb_lowlevel_init(),
without having flushed out the data there.

Add the missing cache management calls, so that the code works again.

This allows the USB keyboard on Tegra's Seaboard/Springbank boards to
work.

Cc: Patrick Georgi <patrick at georgi-clan.de>
Cc: Vincent Palatin <vpalatin at chromium.org>
Cc: Julius Werner <jwerner at chromium.org>
Cc: Simon Glass <sjg at chromium.org>
Cc: Marek Vasut <marex at denx.de>
Signed-off-by: Stephen Warren <swarren at nvidia.com>
---
 drivers/usb/host/ehci-hcd.c |   30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e0f3e4b..5c6aaf6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -903,6 +903,9 @@ int usb_lowlevel_init(int index, void **controller)
 	qh_list->qh_overlay.qt_token =
 			cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
 
+	flush_dcache_range((uint32_t)qh_list,
+			   ALIGN_END_ADDR(struct QH, qh_list, 1));
+
 	/* Set async. queue head pointer. */
 	ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list);
 
@@ -916,6 +919,9 @@ int usb_lowlevel_init(int index, void **controller)
 	periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 	periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
 
+	flush_dcache_range((uint32_t)periodic,
+			   ALIGN_END_ADDR(struct QH, periodic, 1));
+
 	/*
 	 * Step 2: Setup frame-list: Every microframe, USB tries the same list.
 	 *         In particular, device specifications on polling frequency
@@ -933,6 +939,10 @@ int usb_lowlevel_init(int index, void **controller)
 						| QH_LINK_TYPE_QH;
 	}
 
+	flush_dcache_range((uint32_t)ehcic[index].periodic_list,
+			   ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list,
+					  1024));
+
 	/* Set periodic list base address */
 	ehci_writel(&ehcic[index].hcor->or_periodiclistbase,
 		(uint32_t)ehcic[index].periodic_list);
@@ -1144,6 +1154,16 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
 		*buf = buffer + i * elementsize;
 	}
 
+	flush_dcache_range((uint32_t)buffer,
+			   ALIGN_END_ADDR(char, buffer,
+					  queuesize * elementsize));
+	flush_dcache_range((uint32_t)result->first,
+			   ALIGN_END_ADDR(struct QH, result->first,
+					  queuesize));
+	flush_dcache_range((uint32_t)result->tds,
+			   ALIGN_END_ADDR(struct qTD, result->tds,
+					  queuesize));
+
 	if (disable_periodic(ctrl) < 0) {
 		debug("FATAL: periodic should never fail, but did");
 		goto fail3;
@@ -1154,6 +1174,11 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
 	result->last->qh_link = list->qh_link;
 	list->qh_link = (uint32_t)result->first | QH_LINK_TYPE_QH;
 
+	flush_dcache_range((uint32_t)result->last,
+			   ALIGN_END_ADDR(struct QH, result->last, 1));
+	flush_dcache_range((uint32_t)list,
+			   ALIGN_END_ADDR(struct QH, list, 1));
+
 	if (enable_periodic(ctrl) < 0) {
 		debug("FATAL: periodic should never fail, but did");
 		goto fail3;
@@ -1184,6 +1209,8 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
 		return NULL;
 	}
 	/* still active */
+	invalidate_dcache_range((uint32_t)cur,
+				ALIGN_END_ADDR(struct QH, cur, 1));
 	if (cur->qh_overlay.qt_token & 0x80) {
 		debug("Exit poll_int_queue with no completed intr transfer. "
 		      "token is %x\n", cur->qh_overlay.qt_token);
@@ -1290,6 +1317,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 		return -EINVAL;
 	}
 
+	invalidate_dcache_range((uint32_t)buffer,
+				ALIGN_END_ADDR(char, buffer, length));
+
 	ret = destroy_int_queue(dev, queue);
 	if (ret < 0)
 		return ret;
-- 
1.7.10.4



More information about the U-Boot mailing list