All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lucas Stach <dev@lynxeye.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 6/7] tegra: usb: move implementation into right directory
Date: Thu,  7 Feb 2013 18:16:29 +0100	[thread overview]
Message-ID: <1360257390-22899-7-git-send-email-dev@lynxeye.de> (raw)
In-Reply-To: <1360257390-22899-1-git-send-email-dev@lynxeye.de>

This moves the Tegra USB implementation into the drivers/usb/host
directory. Note that this merges the old
/arch/arm/cpu/armv7/tegra20/usb.c file into ehci-tegra.c. No code
changes, just moving stuff around.

v2: While at it also move some defines and the usb.h header file to make
usb driver usable for Tegra30.
NOTE: A lot more work is required to properly init the PHYs and PLL_U on
Tegra30, this is just to make porting easier and it does no harm here.

Signed-off-by: Lucas Stach <dev@lynxeye.de>
Acked-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/cpu/armv7/tegra20/Makefile       |   1 -
 arch/arm/cpu/armv7/tegra20/usb.c          | 555 ------------------------------
 arch/arm/include/asm/arch-tegra/usb.h     | 268 +++++++++++++++
 arch/arm/include/asm/arch-tegra20/tegra.h |   1 -
 arch/arm/include/asm/arch-tegra20/usb.h   | 268 ---------------
 arch/arm/include/asm/arch-tegra30/tegra.h |   2 +
 board/nvidia/common/board.c               |   2 +-
 drivers/usb/host/ehci-tegra.c             | 535 +++++++++++++++++++++++++++-
 8 files changed, 804 insertions(+), 828 deletions(-)
 delete mode 100644 arch/arm/cpu/armv7/tegra20/usb.c
 create mode 100644 arch/arm/include/asm/arch-tegra/usb.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/usb.h

diff --git a/arch/arm/cpu/armv7/tegra20/Makefile b/arch/arm/cpu/armv7/tegra20/Makefile
index 54ed8c4..c8a8504 100644
--- a/arch/arm/cpu/armv7/tegra20/Makefile
+++ b/arch/arm/cpu/armv7/tegra20/Makefile
@@ -27,7 +27,6 @@ include $(TOPDIR)/config.mk
 
 LIB	=  $(obj)lib$(SOC).o
 
-COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 COBJS-$(CONFIG_PWM_TEGRA) += pwm.o
 COBJS-$(CONFIG_VIDEO_TEGRA) += display.o
 
diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c
deleted file mode 100644
index 3fdd5df..0000000
--- a/arch/arm/cpu/armv7/tegra20/usb.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * 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-generic/gpio.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/usb.h>
-#include <usb/ulpi.h>
-#include <libfdt.h>
-#include <fdtdec.h>
-
-#ifdef CONFIG_USB_ULPI
-	#ifndef CONFIG_USB_ULPI_VIEWPORT
-	#error	"To use CONFIG_USB_ULPI on Tegra Boards you have to also \
-		define CONFIG_USB_ULPI_VIEWPORT"
-	#endif
-#endif
-
-enum {
-	USB_PORTS_MAX	= 3,		/* Maximum ports we allow */
-};
-
-/* Parameters we need for USB */
-enum {
-	PARAM_DIVN,                     /* PLL FEEDBACK DIVIDer */
-	PARAM_DIVM,                     /* PLL INPUT DIVIDER */
-	PARAM_DIVP,                     /* POST DIVIDER (2^N) */
-	PARAM_CPCON,                    /* BASE PLLC CHARGE Pump setup ctrl */
-	PARAM_LFCON,                    /* BASE PLLC LOOP FILter setup ctrl */
-	PARAM_ENABLE_DELAY_COUNT,       /* PLL-U Enable Delay Count */
-	PARAM_STABLE_COUNT,             /* PLL-U STABLE count */
-	PARAM_ACTIVE_DELAY_COUNT,       /* PLL-U Active delay count */
-	PARAM_XTAL_FREQ_COUNT,          /* PLL-U XTAL frequency count */
-	PARAM_DEBOUNCE_A_TIME,          /* 10MS DELAY for BIAS_DEBOUNCE_A */
-	PARAM_BIAS_TIME,                /* 20US DELAY AFter bias cell op */
-
-	PARAM_COUNT
-};
-
-/* Possible port types (dual role mode) */
-enum dr_mode {
-	DR_MODE_NONE = 0,
-	DR_MODE_HOST,		/* supports host operation */
-	DR_MODE_DEVICE,		/* supports device operation */
-	DR_MODE_OTG,		/* supports both */
-};
-
-/* Information about a USB port */
-struct fdt_usb {
-	struct usb_ctlr *reg;	/* address of registers in physical memory */
-	unsigned utmi:1;	/* 1 if port has external tranceiver, else 0 */
-	unsigned ulpi:1;	/* 1 if port has external ULPI transceiver */
-	unsigned enabled:1;	/* 1 to enable, 0 to disable */
-	unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */
-	unsigned initialized:1; /* has this port already been initialized? */
-	enum dr_mode dr_mode;	/* dual role mode */
-	enum periph_id periph_id;/* peripheral id */
-	struct fdt_gpio_state vbus_gpio;	/* GPIO for vbus enable */
-	struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */
-};
-
-static struct fdt_usb port[USB_PORTS_MAX];	/* List of valid USB ports */
-static unsigned port_count;			/* Number of available ports */
-
-/*
- * 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 unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_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;
-
-/* Put the port into host mode */
-static void set_host_mode(struct fdt_usb *config)
-{
-	/*
-	 * If we are an OTG port, check if remote host is driving VBus and
-	 * bail out in this case.
-	 */
-	if (config->dr_mode == DR_MODE_OTG &&
-		(readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS))
-		return;
-
-	/*
-	 * If not driving, we set the GPIO to enable VBUS. We assume
-	 * that the pinmux is set up correctly for this.
-	 */
-	if (fdt_gpio_isvalid(&config->vbus_gpio)) {
-		fdtdec_setup_gpio(&config->vbus_gpio);
-		gpio_direction_output(config->vbus_gpio.gpio,
-			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
-				 0 : 1);
-		debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio,
-			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
-				"low" : "high");
-	}
-}
-
-void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr)
-{
-	/* Reset the USB controller with 2us delay */
-	reset_periph(config->periph_id, 2);
-
-	/*
-	 * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under
-	 * base address
-	 */
-	if (config->has_legacy_mode)
-		setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE);
-
-	/* Put UTMIP1/3 in reset */
-	setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET);
-
-	/* Enable the UTMIP PHY */
-	if (config->utmi)
-		setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB);
-}
-
-/* set up the UTMI USB controller with the parameters provided */
-static int init_utmi_usb_controller(struct fdt_usb *config)
-{
-	u32 val;
-	int loop_count;
-	const unsigned *timing;
-	struct usb_ctlr *usbctlr = config->reg;
-
-	clock_enable(config->periph_id);
-
-	/* Reset the usb controller */
-	usbf_reset_controller(config, usbctlr);
-
-	/* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */
-	clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN);
-
-	/* 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 (fdt_gpio_isvalid(&config->vbus_gpio)) {
-		clrsetbits_le32(&usbctlr->usb1_legacy_ctrl,
-			VBUS_SENSE_CTL_MASK,
-			VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT);
-	}
-
-	/*
-	 * PLL Delay CONFIGURATION settings. The following parameters control
-	 * the bring up of the plls.
-	 */
-	timing = usb_pll[clock_get_osc_freq()];
-
-	val = readl(&usbctlr->utmip_misc_cfg1);
-	clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK,
-		timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT);
-	clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK,
-		timing[PARAM_ACTIVE_DELAY_COUNT] <<
-			UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT);
-	writel(val, &usbctlr->utmip_misc_cfg1);
-
-	/* Set PLL enable delay count and crystal frequency count */
-	val = readl(&usbctlr->utmip_pll_cfg1);
-	clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK,
-		timing[PARAM_ENABLE_DELAY_COUNT] <<
-			UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT);
-	clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK,
-		timing[PARAM_XTAL_FREQ_COUNT] <<
-			UTMIP_XTAL_FREQ_COUNT_SHIFT);
-	writel(val, &usbctlr->utmip_pll_cfg1);
-
-	/* Setting the tracking length time */
-	clrsetbits_le32(&usbctlr->utmip_bias_cfg1,
-		UTMIP_BIAS_PDTRK_COUNT_MASK,
-		timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT);
-
-	/* Program debounce time for VBUS to become valid */
-	clrsetbits_le32(&usbctlr->utmip_debounce_cfg0,
-		UTMIP_DEBOUNCE_CFG0_MASK,
-		timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT);
-
-	setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J);
-
-	/* Disable battery charge enabling bit */
-	setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG);
-
-	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE);
-	setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
-
-	/*
-	 * 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);
-	clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK,
-		utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
-	clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK,
-		utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
-	writel(val, &usbctlr->utmip_hsrx_cfg0);
-
-	/* Configure the UTMIP_HS_SYNC_START_DLY */
-	clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1,
-		UTMIP_HS_SYNC_START_DLY_MASK,
-		utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT);
-
-	/* Preceed the crystal clock disable by >100ns delay. */
-	udelay(1);
-
-	/* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */
-	setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN);
-
-	/* Finished the per-controller init. */
-
-	/* De-assert UTMIP_RESET to bring out of reset. */
-	clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET);
-
-	/* Wait for the phy clock to become valid in 100 ms */
-	for (loop_count = 100000; loop_count != 0; loop_count--) {
-		if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID)
-			break;
-		udelay(1);
-	}
-	if (!loop_count)
-		return -1;
-
-	/* Disable ICUSB FS/LS transceiver */
-	clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1);
-
-	/* Select UTMI parallel interface */
-	clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
-			PTS_UTMI << PTS_SHIFT);
-	clrbits_le32(&usbctlr->port_sc1, STS);
-
-	/* Deassert power down state */
-	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN |
-		UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN);
-	clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN |
-		UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN);
-
-	return 0;
-}
-
-#ifdef CONFIG_USB_ULPI
-/* if board file does not set a ULPI reference frequency we default to 24MHz */
-#ifndef CONFIG_ULPI_REF_CLK
-#define CONFIG_ULPI_REF_CLK 24000000
-#endif
-
-/* set up the ULPI USB controller with the parameters provided */
-static int init_ulpi_usb_controller(struct fdt_usb *config)
-{
-	u32 val;
-	int loop_count;
-	struct ulpi_viewport ulpi_vp;
-	struct usb_ctlr *usbctlr = config->reg;
-
-	/* set up ULPI reference clock on pllp_out4 */
-	clock_enable(PERIPH_ID_DEV2_OUT);
-	clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK);
-
-	/* reset ULPI phy */
-	if (fdt_gpio_isvalid(&config->phy_reset_gpio)) {
-		fdtdec_setup_gpio(&config->phy_reset_gpio);
-		gpio_direction_output(config->phy_reset_gpio.gpio, 0);
-		mdelay(5);
-		gpio_set_value(config->phy_reset_gpio.gpio, 1);
-	}
-
-	/* Reset the usb controller */
-	clock_enable(config->periph_id);
-	usbf_reset_controller(config, usbctlr);
-
-	/* enable pinmux bypass */
-	setbits_le32(&usbctlr->ulpi_timing_ctrl_0,
-			ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP);
-
-	/* Select ULPI parallel interface */
-	clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT);
-
-	/* enable ULPI transceiver */
-	setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB);
-
-	/* configure ULPI transceiver timings */
-	val = 0;
-	writel(val, &usbctlr->ulpi_timing_ctrl_1);
-
-	val |= ULPI_DATA_TRIMMER_SEL(4);
-	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
-	val |= ULPI_DIR_TRIMMER_SEL(4);
-	writel(val, &usbctlr->ulpi_timing_ctrl_1);
-	udelay(10);
-
-	val |= ULPI_DATA_TRIMMER_LOAD;
-	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
-	val |= ULPI_DIR_TRIMMER_LOAD;
-	writel(val, &usbctlr->ulpi_timing_ctrl_1);
-
-	/* set up phy for host operation with external vbus supply */
-	ulpi_vp.port_num = 0;
-	ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport;
-
-	if (ulpi_init(&ulpi_vp)) {
-		printf("Tegra ULPI viewport init failed\n");
-		return -1;
-	}
-
-	ulpi_set_vbus(&ulpi_vp, 1, 1);
-	ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0);
-
-	/* enable wakeup events */
-	setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC);
-
-	/* Enable and wait for the phy clock to become valid in 100 ms */
-	setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR);
-	for (loop_count = 100000; loop_count != 0; loop_count--) {
-		if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID)
-			break;
-		udelay(1);
-	}
-	if (!loop_count)
-		return -1;
-	clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR);
-
-	return 0;
-}
-#else
-static int init_ulpi_usb_controller(struct fdt_usb *config)
-{
-	printf("No code to set up ULPI controller, please enable"
-			"CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT");
-	return -1;
-}
-#endif
-
-static void config_clock(const u32 timing[])
-{
-	clock_start_pll(CLOCK_ID_USB,
-		timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP],
-		timing[PARAM_CPCON], timing[PARAM_LFCON]);
-}
-
-int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor)
-{
-	struct fdt_usb *config;
-	struct usb_ctlr *usbctlr;
-
-	if (portnum >= port_count)
-		return -1;
-
-	config = &port[portnum];
-
-	/* skip init, if the port is already initialized */
-	if (config->initialized)
-		goto success;
-
-	if (config->utmi && init_utmi_usb_controller(config)) {
-		printf("tegrausb: Cannot init port %d\n", portnum);
-		return -1;
-	}
-
-	if (config->ulpi && init_ulpi_usb_controller(config)) {
-		printf("tegrausb: Cannot init port %d\n", portnum);
-		return -1;
-	}
-
-	set_host_mode(config);
-
-	config->initialized = 1;
-
-success:
-	usbctlr = config->reg;
-	*hccr = (u32)&usbctlr->cap_length;
-	*hcor = (u32)&usbctlr->usb_cmd;
-	return 0;
-}
-
-int tegrausb_stop_port(int portnum)
-{
-	struct usb_ctlr *usbctlr;
-
-	usbctlr = port[portnum].reg;
-
-	/* Stop controller */
-	writel(0, &usbctlr->usb_cmd);
-	udelay(1000);
-
-	/* Initiate controller reset */
-	writel(2, &usbctlr->usb_cmd);
-	udelay(1000);
-
-	port[portnum].initialized = 0;
-
-	return 0;
-}
-
-int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)
-{
-	const char *phy, *mode;
-
-	config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg");
-	mode = fdt_getprop(blob, node, "dr_mode", NULL);
-	if (mode) {
-		if (0 == strcmp(mode, "host"))
-			config->dr_mode = DR_MODE_HOST;
-		else if (0 == strcmp(mode, "peripheral"))
-			config->dr_mode = DR_MODE_DEVICE;
-		else if (0 == strcmp(mode, "otg"))
-			config->dr_mode = DR_MODE_OTG;
-		else {
-			debug("%s: Cannot decode dr_mode '%s'\n", __func__,
-			      mode);
-			return -FDT_ERR_NOTFOUND;
-		}
-	} else {
-		config->dr_mode = DR_MODE_HOST;
-	}
-
-	phy = fdt_getprop(blob, node, "phy_type", NULL);
-	config->utmi = phy && 0 == strcmp("utmi", phy);
-	config->ulpi = phy && 0 == strcmp("ulpi", phy);
-	config->enabled = fdtdec_get_is_enabled(blob, node);
-	config->has_legacy_mode = fdtdec_get_bool(blob, node,
-						  "nvidia,has-legacy-mode");
-	config->periph_id = clock_decode_periph_id(blob, node);
-	if (config->periph_id == PERIPH_ID_NONE) {
-		debug("%s: Missing/invalid peripheral ID\n", __func__);
-		return -FDT_ERR_NOTFOUND;
-	}
-	fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio);
-	fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio",
-			&config->phy_reset_gpio);
-	debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, "
-		"vbus=%d, phy_reset=%d, dr_mode=%d\n",
-		config->enabled, config->has_legacy_mode, config->utmi,
-		config->ulpi, config->periph_id, config->vbus_gpio.gpio,
-		config->phy_reset_gpio.gpio, config->dr_mode);
-
-	return 0;
-}
-
-int board_usb_init(const void *blob)
-{
-	struct fdt_usb config;
-	enum clock_osc_freq freq;
-	int node_list[USB_PORTS_MAX];
-	int node, count, i;
-
-	/* Set up the USB clocks correctly based on our oscillator frequency */
-	freq = clock_get_osc_freq();
-	config_clock(usb_pll[freq]);
-
-	/* count may return <0 on error */
-	count = fdtdec_find_aliases_for_id(blob, "usb",
-			COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX);
-	for (i = 0; i < count; i++) {
-		if (port_count == USB_PORTS_MAX) {
-			printf("tegrausb: Cannot register more than %d ports\n",
-				USB_PORTS_MAX);
-			return -1;
-		}
-
-		debug("USB %d: ", i);
-		node = node_list[i];
-		if (!node)
-			continue;
-		if (fdt_decode_usb(blob, node, &config)) {
-			debug("Cannot decode USB node %s\n",
-			      fdt_get_name(blob, node, NULL));
-			return -1;
-		}
-		config.initialized = 0;
-
-		/* add new USB port to the list of available ports */
-		port[port_count++] = config;
-	}
-
-	return 0;
-}
diff --git a/arch/arm/include/asm/arch-tegra/usb.h b/arch/arm/include/asm/arch-tegra/usb.h
new file mode 100644
index 0000000..b18c850
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/usb.h
@@ -0,0 +1,268 @@
+/*
+ * 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[4];
+
+	/* 0x424 */
+	uint ulpi_timing_ctrl_0;
+	uint ulpi_timing_ctrl_1;
+	uint reserved13[53];
+
+	/* 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		1
+
+#define VBUS_SENSE_CTL_SHIFT			1
+#define VBUS_SENSE_CTL_MASK			(3 << VBUS_SENSE_CTL_SHIFT)
+#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
+
+/* USB2_IF_ULPI_TIMING_CTRL_0 */
+#define ULPI_OUTPUT_PINMUX_BYP			(1 << 10)
+#define ULPI_CLKOUT_PINMUX_BYP			(1 << 11)
+
+/* USB2_IF_ULPI_TIMING_CTRL_1 */
+#define ULPI_DATA_TRIMMER_LOAD			(1 << 0)
+#define ULPI_DATA_TRIMMER_SEL(x)		(((x) & 0x7) << 1)
+#define ULPI_STPDIRNXT_TRIMMER_LOAD		(1 << 16)
+#define ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
+#define ULPI_DIR_TRIMMER_LOAD			(1 << 24)
+#define ULPI_DIR_TRIMMER_SEL(x)			(((x) & 0x7) << 25)
+
+/* USBx_IF_USB_SUSP_CTRL_0 */
+#define ULPI_PHY_ENB				(1 << 13)
+#define UTMIP_PHY_ENB			        (1 << 12)
+#define UTMIP_RESET			        (1 << 11)
+#define USB_PHY_CLK_VALID			(1 << 7)
+#define USB_SUSP_CLR				(1 << 5)
+
+/* USBx_UTMIP_MISC_CFG1 */
+#define UTMIP_PLLU_STABLE_COUNT_SHIFT		6
+#define UTMIP_PLLU_STABLE_COUNT_MASK		\
+				(0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT)
+#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT	18
+#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK		\
+				(0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT)
+#define UTMIP_PHY_XTAL_CLOCKEN			(1 << 30)
+
+/* USBx_UTMIP_PLL_CFG1_0 */
+#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT	27
+#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK	\
+				(0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT)
+#define UTMIP_XTAL_FREQ_COUNT_SHIFT		0
+#define UTMIP_XTAL_FREQ_COUNT_MASK		0xfff
+
+/* USBx_UTMIP_BIAS_CFG1_0 */
+#define UTMIP_BIAS_PDTRK_COUNT_SHIFT		3
+#define UTMIP_BIAS_PDTRK_COUNT_MASK		\
+				(0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT)
+
+#define UTMIP_DEBOUNCE_CFG0_SHIFT		0
+#define UTMIP_DEBOUNCE_CFG0_MASK		0xffff
+
+/* USBx_UTMIP_TX_CFG0_0 */
+#define UTMIP_FS_PREAMBLE_J			(1 << 19)
+
+/* USBx_UTMIP_BAT_CHRG_CFG0_0 */
+#define UTMIP_PD_CHRG				1
+
+/* USBx_UTMIP_XCVR_CFG0_0 */
+#define UTMIP_XCVR_LSBIAS_SE			(1 << 21)
+
+/* USBx_UTMIP_SPARE_CFG0_0 */
+#define FUSE_SETUP_SEL				(1 << 3)
+
+/* USBx_UTMIP_HSRX_CFG0_0 */
+#define UTMIP_IDLE_WAIT_SHIFT			15
+#define UTMIP_IDLE_WAIT_MASK			(0x1f << UTMIP_IDLE_WAIT_SHIFT)
+#define UTMIP_ELASTIC_LIMIT_SHIFT		10
+#define UTMIP_ELASTIC_LIMIT_MASK		\
+				(0x1f << UTMIP_ELASTIC_LIMIT_SHIFT)
+
+/* USBx_UTMIP_HSRX_CFG0_1 */
+#define UTMIP_HS_SYNC_START_DLY_SHIFT		1
+#define UTMIP_HS_SYNC_START_DLY_MASK		\
+				(0xf << UTMIP_HS_SYNC_START_DLY_SHIFT)
+
+/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */
+#define IC_ENB1					(1 << 3)
+
+/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */
+#define PTS_SHIFT				30
+#define PTS_MASK				(3U << PTS_SHIFT)
+#define PTS_UTMI		0
+#define PTS_RESERVED	1
+#define PTS_ULPI		2
+#define PTS_ICUSB_SER	3
+
+#define STS					(1 << 29)
+#define WKOC				(1 << 22)
+#define WKDS				(1 << 21)
+#define WKCN				(1 << 20)
+
+/* USBx_UTMIP_XCVR_CFG0_0 */
+#define UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
+#define UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
+#define UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
+
+/* USBx_UTMIP_XCVR_CFG1_0 */
+#define UTMIP_FORCE_PDDISC_POWERDOWN		(1 << 0)
+#define UTMIP_FORCE_PDCHRP_POWERDOWN		(1 << 2)
+#define UTMIP_FORCE_PDDR_POWERDOWN		(1 << 4)
+
+/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */
+#define VBUS_VLD_STS			(1 << 26)
+
+
+/* Setup USB on the board */
+int board_usb_init(const void *blob);
+
+/**
+ * Start up the given port number (ports are numbered from 0 on each board).
+ * This returns values for the appropriate hccr and hcor addresses to use for
+ * USB EHCI operations.
+ *
+ * @param portnum	port number to start
+ * @param hccr		returns start address of EHCI HCCR registers
+ * @param hcor		returns start address of EHCI HCOR registers
+ * @return 0 if ok, -1 on error (generally invalid port number)
+ */
+int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor);
+
+/**
+ * Stop the current port
+ *
+ * @return 0 if ok, -1 if no port was active
+ */
+int tegrausb_stop_port(int portnum);
+
+#endif	/* _TEGRA_USB_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/tegra.h b/arch/arm/include/asm/arch-tegra20/tegra.h
index e1de044..ad5c01d 100644
--- a/arch/arm/include/asm/arch-tegra20/tegra.h
+++ b/arch/arm/include/asm/arch-tegra20/tegra.h
@@ -29,7 +29,6 @@
 #include <asm/arch-tegra/tegra.h>
 
 #define TEGRA_USB1_BASE		0xC5000000
