This adds basic USB support for port 0. The other port is not supported by this 
CL.

Signed-off-by: Simon Glass <s...@chromium.org>
---
 arch/arm/include/asm/arch-tegra2/tegra2.h |    2 +
 arch/arm/include/asm/arch-tegra2/usb.h    |  217 ++++++++++++++++++++
 board/nvidia/common/Makefile              |   53 +++++
 board/nvidia/common/board.c               |    5 +
 board/nvidia/common/usb.c                 |  313 +++++++++++++++++++++++++++++
 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 +-
 include/configs/harmony.h                 |    7 +
 include/configs/seaboard.h                |   10 +
 include/configs/tegra2-common.h           |   30 +++
 12 files changed, 755 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-tegra2/usb.h
 create mode 100644 board/nvidia/common/Makefile
 create mode 100644 board/nvidia/common/usb.c
 create mode 100644 drivers/usb/host/ehci-tegra.c

diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h 
b/arch/arm/include/asm/arch-tegra2/tegra2.h
index 742a75a..3bf0051 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -40,6 +40,8 @@
 #define NV_PA_APB_UARTE_BASE   (NV_PA_APB_MISC_BASE + 0x6400)
 #define NV_PA_PMC_BASE         0x7000E400
 #define NV_PA_CSITE_BASE       0x70040000
+#define NV_PA_USB1_BASE                0xC5000000
+#define NV_PA_USB3_BASE                0xC5008000

 #define TEGRA2_SDRC_CS0                NV_PA_SDRAM_BASE
 #define LOW_LEVEL_SRAM_STACK   0x4000FFFC
