summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2011-04-28 10:11:00 -0700
committerSimon Glass <sjg@chromium.org>2011-08-24 09:54:52 -0700
commit893172f218c203f9fcf7210229167b4f168df44a (patch)
treeeda4c428ad3e7fc9eb1da84d3b1ce52087fab90e /drivers/usb
parent696ba76e40fefcc58848b5e86575915927840c6a (diff)
Tegra2: Add USB support
This adds basic USB support for port 0. The other port is not supported by this CL. BUG=chromium-os:13875 TEST=Put USB stick in side port. Then: Tegra2 (SeaBoard) # ext2load usb 0:3 10000000 /boot/vmlinuz Loading file "/boot/vmlinuz" from usb device 0:3 (gpt3) 2745808 bytes read Tegra2 (SeaBoard) # Change-Id: I10f9228377ee7ed7817bb30bf665d69c5e74f239 Review URL: http://codereview.chromium.org/6896012
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-hcd.c39
-rw-r--r--drivers/usb/host/ehci-tegra.c73
-rw-r--r--drivers/usb/host/ehci.h6
4 files changed, 118 insertions, 1 deletions
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 51b2494328..a8e107be67 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -46,6 +46,7 @@ COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
+COBJS-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 70c02c9deb..9647ef4852 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)
@@ -514,9 +542,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-tegra.c b/drivers/usb/host/ehci-tegra.c
new file mode 100644
index 0000000000..04e43b840e
--- /dev/null
+++ b/drivers/usb/host/ehci-tegra.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <usb.h>
+
+#include "ehci.h"
+#include "ehci-core.h"
+
+#include <asm/errno.h>
+#include <asm/arch/usb.h>
+
+
+/*
+ * This is a list of base addresses for each USB port. These CONFIG_TEGRA2_...
+ * values are defined in the board config files. Non-existent ports are zero.
+ */
+int USB_base_addr[5] = {
+ CONFIG_TEGRA2_USB0,
+ CONFIG_TEGRA2_USB1,
+ CONFIG_TEGRA2_USB2,
+ CONFIG_TEGRA2_USB3,
+ 0
+};
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+ /* EHCI registers start at offset 0x100. For now support only port 0*/
+ hccr = (struct ehci_hccr *)(CONFIG_TEGRA2_USB0 + 0x100);
+ hcor = (struct ehci_hcor *)((uint32_t) hccr
+ + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+ return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+#ifdef CONFIG_TEGRA2_USB1_HOST
+ usb1_set_host_mode();
+#endif
+ ehci_writel(&hcor->or_usbcmd, 0);
+ udelay(1000);
+ ehci_writel(&hcor->or_usbcmd, 2);
+ udelay(1000);
+ return 0;
+}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 945ab64f95..29ec82f3b1 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];