-#define TEGRA_USB3_BASE		0xC5008000
 
 #define BCT_ODMDATA_OFFSET	4068	/* 12 bytes from end of BCT */
 
diff --git a/arch/arm/include/asm/arch-tegra20/usb.h b/arch/arm/include/asm/arch-tegra20/usb.h
deleted file mode 100644
index b18c850..0000000
--- a/arch/arm/include/asm/arch-tegra20/usb.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * 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[4];
-
-	/* 0x424 */
-	uint ulpi_timing_ctrl_0;
-	uint ulpi_timing_ctrl_1;
-	uint reserved13[53];
-
-	/* 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		1
-
-#define VBUS_SENSE_CTL_SHIFT			1
-#define VBUS_SENSE_CTL_MASK			(3 << VBUS_SENSE_CTL_SHIFT)
-#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
-
-/* USB2_IF_ULPI_TIMING_CTRL_0 */
-#define ULPI_OUTPUT_PINMUX_BYP			(1 << 10)
-#define ULPI_CLKOUT_PINMUX_BYP			(1 << 11)
-
-/* USB2_IF_ULPI_TIMING_CTRL_1 */
-#define ULPI_DATA_TRIMMER_LOAD			(1 << 0)
-#define ULPI_DATA_TRIMMER_SEL(x)		(((x) & 0x7) << 1)
-#define ULPI_STPDIRNXT_TRIMMER_LOAD		(1 << 16)
-#define ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
-#define ULPI_DIR_TRIMMER_LOAD			(1 << 24)
-#define ULPI_DIR_TRIMMER_SEL(x)			(((x) & 0x7) << 25)
-
-/* USBx_IF_USB_SUSP_CTRL_0 */
-#define ULPI_PHY_ENB				(1 << 13)
-#define UTMIP_PHY_ENB			        (1 << 12)
-#define UTMIP_RESET			        (1 << 11)
-#define USB_PHY_CLK_VALID			(1 << 7)
-#define USB_SUSP_CLR				(1 << 5)
-
-/* USBx_UTMIP_MISC_CFG1 */
-#define UTMIP_PLLU_STABLE_COUNT_SHIFT		6
-#define UTMIP_PLLU_STABLE_COUNT_MASK		\
-				(0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT)
-#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT	18
-#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK		\
-				(0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT)
-#define UTMIP_PHY_XTAL_CLOCKEN			(1 << 30)
-
-/* USBx_UTMIP_PLL_CFG1_0 */
-#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT	27
-#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK	\
-				(0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT)
-#define UTMIP_XTAL_FREQ_COUNT_SHIFT		0
-#define UTMIP_XTAL_FREQ_COUNT_MASK		0xfff
-
-/* USBx_UTMIP_BIAS_CFG1_0 */
-#define UTMIP_BIAS_PDTRK_COUNT_SHIFT		3
-#define UTMIP_BIAS_PDTRK_COUNT_MASK		\
-				(0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT)
-
-#define UTMIP_DEBOUNCE_CFG0_SHIFT		0
-#define UTMIP_DEBOUNCE_CFG0_MASK		0xffff
-
-/* USBx_UTMIP_TX_CFG0_0 */
-#define UTMIP_FS_PREAMBLE_J			(1 << 19)
-
-/* USBx_UTMIP_BAT_CHRG_CFG0_0 */
-#define UTMIP_PD_CHRG				1
-
-/* USBx_UTMIP_XCVR_CFG0_0 */
-#define UTMIP_XCVR_LSBIAS_SE			(1 << 21)
-
-/* USBx_UTMIP_SPARE_CFG0_0 */
-#define FUSE_SETUP_SEL				(1 << 3)
-
-/* USBx_UTMIP_HSRX_CFG0_0 */
-#define UTMIP_IDLE_WAIT_SHIFT			15
-#define UTMIP_IDLE_WAIT_MASK			(0x1f << UTMIP_IDLE_WAIT_SHIFT)
-#define UTMIP_ELASTIC_LIMIT_SHIFT		10
-#define UTMIP_ELASTIC_LIMIT_MASK		\
-				(0x1f << UTMIP_ELASTIC_LIMIT_SHIFT)
-
-/* USBx_UTMIP_HSRX_CFG0_1 */
-#define UTMIP_HS_SYNC_START_DLY_SHIFT		1
-#define UTMIP_HS_SYNC_START_DLY_MASK		\
-				(0xf << UTMIP_HS_SYNC_START_DLY_SHIFT)
-
-/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */
-#define IC_ENB1					(1 << 3)
-
-/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */
-#define PTS_SHIFT				30
-#define PTS_MASK				(3U << PTS_SHIFT)
-#define PTS_UTMI		0
-#define PTS_RESERVED	1
-#define PTS_ULPI		2
-#define PTS_ICUSB_SER	3
-
-#define STS					(1 << 29)
-#define WKOC				(1 << 22)
-#define WKDS				(1 << 21)
-#define WKCN				(1 << 20)
-
-/* USBx_UTMIP_XCVR_CFG0_0 */
-#define UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
-#define UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
-#define UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
-
-/* USBx_UTMIP_XCVR_CFG1_0 */
-#define UTMIP_FORCE_PDDISC_POWERDOWN		(1 << 0)
-#define UTMIP_FORCE_PDCHRP_POWERDOWN		(1 << 2)
-#define UTMIP_FORCE_PDDR_POWERDOWN		(1 << 4)
-
-/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */
-#define VBUS_VLD_STS			(1 << 26)
-
-
-/* Setup USB on the board */
-int board_usb_init(const void *blob);
-
-/**
- * Start up the given port number (ports are numbered from 0 on each board).
- * This returns values for the appropriate hccr and hcor addresses to use for
- * USB EHCI operations.
- *
- * @param portnum	port number to start
- * @param hccr		returns start address of EHCI HCCR registers
- * @param hcor		returns start address of EHCI HCOR registers
- * @return 0 if ok, -1 on error (generally invalid port number)
- */
-int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor);
-
-/**
- * Stop the current port
- *
- * @return 0 if ok, -1 if no port was active
- */
-int tegrausb_stop_port(int portnum);
-
-#endif	/* _TEGRA_USB_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/tegra.h b/arch/arm/include/asm/arch-tegra30/tegra.h
index decf564..c02c5d8 100644
--- a/arch/arm/include/asm/arch-tegra30/tegra.h
+++ b/arch/arm/include/asm/arch-tegra30/tegra.h
@@ -21,6 +21,8 @@
 
 #include <asm/arch-tegra/tegra.h>
 