diff --git a/arch/arm/include/asm/arch-tegra2/usb.h 
b/arch/arm/include/asm/arch-tegra2/usb.h
new file mode 100644
index 0000000..c37f404
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/usb.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * 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
+ */
+
+#ifndef _TEGRA_USB_H_
+#define _TEGRA_USB_H_
+
+
+/* USB Controller (USBx_CONTROLLER_) regs */
+struct usb_ctlr {
+       /* 0x000 */
+       uint id;
+       uint reserved0;
+       uint host;
+       uint device;
+
+       /* 0x010 */
+       uint txbuf;
+       uint rxbuf;
+       uint reserved1[2];
+
+       /* 0x020 */
+       uint reserved2[56];
+
+       /* 0x100 */
+       u16 cap_length;
+       u16 hci_version;
+       uint hcs_params;
+       uint hcc_params;
+       uint reserved3[5];
+
+       /* 0x120 */
+       uint dci_version;
+       uint dcc_params;
+       uint reserved4[6];
+
+       /* 0x140 */
+       uint usb_cmd;
+       uint usb_sts;
+       uint usb_intr;
+       uint frindex;
+
+       /* 0x150 */
+       uint reserved5;
+       uint periodic_list_base;
+       uint async_list_addr;
+       uint async_tt_sts;
+
+       /* 0x160 */
+       uint burst_size;
+       uint tx_fill_tuning;
+       uint reserved6;   /* is this port_sc1 on some controllers? */
+       uint icusb_ctrl;
+
+       /* 0x170 */
+       uint ulpi_viewport;
+       uint reserved7;
+       uint endpt_nak;
+       uint endpt_nak_enable;
+
+       /* 0x180 */
+       uint reserved;
+       uint port_sc1;
+       uint reserved8[6];
+
+       /* 0x1a0 */
+       uint reserved9;
+       uint otgsc;
+       uint usb_mode;
+       uint endpt_setup_stat;
+
+       /* 0x1b0 */
+       uint reserved10[20];
+
+       /* 0x200 */
+       uint reserved11[0x80];
+
+       /* 0x400 */
+       uint susp_ctrl;
+       uint phy_vbus_sensors;
+       uint phy_vbus_wakeup_id;
+       uint phy_alt_vbus_sys;
+
+       /* 0x410 */
+       uint usb1_legacy_ctrl;
+       uint reserved12[3];
+
+       /* 0x420 */
+       uint reserved13[56];
+
+       /* 0x500 */
+       uint reserved14[64 * 3];
+
+       /* 0x800 */
+       uint utmip_pll_cfg0;
+       uint utmip_pll_cfg1;
+       uint utmip_xcvr_cfg0;
+       uint utmip_bias_cfg0;
+
+       /* 0x810 */
+       uint utmip_hsrx_cfg0;
+       uint utmip_hsrx_cfg1;
+       uint utmip_fslsrx_cfg0;
+       uint utmip_fslsrx_cfg1;
+
+       /* 0x820 */
+       uint utmip_tx_cfg0;
+       uint utmip_misc_cfg0;
+       uint utmip_misc_cfg1;
+       uint utmip_debounce_cfg0;
+
+       /* 0x830 */
+       uint utmip_bat_chrg_cfg0;
+       uint utmip_spare_cfg0;
+       uint utmip_xcvr_cfg1;
+       uint utmip_bias_cfg1;
+};
+
+
+/* USB1_LEGACY_CTRL */
+#define USB1_NO_LEGACY_MODE_RANGE              0 : 0
+#define NO_LEGACY_MODE                         1
+
+#define VBUS_SENSE_CTL_RANGE                   2 : 1
+#define VBUS_SENSE_CTL_VBUS_WAKEUP             0
+#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP      1
+#define VBUS_SENSE_CTL_AB_SESS_VLD             2
+#define VBUS_SENSE_CTL_A_SESS_VLD              3
+
+/* USBx_IF_USB_SUSP_CTRL_0 */
+#define UTMIP_PHY_ENB_RANGE                    12 : 12
+#define UTMIP_RESET_RANGE                      11 : 11
+#define USB_PHY_CLK_VALID_RANGE                        7 : 7
+
+/* USBx_UTMIP_MISC_CFG1 */
+#define UTMIP_PLLU_STABLE_COUNT_RANGE          17 : 6
+#define UTMIP_PLL_ACTIVE_DLY_COUNT_RANGE       22 : 18
+#define UTMIP_PHY_XTAL_CLOCKEN_RANGE           30 : 30
+
+/* USBx_UTMIP_PLL_CFG1_0 */
+#define UTMIP_PLLU_ENABLE_DLY_COUNT_RANGE      30 : 27
+#define UTMIP_XTAL_FREQ_COUNT_RANGE            11 : 0
+
+/* USBx_UTMIP_BIAS_CFG1_0 */
+#define UTMIP_BIAS_PDTRK_COUNT_RANGE           7 : 3
+
+#define UTMIP_DEBOUNCE_CFG0_RANGE              15 : 0
+
+/* USBx_UTMIP_TX_CFG0_0 */
+#define UTMIP_FS_PREAMBLE_J_RANGE              19 : 19
+
+/* USBx_UTMIP_BAT_CHRG_CFG0_0 */
+#define UTMIP_PD_CHRG_RANGE                    0 : 0
+
+/* USBx_UTMIP_XCVR_CFG0_0 */
+#define UTMIP_XCVR_LSBIAS_SE_RANGE             21 : 21
+
+/* USBx_UTMIP_SPARE_CFG0_0 */
+#define FUSE_SETUP_SEL_RANGE                   3 : 3
+
+/* USBx_UTMIP_HSRX_CFG0_0 */
+#define UTMIP_IDLE_WAIT_RANGE                  19 : 15
+#define UTMIP_ELASTIC_LIMIT_RANGE              14 : 10
+
+/* USBx_UTMIP_HSRX_CFG0_1 */
+#define UTMIP_HS_SYNC_START_DLY_RANGE          4 : 1
+
+/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */
+#define IC_ENB1_RANGE                          3 : 3
+
+/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */
+#define PTS_RANGE                              31 : 30
+#define PTS_UTMI       0
+#define PTS_RESERVED   1
+#define PTS_ULP                2
+#define PTS_ICUSB_SER  3
+
+#define STS_RANGE                              29 : 29
+
+/* USBx_UTMIP_XCVR_CFG0_0 */
+#define UTMIP_FORCE_PD_POWERDOWN_RANGE         14 : 14
+#define UTMIP_FORCE_PD2_POWERDOWN_RANGE                16 : 16
+#define UTMIP_FORCE_PDZI_POWERDOWN_RANGE       18 : 18
+
+/* USBx_UTMIP_XCVR_CFG1_0 */
+#define UTMIP_FORCE_PDDISC_POWERDOWN_RANGE     0 : 0
+#define UTMIP_FORCE_PDCHRP_POWERDOWN_RANGE     2 : 2
+#define UTMIP_FORCE_PDDR_POWERDOWN_RANGE       4 : 4
+
+/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */
+#define VBUS_VLD_STS_RANGE                     26 : 26
+
+
+/* Change USB port 1 into host mode */
+void usb1_set_host_mode(void);
+
+/* Setup USB on the board */
+void board_usb_init(void);
+
+#endif /* _TEGRA_USB_H_ */
diff --git a/board/nvidia/common/Makefile b/board/nvidia/common/Makefile
new file mode 100644
index 0000000..9bd0bf2
--- /dev/null
+++ b/board/nvidia/common/Makefile
@@ -0,0 +1,53 @@
+# Copyright (c) 2011 The Chromium OS Authors.
+# 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 $(TOPDIR)/config.mk
+
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)board/$(VENDOR)/common)
+endif
+
+LIB    = $(obj)lib$(VENDOR).o
+
+COBJS-y += board.o
+COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+SOBJS  := $(addprefix $(obj),$(SOBJS))
+
+all:   $(LIB)
+
+$(LIB):        $(obj).depend $(OBJS) $(SOBJS)
+       $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+# This is for $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index ac2e3f8..658bf1f 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -32,6 +32,7 @@
 #include <asm/arch/clock.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/uart.h>
