[U-Boot] [PATCH v2 11/17] usb: Add support for data alignment
Simon Glass
sjg at chromium.org
Sat Dec 3 03:11:34 CET 2011
CONFIG_USB_EHCI_DATA_ALIGN sets the required alignment of data for
USB packets (e.g. 4 means word-aligned). This is required for Tegra
to operate.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v2:
- Tidy code style in USB buffer alignment code
- Display prominent warning when alignment code is triggered
README | 6 ++++++
drivers/usb/host/ehci-hcd.c | 29 +++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/README b/README
index fda0190..3194846 100644
--- a/README
+++ b/README
@@ -1096,6 +1096,12 @@ The following options need to be configured:
May be defined to allow interrupt polling
instead of using asynchronous interrupts
+ CONFIG_USB_EHCI_DATA_ALIGN sets the required alignment of
+ data for USB packets (e.g. 4 means word-aligned). This is
+ required for Tegra to operate. Since we want all callers to
+ align data for us, we display a warning when the alignment
+ code is triggered.
+
- USB Device:
Define the below if you wish to use the USB console.
Once firmware is rebuilt from a serial console issue the
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2197119..23458b6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -322,6 +322,24 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
int timeout;
int ret = 0;
+#ifdef CONFIG_USB_EHCI_DATA_ALIGN
+ /* In case ehci host requires alignment for buffers */
+ void *align_buf = NULL;
+ void *orig_buf = buffer;
+ int unaligned = (int)buffer & (CONFIG_USB_EHCI_DATA_ALIGN - 1);
+
+ if (unaligned) {
+ printf("EHCI: Unaligned buffer: performance will suffer\n");
+ align_buf = malloc(length + CONFIG_USB_EHCI_DATA_ALIGN);
+ if (!align_buf)
+ return -1;
+ buffer = (void *)(((ulong)align_buf +
+ CONFIG_USB_EHCI_DATA_ALIGN - 1) &
+ ~(CONFIG_USB_EHCI_DATA_ALIGN - 1));
+ if (usb_pipeout(pipe))
+ memcpy(buffer, orig_buf, length);
+ }
+#endif
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
buffer, length, req);
if (req != NULL)
@@ -513,9 +531,20 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
ehci_readl(&hcor->or_portsc[1]));
}
+#ifdef CONFIG_USB_EHCI_DATA_ALIGN
+ if (unaligned) {
+ if (usb_pipein(pipe) && dev->act_len)
+ memcpy(orig_buf, buffer, length);
+ free(align_buf);
+ }
+#endif
return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
fail:
+#ifdef CONFIG_USB_EHCI_DATA_ALIGN
+ if (unaligned)
+ free(align_buf);
+#endif
td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next);
while (td != (void *)QT_NEXT_TERMINATE) {
qh->qh_overlay.qt_next = td->qt_next;
--
1.7.3.1
More information about the U-Boot
mailing list