+#define TEGRA_USB1_BASE		0x7D000000
+
 #define BCT_ODMDATA_OFFSET	6116	/* 12 bytes from end of BCT */
 
 #define MAX_NUM_CPU		4
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index a4af539..5c17219 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -46,7 +46,7 @@
 #include <asm/arch/emc.h>
 #endif
 #ifdef CONFIG_USB_EHCI_TEGRA
-#include <asm/arch/usb.h>
+#include <asm/arch-tegra/usb.h>
 #endif
 #include <i2c.h>
 #include <spi.h>
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a1c43f8..b77806f 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -1,5 +1,7 @@
 /*
+ * Copyright (c) 2011 The Chromium OS Authors.
  * Copyright (c) 2009-2012 NVIDIA Corporation
+ * Copyright (c) 2013 Lucas Stach
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -21,12 +23,128 @@
  */
 
 #include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/usb.h>
 #include <usb.h>
+#include <usb/ulpi.h>
+#include <libfdt.h>
+#include <fdtdec.h>
 
 #include "ehci.h"
 
-#include <asm/errno.h>
-#include <asm/arch/usb.h>
+#ifdef CONFIG_USB_ULPI
+	#ifndef CONFIG_USB_ULPI_VIEWPORT
+	#error	"To use CONFIG_USB_ULPI on Tegra Boards you have to also \
+		define CONFIG_USB_ULPI_VIEWPORT"
+	#endif
+#endif
+
+enum {
+	USB_PORTS_MAX	= 3,		/* Maximum ports we allow */
+};
+
+/* Parameters we need for USB */
+enum {
+	PARAM_DIVN,                     /* PLL FEEDBACK DIVIDer */
+	PARAM_DIVM,                     /* PLL INPUT DIVIDER */
+	PARAM_DIVP,                     /* POST DIVIDER (2^N) */
+	PARAM_CPCON,                    /* BASE PLLC CHARGE Pump setup ctrl */
+	PARAM_LFCON,                    /* BASE PLLC LOOP FILter setup ctrl */
+	PARAM_ENABLE_DELAY_COUNT,       /* PLL-U Enable Delay Count */
+	PARAM_STABLE_COUNT,             /* PLL-U STABLE count */
+	PARAM_ACTIVE_DELAY_COUNT,       /* PLL-U Active delay count */
+	PARAM_XTAL_FREQ_COUNT,          /* PLL-U XTAL frequency count */
+	PARAM_DEBOUNCE_A_TIME,          /* 10MS DELAY for BIAS_DEBOUNCE_A */
+	PARAM_BIAS_TIME,                /* 20US DELAY AFter bias cell op */
+
+	PARAM_COUNT
+};
+
+/* Possible port types (dual role mode) */
+enum dr_mode {
+	DR_MODE_NONE = 0,
+	DR_MODE_HOST,		/* supports host operation */
+	DR_MODE_DEVICE,		/* supports device operation */
+	DR_MODE_OTG,		/* supports both */
+};
+
+/* Information about a USB port */
+struct fdt_usb {
+	struct usb_ctlr *reg;	/* address of registers in physical memory */
+	unsigned utmi:1;	/* 1 if port has external tranceiver, else 0 */
+	unsigned ulpi:1;	/* 1 if port has external ULPI transceiver */
+	unsigned enabled:1;	/* 1 to enable, 0 to disable */
+	unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */
+	unsigned initialized:1; /* has this port already been initialized? */
+	enum dr_mode dr_mode;	/* dual role mode */
+	enum periph_id periph_id;/* peripheral id */
+	struct fdt_gpio_state vbus_gpio;	/* GPIO for vbus enable */
+	struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */
+};
+
+static struct fdt_usb port[USB_PORTS_MAX];	/* List of valid USB ports */
+static unsigned port_count;			/* Number of available ports */
+
+/*
+ * 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 unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_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;
 
 /*
  * A known hardware issue where Connect Status Change bit of PORTSC register
@@ -45,6 +163,419 @@ void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
 		*reg |= EHCI_PS_CSC;
 }
 
+/* Put the port into host mode */
+static void set_host_mode(struct fdt_usb *config)
+{
+	/*
+	 * If we are an OTG port, check if remote host is driving VBus and
+	 * bail out in this case.
+	 */
+	if (config->dr_mode == DR_MODE_OTG &&
+		(readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS))
+		return;
+
+	/*
+	 * If not driving, we set the GPIO to enable VBUS. We assume
+	 * that the pinmux is set up correctly for this.
+	 */
+	if (fdt_gpio_isvalid(&config->vbus_gpio)) {
+		fdtdec_setup_gpio(&config->vbus_gpio);
+		gpio_direction_output(config->vbus_gpio.gpio,
+			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
+				 0 : 1);
+		debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio,
+			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
+				"low" : "high");
+	}
+}
+
+void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr)
+{
+	/* Reset the USB controller with 2us delay */
+	reset_periph(config->periph_id, 2);
+
+	/*
+	 * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under
+	 * base address
+	 */
+	if (config->has_legacy_mode)
+		setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE);
+
+	/* Put UTMIP1/3 in reset */
+	setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET);
+
+	/* Enable the UTMIP PHY */
+	if (config->utmi)
+		setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB);
+}
+
+/* set up the UTMI USB controller with the parameters provided */
+static int init_utmi_usb_controller(struct fdt_usb *config)
+{
+	u32 val;
+	int loop_count;
+	const unsigned *timing;
+	struct usb_ctlr *usbctlr = config->reg;
+
+	clock_enable(config->periph_id);
+
+	/* Reset the usb controller */
+	usbf_reset_controller(config, usbctlr);
+
+	/* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */
+	clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN);
+
+	/* 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 (fdt_gpio_isvalid(&config->vbus_gpio)) {
+		clrsetbits_le32(&usbctlr->usb1_legacy_ctrl,
+			VBUS_SENSE_CTL_MASK,
+			VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT);
+	}
+
+	/*
+	 * PLL Delay CONFIGURATION settings. The following parameters control
+	 * the bring up of the plls.
+	 */
+	timing = usb_pll[clock_get_osc_freq()];
+
+	val = readl(&usbctlr->utmip_misc_cfg1);
+	clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK,
+		timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT);
+	clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK,
+		timing[PARAM_ACTIVE_DELAY_COUNT] <<
+			UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT);
+	writel(val, &usbctlr->utmip_misc_cfg1);
+
+	/* Set PLL enable delay count and crystal frequency count */
+	val = readl(&usbctlr->utmip_pll_cfg1);
+	clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK,
+		timing[PARAM_ENABLE_DELAY_COUNT] <<
+			UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT);
+	clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK,
+		timing[PARAM_XTAL_FREQ_COUNT] <<
+			UTMIP_XTAL_FREQ_COUNT_SHIFT);
+	writel(val, &usbctlr->utmip_pll_cfg1);
+
+	/* Setting the tracking length time */
+	clrsetbits_le32(&usbctlr->utmip_bias_cfg1,
+		UTMIP_BIAS_PDTRK_COUNT_MASK,
+		timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT);
+
+	/* Program debounce time for VBUS to become valid */
+	clrsetbits_le32(&usbctlr->utmip_debounce_cfg0,
+		UTMIP_DEBOUNCE_CFG0_MASK,
+		timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT);
+
+	setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J);
+
+	/* Disable battery charge enabling bit */
+	setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG);
+
+	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE);
+	setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
+
+	/*
+	 * 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);
+	clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK,
+		utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
+	clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK,
+		utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
+	writel(val, &usbctlr->utmip_hsrx_cfg0);
+
+	/* Configure the UTMIP_HS_SYNC_START_DLY */
+	clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1,
+		UTMIP_HS_SYNC_START_DLY_MASK,
+		utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT);
+
+	/* Preceed the crystal clock disable by >100ns delay. */
+	udelay(1);
+
+	/* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */
+	setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN);
+
+	/* Finished the per-controller init. */
+
+	/* De-assert UTMIP_RESET to bring out of reset. */
+	clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET);
+
+	/* Wait for the phy clock to become valid in 100 ms */
+	for (loop_count = 100000; loop_count != 0; loop_count--) {
+		if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID)
+			break;
+		udelay(1);
+	}
+	if (!loop_count)
+		return -1;
+
+	/* Disable ICUSB FS/LS transceiver */
+	clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1);
+
+	/* Select UTMI parallel interface */
+	clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
+			PTS_UTMI << PTS_SHIFT);
+	clrbits_le32(&usbctlr->port_sc1, STS);
+
+	/* Deassert power down state */
+	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN |
+		UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN);
+	clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN |
+		UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN);
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_ULPI
+/* if board file does not set a ULPI reference frequency we default to 24MHz */
+#ifndef CONFIG_ULPI_REF_CLK
+#define CONFIG_ULPI_REF_CLK 24000000
+#endif
+
+/* set up the ULPI USB controller with the parameters provided */
+static int init_ulpi_usb_controller(struct fdt_usb *config)
+{
+	u32 val;
+	int loop_count;
+	struct ulpi_viewport ulpi_vp;
+	struct usb_ctlr *usbctlr = config->reg;
+
+	/* set up ULPI reference clock on pllp_out4 */
+	clock_enable(PERIPH_ID_DEV2_OUT);
+	clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK);
+
+	/* reset ULPI phy */
+	if (fdt_gpio_isvalid(&config->phy_reset_gpio)) {
+		fdtdec_setup_gpio(&config->phy_reset_gpio);
+		gpio_direction_output(config->phy_reset_gpio.gpio, 0);
+		mdelay(5);
+		gpio_set_value(config->phy_reset_gpio.gpio, 1);
+	}
+
+	/* Reset the usb controller */
+	clock_enable(config->periph_id);
+	usbf_reset_controller(config, usbctlr);
+
+	/* enable pinmux bypass */
+	setbits_le32(&usbctlr->ulpi_timing_ctrl_0,
+			ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP);
+
+	/* Select ULPI parallel interface */
+	clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT);
+
+	/* enable ULPI transceiver */
+	setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB);
+
+	/* configure ULPI transceiver timings */
+	val = 0;
+	writel(val, &usbctlr->ulpi_timing_ctrl_1);
+
+	val |= ULPI_DATA_TRIMMER_SEL(4);
+	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
+	val |= ULPI_DIR_TRIMMER_SEL(4);
+	writel(val, &usbctlr->ulpi_timing_ctrl_1);
+	udelay(10);
+
+	val |= ULPI_DATA_TRIMMER_LOAD;
+	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
+	val |= ULPI_DIR_TRIMMER_LOAD;
+	writel(val, &usbctlr->ulpi_timing_ctrl_1);
+
+	/* set up phy for host operation with external vbus supply */
+	ulpi_vp.port_num = 0;
+	ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport;
+
+	if (ulpi_init(&ulpi_vp)) {
+		printf("Tegra ULPI viewport init failed\n");
+		return -1;
+	}
+
+	ulpi_set_vbus(&ulpi_vp, 1, 1);
+	ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0);
+
+	/* enable wakeup events */
+	setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC);
+
+	/* Enable and wait for the phy clock to become valid in 100 ms */
+	setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR);
+	for (loop_count = 100000; loop_count != 0; loop_count--) {
+		if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID)
+			break;
+		udelay(1);
+	}
+	if (!loop_count)
+		return -1;
+	clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR);
+
+	return 0;
+}
+#else
+static int init_ulpi_usb_controller(struct fdt_usb *config)
+{
+	printf("No code to set up ULPI controller, please enable"
+			"CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT");
+	return -1;
+}
+#endif
+
+static void config_clock(const u32 timing[])
+{
+	clock_start_pll(CLOCK_ID_USB,
+		timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP],
+		timing[PARAM_CPCON], timing[PARAM_LFCON]);
+}
+
+int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor)
+{
+	struct fdt_usb *config;
+	struct usb_ctlr *usbctlr;
+
+	if (portnum >= port_count)
+		return -1;
+
+	config = &port[portnum];
+
+	/* skip init, if the port is already initialized */
+	if (config->initialized)
+		goto success;
+
+	if (config->utmi && init_utmi_usb_controller(config)) {
+		printf("tegrausb: Cannot init port %d\n", portnum);
+		return -1;
+	}
+
+	if (config->ulpi && init_ulpi_usb_controller(config)) {
+		printf("tegrausb: Cannot init port %d\n", portnum);
+		return -1;
+	}
+
+	set_host_mode(config);
+
+	config->initialized = 1;
+
+success:
+	usbctlr = config->reg;
+	*hccr = (u32)&usbctlr->cap_length;
+	*hcor = (u32)&usbctlr->usb_cmd;
+	return 0;
+}
+
+int tegrausb_stop_port(int portnum)
+{
+	struct usb_ctlr *usbctlr;
+
+	usbctlr = port[portnum].reg;
+
+	/* Stop controller */
+	writel(0, &usbctlr->usb_cmd);
+	udelay(1000);
+
+	/* Initiate controller reset */
+	writel(2, &usbctlr->usb_cmd);
+	udelay(1000);
+
+	port[portnum].initialized = 0;
+
+	return 0;
+}
+
+int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)
+{
+	const char *phy, *mode;
+
+	config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg");
+	mode = fdt_getprop(blob, node, "dr_mode", NULL);
+	if (mode) {
+		if (0 == strcmp(mode, "host"))
+			config->dr_mode = DR_MODE_HOST;
+		else if (0 == strcmp(mode, "peripheral"))
+			config->dr_mode = DR_MODE_DEVICE;
+		else if (0 == strcmp(mode, "otg"))
+			config->dr_mode = DR_MODE_OTG;
+		else {
+			debug("%s: Cannot decode dr_mode '%s'\n", __func__,
+			      mode);
+			return -FDT_ERR_NOTFOUND;
+		}
+	} else {
+		config->dr_mode = DR_MODE_HOST;
+	}
+
+	phy = fdt_getprop(blob, node, "phy_type", NULL);
+	config->utmi = phy && 0 == strcmp("utmi", phy);
+	config->ulpi = phy && 0 == strcmp("ulpi", phy);
+	config->enabled = fdtdec_get_is_enabled(blob, node);
+	config->has_legacy_mode = fdtdec_get_bool(blob, node,
+						  "nvidia,has-legacy-mode");
+	config->periph_id = clock_decode_periph_id(blob, node);
+	if (config->periph_id == PERIPH_ID_NONE) {
+		debug("%s: Missing/invalid peripheral ID\n", __func__);
+		return -FDT_ERR_NOTFOUND;
+	}
+	fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio);
+	fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio",
+			&config->phy_reset_gpio);
+	debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, "
+		"vbus=%d, phy_reset=%d, dr_mode=%d\n",
+		config->enabled, config->has_legacy_mode, config->utmi,
+		config->ulpi, config->periph_id, config->vbus_gpio.gpio,
+		config->phy_reset_gpio.gpio, config->dr_mode);
+
+	return 0;
+}
+
+int board_usb_init(const void *blob)
+{
+	struct fdt_usb config;
+	enum clock_osc_freq freq;
+	int node_list[USB_PORTS_MAX];
+	int node, count, i;
+
+	/* Set up the USB clocks correctly based on our oscillator frequency */
+	freq = clock_get_osc_freq();
+	config_clock(usb_pll[freq]);
+
+	/* count may return <0 on error */
+	count = fdtdec_find_aliases_for_id(blob, "usb",
+			COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX);
+	for (i = 0; i < count; i++) {
+		if (port_count == USB_PORTS_MAX) {
+			printf("tegrausb: Cannot register more than %d ports\n",
+				USB_PORTS_MAX);
+			return -1;
+		}
+
+		debug("USB %d: ", i);
+		node = node_list[i];
+		if (!node)
+			continue;
+		if (fdt_decode_usb(blob, node, &config)) {
+			debug("Cannot decode USB node %s\n",
+			      fdt_get_name(blob, node, NULL));
+			return -1;
+		}
+		config.initialized = 0;
+
+		/* add new USB port to the list of available ports */
+		port[port_count++] = config;
+	}
+
+	return 0;
+}
+
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
-- 
1.8.1

  parent reply	other threads:[~2013-02-07 17:16 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-07 17:16 [U-Boot] [PATCH v3 0/7] Move Tegra EHCI drive to correct place Lucas Stach
2013-02-07 17:16 ` [U-Boot] [PATCH v3 1/7] tegra: usb: set USB_PORTS_MAX to correct value Lucas Stach
2013-02-07 17:16 ` [U-Boot] [PATCH v3 2/7] tegra: usb: make controller init functions more self contained Lucas Stach
2013-02-07 17:16 ` [U-Boot] [PATCH v3 3/7] tegra: usb: remove unneeded function parameter Lucas Stach
2013-02-07 17:16 ` [U-Boot] [PATCH v3 4/7] tegra: usb: move controller init into start_port Lucas Stach
2013-02-07 17:16 ` [U-Boot] [PATCH v3 5/7] tegra: usb: various small cleanups Lucas Stach
2013-02-07 17:16 ` Lucas Stach [this message]
2013-02-07 17:16 ` [U-Boot] [PATCH v3 7/7] tegra: usb: move [start|stop]_port into ehci_hcd_[init|stop] Lucas Stach
2013-02-12 18:32   ` Simon Glass
2013-02-11  7:04 ` [U-Boot] [PATCH v3 0/7] Move Tegra EHCI drive to correct place Marek Vasut
2013-02-14 16:27 ` Marek Vasut
2013-02-15  0:00   ` Lucas Stach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1360257390-22899-7-git-send-email-dev@lynxeye.de \
    --to=dev@lynxeye.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.