+#include <asm/arch/usb.h>
 #include "board.h"

 DECLARE_GLOBAL_DATA_PTR;
@@ -191,5 +192,9 @@ int board_init(void)
        /* board id for Linux */
        gd->bd->bi_arch_number = CONFIG_MACH_TYPE;

+#ifdef CONFIG_USB_EHCI_TEGRA
+       board_usb_init();
+#endif
+
        return 0;
 }
diff --git a/board/nvidia/common/usb.c b/board/nvidia/common/usb.c
new file mode 100644
index 0000000..0f70306
--- /dev/null
+++ b/board/nvidia/common/usb.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010,2011 NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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 <asm/io.h>
+#include <asm/arch/bitfield.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/sys_proto.h>
+
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/uart.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/usb.h>
+
+
+/* The fields for USB PLLU configuration parameters */
+struct usb_pll_params {
+       unsigned divn;          /* PLL feedback divider */
+       unsigned divm;          /* PLL input divider */
+       unsigned divp;          /* post divider (2^n) */
+       unsigned cpcon;         /* Base PLLC charge pump setup control */
+       unsigned lfcon;         /* Base PLLC loop filter setup control */
+       u8 enable_delay_count;  /* Pll-U Enable Delay Count */
+       u8 stable_count;        /* PLL-U Stable count */
+       u8 active_delay_count;  /* Pll-U Active delay count */
+       u8 xtal_freq_count;     /* PLL-U Xtal frequency count */
+       unsigned debounce_a_time; /* 10ms delay for BIAS_DEBOUNCE_A */
+       unsigned bias_time;     /* 20us delay after bias cell op */
+};
+
+/*
+ * This table has USB timing parameters for each Oscillator frequency we
+ * support. There are four sets of values:
+ *
+ * 1. PLLU configuration information (reference clock is osc/clk_m and
+ * PLLU-FOs are fixed at 12MHz/60MHz/480MHz).
+ *
+ *  Reference frequency     13.0MHz      19.2MHz      12.0MHz      26.0MHz
+ *  ----------------------------------------------------------------------
+ *      DIVN                960 (0x3c0)  200 (0c8)    960 (3c0h)   960 (3c0)
+ *      DIVM                13 (0d)      4 (04)       12 (0c)      26 (1a)
+ * Filter frequency (MHz)   1            4.8          6            2
+ * CPCON                    1100b        0011b        1100b        1100b
+ * LFCON0                   0            0            0            0
+ *
+ * 2. PLL CONFIGURATION & PARAMETERS for different clock generators:
+ *
+ * Reference frequency     13.0MHz         19.2MHz         12.0MHz     26.0MHz
+ * ---------------------------------------------------------------------------
+ * PLLU_ENABLE_DLY_COUNT   02 (0x02)       03 (03)         02 (02)     04 (04)
+ * PLLU_STABLE_COUNT       51 (33)         75 (4B)         47 (2F)    102 (66)
+ * PLL_ACTIVE_DLY_COUNT    05 (05)         06 (06)         04 (04)     09 (09)
+ * XTAL_FREQ_COUNT        127 (7F)        187 (BB)        118 (76)    254 (FE)
+ *
+ * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and
+ * SessEnd. Each of these signals have their own debouncer and for each of
+ * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or
+ * BIAS_DEBOUNCE_B).
+ *
+ * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows:
+ *    0xffff -> No debouncing at all
+ *    <n> ms = <n> *1000 / (1/19.2MHz) / 4
+ *
+ * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have:
+ * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4  = 4800 = 0x12c0
+ *
+ * We need to use only DebounceA for BOOTROM. We don't need the DebounceB
+ * values, so we can keep those to default.
+ *
+ * 4. The 20 microsecond delay after bias cell operation.
+ */
+static const struct usb_pll_params usb_pll[CLOCK_OSC_FREQ_COUNT] = {
+       /* DivN, DivM, DivP, CPCON, LFCON, Delays             Debounce, Bias */
+       { 0x3C0, 0x0D, 0x00, 0xC,   0,  0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 },
+       { 0x0C8, 0x04, 0x00, 0x3,   0,  0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 },
+       { 0x3C0, 0x0C, 0x00, 0xC,   0,  0x02, 0x2F, 0x04, 0x76, 0x7530, 5 },
+       { 0x3C0, 0x1A, 0x00, 0xC,   0,  0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 }
+};
+
+/* UTMIP Idle Wait Delay */
+static const u8 utmip_idle_wait_delay = 17;
+
+/* UTMIP Elastic limit */
+static const u8 utmip_elastic_limit = 16;
+
+/* UTMIP High Speed Sync Start Delay */
+static const u8 utmip_hs_sync_start_delay = 9;
+
+
+void usb1_set_host_mode(void)
+{
+       struct usb_ctlr *usbctlr = (struct usb_ctlr *)NV_PA_USB1_BASE;
+
+       /* Check whether remote host from USB1 is driving VBus */
+       if (bf_readl(VBUS_VLD_STS, &usbctlr->phy_vbus_sensors))
+               return;
+
+       /*
+        * If not driving, we set GPIO USB1_VBus_En. Seaboard platform uses
+        * PAD SLXK (GPIO D.00) as USB1_VBus_En Config as GPIO
+        */
+       gpio_direction_output(GPIO_PD0, 1);
+
+       /* Z_SLXK = 0, normal, not tristate */
+       pinmux_tristate_disable(PIN_SLXK);
+}
+
+void usbf_reset_controller(enum periph_id id, struct usb_ctlr *usbctlr)
+{
+       /* Reset the USB controller with 2us delay */
+       reset_periph(id, 2);
+
+       /*
+        * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under
+        * base address
+        */
+       if (id == PERIPH_ID_USBD)
+               bf_writel(USB1_NO_LEGACY_MODE, NO_LEGACY_MODE,
+                       &usbctlr->usb1_legacy_ctrl);
+
+       /* Put UTMIP1/3 in reset */
+       bf_writel(UTMIP_RESET, 1, &usbctlr->susp_ctrl);
+
+       /* Set USB3 to use UTMIP PHY */
+       if (id == PERIPH_ID_USB3)
+               bf_writel(UTMIP_PHY_ENB, 1, &usbctlr->susp_ctrl);
+
+       /*
+        * TODO: where do we take the USB1 out of reset? The old code would
+        * take USB3 out of reset, but not USB1. This code doesn't do either.
+        */
+}
+
+/* set up the USB controller with the parameters provided */
+static void init_usb_controller(enum periph_id id, struct usb_ctlr *usbctlr,
+               const struct usb_pll_params *params)
+{
+       u32 val;
+       int loop_count;
+
+       clock_enable(id);
+
+       /* Reset the usb controller */
+       usbf_reset_controller(id, usbctlr);
+
+       /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */
+       bf_clearl(UTMIP_PHY_XTAL_CLOCKEN, &usbctlr->utmip_misc_cfg1);
+
+       /* Follow the crystal clock disable by >100ns delay */
+       udelay(1);
+
+       /*
+        * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP
+        * mux must be switched to actually use a_sess_vld threshold.
+        */
+       if (id == PERIPH_ID_USBD)
+               bf_enum_writel(VBUS_SENSE_CTL, A_SESS_VLD,
+                               &usbctlr->usb1_legacy_ctrl);
+
+       /*
+        * PLL Delay CONFIGURATION settings. The following parameters control
+        * the bring up of the plls.
+        */
+       val = readl(&usbctlr->utmip_misc_cfg1);
+       bf_update(UTMIP_PLLU_STABLE_COUNT, val, params->stable_count);
+       bf_update(UTMIP_PLL_ACTIVE_DLY_COUNT, val,
+                    params->active_delay_count);
+       writel(val, &usbctlr->utmip_misc_cfg1);
+
+       /* Set PLL enable delay count and crystal frequency count */
+       val = readl(&usbctlr->utmip_pll_cfg1);
+       bf_update(UTMIP_PLLU_ENABLE_DLY_COUNT, val,
+                    params->enable_delay_count);
+       bf_update(UTMIP_XTAL_FREQ_COUNT, val, params->xtal_freq_count);
+       writel(val, &usbctlr->utmip_pll_cfg1);
+
+       /* Setting the tracking length time */
+       bf_writel(UTMIP_BIAS_PDTRK_COUNT, params->bias_time,
+                       &usbctlr->utmip_bias_cfg1);
+
+       /* Program debounce time for VBUS to become valid */
+       bf_writel(UTMIP_DEBOUNCE_CFG0, params->debounce_a_time,
+                       &usbctlr->utmip_debounce_cfg0);
+
+       /* Set UTMIP_FS_PREAMBLE_J to 1 */
+       bf_writel(UTMIP_FS_PREAMBLE_J, 1, &usbctlr->utmip_tx_cfg0);
+
+       /* Disable battery charge enabling bit */
+       bf_writel(UTMIP_PD_CHRG, 1, &usbctlr->utmip_bat_chrg_cfg0);
+
+       /* Set UTMIP_XCVR_LSBIAS_SEL to 0 */
+       bf_writel(UTMIP_XCVR_LSBIAS_SE, 0, &usbctlr->utmip_xcvr_cfg0);
+
+       /* Set bit 3 of UTMIP_SPARE_CFG0 to 1 */
+       bf_writel(FUSE_SETUP_SEL, 1, &usbctlr->utmip_spare_cfg0);
+
+       /*
+        * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
+        * Setting these fields, together with default values of the
+        * other fields, results in programming the registers below as
+        * follows:
+        *         UTMIP_HSRX_CFG0 = 0x9168c000
+        *         UTMIP_HSRX_CFG1 = 0x13
+        */
+
+       /* Set PLL enable delay count and Crystal frequency count */
+       val = readl(&usbctlr->utmip_hsrx_cfg0);
+       bf_update(UTMIP_IDLE_WAIT, val, utmip_idle_wait_delay);
+       bf_update(UTMIP_ELASTIC_LIMIT, val, utmip_elastic_limit);
+       writel(val, &usbctlr->utmip_hsrx_cfg0);
+
+       /* Configure the UTMIP_HS_SYNC_START_DLY */
+       bf_writel(UTMIP_HS_SYNC_START_DLY, utmip_hs_sync_start_delay,
+                       &usbctlr->utmip_hsrx_cfg1);
+
+       /* Preceed the crystal clock disable by >100ns delay. */
+       udelay(1);
+
+       /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */
+       bf_writel(UTMIP_PHY_XTAL_CLOCKEN, 1, &usbctlr->utmip_misc_cfg1);
+
+       /* Finished the per-controller init. */
+
+       /* De-assert UTMIP_RESET to bring out of reset. */
+       bf_clearl(UTMIP_RESET, &usbctlr->susp_ctrl);
+
+       /* Wait for the phy clock to become valid in 100 ms */
+       for (loop_count = 100000; loop_count != 0; loop_count--) {
+               if (bf_readl(USB_PHY_CLK_VALID, &usbctlr->susp_ctrl))
+                       break;
+               udelay(1);
+       }
+}
+
+static void power_up_port(struct usb_ctlr *usbctlr)
+{
+       u32 val;
+
+       /* Deassert power down state */
+       val = readl(&usbctlr->utmip_xcvr_cfg0);
+       bf_update(UTMIP_FORCE_PD_POWERDOWN, val, 0);
+       bf_update(UTMIP_FORCE_PD2_POWERDOWN, val, 0);
+       bf_update(UTMIP_FORCE_PDZI_POWERDOWN, val, 0);
+       writel(val, &usbctlr->utmip_xcvr_cfg0);
+
+       val = readl(&usbctlr->utmip_xcvr_cfg1);
+       bf_update(UTMIP_FORCE_PDDISC_POWERDOWN, val, 0);
+       bf_update(UTMIP_FORCE_PDCHRP_POWERDOWN, val, 0);
+       bf_update(UTMIP_FORCE_PDDR_POWERDOWN, val, 0);
+       writel(val, &usbctlr->utmip_xcvr_cfg1);
+}
+
+void board_usb_init(void)
+{
+       enum clock_osc_freq freq;
+       const struct usb_pll_params *params;
+       struct usb_ctlr *usbctlr;
+       u32 val;
+       unsigned stable_time;
+
+       /* Get the Oscillator frequency */
+       freq = clock_get_osc_freq();
+
+       /* Enable PLL U for USB */
+       params = &usb_pll[freq];
+       stable_time = clock_start_pll(CLOCK_PLL_ID_USB,
+               params->divm, params->divn, params->divp, params->cpcon,
+               params->lfcon);
+       /* TODO: what should we do with stable_time? */
+
+       /* Set up our two ports */
+       usbctlr = (struct usb_ctlr *)NV_PA_USB1_BASE;
+       init_usb_controller(PERIPH_ID_USBD, usbctlr, params);
+
+       usbctlr = (struct usb_ctlr *)NV_PA_USB3_BASE;
+       init_usb_controller(PERIPH_ID_USB3, usbctlr, params);
+
+       /* Disable ICUSB FS/LS transceiver */
+       bf_writel(IC_ENB1, 0, &usbctlr->icusb_ctrl);
+
+       /* Select UTMI parallel interface */
+       bf_writel(PTS, PTS_UTMI, &usbctlr->port_sc1);
+       bf_writel(STS, 0, &usbctlr->port_sc1);
+
+       power_up_port(usbctlr);
+
+#ifdef CONFIG_TEGRA2_USB1_HOST
+       usb1_set_host_mode();
+#endif
+}
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 51b2494..a8e107b 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 70c02c9..1049612 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 0000000..04e43b8
--- /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 945ab64..29ec82f 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];
diff --git a/include/configs/harmony.h b/include/configs/harmony.h
index 34bd899..0f49d88 100644
--- a/include/configs/harmony.h
+++ b/include/configs/harmony.h
@@ -47,4 +47,11 @@
 #define CONFIG_SYS_BOARD_ODMDATA       0x300d8011 /* lp1, 1GB */

 #define CONFIG_BOARD_EARLY_INIT_F
