From 893172f218c203f9fcf7210229167b4f168df44a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Apr 2011 10:11:00 -0700 Subject: 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 --- drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-hcd.c | 39 +++++++++++++++++++++++ drivers/usb/host/ehci-tegra.c | 73 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 6 +++- 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ehci-tegra.c (limited to 'drivers/usb') 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 +#include + +#include "ehci.h" +#include "ehci-core.h" + +#include +#include + + +/* + * 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]; -- cgit v1.2.3