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 <s...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to