+
+/* To select the order in which U-Boot sees USB ports */
+#define CONFIG_TEGRA2_USB0     NV_PA_USB3_BASE
+#define CONFIG_TEGRA2_USB1     NV_PA_USB1_BASE
+#define CONFIG_TEGRA2_USB2     0
+#define CONFIG_TEGRA2_USB3     0
+
 #endif /* __CONFIG_H */
diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h
index 06ce3e2..9c062e8 100644
--- a/include/configs/seaboard.h
+++ b/include/configs/seaboard.h
@@ -41,4 +41,14 @@
 #define CONFIG_SYS_BOARD_ODMDATA       0x300d8011 /* lp1, 1GB */

 #define CONFIG_BOARD_EARLY_INIT_F
+
+/* To select the order in which U-Boot sees USB ports */
+#define CONFIG_TEGRA2_USB0     NV_PA_USB3_BASE
+#define CONFIG_TEGRA2_USB1     NV_PA_USB1_BASE
+#define CONFIG_TEGRA2_USB2     0
+#define CONFIG_TEGRA2_USB3     0
+
+/* Put USB1 in host mode */
+#define CONFIG_TEGRA2_USB1_HOST
+
 #endif /* __CONFIG_H */
diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h
index febce35..ae417ea 100644
--- a/include/configs/tegra2-common.h
+++ b/include/configs/tegra2-common.h
@@ -84,6 +84,36 @@
 #define CONFIG_SYS_BAUDRATE_TABLE      {4800, 9600, 19200, 38400, 57600,\
                                        115200}

+
+/*
+ * USB Host.
+ */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_TEGRA
+#define CONFIG_USB_CONTROLLER_INSTANCES        2
+
+/* Tegra2 requires USB buffers to be aligned to a word boundary */
+#define CONFIG_USB_EHCI_DATA_ALIGN     4
+
+/*
+ * This parameter affects a TXFILLTUNING field that controls how much data is
+ * sent to the latency fifo before it is sent to the wire. Without this
+ * parameter, the default (2) causes occasional Data Buffer Errors in OUT
+ * packets depending on the buffer address and size.
+ */
+#define CONFIG_USB_EHCI_TXFIFO_THRESH  10
+
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+
+#define CONFIG_CMD_USB         /* USB Host support             */
+
+/* partition types and file systems we want */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_EXT2
+
+
 /* include default commands */
 #include <config_cmd_default.h>

--
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