[U-Boot] [PATCH 09/14] tegra: usb: Add support for data alignment and txfifo threshold
Simon Glass
sjg at chromium.org
Thu Nov 24 04:54:51 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.
CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the txfilltuning
field in the EHCI controller on reset.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
README | 7 +++++++
drivers/usb/host/ehci-hcd.c | 39 +++++++++++++++++++++++++++++++++++++++
drivers/usb/host/ehci.h | 6 +++++-
3 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/README b/README
index 07f1d11..d3289d2 100644
--- a/README
+++ b/README
@@ -1096,6 +1096,13 @@ 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.
+
+ CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the
+ txfilltuning field in the EHCI controller on reset.
+
- 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..d3eeefe 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -247,6 +247,13 @@ static int ehci_reset(void)
#endif
ehci_writel(reg_ptr, tmp);
}
+
+#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
+ cmd = ehci_readl(&hcor->or_txfilltuning);
+ cmd &= ~TXFIFO_THRESH(0x3f);
+ cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
+ ehci_writel(&hcor->or_txfilltuning, cmd);
+#endif
out:
return ret;
}
@@ -322,6 +329,27 @@ 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)) != 0;
+
+ if (unaligned) {
+ align_buf = malloc(length + CONFIG_USB_EHCI_DATA_ALIGN);
+ if (!align_buf)
+ return -1;
+ if ((int)align_buf & (CONFIG_USB_EHCI_DATA_ALIGN - 1))
+ buffer = (void *)((int)align_buf +
+ CONFIG_USB_EHCI_DATA_ALIGN -
+ ((int)align_buf &
+ (CONFIG_USB_EHCI_DATA_ALIGN - 1)));
+ else
+ buffer = align_buf;
+ 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 +541,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;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 3d0ad0c..cc00ce4 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -80,7 +80,11 @@ struct ehci_hcor {
uint32_t or_ctrldssegment;
uint32_t or_periodiclistbase;
uint32_t or_asynclistaddr;
- uint32_t _reserved_[9];
+ uint32_t _reserved_0_;
+ uint32_t or_burstsize;
+ uint32_t or_txfilltuning;
+#define TXFIFO_THRESH(p) ((p & 0x3f) << 16)
+ uint32_t _reserved_1_[6];
uint32_t or_configflag;
#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */
uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
--
1.7.3.1
More information about the U-Boot
mailing list