All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/1] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
@ 2012-04-18 18:17 Allen Martin
  2012-04-18 18:17 ` [U-Boot] [PATCH 1/1] " Allen Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Allen Martin @ 2012-04-18 18:17 UTC (permalink / raw)
  To: u-boot

This is part of an upcoming patch set to move all armv4t code out of
tegra2 u-boot and put it into an SPL, but I wanted to get some early
feedback on this patch.  This moves most of the tegra2 SoC code from
arch/arm/cpu/armv7 to a new directory arch/arm/cpu/tegra2-common.
This code will be shared between the armv7 and armv4t builds of
tegra2.

-Allen
nvpublic

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/1] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-18 18:17 [U-Boot] [PATCH 0/1] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common Allen Martin
@ 2012-04-18 18:17 ` Allen Martin
  2012-04-18 22:46   ` [U-Boot] [PATCH] " Allen Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Allen Martin @ 2012-04-18 18:17 UTC (permalink / raw)
  To: u-boot

In preparation for splitting out the armv4t code from tegra2, move the
tegra2 SoC code to arch/arm/cpu/tegra2-common.  This code will be
compiled armv4t for the arm7tdmi and armv7 for the cortex A9.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 Makefile                                   |    3 +
 arch/arm/cpu/armv7/tegra2/Makefile         |   12 +-
 arch/arm/cpu/armv7/tegra2/ap20.c           |  324 ---------
 arch/arm/cpu/armv7/tegra2/ap20.h           |  102 ---
 arch/arm/cpu/armv7/tegra2/board.c          |  151 ----
 arch/arm/cpu/armv7/tegra2/clock.c          | 1052 ----------------------------
 arch/arm/cpu/armv7/tegra2/funcmux.c        |  184 -----
 arch/arm/cpu/armv7/tegra2/lowlevel_init.S  |   41 --
 arch/arm/cpu/armv7/tegra2/pinmux.c         |  572 ---------------
 arch/arm/cpu/armv7/tegra2/sys_info.c       |   35 -
 arch/arm/cpu/armv7/tegra2/timer.c          |  111 ---
 arch/arm/cpu/tegra2-common/Makefile        |   56 ++
 arch/arm/cpu/tegra2-common/ap20.c          |  324 +++++++++
 arch/arm/cpu/tegra2-common/ap20.h          |  102 +++
 arch/arm/cpu/tegra2-common/board.c         |  151 ++++
 arch/arm/cpu/tegra2-common/clock.c         | 1052 ++++++++++++++++++++++++++++
 arch/arm/cpu/tegra2-common/funcmux.c       |  184 +++++
 arch/arm/cpu/tegra2-common/lowlevel_init.S |   41 ++
 arch/arm/cpu/tegra2-common/pinmux.c        |  572 +++++++++++++++
 arch/arm/cpu/tegra2-common/sys_info.c      |   35 +
 arch/arm/cpu/tegra2-common/timer.c         |  111 +++
 spl/Makefile                               |    4 +
 22 files changed, 2637 insertions(+), 2582 deletions(-)
 delete mode 100644 arch/arm/cpu/armv7/tegra2/ap20.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/ap20.h
 delete mode 100644 arch/arm/cpu/armv7/tegra2/board.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/clock.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/funcmux.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/lowlevel_init.S
 delete mode 100644 arch/arm/cpu/armv7/tegra2/pinmux.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/sys_info.c
 delete mode 100644 arch/arm/cpu/armv7/tegra2/timer.c
 create mode 100644 arch/arm/cpu/tegra2-common/Makefile
 create mode 100644 arch/arm/cpu/tegra2-common/ap20.c
 create mode 100644 arch/arm/cpu/tegra2-common/ap20.h
 create mode 100644 arch/arm/cpu/tegra2-common/board.c
 create mode 100644 arch/arm/cpu/tegra2-common/clock.c
 create mode 100644 arch/arm/cpu/tegra2-common/funcmux.c
 create mode 100644 arch/arm/cpu/tegra2-common/lowlevel_init.S
 create mode 100644 arch/arm/cpu/tegra2-common/pinmux.c
 create mode 100644 arch/arm/cpu/tegra2-common/sys_info.c
 create mode 100644 arch/arm/cpu/tegra2-common/timer.c

diff --git a/Makefile b/Makefile
index 4ddf8d6..6639de0 100644
--- a/Makefile
+++ b/Makefile
@@ -319,6 +319,9 @@ endif
 ifeq ($(SOC),exynos)
 LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
 endif
+ifeq ($(SOC),tegra2)
+LIBS += $(OBJTREE)/arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
 
 LIBS := $(addprefix $(obj),$(sort $(LIBS)))
 .PHONY : $(LIBS)
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index e9ac6c9..34452c4 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -22,23 +22,15 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 # MA 02111-1307 USA
 #
-
-# The AVP is ARMv4T architecture so we must use special compiler
-# flags for any startup files it might use.
-CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t
-CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t
-
 include $(TOPDIR)/config.mk
 
 LIB	=  $(obj)lib$(SOC).o
 
-SOBJS	:= lowlevel_init.o
-COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 
 COBJS	:= $(COBJS-y)
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
 
 all:	 $(obj).depend $(LIB)
 
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
deleted file mode 100644
index b749821..0000000
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-* (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 "ap20.h"
-#include <asm/io.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/clk_rst.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/pmc.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/scu.h>
-#include <common.h>
-
-/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
-static int ap20_cpu_is_cortexa9(void)
-{
-	u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
-	return id == (PG_UP_TAG_0_PID_CPU & 0xff);
-}
-
-void init_pllx(void)
-{
-	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
-	u32 reg;
-
-	/* If PLLX is already enabled, just return */
-	if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
-		return;
-
-	/* Set PLLX_MISC */
-	writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
-
-	/* Use 12MHz clock here */
-	reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
-	reg |= 1000 << PLL_DIVN_SHIFT;
-	writel(reg, &pll->pll_base);
-
-	reg |= PLL_ENABLE_MASK;
-	writel(reg, &pll->pll_base);
-
-	reg &= ~PLL_BYPASS_MASK;
-	writel(reg, &pll->pll_base);
-}
-
-static void enable_cpu_clock(int enable)
-{
-	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	u32 clk;
-
-	/*
-	 * NOTE:
-	 * Regardless of whether the request is to enable or disable the CPU
-	 * clock, every processor in the CPU complex except the master (CPU 0)
-	 * will have it's clock stopped because the AVP only talks to the
-	 * master. The AVP does not know (nor does it need to know) that there
-	 * are multiple processors in the CPU complex.
-	 */
-
-	if (enable) {
-		/* Initialize PLLX */
-		init_pllx();
-
-		/* Wait until all clocks are stable */
-		udelay(PLL_STABILIZATION_DELAY);
-
-		writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
-		writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
-	}
-
-	/*
-	 * Read the register containing the individual CPU clock enables and
-	 * always stop the clock to CPU 1.
-	 */
-	clk = readl(&clkrst->crc_clk_cpu_cmplx);
-	clk |= 1 << CPU1_CLK_STP_SHIFT;
-
-	/* Stop/Unstop the CPU clock */
-	clk &= ~CPU0_CLK_STP_MASK;
-	clk |= !enable << CPU0_CLK_STP_SHIFT;
-	writel(clk, &clkrst->crc_clk_cpu_cmplx);
-
-	clock_enable(PERIPH_ID_CPU);
-}
-
-static int is_cpu_powered(void)
-{
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-
-	return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
-}
-
-static void remove_cpu_io_clamps(void)
-{
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-	u32 reg;
-
-	/* Remove the clamps on the CPU I/O signals */
-	reg = readl(&pmc->pmc_remove_clamping);
-	reg |= CPU_CLMP;
-	writel(reg, &pmc->pmc_remove_clamping);
-
-	/* Give I/O signals time to stabilize */
-	udelay(IO_STABILIZATION_DELAY);
-}
-
-static void powerup_cpu(void)
-{
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-	u32 reg;
-	int timeout = IO_STABILIZATION_DELAY;
-
-	if (!is_cpu_powered()) {
-		/* Toggle the CPU power state (OFF -> ON) */
-		reg = readl(&pmc->pmc_pwrgate_toggle);
-		reg &= PARTID_CP;
-		reg |= START_CP;
-		writel(reg, &pmc->pmc_pwrgate_toggle);
-
-		/* Wait for the power to come up */
-		while (!is_cpu_powered()) {
-			if (timeout-- == 0)
-				printf("CPU failed to power up!\n");
-			else
-				udelay(10);
-		}
-
-		/*
-		 * Remove the I/O clamps from CPU power partition.
-		 * Recommended only on a Warm boot, if the CPU partition gets
-		 * power gated. Shouldn't cause any harm when called after a
-		 * cold boot according to HW, probably just redundant.
-		 */
-		remove_cpu_io_clamps();
-	}
-}
-
-static void enable_cpu_power_rail(void)
-{
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-	u32 reg;
-
-	reg = readl(&pmc->pmc_cntrl);
-	reg |= CPUPWRREQ_OE;
-	writel(reg, &pmc->pmc_cntrl);
-
-	/*
-	 * The TI PMU65861C needs a 3.75ms delay between enabling
-	 * the power rail and enabling the CPU clock.  This delay
-	 * between SM1EN and SM1 is for switching time + the ramp
-	 * up of the voltage to the CPU (VDD_CPU from PMU).
-	 */
-	udelay(3750);
-}
-
-static void reset_A9_cpu(int reset)
-{
-	/*
-	* NOTE:  Regardless of whether the request is to hold the CPU in reset
-	*        or take it out of reset, every processor in the CPU complex
-	*        except the master (CPU 0) will be held in reset because the
-	*        AVP only talks to the master. The AVP does not know that there
-	*        are multiple processors in the CPU complex.
-	*/
-
-	/* Hold CPU 1 in reset, and CPU 0 if asked */
-	reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
-	reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
-			       reset);
-
-	/* Enable/Disable master CPU reset */
-	reset_set_enable(PERIPH_ID_CPU, reset);
-}
-
-static void clock_enable_coresight(int enable)
-{
-	u32 rst, src;
-
-	clock_set_enable(PERIPH_ID_CORESIGHT, enable);
-	reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
-
-	if (enable) {
-		/*
-		 * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
-		 *  1.5, giving an effective frequency of 144MHz.
-		 * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
-		 *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
-		 */
-		src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
-		clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
-
-		/* Unlock the CPU CoreSight interfaces */
-		rst = 0xC5ACCE55;
-		writel(rst, CSITE_CPU_DBG0_LAR);
-		writel(rst, CSITE_CPU_DBG1_LAR);
-	}
-}
-
-void start_cpu(u32 reset_vector)
-{
-	/* Enable VDD_CPU */
-	enable_cpu_power_rail();
-
-	/* Hold the CPUs in reset */
-	reset_A9_cpu(1);
-
-	/* Disable the CPU clock */
-	enable_cpu_clock(0);
-
-	/* Enable CoreSight */
-	clock_enable_coresight(1);
-
-	/*
-	 * Set the entry point for CPU execution from reset,
-	 *  if it's a non-zero value.
-	 */
-	if (reset_vector)
-		writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
-
-	/* Enable the CPU clock */
-	enable_cpu_clock(1);
-
-	/* If the CPU doesn't already have power, power it up */
-	powerup_cpu();
-
-	/* Take the CPU out of reset */
-	reset_A9_cpu(0);
-}
-
-
-void halt_avp(void)
-{
-	for (;;) {
-		writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
-			| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
-			FLOW_CTLR_HALT_COP_EVENTS);
-	}
-}
-
-void enable_scu(void)
-{
-	struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
-	u32 reg;
-
-	/* If SCU already setup/enabled, return */
-	if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
-		return;
-
-	/* Invalidate all ways for all processors */
-	writel(0xFFFF, &scu->scu_inv_all);
-
-	/* Enable SCU - bit 0 */
-	reg = readl(&scu->scu_ctrl);
-	reg |= SCU_CTRL_ENABLE;
-	writel(reg, &scu->scu_ctrl);
-}
-
-void init_pmc_scratch(void)
-{
-	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-	int i;
-
-	/* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
-	for (i = 0; i < 23; i++)
-		writel(0, &pmc->pmc_scratch1+i);
-
-	/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
-	writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
-}
-
-void tegra2_start(void)
-{
-	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-
-	/* If we are the AVP, start up the first Cortex-A9 */
-	if (!ap20_cpu_is_cortexa9()) {
-		/* enable JTAG */
-		writel(0xC0, &pmt->pmt_cfg_ctl);
-
-		/*
-		 * If we are ARM7 - give it a different stack. We are about to
-		 * start up the A9 which will want to use this one.
-		 */
-		asm volatile("mov	sp, %0\n"
-			: : "r"(AVP_EARLY_BOOT_STACK_LIMIT));
-
-		start_cpu((u32)_start);
-		halt_avp();
-		/* not reached */
-	}
-
-	/* Init PMC scratch memory */
-	init_pmc_scratch();
-
-	enable_scu();
-
-	/* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
-	asm volatile(
-		"mrc	p15, 0, r0, c1, c0, 1\n"
-		"orr	r0, r0, #0x41\n"
-		"mcr	p15, 0, r0, c1, c0, 1\n");
-
-	/* FIXME: should have ap20's L2 disabled too? */
-}
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/cpu/armv7/tegra2/ap20.h
deleted file mode 100644
index a4b4d73..0000000
--- a/arch/arm/cpu/armv7/tegra2/ap20.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * (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 <asm/types.h>
-
-/* Stabilization delays, in usec */
-#define PLL_STABILIZATION_DELAY (300)
-#define IO_STABILIZATION_DELAY	(1000)
-
-#define NVBL_PLLP_KHZ	(216000)
-
-#define PLLX_ENABLED		(1 << 30)
-#define CCLK_BURST_POLICY	0x20008888
-#define SUPER_CCLK_DIVIDER	0x80000000
-
-/* Calculate clock fractional divider value from ref and target frequencies */
-#define CLK_DIVIDER(REF, FREQ)  ((((REF) * 2) / FREQ) - 2)
-
-/* Calculate clock frequency value from reference and clock divider value */
-#define CLK_FREQUENCY(REF, REG)  (((REF) * 2) / (REG + 2))
-
-/* AVP/CPU ID */
-#define PG_UP_TAG_0_PID_CPU	0x55555555	/* CPU aka "a9" aka "mpcore" */
-#define PG_UP_TAG_0             0x0
-
-#define CORESIGHT_UNLOCK	0xC5ACCE55;
-
-/* AP20-Specific Base Addresses */
-
-/* AP20 Base physical address of SDRAM. */
-#define AP20_BASE_PA_SDRAM      0x00000000
-/* AP20 Base physical address of internal SRAM. */
-#define AP20_BASE_PA_SRAM       0x40000000
-/* AP20 Size of internal SRAM (256KB). */
-#define AP20_BASE_PA_SRAM_SIZE  0x00040000
-/* AP20 Base physical address of flash. */
-#define AP20_BASE_PA_NOR_FLASH  0xD0000000
-/* AP20 Base physical address of boot information table. */
-#define AP20_BASE_PA_BOOT_INFO  AP20_BASE_PA_SRAM
-
-/*
- * Super-temporary stacks for EXTREMELY early startup. The values chosen for
- * these addresses must be valid on ALL SOCs because this value is used before
- * we are able to differentiate between the SOC types.
- *
- * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
- *       stack is placed below the AVP stack. Once the CPU stack has been moved,
- *       the AVP is free to use the IRAM the CPU stack previously occupied if
- *       it should need to do so.
- *
- * NOTE: In multi-processor CPU complex configurations, each processor will have
- *       its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
- *       limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
- *       stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
- *       CPU.
- */
-
-/* Common AVP early boot stack limit */
-#define AVP_EARLY_BOOT_STACK_LIMIT	\
-	(AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
-/* Common AVP early boot stack size */
-#define AVP_EARLY_BOOT_STACK_SIZE	0x1000
-/* Common CPU early boot stack limit */
-#define CPU_EARLY_BOOT_STACK_LIMIT	\
-	(AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
-/* Common CPU early boot stack size */
-#define CPU_EARLY_BOOT_STACK_SIZE	0x1000
-
-#define EXCEP_VECTOR_CPU_RESET_VECTOR	(NV_PA_EVP_BASE + 0x100)
-#define CSITE_CPU_DBG0_LAR		(NV_PA_CSITE_BASE + 0x10FB0)
-#define CSITE_CPU_DBG1_LAR		(NV_PA_CSITE_BASE + 0x12FB0)
-
-#define FLOW_CTLR_HALT_COP_EVENTS	(NV_PA_FLOW_BASE + 4)
-#define FLOW_MODE_STOP			2
-#define HALT_COP_EVENT_JTAG		(1 << 28)
-#define HALT_COP_EVENT_IRQ_1		(1 << 11)
-#define HALT_COP_EVENT_FIQ_1		(1 << 9)
-
-/* Start up the tegra2 SOC */
-void tegra2_start(void);
-
-/* This is the main entry into U-Boot, used by the Cortex-A9 */
-extern void _start(void);
diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c
deleted file mode 100644
index a797e6f..0000000
--- a/arch/arm/cpu/armv7/tegra2/board.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  (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 "ap20.h"
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/pmc.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-enum {
-	/* UARTs which we can enable */
-	UARTA	= 1 << 0,
-	UARTB	= 1 << 1,
-	UARTD	= 1 << 3,
-	UART_COUNT = 4,
-};
-
-/*
- * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
- * so we are using this value to identify memory size.
- */
-
-unsigned int query_sdram_size(void)
-{
-	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-	u32 reg;
-
-	reg = readl(&pmc->pmc_scratch20);
-	debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
-
-	/* bits 31:28 in OdmData are used for RAM size  */
-	switch ((reg) >> 28) {
-	case 1:
-		return 0x10000000;	/* 256 MB */
-	case 2:
-	default:
-		return 0x20000000;	/* 512 MB */
-	case 3:
-		return 0x40000000;	/* 1GB */
-	}
-}
-
-int dram_init(void)
-{
-	/* We do not initialise DRAM here. We just query the size */
-	gd->ram_size = query_sdram_size();
-	return 0;
-}
-
-#ifdef CONFIG_DISPLAY_BOARDINFO
-int checkboard(void)
-{
-	printf("Board: %s\n", sysinfo.board_string);
-	return 0;
-}
-#endif	/* CONFIG_DISPLAY_BOARDINFO */
-
-#ifdef CONFIG_ARCH_CPU_INIT
-/*
- * Note this function is executed by the ARM7TDMI AVP. It does not return
- * in this case. It is also called once the A9 starts up, but does nothing in
- * that case.
- */
-int arch_cpu_init(void)
-{
-	/* Fire up the Cortex A9 */
-	tegra2_start();
-
-	/* We didn't do this init in start.S, so do it now */
-	cpu_init_cp15();
-
-	/* Initialize essential common plls */
-	clock_early_init();
-
-	return 0;
-}
-#endif
-
-/**
- * Set up the specified uarts
- *
- * @param uarts_ids	Mask containing UARTs to init (UARTx)
- */
-static void setup_uarts(int uart_ids)
-{
-	static enum periph_id id_for_uart[] = {
-		PERIPH_ID_UART1,
-		PERIPH_ID_UART2,
-		PERIPH_ID_UART3,
-		PERIPH_ID_UART4,
-	};
-	size_t i;
-
-	for (i = 0; i < UART_COUNT; i++) {
-		if (uart_ids & (1 << i)) {
-			enum periph_id id = id_for_uart[i];
-
-			funcmux_select(id, FUNCMUX_DEFAULT);
-			clock_ll_start_uart(id);
-		}
-	}
-}
-
-void board_init_uart_f(void)
-{
-	int uart_ids = 0;	/* bit mask of which UART ids to enable */
-
-#ifdef CONFIG_TEGRA2_ENABLE_UARTA
-	uart_ids |= UARTA;
-#endif
-#ifdef CONFIG_TEGRA2_ENABLE_UARTB
-	uart_ids |= UARTB;
-#endif
-#ifdef CONFIG_TEGRA2_ENABLE_UARTD
-	uart_ids |= UARTD;
-#endif
-	setup_uarts(uart_ids);
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
-	/* Enable D-cache. I-cache is already enabled in start.S */
-	dcache_enable();
-}
-#endif
diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c
deleted file mode 100644
index 39376ab..0000000
--- a/arch/arm/cpu/armv7/tegra2/clock.c
+++ /dev/null
@@ -1,1052 +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
- */
-
-/* Tegra2 Clock control functions */
-
-#include <asm/io.h>
-#include <asm/arch/clk_rst.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/timer.h>
-#include <asm/arch/tegra2.h>
-#include <common.h>
-#include <div64.h>
-#include <fdtdec.h>
-
-/*
- * This is our record of the current clock rate of each clock. We don't
- * fill all of these in since we are only really interested in clocks which
- * we use as parents.
- */
-static unsigned pll_rate[CLOCK_ID_COUNT];
-
-/*
- * The oscillator frequency is fixed to one of four set values. Based on this
- * the other clocks are set up appropriately.
- */
-static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
-	13000000,
-	19200000,
-	12000000,
-	26000000,
-};
-
-/*
- * Clock types that we can use as a source. The Tegra2 has muxes for the
- * peripheral clocks, and in most cases there are four options for the clock
- * source. This gives us a clock 'type' and exploits what commonality exists
- * in the device.
- *
- * Letters are obvious, except for T which means CLK_M, and S which means the
- * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
- * datasheet) and PLL_M are different things. The former is the basic
- * clock supplied to the SOC from an external oscillator. The latter is the
- * memory clock PLL.
- *
- * See definitions in clock_id in the header file.
- */
-enum clock_type_id {
-	CLOCK_TYPE_AXPT,	/* PLL_A, PLL_X, PLL_P, CLK_M */
-	CLOCK_TYPE_MCPA,	/* and so on */
-	CLOCK_TYPE_MCPT,
-	CLOCK_TYPE_PCM,
-	CLOCK_TYPE_PCMT,
-	CLOCK_TYPE_PCMT16,	/* CLOCK_TYPE_PCMT with 16-bit divider */
-	CLOCK_TYPE_PCXTS,
-	CLOCK_TYPE_PDCT,
-
-	CLOCK_TYPE_COUNT,
-	CLOCK_TYPE_NONE = -1,	/* invalid clock type */
-};
-
-/* return 1 if a peripheral ID is in range */
-#define clock_type_id_isvalid(id) ((id) >= 0 && \
-		(id) < CLOCK_TYPE_COUNT)
-
-char pllp_valid = 1;	/* PLLP is set up correctly */
-
-enum {
-	CLOCK_MAX_MUX	= 4	/* number of source options for each clock */
-};
-
-/*
- * Clock source mux for each clock type. This just converts our enum into
- * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS
- * is special as it has 5 sources. Since it also has a different number of
- * bits in its register for the source, we just handle it with a special
- * case in the code.
- */
-#define CLK(x) CLOCK_ID_ ## x
-static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
-	{ CLK(AUDIO),	CLK(XCPU),	CLK(PERIPH),	CLK(OSC)	},
-	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(AUDIO)	},
-	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(OSC)	},
-	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(NONE)	},
-	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	},
-	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	},
-	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(XCPU),	CLK(OSC)	},
-	{ CLK(PERIPH),	CLK(DISPLAY),	CLK(CGENERAL),	CLK(OSC)	},
-};
-
-/*
- * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is
- * not in the header file since it is for purely internal use - we want
- * callers to use the PERIPH_ID for all access to peripheral clocks to avoid
- * confusion bewteen PERIPH_ID_... and PERIPHC_...
- *
- * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
- * confusing.
- *
- * Note to SOC vendors: perhaps define a unified numbering for peripherals and
- * use it for reset, clock enable, clock source/divider and even pinmuxing
- * if you can.
- */
-enum periphc_internal_id {
-	/* 0x00 */
-	PERIPHC_I2S1,
-	PERIPHC_I2S2,
-	PERIPHC_SPDIF_OUT,
-	PERIPHC_SPDIF_IN,
-	PERIPHC_PWM,
-	PERIPHC_SPI1,
-	PERIPHC_SPI2,
-	PERIPHC_SPI3,
-
-	/* 0x08 */
-	PERIPHC_XIO,
-	PERIPHC_I2C1,
-	PERIPHC_DVC_I2C,
-	PERIPHC_TWC,
-	PERIPHC_0c,
-	PERIPHC_10,	/* PERIPHC_SPI1, what is this really? */
-	PERIPHC_DISP1,
-	PERIPHC_DISP2,
-
-	/* 0x10 */
-	PERIPHC_CVE,
-	PERIPHC_IDE0,
-	PERIPHC_VI,
-	PERIPHC_1c,
-	PERIPHC_SDMMC1,
-	PERIPHC_SDMMC2,
-	PERIPHC_G3D,
-	PERIPHC_G2D,
-
-	/* 0x18 */
-	PERIPHC_NDFLASH,
-	PERIPHC_SDMMC4,
-	PERIPHC_VFIR,
-	PERIPHC_EPP,
-	PERIPHC_MPE,
-	PERIPHC_MIPI,
-	PERIPHC_UART1,
-	PERIPHC_UART2,
-
-	/* 0x20 */
-	PERIPHC_HOST1X,
-	PERIPHC_21,
-	PERIPHC_TVO,
-	PERIPHC_HDMI,
-	PERIPHC_24,
-	PERIPHC_TVDAC,
-	PERIPHC_I2C2,
-	PERIPHC_EMC,
-
-	/* 0x28 */
-	PERIPHC_UART3,
-	PERIPHC_29,
-	PERIPHC_VI_SENSOR,
-	PERIPHC_2b,
-	PERIPHC_2c,
-	PERIPHC_SPI4,
-	PERIPHC_I2C3,
-	PERIPHC_SDMMC3,
-
-	/* 0x30 */
-	PERIPHC_UART4,
-	PERIPHC_UART5,
-	PERIPHC_VDE,
-	PERIPHC_OWR,
-	PERIPHC_NOR,
-	PERIPHC_CSITE,
-
-	PERIPHC_COUNT,
-
-	PERIPHC_NONE = -1,
-};
-
-/* return 1 if a periphc_internal_id is in range */
-#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
-		(id) < PERIPHC_COUNT)
-
-/*
- * Clock type for each peripheral clock source. We put the name in each
- * record just so it is easy to match things up
- */
-#define TYPE(name, type) type
-static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
-	/* 0x00 */
-	TYPE(PERIPHC_I2S1,	CLOCK_TYPE_AXPT),
-	TYPE(PERIPHC_I2S2,	CLOCK_TYPE_AXPT),
-	TYPE(PERIPHC_SPDIF_OUT,	CLOCK_TYPE_AXPT),
-	TYPE(PERIPHC_SPDIF_IN,	CLOCK_TYPE_PCM),
-	TYPE(PERIPHC_PWM,	CLOCK_TYPE_PCXTS),
-	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_SPI22,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_SPI3,	CLOCK_TYPE_PCMT),
-
-	/* 0x08 */
-	TYPE(PERIPHC_XIO,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_I2C1,	CLOCK_TYPE_PCMT16),
-	TYPE(PERIPHC_DVC_I2C,	CLOCK_TYPE_PCMT16),
-	TYPE(PERIPHC_TWC,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_DISP1,	CLOCK_TYPE_PDCT),
-	TYPE(PERIPHC_DISP2,	CLOCK_TYPE_PDCT),
-
-	/* 0x10 */
-	TYPE(PERIPHC_CVE,	CLOCK_TYPE_PDCT),
-	TYPE(PERIPHC_IDE0,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_SDMMC1,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_SDMMC2,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_G3D,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_G2D,	CLOCK_TYPE_MCPA),
-
-	/* 0x18 */
-	TYPE(PERIPHC_NDFLASH,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_SDMMC4,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_VFIR,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_EPP,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_MPE,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_MIPI,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_UART1,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_UART2,	CLOCK_TYPE_PCMT),
-
-	/* 0x20 */
-	TYPE(PERIPHC_HOST1X,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_TVO,	CLOCK_TYPE_PDCT),
-	TYPE(PERIPHC_HDMI,	CLOCK_TYPE_PDCT),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_TVDAC,	CLOCK_TYPE_PDCT),
-	TYPE(PERIPHC_I2C2,	CLOCK_TYPE_PCMT16),
-	TYPE(PERIPHC_EMC,	CLOCK_TYPE_MCPT),
-
-	/* 0x28 */
-	TYPE(PERIPHC_UART3,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
-	TYPE(PERIPHC_SPI4,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_I2C3,	CLOCK_TYPE_PCMT16),
-	TYPE(PERIPHC_SDMMC3,	CLOCK_TYPE_PCMT),
-
-	/* 0x30 */
-	TYPE(PERIPHC_UART4,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_UART5,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_VDE,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_OWR,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_NOR,	CLOCK_TYPE_PCMT),
-	TYPE(PERIPHC_CSITE,	CLOCK_TYPE_PCMT),
-};
-
-/*
- * This array translates a periph_id to a periphc_internal_id
- *
- * Not present/matched up:
- *	uint vi_sensor;	 _VI_SENSOR_0,		0x1A8
- *	SPDIF - which is both 0x08 and 0x0c
- *
- */
-#define NONE(name) (-1)
-#define OFFSET(name, value) PERIPHC_ ## name
-static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
-	/* Low word: 31:0 */
-	NONE(CPU),
-	NONE(RESERVED1),
-	NONE(RESERVED2),
-	NONE(AC97),
-	NONE(RTC),
-	NONE(TMR),
-	PERIPHC_UART1,
-	PERIPHC_UART2,	/* and vfir 0x68 */
-
-	/* 0x08 */
-	NONE(GPIO),
-	PERIPHC_SDMMC2,
-	NONE(SPDIF),		/* 0x08 and 0x0c, unclear which to use */
-	PERIPHC_I2S1,
-	PERIPHC_I2C1,
-	PERIPHC_NDFLASH,
-	PERIPHC_SDMMC1,
-	PERIPHC_SDMMC4,
-
-	/* 0x10 */
-	PERIPHC_TWC,
-	PERIPHC_PWM,
-	PERIPHC_I2S2,
-	PERIPHC_EPP,
-	PERIPHC_VI,
-	PERIPHC_G2D,
-	NONE(USBD),
-	NONE(ISP),
-
-	/* 0x18 */
-	PERIPHC_G3D,
-	PERIPHC_IDE0,
-	PERIPHC_DISP2,
-	PERIPHC_DISP1,
-	PERIPHC_HOST1X,
-	NONE(VCP),
-	NONE(RESERVED30),
-	NONE(CACHE2),
-
-	/* Middle word: 63:32 */
-	NONE(MEM),
-	NONE(AHBDMA),
-	NONE(APBDMA),
-	NONE(RESERVED35),
-	NONE(KBC),
-	NONE(STAT_MON),
-	NONE(PMC),
-	NONE(FUSE),
-
-	/* 0x28 */
-	NONE(KFUSE),
-	NONE(SBC1),	/* SBC1, 0x34, is this SPI1? */
-	PERIPHC_NOR,
-	PERIPHC_SPI1,
-	PERIPHC_SPI2,
-	PERIPHC_XIO,
-	PERIPHC_SPI3,
-	PERIPHC_DVC_I2C,
-
-	/* 0x30 */
-	NONE(DSI),
-	PERIPHC_TVO,	/* also CVE 0x40 */
-	PERIPHC_MIPI,
-	PERIPHC_HDMI,
-	PERIPHC_CSITE,
-	PERIPHC_TVDAC,
-	PERIPHC_I2C2,
-	PERIPHC_UART3,
-
-	/* 0x38 */
-	NONE(RESERVED56),
-	PERIPHC_EMC,
-	NONE(USB2),
-	NONE(USB3),
-	PERIPHC_MPE,
-	PERIPHC_VDE,
-	NONE(BSEA),
-	NONE(BSEV),
-
-	/* Upper word 95:64 */
-	NONE(SPEEDO),
-	PERIPHC_UART4,
-	PERIPHC_UART5,
-	PERIPHC_I2C3,
-	PERIPHC_SPI4,
-	PERIPHC_SDMMC3,
-	NONE(PCIE),
-	PERIPHC_OWR,
-
-	/* 0x48 */
-	NONE(AFI),
-	NONE(CORESIGHT),
-	NONE(RESERVED74),
-	NONE(AVPUCQ),
-	NONE(RESERVED76),
-	NONE(RESERVED77),
-	NONE(RESERVED78),
-	NONE(RESERVED79),
-
-	/* 0x50 */
-	NONE(RESERVED80),
-	NONE(RESERVED81),
-	NONE(RESERVED82),
-	NONE(RESERVED83),
-	NONE(IRAMA),
-	NONE(IRAMB),
-	NONE(IRAMC),
-	NONE(IRAMD),
-
-	/* 0x58 */
-	NONE(CRAM2),
-};
-
-/*
- * Get the oscillator frequency, from the corresponding hardware configuration
- * field.
- */
-enum clock_osc_freq clock_get_osc_freq(void)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	u32 reg;
-
-	reg = readl(&clkrst->crc_osc_ctrl);
-	return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
-}
-
-/* Returns a pointer to the registers of the given pll */
-static struct clk_pll *get_pll(enum clock_id clkid)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-
-	assert(clock_id_isvalid(clkid));
-	return &clkrst->crc_pll[clkid];
-}
-
-unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
-		u32 divp, u32 cpcon, u32 lfcon)
-{
-	struct clk_pll *pll = get_pll(clkid);
-	u32 data;
-
-	/*
-	 * We cheat by treating all PLL (except PLLU) in the same fashion.
-	 * This works only because:
-	 * - same fields are always mapped at same offsets, except DCCON
-	 * - DCCON is always 0, doesn't conflict
-	 * - M,N, P of PLLP values are ignored for PLLP
-	 */
-	data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
-	writel(data, &pll->pll_misc);
-
-	data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
-			(0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
-
-	if (clkid == CLOCK_ID_USB)
-		data |= divp << PLLU_VCO_FREQ_SHIFT;
-	else
-		data |= divp << PLL_DIVP_SHIFT;
-	writel(data, &pll->pll_base);
-
-	/* calculate the stable time */
-	return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
-}
-
-/* return 1 if a peripheral ID is in range and valid */
-static int clock_periph_id_isvalid(enum periph_id id)
-{
-	if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
-		printf("Peripheral id %d out of range\n", id);
-	else {
-		switch (id) {
-		case PERIPH_ID_RESERVED1:
-		case PERIPH_ID_RESERVED2:
-		case PERIPH_ID_RESERVED30:
-		case PERIPH_ID_RESERVED35:
-		case PERIPH_ID_RESERVED56:
-		case PERIPH_ID_RESERVED74:
-		case PERIPH_ID_RESERVED76:
-		case PERIPH_ID_RESERVED77:
-		case PERIPH_ID_RESERVED78:
-		case PERIPH_ID_RESERVED79:
-		case PERIPH_ID_RESERVED80:
-		case PERIPH_ID_RESERVED81:
-		case PERIPH_ID_RESERVED82:
-		case PERIPH_ID_RESERVED83:
-			printf("Peripheral id %d is reserved\n", id);
-			break;
-		default:
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/* Returns a pointer to the clock source register for a peripheral */
-static u32 *get_periph_source_reg(enum periph_id periph_id)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	enum periphc_internal_id internal_id;
-
-	assert(clock_periph_id_isvalid(periph_id));
-	internal_id = periph_id_to_internal_id[periph_id];
-	assert(internal_id != -1);
-	return &clkrst->crc_clk_src[internal_id];
-}
-
-void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
-			      unsigned divisor)
-{
-	u32 *reg = get_periph_source_reg(periph_id);
-	u32 value;
-
-	value = readl(reg);
-
-	value &= ~OUT_CLK_SOURCE_MASK;
-	value |= source << OUT_CLK_SOURCE_SHIFT;
-
-	value &= ~OUT_CLK_DIVISOR_MASK;
-	value |= divisor << OUT_CLK_DIVISOR_SHIFT;
-
-	writel(value, reg);
-}
-
-void clock_ll_set_source(enum periph_id periph_id, unsigned source)
-{
-	u32 *reg = get_periph_source_reg(periph_id);
-
-	clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
-			source << OUT_CLK_SOURCE_SHIFT);
-}
-
-/**
- * Given the parent's rate and the required rate for the children, this works
- * out the peripheral clock divider to use, in 7.1 binary format.
- *
- * @param divider_bits	number of divider bits (8 or 16)
- * @param parent_rate	clock rate of parent clock in Hz
- * @param rate		required clock rate for this clock
- * @return divider which should be used
- */
-static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
-			   unsigned long rate)
-{
-	u64 divider = parent_rate * 2;
-	unsigned max_divider = 1 << divider_bits;
-
-	divider += rate - 1;
-	do_div(divider, rate);
-
-	if ((s64)divider - 2 < 0)
-		return 0;
-
-	if ((s64)divider - 2 >= max_divider)
-		return -1;
-
-	return divider - 2;
-}
-
-/**
- * Given the parent's rate and the divider in 7.1 format, this works out the
- * resulting peripheral clock rate.
- *
- * @param parent_rate	clock rate of parent clock in Hz
- * @param divider which should be used in 7.1 format
- * @return effective clock rate of peripheral
- */
-static unsigned long get_rate_from_divider(unsigned long parent_rate,
-					   int divider)
-{
-	u64 rate;
-
-	rate = (u64)parent_rate * 2;
-	do_div(rate, divider + 2);
-	return rate;
-}
-
-unsigned long clock_get_periph_rate(enum periph_id periph_id,
-		enum clock_id parent)
-{
-	u32 *reg = get_periph_source_reg(periph_id);
-
-	return get_rate_from_divider(pll_rate[parent],
-		(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
-}
-
-/**
- * Find the best available 7.1 format divisor given a parent clock rate and
- * required child clock rate. This function assumes that a second-stage
- * divisor is available which can divide by powers of 2 from 1 to 256.
- *
- * @param divider_bits	number of divider bits (8 or 16)
- * @param parent_rate	clock rate of parent clock in Hz
- * @param rate		required clock rate for this clock
- * @param extra_div	value for the second-stage divisor (not set if this
- *			function returns -1.
- * @return divider which should be used, or -1 if nothing is valid
- *
- */
-static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
-			     unsigned long rate, int *extra_div)
-{
-	int shift;
-	int best_divider = -1;
-	int best_error = rate;
-
-	/* try dividers from 1 to 256 and find closest match */
-	for (shift = 0; shift <= 8 && best_error > 0; shift++) {
-		unsigned divided_parent = parent_rate >> shift;
-		int divider = clk_get_divider(divider_bits, divided_parent,
-					      rate);
-		unsigned effective_rate = get_rate_from_divider(divided_parent,
-						       divider);
-		int error = rate - effective_rate;
-
-		/* Given a valid divider, look for the lowest error */
-		if (divider != -1 && error < best_error) {
-			best_error = error;
-			*extra_div = 1 << shift;
-			best_divider = divider;
-		}
-	}
-
-	/* return what we found - *extra_div will already be set */
-	return best_divider;
-}
-
-/**
- * Given a peripheral ID and the required source clock, this returns which
- * value should be programmed into the source mux for that peripheral.
- *
- * There is special code here to handle the one source type with 5 sources.
- *
- * @param periph_id	peripheral to start
- * @param source	PLL id of required parent clock
- * @param mux_bits	Set to number of bits in mux register: 2 or 4
- * @param divider_bits	Set to number of divider bits (8 or 16)
- * @return mux value (0-4, or -1 if not found)
- */
-static int get_periph_clock_source(enum periph_id periph_id,
-		enum clock_id parent, int *mux_bits, int *divider_bits)
-{
-	enum clock_type_id type;
-	enum periphc_internal_id internal_id;
-	int mux;
-
-	assert(clock_periph_id_isvalid(periph_id));
-
-	internal_id = periph_id_to_internal_id[periph_id];
-	assert(periphc_internal_id_isvalid(internal_id));
-
-	type = clock_periph_type[internal_id];
-	assert(clock_type_id_isvalid(type));
-
-	/*
-	 * Special cases here for the clock with a 4-bit source mux and I2C
-	 * with its 16-bit divisor
-	 */
-	if (type == CLOCK_TYPE_PCXTS)
-		*mux_bits = 4;
-	else
-		*mux_bits = 2;
-	if (type == CLOCK_TYPE_PCMT16)
-		*divider_bits = 16;
-	else
-		*divider_bits = 8;
-
-	for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
-		if (clock_source[type][mux] == parent)
-			return mux;
-
-	/*
-	 * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS
-	 * which is not in our table. If not, then they are asking for a
-	 * source which this peripheral can't access through its mux.
-	 */
-	assert(type == CLOCK_TYPE_PCXTS);
-	assert(parent == CLOCK_ID_SFROM32KHZ);
-	if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ)
-		return 4;	/* mux value for this clock */
-
-	/* if we get here, either us or the caller has made a mistake */
-	printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
-		parent);
-	return -1;
-}
-
-/**
- * Adjust peripheral PLL to use the given divider and source.
- *
- * @param periph_id	peripheral to adjust
- * @param source	Source number (0-3 or 0-7)
- * @param mux_bits	Number of mux bits (2 or 4)
- * @param divider	Required divider in 7.1 or 15.1 format
- * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
- *		for this peripheral)
- */
-static int adjust_periph_pll(enum periph_id periph_id, int source,
-			     int mux_bits, unsigned divider)
-{
-	u32 *reg = get_periph_source_reg(periph_id);
-
-	clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
-			divider << OUT_CLK_DIVISOR_SHIFT);
-	udelay(1);
-
-	/* work out the source clock and set it */
-	if (source < 0)
-		return -1;
-	if (mux_bits == 4) {
-		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
-			source << OUT_CLK_SOURCE4_SHIFT);
-	} else {
-		clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
-			source << OUT_CLK_SOURCE_SHIFT);
-	}
-	udelay(2);
-	return 0;
-}
-
-unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
-		enum clock_id parent, unsigned rate, int *extra_div)
-{
-	unsigned effective_rate;
-	int mux_bits, divider_bits, source;
-	int divider;
-
-	/* work out the source clock and set it */
-	source = get_periph_clock_source(periph_id, parent, &mux_bits,
-					 &divider_bits);
-
-	if (extra_div)
-		divider = find_best_divider(divider_bits, pll_rate[parent],
-					    rate, extra_div);
-	else
-		divider = clk_get_divider(divider_bits, pll_rate[parent],
-					  rate);
-	assert(divider >= 0);
-	if (adjust_periph_pll(periph_id, source, mux_bits, divider))
-		return -1U;
-	debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
-		get_periph_source_reg(periph_id),
-		readl(get_periph_source_reg(periph_id)));
-
-	/* Check what we ended up with. This shouldn't matter though */
-	effective_rate = clock_get_periph_rate(periph_id, parent);
-	if (extra_div)
-		effective_rate /= *extra_div;
-	if (rate != effective_rate)
-		debug("Requested clock rate %u not honored (got %u)\n",
-		       rate, effective_rate);
-	return effective_rate;
-}
-
-unsigned clock_start_periph_pll(enum periph_id periph_id,
-		enum clock_id parent, unsigned rate)
-{
-	unsigned effective_rate;
-
-	reset_set_enable(periph_id, 1);
-	clock_enable(periph_id);
-
-	effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
-						 NULL);
-
-	reset_set_enable(periph_id, 0);
-	return effective_rate;
-}
-
-void clock_set_enable(enum periph_id periph_id, int enable)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
-	u32 reg;
-
-	/* Enable/disable the clock to this peripheral */
-	assert(clock_periph_id_isvalid(periph_id));
-	reg = readl(clk);
-	if (enable)
-		reg |= PERIPH_MASK(periph_id);
-	else
-		reg &= ~PERIPH_MASK(periph_id);
-	writel(reg, clk);
-}
-
-void clock_enable(enum periph_id clkid)
-{
-	clock_set_enable(clkid, 1);
-}
-
-void clock_disable(enum periph_id clkid)
-{
-	clock_set_enable(clkid, 0);
-}
-
-void reset_set_enable(enum periph_id periph_id, int enable)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
-	u32 reg;
-
-	/* Enable/disable reset to the peripheral */
-	assert(clock_periph_id_isvalid(periph_id));
-	reg = readl(reset);
-	if (enable)
-		reg |= PERIPH_MASK(periph_id);
-	else
-		reg &= ~PERIPH_MASK(periph_id);
-	writel(reg, reset);
-}
-
-void reset_periph(enum periph_id periph_id, int us_delay)
-{
-	/* Put peripheral into reset */
-	reset_set_enable(periph_id, 1);
-	udelay(us_delay);
-
-	/* Remove reset */
-	reset_set_enable(periph_id, 0);
-
-	udelay(us_delay);
-}
-
-void reset_cmplx_set_enable(int cpu, int which, int reset)
-{
-	struct clk_rst_ctlr *clkrst =
-			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	u32 mask;
-
-	/* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */
-	assert(cpu >= 0 && cpu < 2);
-	mask = which << cpu;
-
-	/* either enable or disable those reset for that CPU */
-	if (reset)
-		writel(mask, &clkrst->crc_cpu_cmplx_set);
-	else
-		writel(mask, &clkrst->crc_cpu_cmplx_clr);
-}
-
-unsigned clock_get_rate(enum clock_id clkid)
-{
-	struct clk_pll *pll;
-	u32 base;
-	u32 divm;
-	u64 parent_rate;
-	u64 rate;
-
-	parent_rate = osc_freq[clock_get_osc_freq()];
-	if (clkid == CLOCK_ID_OSC)
-		return parent_rate;
-
-	pll = get_pll(clkid);
-	base = readl(&pll->pll_base);
-
-	/* Oh for bf_unpack()... */
-	rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
-	divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-	if (clkid == CLOCK_ID_USB)
-		divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
-	else
-		divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
-	do_div(rate, divm);
-	return rate;
-}
-
-/**
- * Set the output frequency you want for each PLL clock.
- * PLL output frequencies are programmed by setting their N, M and P values.
- * The governing equations are:
- *     VCO = (Fi / m) * n, Fo = VCO / (2^p)
- *     where Fo is the output frequency from the PLL.
- * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
- *     216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
- * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
- *
- * @param n PLL feedback divider(DIVN)
- * @param m PLL input divider(DIVN)
- * @param p post divider(DIVP)
- * @param cpcon base PLL charge pump(CPCON)
- * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
- *		be overriden), 1 if PLL is already correct
- */
-static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
-{
-	u32 base_reg;
-	u32 misc_reg;
-	struct clk_pll *pll;
-
-	pll = get_pll(clkid);
-
-	base_reg = readl(&pll->pll_base);
-
-	/* Set BYPASS, m, n and p to PLL_BASE */
-	base_reg &= ~PLL_DIVM_MASK;
-	base_reg |= m << PLL_DIVM_SHIFT;
-
-	base_reg &= ~PLL_DIVN_MASK;
-	base_reg |= n << PLL_DIVN_SHIFT;
-
-	base_reg &= ~PLL_DIVP_MASK;
-	base_reg |= p << PLL_DIVP_SHIFT;
-
-	if (clkid == CLOCK_ID_PERIPH) {
-		/*
-		 * If the PLL is already set up, check that it is correct
-		 * and record this info for clock_verify() to check.
-		 */
-		if (base_reg & PLL_BASE_OVRRIDE_MASK) {
-			base_reg |= PLL_ENABLE_MASK;
-			if (base_reg != readl(&pll->pll_base))
-				pllp_valid = 0;
-			return pllp_valid ? 1 : -1;
-		}
-		base_reg |= PLL_BASE_OVRRIDE_MASK;
-	}
-
-	base_reg |= PLL_BYPASS_MASK;
-	writel(base_reg, &pll->pll_base);
-
-	/* Set cpcon to PLL_MISC */
-	misc_reg = readl(&pll->pll_misc);
-	misc_reg &= ~PLL_CPCON_MASK;
-	misc_reg |= cpcon << PLL_CPCON_SHIFT;
-	writel(misc_reg, &pll->pll_misc);
-
-	/* Enable PLL */
-	base_reg |= PLL_ENABLE_MASK;
-	writel(base_reg, &pll->pll_base);
-
-	/* Disable BYPASS */
-	base_reg &= ~PLL_BYPASS_MASK;
-	writel(base_reg, &pll->pll_base);
-
-	return 0;
-}
-
-void clock_ll_start_uart(enum periph_id periph_id)
-{
-	/* Assert UART reset and enable clock */
-	reset_set_enable(periph_id, 1);
-	clock_enable(periph_id);
-	clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
-
-	/* wait for 2us */
-	udelay(2);
-
-	/* De-assert reset to UART */
-	reset_set_enable(periph_id, 0);
-}
-
-#ifdef CONFIG_OF_CONTROL
-/*
- * Convert a device tree clock ID to our peripheral ID. They are mostly
- * the same but we are very cautious so we check that a valid clock ID is
- * provided.
- *
- * @param clk_id	Clock ID according to tegra2 device tree binding
- * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
- */
-static enum periph_id clk_id_to_periph_id(int clk_id)
-{
-	if (clk_id > 95)
-		return PERIPH_ID_NONE;
-
-	switch (clk_id) {
-	case 1:
-	case 2:
-	case 7:
-	case 10:
-	case 20:
-	case 30:
-	case 35:
-	case 49:
-	case 56:
-	case 74:
-	case 76:
-	case 77:
-	case 78:
-	case 79:
-	case 80:
-	case 81:
-	case 82:
-	case 83:
-	case 91:
-	case 95:
-		return PERIPH_ID_NONE;
-	default:
-		return clk_id;
-	}
-}
-
-int clock_decode_periph_id(const void *blob, int node)
-{
-	enum periph_id id;
-	u32 cell[2];
-	int err;
-
-	err = fdtdec_get_int_array(blob, node, "clocks", cell,
-				   ARRAY_SIZE(cell));
-	if (err)
-		return -1;
-	id = clk_id_to_periph_id(cell[1]);
-	assert(clock_periph_id_isvalid(id));
-	return id;
-}
-#endif /* CONFIG_OF_CONTROL */
-
-int clock_verify(void)
-{
-	struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
-	u32 reg = readl(&pll->pll_base);
-
-	if (!pllp_valid) {
-		printf("Warning: PLLP %x is not correct\n", reg);
-		return -1;
-	}
-	debug("PLLX %x is correct\n", reg);
-	return 0;
-}
-
-void clock_early_init(void)
-{
-	/*
-	 * PLLP output frequency set to 216MHz
-	 * PLLC output frequency set to 600Mhz
-	 *
-	 * TODO: Can we calculate these values instead of hard-coding?
-	 */
-	switch (clock_get_osc_freq()) {
-	case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8);
-		clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
-		break;
-
-	case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8);
-		clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
-		break;
-
-	case CLOCK_OSC_FREQ_13_0:
-	case CLOCK_OSC_FREQ_19_2:
-	default:
-		/*
-		 * These are not supported. It is too early to print a
-		 * message and the UART likely won't work anyway due to the
-		 * oscillator being wrong.
-		 */
-		break;
-	}
-}
-
-void clock_init(void)
-{
-	pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
-	pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
-	pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
-	pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
-	pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
-	debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
-	debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
-	debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
-}
diff --git a/arch/arm/cpu/armv7/tegra2/funcmux.c b/arch/arm/cpu/armv7/tegra2/funcmux.c
deleted file mode 100644
index c1d2dfe..0000000
--- a/arch/arm/cpu/armv7/tegra2/funcmux.c
+++ /dev/null
@@ -1,184 +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
- */
-
-/* Tegra2 high-level function multiplexing */
-#include <common.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch/pinmux.h>
-
-int funcmux_select(enum periph_id id, int config)
-{
-	int bad_config = config != FUNCMUX_DEFAULT;
-
-	switch (id) {
-	case PERIPH_ID_UART1:
-		if (config == FUNCMUX_UART1_IRRX_IRTX) {
-			pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
-			pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
-			pinmux_tristate_disable(PINGRP_IRRX);
-			pinmux_tristate_disable(PINGRP_IRTX);
-			/*
-			 * Tegra appears to boot with function UARTA pre-
-			 * selected on mux group SDB. If two mux groups are
-			 * both set to the same function, it's unclear which
-			 * group's pins drive the RX signals into the HW.
-			 * For UARTA, SDB certainly overrides group IRTX in
-			 * practice. To solve this, configure some alternative
-			 * function on SDB to avoid the conflict. Also, tri-
-			 * state the group to avoid driving any signal onto it
-			 * until we know what's connected.
-			 */
-			pinmux_tristate_enable(PINGRP_SDB);
-			pinmux_set_func(PINGRP_SDB,  PMUX_FUNC_SDIO3);
-		}
-		break;
-
-	case PERIPH_ID_UART2:
-		if (config == FUNCMUX_UART2_IRDA) {
-			pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
-			pinmux_tristate_disable(PINGRP_UAD);
-		}
-		break;
-
-	case PERIPH_ID_UART4:
-		if (config == FUNCMUX_UART4_GMC) {
-			pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
-			pinmux_tristate_disable(PINGRP_GMC);
-		}
-		break;
-
-	case PERIPH_ID_DVC_I2C:
-		/* there is only one selection, pinmux_config is ignored */
-		if (config == FUNCMUX_DVC_I2CP) {
-			pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
-			pinmux_tristate_disable(PINGRP_I2CP);
-		}
-		break;
-
-	case PERIPH_ID_I2C1:
-		/* support pinmux_config of 0 for now, */
-		if (config == FUNCMUX_I2C1_RM) {
-			pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
-			pinmux_tristate_disable(PINGRP_RM);
-		}
-		break;
-	case PERIPH_ID_I2C2: /* I2C2 */
-		switch (config) {
-		case FUNCMUX_I2C2_DDC:	/* DDC pin group, select I2C2 */
-			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
-			/* PTA to HDMI */
-			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
-			pinmux_tristate_disable(PINGRP_DDC);
-			break;
-		case FUNCMUX_I2C2_PTA:	/* PTA pin group, select I2C2 */
-			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
-			/* set DDC_SEL to RSVDx (RSVD2 works for now) */
-			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
-			pinmux_tristate_disable(PINGRP_PTA);
-			bad_config = 0;
-			break;
-		}
-		break;
-	case PERIPH_ID_I2C3: /* I2C3 */
-		/* support pinmux_config of 0 for now */
-		if (config == FUNCMUX_I2C3_DTF) {
-			pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
-			pinmux_tristate_disable(PINGRP_DTF);
-		}
-		break;
-
-	case PERIPH_ID_SDMMC2:
-		if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
-			pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
-			pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
-
-			pinmux_tristate_disable(PINGRP_DTA);
-			pinmux_tristate_disable(PINGRP_DTD);
-		}
-		break;
-
-	case PERIPH_ID_SDMMC3:
-		switch (config) {
-		case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
-			pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
-			pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
-			pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
-			pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
-
-			pinmux_tristate_disable(PINGRP_SLXA);
-			pinmux_tristate_disable(PINGRP_SLXC);
-			pinmux_tristate_disable(PINGRP_SLXD);
-			pinmux_tristate_disable(PINGRP_SLXK);
-			/* fall through */
-
-		case FUNCMUX_SDMMC3_SDB_4BIT:
-			pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
-			pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
-			pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
-
-			pinmux_tristate_disable(PINGRP_SDB);
-			pinmux_tristate_disable(PINGRP_SDC);
-			pinmux_tristate_disable(PINGRP_SDD);
-			bad_config = 0;
-			break;
-		}
-		break;
-
-	case PERIPH_ID_SDMMC4:
-		switch (config) {
-		case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
-			pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
-			pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
-
-			pinmux_tristate_disable(PINGRP_ATC);
-			pinmux_tristate_disable(PINGRP_ATD);
-			break;
-
-		case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
-			pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
-			pinmux_tristate_disable(PINGRP_GME);
-			/* fall through */
-
-		case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
-			pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
-			pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
-
-			pinmux_tristate_disable(PINGRP_ATB);
-			pinmux_tristate_disable(PINGRP_GMA);
-			bad_config = 0;
-			break;
-		}
-		break;
-
-	default:
-		debug("%s: invalid periph_id %d", __func__, id);
-		return -1;
-	}
-
-	if (bad_config) {
-		debug("%s: invalid config %d for periph_id %d", __func__,
-		      config, id);
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
deleted file mode 100644
index 6b86647..0000000
--- a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SoC-specific setup info
- *
- * (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 <config.h>
-#include <version.h>
-
-	.align	5
-.global reset_cpu
-reset_cpu:
-	ldr	r1, rstctl			@ get addr for global reset
-						@ reg
-	ldr	r3, [r1]
-	orr	r3, r3, #0x10
-	str	r3, [r1]			@ force reset
-	mov	r0, r0
-_loop_forever:
-	b	_loop_forever
-rstctl:
-	.word	PRM_RSTCTRL
diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/armv7/tegra2/pinmux.c
deleted file mode 100644
index b053f90..0000000
--- a/arch/arm/cpu/armv7/tegra2/pinmux.c
+++ /dev/null
@@ -1,572 +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
- */
-
-/* Tegra2 pin multiplexing functions */
-
-#include <asm/io.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/pinmux.h>
-#include <common.h>
-
-
-/*
- * This defines the order of the pin mux control bits in the registers. For
- * some reason there is no correspendence between the tristate, pin mux and
- * pullup/pulldown registers.
- */
-enum pmux_ctlid {
-	/* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */
-	MUXCTL_UAA,
-	MUXCTL_UAB,
-	MUXCTL_UAC,
-	MUXCTL_UAD,
-	MUXCTL_UDA,
-	MUXCTL_RESERVED5,
-	MUXCTL_ATE,
-	MUXCTL_RM,
-
-	MUXCTL_ATB,
-	MUXCTL_RESERVED9,
-	MUXCTL_ATD,
-	MUXCTL_ATC,
-	MUXCTL_ATA,
-	MUXCTL_KBCF,
-	MUXCTL_KBCE,
-	MUXCTL_SDMMC1,
-
-	/* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */
-	MUXCTL_GMA,
-	MUXCTL_GMC,
-	MUXCTL_HDINT,
-	MUXCTL_SLXA,
-	MUXCTL_OWC,
-	MUXCTL_SLXC,
-	MUXCTL_SLXD,
-	MUXCTL_SLXK,
-
-	MUXCTL_UCA,
-	MUXCTL_UCB,
-	MUXCTL_DTA,
-	MUXCTL_DTB,
-	MUXCTL_RESERVED28,
-	MUXCTL_DTC,
-	MUXCTL_DTD,
-	MUXCTL_DTE,
-
-	/* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */
-	MUXCTL_DDC,
-	MUXCTL_CDEV1,
-	MUXCTL_CDEV2,
-	MUXCTL_CSUS,
-	MUXCTL_I2CP,
-	MUXCTL_KBCA,
-	MUXCTL_KBCB,
-	MUXCTL_KBCC,
-
-	MUXCTL_IRTX,
-	MUXCTL_IRRX,
-	MUXCTL_DAP1,
-	MUXCTL_DAP2,
-	MUXCTL_DAP3,
-	MUXCTL_DAP4,
-	MUXCTL_GMB,
-	MUXCTL_GMD,
-
-	/* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */
-	MUXCTL_GME,
-	MUXCTL_GPV,
-	MUXCTL_GPU,
-	MUXCTL_SPDO,
-	MUXCTL_SPDI,
-	MUXCTL_SDB,
-	MUXCTL_SDC,
-	MUXCTL_SDD,
-
-	MUXCTL_SPIH,
-	MUXCTL_SPIG,
-	MUXCTL_SPIF,
-	MUXCTL_SPIE,
-	MUXCTL_SPID,
-	MUXCTL_SPIC,
-	MUXCTL_SPIB,
-	MUXCTL_SPIA,
-
-	/* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */
-	MUXCTL_LPW0,
-	MUXCTL_LPW1,
-	MUXCTL_LPW2,
-	MUXCTL_LSDI,
-	MUXCTL_LSDA,
-	MUXCTL_LSPI,
-	MUXCTL_LCSN,
-	MUXCTL_LDC,
-
-	MUXCTL_LSCK,
-	MUXCTL_LSC0,
-	MUXCTL_LSC1,
-	MUXCTL_LHS,
-	MUXCTL_LVS,
-	MUXCTL_LM0,
-	MUXCTL_LM1,
-	MUXCTL_LVP0,
-
-	/* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */
-	MUXCTL_LD0,
-	MUXCTL_LD1,
-	MUXCTL_LD2,
-	MUXCTL_LD3,
-	MUXCTL_LD4,
-	MUXCTL_LD5,
-	MUXCTL_LD6,
-	MUXCTL_LD7,
-
-	MUXCTL_LD8,
-	MUXCTL_LD9,
-	MUXCTL_LD10,
-	MUXCTL_LD11,
-	MUXCTL_LD12,
-	MUXCTL_LD13,
-	MUXCTL_LD14,
-	MUXCTL_LD15,
-
-	/* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */
-	MUXCTL_LD16,
-	MUXCTL_LD17,
-	MUXCTL_LHP1,
-	MUXCTL_LHP2,
-	MUXCTL_LVP1,
-	MUXCTL_LHP0,
-	MUXCTL_RESERVED102,
-	MUXCTL_LPP,
-
-	MUXCTL_LDI,
-	MUXCTL_PMC,
-	MUXCTL_CRTP,
-	MUXCTL_PTA,
-	MUXCTL_RESERVED108,
-	MUXCTL_KBCD,
-	MUXCTL_GPU7,
-	MUXCTL_DTF,
-
-	MUXCTL_NONE = -1,
-};
-
-/*
- * And this defines the order of the pullup/pulldown controls which are again
- * in a different order
- */
-enum pmux_pullid {
-	/* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */
-	PUCTL_ATA,
-	PUCTL_ATB,
-	PUCTL_ATC,
-	PUCTL_ATD,
-	PUCTL_ATE,
-	PUCTL_DAP1,
-	PUCTL_DAP2,
-	PUCTL_DAP3,
-
-	PUCTL_DAP4,
-	PUCTL_DTA,
-	PUCTL_DTB,
-	PUCTL_DTC,
-	PUCTL_DTD,
-	PUCTL_DTE,
-	PUCTL_DTF,
-	PUCTL_GPV,
-
-	/* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */
-	PUCTL_RM,
-	PUCTL_I2CP,
-	PUCTL_PTA,
-	PUCTL_GPU7,
-	PUCTL_KBCA,
-	PUCTL_KBCB,
-	PUCTL_KBCC,
-	PUCTL_KBCD,
-
-	PUCTL_SPDI,
-	PUCTL_SPDO,
-	PUCTL_GPSLXAU,
-	PUCTL_CRTP,
-	PUCTL_SLXC,
-	PUCTL_SLXD,
-	PUCTL_SLXK,
-
-	/* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */
-	PUCTL_CDEV1,
-	PUCTL_CDEV2,
-	PUCTL_SPIA,
-	PUCTL_SPIB,
-	PUCTL_SPIC,
-	PUCTL_SPID,
-	PUCTL_SPIE,
-	PUCTL_SPIF,
-
-	PUCTL_SPIG,
-	PUCTL_SPIH,
-	PUCTL_IRTX,
-	PUCTL_IRRX,
-	PUCTL_GME,
-	PUCTL_RESERVED45,
-	PUCTL_XM2D,
-	PUCTL_XM2C,
-
-	/* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */
-	PUCTL_UAA,
-	PUCTL_UAB,
-	PUCTL_UAC,
-	PUCTL_UAD,
-	PUCTL_UCA,
-	PUCTL_UCB,
-	PUCTL_LD17,
-	PUCTL_LD19_18,
-
-	PUCTL_LD21_20,
-	PUCTL_LD23_22,
-	PUCTL_LS,
-	PUCTL_LC,
-	PUCTL_CSUS,
-	PUCTL_DDRC,
-	PUCTL_SDC,
-	PUCTL_SDD,
-
-	/* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */
-	PUCTL_KBCF,
-	PUCTL_KBCE,
-	PUCTL_PMCA,
-	PUCTL_PMCB,
-	PUCTL_PMCC,
-	PUCTL_PMCD,
-	PUCTL_PMCE,
-	PUCTL_CK32,
-
-	PUCTL_UDA,
-	PUCTL_SDMMC1,
-	PUCTL_GMA,
-	PUCTL_GMB,
-	PUCTL_GMC,
-	PUCTL_GMD,
-	PUCTL_DDC,
-	PUCTL_OWC,
-
-	PUCTL_NONE = -1
-};
-
-struct tegra_pingroup_desc {
-	const char *name;
-	enum pmux_func funcs[4];
-	enum pmux_func func_safe;
-	enum pmux_vddio vddio;
-	enum pmux_ctlid ctl_id;
-	enum pmux_pullid pull_id;
-};
-
-
-/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */
-#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5)
-
-/* Mask value for a tristate (within TRISTATE_REG(id)) */
-#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f))
-
-/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */
-#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4)
-
-/* Converts a PUCTL id to a shift position */
-#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f)
-
-/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */
-#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4)
-
-/* Converts a MUXCTL id to a shift position */
-#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f)
-
-/* Convenient macro for defining pin group properties */
-#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd)		\
-	{						\
-		.vddio = PMUX_VDDIO_ ## vdd,		\
-		.funcs = {				\
-			PMUX_FUNC_ ## f0,			\
-			PMUX_FUNC_ ## f1,			\
-			PMUX_FUNC_ ## f2,			\
-			PMUX_FUNC_ ## f3,			\
-		},					\
-		.func_safe = PMUX_FUNC_ ## f_safe,		\
-		.ctl_id = mux,				\
-		.pull_id = pupd				\
-	}
-
-/* A normal pin group where the mux name and pull-up name match */
-#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe)		\
-		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\
-			MUXCTL_ ## pg_name, PUCTL_ ## pg_name)
-
-/* A pin group where the pull-up name doesn't have a 1-1 mapping */
-#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd)		\
-		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\
-			MUXCTL_ ## pg_name, PUCTL_ ## pupd)
-
-/* A pin group number which is not used */
-#define PIN_RESERVED \
-	PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE)
-
-const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
-	PIN(ATA,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE),
-	PIN(ATB,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
-	PIN(ATC,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
-	PIN(ATD,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
-	PIN(CDEV1, AUDIO, OSC,   PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC),
-	PIN(CDEV2, AUDIO, OSC,   AHB_CLK, APB_CLK, PLLP_OUT4,    OSC),
-	PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK,
-		PLLC_OUT1),
-	PIN(DAP1, AUDIO, DAP1,   RSVD,   GMI,       SDIO2,       DAP1),
-
-	PIN(DAP2, AUDIO, DAP2,   TWC,    RSVD,      GMI,         DAP2),
-	PIN(DAP3, BB,    DAP3,   RSVD,   RSVD,      RSVD,        DAP3),
-	PIN(DAP4, UART,  DAP4,   RSVD,   GMI,       RSVD,        DAP4),
-	PIN(DTA,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD4),
-	PIN(DTB,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1),
-	PIN(DTC,  VI,    RSVD,   RSVD,   VI,        RSVD,        RSVD1),
-	PIN(DTD,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD1),
-	PIN(DTE,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1),
-
-	PINP(GPU, UART,  PWM,    UARTA,  GMI,       RSVD,        RSVD4,
-		GPSLXAU),
-	PIN(GPV,  SD,    PCIE,   RSVD,   RSVD,      RSVD,        PCIE),
-	PIN(I2CP, SYS,   I2C,    RSVD,   RSVD,      RSVD,        RSVD4),
-	PIN(IRTX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB),
-	PIN(IRRX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB),
-	PIN(KBCB, SYS,   KBC,    NAND,   SDIO2,     MIO,         KBC),
-	PIN(KBCA, SYS,   KBC,    NAND,   SDIO2,     EMC_TEST0_DLL, KBC),
-	PINP(PMC, SYS,   PWR_ON, PWR_INTR, RSVD,    RSVD,        PWR_ON, NONE),
-
-	PIN(PTA,  NAND,  I2C2,   HDMI,   GMI,       RSVD,        RSVD4),
-	PIN(RM,   UART,  I2C,    RSVD,   RSVD,      RSVD,        RSVD4),
-	PIN(KBCE, SYS,   KBC,    NAND,   OWR,       RSVD,        KBC),
-	PIN(KBCF, SYS,   KBC,    NAND,   TRACE,     MIO,         KBC),
-	PIN(GMA,  NAND,  UARTE,  SPI3,   GMI,       SDIO4,       SPI3),
-	PIN(GMC,  NAND,  UARTD,  SPI4,   GMI,       SFLASH,      SPI4),
-	PIN(SDMMC1, BB,  SDIO1,  RSVD,   UARTE,     UARTA,       RSVD2),
-	PIN(OWC,  SYS,   OWR,    RSVD,   RSVD,      RSVD,        OWR),
-
-	PIN(GME,  NAND,  RSVD,   DAP5,   GMI,       SDIO4,       GMI),
-	PIN(SDC,  SD,    PWM,    TWC,    SDIO3,     SPI3,        TWC),
-	PIN(SDD,  SD,    UARTA,  PWM,    SDIO3,     SPI3,        PWM),
-	PIN_RESERVED,
-	PINP(SLXA, SD,   PCIE,   SPI4,   SDIO3,     SPI2,        PCIE, CRTP),
-	PIN(SLXC, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4),
-	PIN(SLXD, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4),
-	PIN(SLXK, SD,    PCIE,   SPI4,   SDIO3,     SPI2,        PCIE),
-
-	PIN(SPDI, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2),
-	PIN(SPDO, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2),
-	PIN(SPIA, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
-	PIN(SPIB, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
-	PIN(SPIC, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
-	PIN(SPID, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI),
-	PIN(SPIE, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI),
-	PIN(SPIF, AUDIO, SPI3,   SPI1,   SPI2,      RSVD,        RSVD4),
-
-	PIN(SPIG, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT),
-	PIN(SPIH, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT),
-	PIN(UAA,  BB,    SPI3,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
-	PIN(UAB,  BB,    SPI2,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
-	PIN(UAC,  BB,    OWR,    RSVD,   RSVD,      RSVD,        RSVD4),
-	PIN(UAD,  UART,  IRDA,   SPDIF,  UARTA,     SPI4,        SPDIF),
-	PIN(UCA,  UART,  UARTC,  RSVD,   GMI,       RSVD,        RSVD4),
-	PIN(UCB,  UART,  UARTC,  PWM,    GMI,       RSVD,        RSVD4),
-
-	PIN_RESERVED,
-	PIN(ATE,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE),
-	PIN(KBCC, SYS,   KBC,    NAND,   TRACE,     EMC_TEST1_DLL, KBC),
-	PIN_RESERVED,
-	PIN_RESERVED,
-	PIN(GMB,  NAND,  IDE,    NAND,   GMI,       GMI_INT,     GMI),
-	PIN(GMD,  NAND,  RSVD,   NAND,   GMI,       SFLASH,      GMI),
-	PIN(DDC,  LCD,   I2C2,   RSVD,   RSVD,      RSVD,        RSVD4),
-
-	/* 64 */
-	PINP(LD0,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD1,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD2,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD3,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD4,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD5,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD6,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD7,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-
-	PINP(LD8,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD9,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD10, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD11, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD12, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD13, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD14, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD15, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-
-	PINP(LD16, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
-	PINP(LD17, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD17),
-	PINP(LHP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20),
-	PINP(LHP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18),
-	PINP(LHP2, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18),
-	PINP(LVP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LC),
-	PINP(LVP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20),
-	PINP(HDINT, LCD, HDMI,   RSVD,   RSVD,      RSVD,     HDMI , LC),
-
-	PINP(LM0,  LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LC),
-	PINP(LM1,  LCD,  DISPA,  DISPB,  RSVD,      CRT,      RSVD3, LC),
-	PINP(LVS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
-	PINP(LSC0, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
-	PINP(LSC1, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
-	PINP(LSCK, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
-	PINP(LDC,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS),
-	PINP(LCSN, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LS),
-
-	/* 96 */
-	PINP(LSPI, LCD,  DISPA,  DISPB,  XIO,       HDMI,     DISPA, LC),
-	PINP(LSDA, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
-	PINP(LSDI, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     DISPA, LS),
-	PINP(LPW0, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
-	PINP(LPW1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS),
-	PINP(LPW2, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
-	PINP(LDI,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22),
-	PINP(LHS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
-
-	PINP(LPP,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22),
-	PIN_RESERVED,
-	PIN(KBCD,  SYS,  KBC,    NAND,   SDIO2,     MIO,      KBC),
-	PIN(GPU7,  SYS,  RTCK,   RSVD,   RSVD,      RSVD,     RTCK),
-	PIN(DTF,   VI,   I2C3,   RSVD,   VI,        RSVD,     RSVD4),
-	PIN(UDA,   BB,   SPI1,   RSVD,   UARTD,     ULPI,     RSVD2),
-	PIN(CRTP,  LCD,  CRT,    RSVD,   RSVD,      RSVD,     RSVD),
-	PINP(SDB,  SD,   UARTA,  PWM,    SDIO3,     SPI2,     PWM,   NONE),
-
-	/* these pin groups only have pullup and pull down control */
-	PINALL(CK32,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(DDRC,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(PMCA,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(PMCB,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(PMCC,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(PMCD,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(PMCE,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(XM2C,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-	PINALL(XM2D,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
-		PUCTL_NONE),
-};
-
-void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
-{
-	struct pmux_tri_ctlr *pmt =
-			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-	u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)];
-	u32 reg;
-
-	reg = readl(tri);
-	if (enable)
-		reg |= TRISTATE_MASK(pin);
-	else
-		reg &= ~TRISTATE_MASK(pin);
-	writel(reg, tri);
-}
-
-void pinmux_tristate_enable(enum pmux_pingrp pin)
-{
-	pinmux_set_tristate(pin, 1);
-}
-
-void pinmux_tristate_disable(enum pmux_pingrp pin)
-{
-	pinmux_set_tristate(pin, 0);
-}
-
-void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
-{
-	struct pmux_tri_ctlr *pmt =
-			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-	enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id;
-	u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)];
-	u32 mask_bit;
-	u32 reg;
-	mask_bit = PULL_SHIFT(pull_id);
-
-	reg = readl(pull);
-	reg &= ~(0x3 << mask_bit);
-	reg |= pupd << mask_bit;
-	writel(reg, pull);
-}
-
-void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
-{
-	struct pmux_tri_ctlr *pmt =
-			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-	enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
-	u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
-	u32 mask_bit;
-	int i, mux = -1;
-	u32 reg;
-
-	assert(pmux_func_isvalid(func));
-
-	/* Handle special values */
-	if (func >= PMUX_FUNC_RSVD1) {
-		mux = (func - PMUX_FUNC_RSVD1) & 0x3;
-	} else {
-		/* Search for the appropriate function */
-		for (i = 0; i < 4; i++) {
-			if (tegra_soc_pingroups[pin].funcs[i] == func) {
-				mux = i;
-				break;
-			}
-		}
-	}
-	assert(mux != -1);
-
-	mask_bit = MUXCTL_SHIFT(mux_id);
-	reg = readl(muxctl);
-	reg &= ~(0x3 << mask_bit);
-	reg |= mux << mask_bit;
-	writel(reg, muxctl);
-}
-
-void pinmux_config_pingroup(struct pingroup_config *config)
-{
-	enum pmux_pingrp pin = config->pingroup;
-
-	pinmux_set_func(pin, config->func);
-	pinmux_set_pullupdown(pin, config->pull);
-	pinmux_set_tristate(pin, config->tristate);
-}
-
-void pinmux_config_table(struct pingroup_config *config, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		pinmux_config_pingroup(&config[i]);
-}
diff --git a/arch/arm/cpu/armv7/tegra2/sys_info.c b/arch/arm/cpu/armv7/tegra2/sys_info.c
deleted file mode 100644
index 6d11dc1..0000000
--- a/arch/arm/cpu/armv7/tegra2/sys_info.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * (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>
-
-#ifdef CONFIG_DISPLAY_CPUINFO
-/* Print CPU information */
-int print_cpuinfo(void)
-{
-	puts("TEGRA2\n");
-
-	/* TBD: Add printf of major/minor rev info, stepping, etc. */
-	return 0;
-}
-#endif	/* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c
deleted file mode 100644
index b12b12c..0000000
--- a/arch/arm/cpu/armv7/tegra2/timer.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * (C) Copyright 2008
- * Texas Instruments
- *
- * Richard Woodruff <r-woodruff2@ti.com>
- * Syed Moahmmed Khasim <khasim@ti.com>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- * Alex Zuepke <azu@sysgo.de>
- *
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
- *
- * 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/tegra2.h>
-#include <asm/arch/timer.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* counter runs at 1MHz */
-#define TIMER_CLK	1000000
-#define TIMER_LOAD_VAL	0xffffffff
-
-/* timer without interrupts */
-ulong get_timer(ulong base)
-{
-	return get_timer_masked() - base;
-}
-
-/* delay x useconds */
-void __udelay(unsigned long usec)
-{
-	long tmo = usec * (TIMER_CLK / 1000) / 1000;
-	unsigned long now, last = timer_get_us();
-
-	while (tmo > 0) {
-		now = timer_get_us();
-		if (last > now) /* count up timer overflow */
-			tmo -= TIMER_LOAD_VAL - last + now;
-		else
-			tmo -= now - last;
-		last = now;
-	}
-}
-
-ulong get_timer_masked(void)
-{
-	ulong now;
-
-	/* current tick value */
-	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
-
-	if (now >= gd->lastinc)	/* normal mode (non roll) */
-		/* move stamp forward with absolute diff ticks */
-		gd->tbl += (now - gd->lastinc);
-	else	/* we have rollover of incrementer */
-		gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
-				- gd->lastinc) + now;
-	gd->lastinc = now;
-	return gd->tbl;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
-{
-	return get_timer(0);
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
-	return CONFIG_SYS_HZ;
-}
-
-unsigned long timer_get_us(void)
-{
-	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
-
-	return readl(&timer_base->cntr_1us);
-}
diff --git a/arch/arm/cpu/tegra2-common/Makefile b/arch/arm/cpu/tegra2-common/Makefile
new file mode 100644
index 0000000..8de59cf
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/Makefile
@@ -0,0 +1,56 @@
+#
+# (C) Copyright 2010,2011 Nvidia Corporation.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# 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
+
+# The AVP is ARMv4T architecture so we must use special compiler
+# flags for any startup files it might use.
+CFLAGS_arch/arm/cpu/tegra2-common/ap20.o += -march=armv4t
+CFLAGS_arch/arm/cpu/tegra2-common/clock.o += -march=armv4t
+
+LIB	= $(obj)lib$(SOC)-common.o
+
+SOBJS += lowlevel_init.o
+COBJS-y	+= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+$(obj).depend:
+	echo wtf
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/tegra2-common/ap20.c b/arch/arm/cpu/tegra2-common/ap20.c
new file mode 100644
index 0000000..b749821
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/ap20.c
@@ -0,0 +1,324 @@
+/*
+* (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 "ap20.h"
+#include <asm/io.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/scu.h>
+#include <common.h>
+
+/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
+static int ap20_cpu_is_cortexa9(void)
+{
+	u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
+	return id == (PG_UP_TAG_0_PID_CPU & 0xff);
+}
+
+void init_pllx(void)
+{
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
+	u32 reg;
+
+	/* If PLLX is already enabled, just return */
+	if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
+		return;
+
+	/* Set PLLX_MISC */
+	writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
+
+	/* Use 12MHz clock here */
+	reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
+	reg |= 1000 << PLL_DIVN_SHIFT;
+	writel(reg, &pll->pll_base);
+
+	reg |= PLL_ENABLE_MASK;
+	writel(reg, &pll->pll_base);
+
+	reg &= ~PLL_BYPASS_MASK;
+	writel(reg, &pll->pll_base);
+}
+
+static void enable_cpu_clock(int enable)
+{
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 clk;
+
+	/*
+	 * NOTE:
+	 * Regardless of whether the request is to enable or disable the CPU
+	 * clock, every processor in the CPU complex except the master (CPU 0)
+	 * will have it's clock stopped because the AVP only talks to the
+	 * master. The AVP does not know (nor does it need to know) that there
+	 * are multiple processors in the CPU complex.
+	 */
+
+	if (enable) {
+		/* Initialize PLLX */
+		init_pllx();
+
+		/* Wait until all clocks are stable */
+		udelay(PLL_STABILIZATION_DELAY);
+
+		writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+		writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
+	}
+
+	/*
+	 * Read the register containing the individual CPU clock enables and
+	 * always stop the clock to CPU 1.
+	 */
+	clk = readl(&clkrst->crc_clk_cpu_cmplx);
+	clk |= 1 << CPU1_CLK_STP_SHIFT;
+
+	/* Stop/Unstop the CPU clock */
+	clk &= ~CPU0_CLK_STP_MASK;
+	clk |= !enable << CPU0_CLK_STP_SHIFT;
+	writel(clk, &clkrst->crc_clk_cpu_cmplx);
+
+	clock_enable(PERIPH_ID_CPU);
+}
+
+static int is_cpu_powered(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+
+	return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+}
+
+static void remove_cpu_io_clamps(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	u32 reg;
+
+	/* Remove the clamps on the CPU I/O signals */
+	reg = readl(&pmc->pmc_remove_clamping);
+	reg |= CPU_CLMP;
+	writel(reg, &pmc->pmc_remove_clamping);
+
+	/* Give I/O signals time to stabilize */
+	udelay(IO_STABILIZATION_DELAY);
+}
+
+static void powerup_cpu(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	u32 reg;
+	int timeout = IO_STABILIZATION_DELAY;
+
+	if (!is_cpu_powered()) {
+		/* Toggle the CPU power state (OFF -> ON) */
+		reg = readl(&pmc->pmc_pwrgate_toggle);
+		reg &= PARTID_CP;
+		reg |= START_CP;
+		writel(reg, &pmc->pmc_pwrgate_toggle);
+
+		/* Wait for the power to come up */
+		while (!is_cpu_powered()) {
+			if (timeout-- == 0)
+				printf("CPU failed to power up!\n");
+			else
+				udelay(10);
+		}
+
+		/*
+		 * Remove the I/O clamps from CPU power partition.
+		 * Recommended only on a Warm boot, if the CPU partition gets
+		 * power gated. Shouldn't cause any harm when called after a
+		 * cold boot according to HW, probably just redundant.
+		 */
+		remove_cpu_io_clamps();
+	}
+}
+
+static void enable_cpu_power_rail(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	u32 reg;
+
+	reg = readl(&pmc->pmc_cntrl);
+	reg |= CPUPWRREQ_OE;
+	writel(reg, &pmc->pmc_cntrl);
+
+	/*
+	 * The TI PMU65861C needs a 3.75ms delay between enabling
+	 * the power rail and enabling the CPU clock.  This delay
+	 * between SM1EN and SM1 is for switching time + the ramp
+	 * up of the voltage to the CPU (VDD_CPU from PMU).
+	 */
+	udelay(3750);
+}
+
+static void reset_A9_cpu(int reset)
+{
+	/*
+	* NOTE:  Regardless of whether the request is to hold the CPU in reset
+	*        or take it out of reset, every processor in the CPU complex
+	*        except the master (CPU 0) will be held in reset because the
+	*        AVP only talks to the master. The AVP does not know that there
+	*        are multiple processors in the CPU complex.
+	*/
+
+	/* Hold CPU 1 in reset, and CPU 0 if asked */
+	reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
+	reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
+			       reset);
+
+	/* Enable/Disable master CPU reset */
+	reset_set_enable(PERIPH_ID_CPU, reset);
+}
+
+static void clock_enable_coresight(int enable)
+{
+	u32 rst, src;
+
+	clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+	reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
+
+	if (enable) {
+		/*
+		 * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
+		 *  1.5, giving an effective frequency of 144MHz.
+		 * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
+		 *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
+		 */
+		src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
+		clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
+
+		/* Unlock the CPU CoreSight interfaces */
+		rst = 0xC5ACCE55;
+		writel(rst, CSITE_CPU_DBG0_LAR);
+		writel(rst, CSITE_CPU_DBG1_LAR);
+	}
+}
+
+void start_cpu(u32 reset_vector)
+{
+	/* Enable VDD_CPU */
+	enable_cpu_power_rail();
+
+	/* Hold the CPUs in reset */
+	reset_A9_cpu(1);
+
+	/* Disable the CPU clock */
+	enable_cpu_clock(0);
+
+	/* Enable CoreSight */
+	clock_enable_coresight(1);
+
+	/*
+	 * Set the entry point for CPU execution from reset,
+	 *  if it's a non-zero value.
+	 */
+	if (reset_vector)
+		writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+	/* Enable the CPU clock */
+	enable_cpu_clock(1);
+
+	/* If the CPU doesn't already have power, power it up */
+	powerup_cpu();
+
+	/* Take the CPU out of reset */
+	reset_A9_cpu(0);
+}
+
+
+void halt_avp(void)
+{
+	for (;;) {
+		writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
+			| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
+			FLOW_CTLR_HALT_COP_EVENTS);
+	}
+}
+
+void enable_scu(void)
+{
+	struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
+	u32 reg;
+
+	/* If SCU already setup/enabled, return */
+	if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
+		return;
+
+	/* Invalidate all ways for all processors */
+	writel(0xFFFF, &scu->scu_inv_all);
+
+	/* Enable SCU - bit 0 */
+	reg = readl(&scu->scu_ctrl);
+	reg |= SCU_CTRL_ENABLE;
+	writel(reg, &scu->scu_ctrl);
+}
+
+void init_pmc_scratch(void)
+{
+	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	int i;
+
+	/* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
+	for (i = 0; i < 23; i++)
+		writel(0, &pmc->pmc_scratch1+i);
+
+	/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
+	writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+}
+
+void tegra2_start(void)
+{
+	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+
+	/* If we are the AVP, start up the first Cortex-A9 */
+	if (!ap20_cpu_is_cortexa9()) {
+		/* enable JTAG */
+		writel(0xC0, &pmt->pmt_cfg_ctl);
+
+		/*
+		 * If we are ARM7 - give it a different stack. We are about to
+		 * start up the A9 which will want to use this one.
+		 */
+		asm volatile("mov	sp, %0\n"
+			: : "r"(AVP_EARLY_BOOT_STACK_LIMIT));
+
+		start_cpu((u32)_start);
+		halt_avp();
+		/* not reached */
+	}
+
+	/* Init PMC scratch memory */
+	init_pmc_scratch();
+
+	enable_scu();
+
+	/* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
+	asm volatile(
+		"mrc	p15, 0, r0, c1, c0, 1\n"
+		"orr	r0, r0, #0x41\n"
+		"mcr	p15, 0, r0, c1, c0, 1\n");
+
+	/* FIXME: should have ap20's L2 disabled too? */
+}
diff --git a/arch/arm/cpu/tegra2-common/ap20.h b/arch/arm/cpu/tegra2-common/ap20.h
new file mode 100644
index 0000000..a4b4d73
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/ap20.h
@@ -0,0 +1,102 @@
+/*
+ * (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 <asm/types.h>
+
+/* Stabilization delays, in usec */
+#define PLL_STABILIZATION_DELAY (300)
+#define IO_STABILIZATION_DELAY	(1000)
+
+#define NVBL_PLLP_KHZ	(216000)
+
+#define PLLX_ENABLED		(1 << 30)
+#define CCLK_BURST_POLICY	0x20008888
+#define SUPER_CCLK_DIVIDER	0x80000000
+
+/* Calculate clock fractional divider value from ref and target frequencies */
+#define CLK_DIVIDER(REF, FREQ)  ((((REF) * 2) / FREQ) - 2)
+
+/* Calculate clock frequency value from reference and clock divider value */
+#define CLK_FREQUENCY(REF, REG)  (((REF) * 2) / (REG + 2))
+
+/* AVP/CPU ID */
+#define PG_UP_TAG_0_PID_CPU	0x55555555	/* CPU aka "a9" aka "mpcore" */
+#define PG_UP_TAG_0             0x0
+
+#define CORESIGHT_UNLOCK	0xC5ACCE55;
+
+/* AP20-Specific Base Addresses */
+
+/* AP20 Base physical address of SDRAM. */
+#define AP20_BASE_PA_SDRAM      0x00000000
+/* AP20 Base physical address of internal SRAM. */
+#define AP20_BASE_PA_SRAM       0x40000000
+/* AP20 Size of internal SRAM (256KB). */
+#define AP20_BASE_PA_SRAM_SIZE  0x00040000
+/* AP20 Base physical address of flash. */
+#define AP20_BASE_PA_NOR_FLASH  0xD0000000
+/* AP20 Base physical address of boot information table. */
+#define AP20_BASE_PA_BOOT_INFO  AP20_BASE_PA_SRAM
+
+/*
+ * Super-temporary stacks for EXTREMELY early startup. The values chosen for
+ * these addresses must be valid on ALL SOCs because this value is used before
+ * we are able to differentiate between the SOC types.
+ *
+ * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
+ *       stack is placed below the AVP stack. Once the CPU stack has been moved,
+ *       the AVP is free to use the IRAM the CPU stack previously occupied if
+ *       it should need to do so.
+ *
+ * NOTE: In multi-processor CPU complex configurations, each processor will have
+ *       its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
+ *       limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
+ *       stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
+ *       CPU.
+ */
+
+/* Common AVP early boot stack limit */
+#define AVP_EARLY_BOOT_STACK_LIMIT	\
+	(AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
+/* Common AVP early boot stack size */
+#define AVP_EARLY_BOOT_STACK_SIZE	0x1000
+/* Common CPU early boot stack limit */
+#define CPU_EARLY_BOOT_STACK_LIMIT	\
+	(AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
+/* Common CPU early boot stack size */
+#define CPU_EARLY_BOOT_STACK_SIZE	0x1000
+
+#define EXCEP_VECTOR_CPU_RESET_VECTOR	(NV_PA_EVP_BASE + 0x100)
+#define CSITE_CPU_DBG0_LAR		(NV_PA_CSITE_BASE + 0x10FB0)
+#define CSITE_CPU_DBG1_LAR		(NV_PA_CSITE_BASE + 0x12FB0)
+
+#define FLOW_CTLR_HALT_COP_EVENTS	(NV_PA_FLOW_BASE + 4)
+#define FLOW_MODE_STOP			2
+#define HALT_COP_EVENT_JTAG		(1 << 28)
+#define HALT_COP_EVENT_IRQ_1		(1 << 11)
+#define HALT_COP_EVENT_FIQ_1		(1 << 9)
+
+/* Start up the tegra2 SOC */
+void tegra2_start(void);
+
+/* This is the main entry into U-Boot, used by the Cortex-A9 */
+extern void _start(void);
diff --git a/arch/arm/cpu/tegra2-common/board.c b/arch/arm/cpu/tegra2-common/board.c
new file mode 100644
index 0000000..a797e6f
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/board.c
@@ -0,0 +1,151 @@
+/*
+ *  (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 "ap20.h"
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/pmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	/* UARTs which we can enable */
+	UARTA	= 1 << 0,
+	UARTB	= 1 << 1,
+	UARTD	= 1 << 3,
+	UART_COUNT = 4,
+};
+
+/*
+ * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
+ * so we are using this value to identify memory size.
+ */
+
+unsigned int query_sdram_size(void)
+{
+	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	u32 reg;
+
+	reg = readl(&pmc->pmc_scratch20);
+	debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
+
+	/* bits 31:28 in OdmData are used for RAM size  */
+	switch ((reg) >> 28) {
+	case 1:
+		return 0x10000000;	/* 256 MB */
+	case 2:
+	default:
+		return 0x20000000;	/* 512 MB */
+	case 3:
+		return 0x40000000;	/* 1GB */
+	}
+}
+
+int dram_init(void)
+{
+	/* We do not initialise DRAM here. We just query the size */
+	gd->ram_size = query_sdram_size();
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	printf("Board: %s\n", sysinfo.board_string);
+	return 0;
+}
+#endif	/* CONFIG_DISPLAY_BOARDINFO */
+
+#ifdef CONFIG_ARCH_CPU_INIT
+/*
+ * Note this function is executed by the ARM7TDMI AVP. It does not return
+ * in this case. It is also called once the A9 starts up, but does nothing in
+ * that case.
+ */
+int arch_cpu_init(void)
+{
+	/* Fire up the Cortex A9 */
+	tegra2_start();
+
+	/* We didn't do this init in start.S, so do it now */
+	cpu_init_cp15();
+
+	/* Initialize essential common plls */
+	clock_early_init();
+
+	return 0;
+}
+#endif
+
+/**
+ * Set up the specified uarts
+ *
+ * @param uarts_ids	Mask containing UARTs to init (UARTx)
+ */
+static void setup_uarts(int uart_ids)
+{
+	static enum periph_id id_for_uart[] = {
+		PERIPH_ID_UART1,
+		PERIPH_ID_UART2,
+		PERIPH_ID_UART3,
+		PERIPH_ID_UART4,
+	};
+	size_t i;
+
+	for (i = 0; i < UART_COUNT; i++) {
+		if (uart_ids & (1 << i)) {
+			enum periph_id id = id_for_uart[i];
+
+			funcmux_select(id, FUNCMUX_DEFAULT);
+			clock_ll_start_uart(id);
+		}
+	}
+}
+
+void board_init_uart_f(void)
+{
+	int uart_ids = 0;	/* bit mask of which UART ids to enable */
+
+#ifdef CONFIG_TEGRA2_ENABLE_UARTA
+	uart_ids |= UARTA;
+#endif
+#ifdef CONFIG_TEGRA2_ENABLE_UARTB
+	uart_ids |= UARTB;
+#endif
+#ifdef CONFIG_TEGRA2_ENABLE_UARTD
+	uart_ids |= UARTD;
+#endif
+	setup_uarts(uart_ids);
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/tegra2-common/clock.c b/arch/arm/cpu/tegra2-common/clock.c
new file mode 100644
index 0000000..39376ab
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/clock.c
@@ -0,0 +1,1052 @@
+/*
+ * 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
+ */
+
+/* Tegra2 Clock control functions */
+
+#include <asm/io.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/tegra2.h>
+#include <common.h>
+#include <div64.h>
+#include <fdtdec.h>
+
+/*
+ * This is our record of the current clock rate of each clock. We don't
+ * fill all of these in since we are only really interested in clocks which
+ * we use as parents.
+ */
+static unsigned pll_rate[CLOCK_ID_COUNT];
+
+/*
+ * The oscillator frequency is fixed to one of four set values. Based on this
+ * the other clocks are set up appropriately.
+ */
+static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
+	13000000,
+	19200000,
+	12000000,
+	26000000,
+};
+
+/*
+ * Clock types that we can use as a source. The Tegra2 has muxes for the
+ * peripheral clocks, and in most cases there are four options for the clock
+ * source. This gives us a clock 'type' and exploits what commonality exists
+ * in the device.
+ *
+ * Letters are obvious, except for T which means CLK_M, and S which means the
+ * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
+ * datasheet) and PLL_M are different things. The former is the basic
+ * clock supplied to the SOC from an external oscillator. The latter is the
+ * memory clock PLL.
+ *
+ * See definitions in clock_id in the header file.
+ */
+enum clock_type_id {
+	CLOCK_TYPE_AXPT,	/* PLL_A, PLL_X, PLL_P, CLK_M */
+	CLOCK_TYPE_MCPA,	/* and so on */
+	CLOCK_TYPE_MCPT,
+	CLOCK_TYPE_PCM,
+	CLOCK_TYPE_PCMT,
+	CLOCK_TYPE_PCMT16,	/* CLOCK_TYPE_PCMT with 16-bit divider */
+	CLOCK_TYPE_PCXTS,
+	CLOCK_TYPE_PDCT,
+
+	CLOCK_TYPE_COUNT,
+	CLOCK_TYPE_NONE = -1,	/* invalid clock type */
+};
+
+/* return 1 if a peripheral ID is in range */
+#define clock_type_id_isvalid(id) ((id) >= 0 && \
+		(id) < CLOCK_TYPE_COUNT)
+
+char pllp_valid = 1;	/* PLLP is set up correctly */
+
+enum {
+	CLOCK_MAX_MUX	= 4	/* number of source options for each clock */
+};
+
+/*
+ * Clock source mux for each clock type. This just converts our enum into
+ * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS
+ * is special as it has 5 sources. Since it also has a different number of
+ * bits in its register for the source, we just handle it with a special
+ * case in the code.
+ */
+#define CLK(x) CLOCK_ID_ ## x
+static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
+	{ CLK(AUDIO),	CLK(XCPU),	CLK(PERIPH),	CLK(OSC)	},
+	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(AUDIO)	},
+	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(OSC)	},
+	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(NONE)	},
+	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	},
+	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	},
+	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(XCPU),	CLK(OSC)	},
+	{ CLK(PERIPH),	CLK(DISPLAY),	CLK(CGENERAL),	CLK(OSC)	},
+};
+
+/*
+ * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is
+ * not in the header file since it is for purely internal use - we want
+ * callers to use the PERIPH_ID for all access to peripheral clocks to avoid
+ * confusion bewteen PERIPH_ID_... and PERIPHC_...
+ *
+ * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
+ * confusing.
+ *
+ * Note to SOC vendors: perhaps define a unified numbering for peripherals and
+ * use it for reset, clock enable, clock source/divider and even pinmuxing
+ * if you can.
+ */
+enum periphc_internal_id {
+	/* 0x00 */
+	PERIPHC_I2S1,
+	PERIPHC_I2S2,
+	PERIPHC_SPDIF_OUT,
+	PERIPHC_SPDIF_IN,
+	PERIPHC_PWM,
+	PERIPHC_SPI1,
+	PERIPHC_SPI2,
+	PERIPHC_SPI3,
+
+	/* 0x08 */
+	PERIPHC_XIO,
+	PERIPHC_I2C1,
+	PERIPHC_DVC_I2C,
+	PERIPHC_TWC,
+	PERIPHC_0c,
+	PERIPHC_10,	/* PERIPHC_SPI1, what is this really? */
+	PERIPHC_DISP1,
+	PERIPHC_DISP2,
+
+	/* 0x10 */
+	PERIPHC_CVE,
+	PERIPHC_IDE0,
+	PERIPHC_VI,
+	PERIPHC_1c,
+	PERIPHC_SDMMC1,
+	PERIPHC_SDMMC2,
+	PERIPHC_G3D,
+	PERIPHC_G2D,
+
+	/* 0x18 */
+	PERIPHC_NDFLASH,
+	PERIPHC_SDMMC4,
+	PERIPHC_VFIR,
+	PERIPHC_EPP,
+	PERIPHC_MPE,
+	PERIPHC_MIPI,
+	PERIPHC_UART1,
+	PERIPHC_UART2,
+
+	/* 0x20 */
+	PERIPHC_HOST1X,
+	PERIPHC_21,
+	PERIPHC_TVO,
+	PERIPHC_HDMI,
+	PERIPHC_24,
+	PERIPHC_TVDAC,
+	PERIPHC_I2C2,
+	PERIPHC_EMC,
+
+	/* 0x28 */
+	PERIPHC_UART3,
+	PERIPHC_29,
+	PERIPHC_VI_SENSOR,
+	PERIPHC_2b,
+	PERIPHC_2c,
+	PERIPHC_SPI4,
+	PERIPHC_I2C3,
+	PERIPHC_SDMMC3,
+
+	/* 0x30 */
+	PERIPHC_UART4,
+	PERIPHC_UART5,
+	PERIPHC_VDE,
+	PERIPHC_OWR,
+	PERIPHC_NOR,
+	PERIPHC_CSITE,
+
+	PERIPHC_COUNT,
+
+	PERIPHC_NONE = -1,
+};
+
+/* return 1 if a periphc_internal_id is in range */
+#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
+		(id) < PERIPHC_COUNT)
+
+/*
+ * Clock type for each peripheral clock source. We put the name in each
+ * record just so it is easy to match things up
+ */
+#define TYPE(name, type) type
+static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
+	/* 0x00 */
+	TYPE(PERIPHC_I2S1,	CLOCK_TYPE_AXPT),
+	TYPE(PERIPHC_I2S2,	CLOCK_TYPE_AXPT),
+	TYPE(PERIPHC_SPDIF_OUT,	CLOCK_TYPE_AXPT),
+	TYPE(PERIPHC_SPDIF_IN,	CLOCK_TYPE_PCM),
+	TYPE(PERIPHC_PWM,	CLOCK_TYPE_PCXTS),
+	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_SPI22,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_SPI3,	CLOCK_TYPE_PCMT),
+
+	/* 0x08 */
+	TYPE(PERIPHC_XIO,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_I2C1,	CLOCK_TYPE_PCMT16),
+	TYPE(PERIPHC_DVC_I2C,	CLOCK_TYPE_PCMT16),
+	TYPE(PERIPHC_TWC,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_DISP1,	CLOCK_TYPE_PDCT),
+	TYPE(PERIPHC_DISP2,	CLOCK_TYPE_PDCT),
+
+	/* 0x10 */
+	TYPE(PERIPHC_CVE,	CLOCK_TYPE_PDCT),
+	TYPE(PERIPHC_IDE0,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_SDMMC1,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_SDMMC2,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_G3D,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_G2D,	CLOCK_TYPE_MCPA),
+
+	/* 0x18 */
+	TYPE(PERIPHC_NDFLASH,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_SDMMC4,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_VFIR,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_EPP,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_MPE,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_MIPI,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_UART1,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_UART2,	CLOCK_TYPE_PCMT),
+
+	/* 0x20 */
+	TYPE(PERIPHC_HOST1X,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_TVO,	CLOCK_TYPE_PDCT),
+	TYPE(PERIPHC_HDMI,	CLOCK_TYPE_PDCT),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_TVDAC,	CLOCK_TYPE_PDCT),
+	TYPE(PERIPHC_I2C2,	CLOCK_TYPE_PCMT16),
+	TYPE(PERIPHC_EMC,	CLOCK_TYPE_MCPT),
+
+	/* 0x28 */
+	TYPE(PERIPHC_UART3,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE),
+	TYPE(PERIPHC_SPI4,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_I2C3,	CLOCK_TYPE_PCMT16),
+	TYPE(PERIPHC_SDMMC3,	CLOCK_TYPE_PCMT),
+
+	/* 0x30 */
+	TYPE(PERIPHC_UART4,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_UART5,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_VDE,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_OWR,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_NOR,	CLOCK_TYPE_PCMT),
+	TYPE(PERIPHC_CSITE,	CLOCK_TYPE_PCMT),
+};
+
+/*
+ * This array translates a periph_id to a periphc_internal_id
+ *
+ * Not present/matched up:
+ *	uint vi_sensor;	 _VI_SENSOR_0,		0x1A8
+ *	SPDIF - which is both 0x08 and 0x0c
+ *
+ */
+#define NONE(name) (-1)
+#define OFFSET(name, value) PERIPHC_ ## name
+static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
+	/* Low word: 31:0 */
+	NONE(CPU),
+	NONE(RESERVED1),
+	NONE(RESERVED2),
+	NONE(AC97),
+	NONE(RTC),
+	NONE(TMR),
+	PERIPHC_UART1,
+	PERIPHC_UART2,	/* and vfir 0x68 */
+
+	/* 0x08 */
+	NONE(GPIO),
+	PERIPHC_SDMMC2,
+	NONE(SPDIF),		/* 0x08 and 0x0c, unclear which to use */
+	PERIPHC_I2S1,
+	PERIPHC_I2C1,
+	PERIPHC_NDFLASH,
+	PERIPHC_SDMMC1,
+	PERIPHC_SDMMC4,
+
+	/* 0x10 */
+	PERIPHC_TWC,
+	PERIPHC_PWM,
+	PERIPHC_I2S2,
+	PERIPHC_EPP,
+	PERIPHC_VI,
+	PERIPHC_G2D,
+	NONE(USBD),
+	NONE(ISP),
+
+	/* 0x18 */
+	PERIPHC_G3D,
+	PERIPHC_IDE0,
+	PERIPHC_DISP2,
+	PERIPHC_DISP1,
+	PERIPHC_HOST1X,
+	NONE(VCP),
+	NONE(RESERVED30),
+	NONE(CACHE2),
+
+	/* Middle word: 63:32 */
+	NONE(MEM),
+	NONE(AHBDMA),
+	NONE(APBDMA),
+	NONE(RESERVED35),
+	NONE(KBC),
+	NONE(STAT_MON),
+	NONE(PMC),
+	NONE(FUSE),
+
+	/* 0x28 */
+	NONE(KFUSE),
+	NONE(SBC1),	/* SBC1, 0x34, is this SPI1? */
+	PERIPHC_NOR,
+	PERIPHC_SPI1,
+	PERIPHC_SPI2,
+	PERIPHC_XIO,
+	PERIPHC_SPI3,
+	PERIPHC_DVC_I2C,
+
+	/* 0x30 */
+	NONE(DSI),
+	PERIPHC_TVO,	/* also CVE 0x40 */
+	PERIPHC_MIPI,
+	PERIPHC_HDMI,
+	PERIPHC_CSITE,
+	PERIPHC_TVDAC,
+	PERIPHC_I2C2,
+	PERIPHC_UART3,
+
+	/* 0x38 */
+	NONE(RESERVED56),
+	PERIPHC_EMC,
+	NONE(USB2),
+	NONE(USB3),
+	PERIPHC_MPE,
+	PERIPHC_VDE,
+	NONE(BSEA),
+	NONE(BSEV),
+
+	/* Upper word 95:64 */
+	NONE(SPEEDO),
+	PERIPHC_UART4,
+	PERIPHC_UART5,
+	PERIPHC_I2C3,
+	PERIPHC_SPI4,
+	PERIPHC_SDMMC3,
+	NONE(PCIE),
+	PERIPHC_OWR,
+
+	/* 0x48 */
+	NONE(AFI),
+	NONE(CORESIGHT),
+	NONE(RESERVED74),
+	NONE(AVPUCQ),
+	NONE(RESERVED76),
+	NONE(RESERVED77),
+	NONE(RESERVED78),
+	NONE(RESERVED79),
+
+	/* 0x50 */
+	NONE(RESERVED80),
+	NONE(RESERVED81),
+	NONE(RESERVED82),
+	NONE(RESERVED83),
+	NONE(IRAMA),
+	NONE(IRAMB),
+	NONE(IRAMC),
+	NONE(IRAMD),
+
+	/* 0x58 */
+	NONE(CRAM2),
+};
+
+/*
+ * Get the oscillator frequency, from the corresponding hardware configuration
+ * field.
+ */
+enum clock_osc_freq clock_get_osc_freq(void)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 reg;
+
+	reg = readl(&clkrst->crc_osc_ctrl);
+	return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+}
+
+/* Returns a pointer to the registers of the given pll */
+static struct clk_pll *get_pll(enum clock_id clkid)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+
+	assert(clock_id_isvalid(clkid));
+	return &clkrst->crc_pll[clkid];
+}
+
+unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
+		u32 divp, u32 cpcon, u32 lfcon)
+{
+	struct clk_pll *pll = get_pll(clkid);
+	u32 data;
+
+	/*
+	 * We cheat by treating all PLL (except PLLU) in the same fashion.
+	 * This works only because:
+	 * - same fields are always mapped at same offsets, except DCCON
+	 * - DCCON is always 0, doesn't conflict
+	 * - M,N, P of PLLP values are ignored for PLLP
+	 */
+	data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
+	writel(data, &pll->pll_misc);
+
+	data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
+			(0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
+
+	if (clkid == CLOCK_ID_USB)
+		data |= divp << PLLU_VCO_FREQ_SHIFT;
+	else
+		data |= divp << PLL_DIVP_SHIFT;
+	writel(data, &pll->pll_base);
+
+	/* calculate the stable time */
+	return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
+}
+
+/* return 1 if a peripheral ID is in range and valid */
+static int clock_periph_id_isvalid(enum periph_id id)
+{
+	if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
+		printf("Peripheral id %d out of range\n", id);
+	else {
+		switch (id) {
+		case PERIPH_ID_RESERVED1:
+		case PERIPH_ID_RESERVED2:
+		case PERIPH_ID_RESERVED30:
+		case PERIPH_ID_RESERVED35:
+		case PERIPH_ID_RESERVED56:
+		case PERIPH_ID_RESERVED74:
+		case PERIPH_ID_RESERVED76:
+		case PERIPH_ID_RESERVED77:
+		case PERIPH_ID_RESERVED78:
+		case PERIPH_ID_RESERVED79:
+		case PERIPH_ID_RESERVED80:
+		case PERIPH_ID_RESERVED81:
+		case PERIPH_ID_RESERVED82:
+		case PERIPH_ID_RESERVED83:
+			printf("Peripheral id %d is reserved\n", id);
+			break;
+		default:
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* Returns a pointer to the clock source register for a peripheral */
+static u32 *get_periph_source_reg(enum periph_id periph_id)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	enum periphc_internal_id internal_id;
+
+	assert(clock_periph_id_isvalid(periph_id));
+	internal_id = periph_id_to_internal_id[periph_id];
+	assert(internal_id != -1);
+	return &clkrst->crc_clk_src[internal_id];
+}
+
+void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
+			      unsigned divisor)
+{
+	u32 *reg = get_periph_source_reg(periph_id);
+	u32 value;
+
+	value = readl(reg);
+
+	value &= ~OUT_CLK_SOURCE_MASK;
+	value |= source << OUT_CLK_SOURCE_SHIFT;
+
+	value &= ~OUT_CLK_DIVISOR_MASK;
+	value |= divisor << OUT_CLK_DIVISOR_SHIFT;
+
+	writel(value, reg);
+}
+
+void clock_ll_set_source(enum periph_id periph_id, unsigned source)
+{
+	u32 *reg = get_periph_source_reg(periph_id);
+
+	clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+			source << OUT_CLK_SOURCE_SHIFT);
+}
+
+/**
+ * Given the parent's rate and the required rate for the children, this works
+ * out the peripheral clock divider to use, in 7.1 binary format.
+ *
+ * @param divider_bits	number of divider bits (8 or 16)
+ * @param parent_rate	clock rate of parent clock in Hz
+ * @param rate		required clock rate for this clock
+ * @return divider which should be used
+ */
+static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
+			   unsigned long rate)
+{
+	u64 divider = parent_rate * 2;
+	unsigned max_divider = 1 << divider_bits;
+
+	divider += rate - 1;
+	do_div(divider, rate);
+
+	if ((s64)divider - 2 < 0)
+		return 0;
+
+	if ((s64)divider - 2 >= max_divider)
+		return -1;
+
+	return divider - 2;
+}
+
+/**
+ * Given the parent's rate and the divider in 7.1 format, this works out the
+ * resulting peripheral clock rate.
+ *
+ * @param parent_rate	clock rate of parent clock in Hz
+ * @param divider which should be used in 7.1 format
+ * @return effective clock rate of peripheral
+ */
+static unsigned long get_rate_from_divider(unsigned long parent_rate,
+					   int divider)
+{
+	u64 rate;
+
+	rate = (u64)parent_rate * 2;
+	do_div(rate, divider + 2);
+	return rate;
+}
+
+unsigned long clock_get_periph_rate(enum periph_id periph_id,
+		enum clock_id parent)
+{
+	u32 *reg = get_periph_source_reg(periph_id);
+
+	return get_rate_from_divider(pll_rate[parent],
+		(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
+}
+
+/**
+ * Find the best available 7.1 format divisor given a parent clock rate and
+ * required child clock rate. This function assumes that a second-stage
+ * divisor is available which can divide by powers of 2 from 1 to 256.
+ *
+ * @param divider_bits	number of divider bits (8 or 16)
+ * @param parent_rate	clock rate of parent clock in Hz
+ * @param rate		required clock rate for this clock
+ * @param extra_div	value for the second-stage divisor (not set if this
+ *			function returns -1.
+ * @return divider which should be used, or -1 if nothing is valid
+ *
+ */
+static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
+			     unsigned long rate, int *extra_div)
+{
+	int shift;
+	int best_divider = -1;
+	int best_error = rate;
+
+	/* try dividers from 1 to 256 and find closest match */
+	for (shift = 0; shift <= 8 && best_error > 0; shift++) {
+		unsigned divided_parent = parent_rate >> shift;
+		int divider = clk_get_divider(divider_bits, divided_parent,
+					      rate);
+		unsigned effective_rate = get_rate_from_divider(divided_parent,
+						       divider);
+		int error = rate - effective_rate;
+
+		/* Given a valid divider, look for the lowest error */
+		if (divider != -1 && error < best_error) {
+			best_error = error;
+			*extra_div = 1 << shift;
+			best_divider = divider;
+		}
+	}
+
+	/* return what we found - *extra_div will already be set */
+	return best_divider;
+}
+
+/**
+ * Given a peripheral ID and the required source clock, this returns which
+ * value should be programmed into the source mux for that peripheral.
+ *
+ * There is special code here to handle the one source type with 5 sources.
+ *
+ * @param periph_id	peripheral to start
+ * @param source	PLL id of required parent clock
+ * @param mux_bits	Set to number of bits in mux register: 2 or 4
+ * @param divider_bits	Set to number of divider bits (8 or 16)
+ * @return mux value (0-4, or -1 if not found)
+ */
+static int get_periph_clock_source(enum periph_id periph_id,
+		enum clock_id parent, int *mux_bits, int *divider_bits)
+{
+	enum clock_type_id type;
+	enum periphc_internal_id internal_id;
+	int mux;
+
+	assert(clock_periph_id_isvalid(periph_id));
+
+	internal_id = periph_id_to_internal_id[periph_id];
+	assert(periphc_internal_id_isvalid(internal_id));
+
+	type = clock_periph_type[internal_id];
+	assert(clock_type_id_isvalid(type));
+
+	/*
+	 * Special cases here for the clock with a 4-bit source mux and I2C
+	 * with its 16-bit divisor
+	 */
+	if (type == CLOCK_TYPE_PCXTS)
+		*mux_bits = 4;
+	else
+		*mux_bits = 2;
+	if (type == CLOCK_TYPE_PCMT16)
+		*divider_bits = 16;
+	else
+		*divider_bits = 8;
+
+	for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
+		if (clock_source[type][mux] == parent)
+			return mux;
+
+	/*
+	 * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS
+	 * which is not in our table. If not, then they are asking for a
+	 * source which this peripheral can't access through its mux.
+	 */
+	assert(type == CLOCK_TYPE_PCXTS);
+	assert(parent == CLOCK_ID_SFROM32KHZ);
+	if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ)
+		return 4;	/* mux value for this clock */
+
+	/* if we get here, either us or the caller has made a mistake */
+	printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
+		parent);
+	return -1;
+}
+
+/**
+ * Adjust peripheral PLL to use the given divider and source.
+ *
+ * @param periph_id	peripheral to adjust
+ * @param source	Source number (0-3 or 0-7)
+ * @param mux_bits	Number of mux bits (2 or 4)
+ * @param divider	Required divider in 7.1 or 15.1 format
+ * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
+ *		for this peripheral)
+ */
+static int adjust_periph_pll(enum periph_id periph_id, int source,
+			     int mux_bits, unsigned divider)
+{
+	u32 *reg = get_periph_source_reg(periph_id);
+
+	clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
+			divider << OUT_CLK_DIVISOR_SHIFT);
+	udelay(1);
+
+	/* work out the source clock and set it */
+	if (source < 0)
+		return -1;
+	if (mux_bits == 4) {
+		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
+			source << OUT_CLK_SOURCE4_SHIFT);
+	} else {
+		clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+			source << OUT_CLK_SOURCE_SHIFT);
+	}
+	udelay(2);
+	return 0;
+}
+
+unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
+		enum clock_id parent, unsigned rate, int *extra_div)
+{
+	unsigned effective_rate;
+	int mux_bits, divider_bits, source;
+	int divider;
+
+	/* work out the source clock and set it */
+	source = get_periph_clock_source(periph_id, parent, &mux_bits,
+					 &divider_bits);
+
+	if (extra_div)
+		divider = find_best_divider(divider_bits, pll_rate[parent],
+					    rate, extra_div);
+	else
+		divider = clk_get_divider(divider_bits, pll_rate[parent],
+					  rate);
+	assert(divider >= 0);
+	if (adjust_periph_pll(periph_id, source, mux_bits, divider))
+		return -1U;
+	debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
+		get_periph_source_reg(periph_id),
+		readl(get_periph_source_reg(periph_id)));
+
+	/* Check what we ended up with. This shouldn't matter though */
+	effective_rate = clock_get_periph_rate(periph_id, parent);
+	if (extra_div)
+		effective_rate /= *extra_div;
+	if (rate != effective_rate)
+		debug("Requested clock rate %u not honored (got %u)\n",
+		       rate, effective_rate);
+	return effective_rate;
+}
+
+unsigned clock_start_periph_pll(enum periph_id periph_id,
+		enum clock_id parent, unsigned rate)
+{
+	unsigned effective_rate;
+
+	reset_set_enable(periph_id, 1);
+	clock_enable(periph_id);
+
+	effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
+						 NULL);
+
+	reset_set_enable(periph_id, 0);
+	return effective_rate;
+}
+
+void clock_set_enable(enum periph_id periph_id, int enable)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
+	u32 reg;
+
+	/* Enable/disable the clock to this peripheral */
+	assert(clock_periph_id_isvalid(periph_id));
+	reg = readl(clk);
+	if (enable)
+		reg |= PERIPH_MASK(periph_id);
+	else
+		reg &= ~PERIPH_MASK(periph_id);
+	writel(reg, clk);
+}
+
+void clock_enable(enum periph_id clkid)
+{
+	clock_set_enable(clkid, 1);
+}
+
+void clock_disable(enum periph_id clkid)
+{
+	clock_set_enable(clkid, 0);
+}
+
+void reset_set_enable(enum periph_id periph_id, int enable)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
+	u32 reg;
+
+	/* Enable/disable reset to the peripheral */
+	assert(clock_periph_id_isvalid(periph_id));
+	reg = readl(reset);
+	if (enable)
+		reg |= PERIPH_MASK(periph_id);
+	else
+		reg &= ~PERIPH_MASK(periph_id);
+	writel(reg, reset);
+}
+
+void reset_periph(enum periph_id periph_id, int us_delay)
+{
+	/* Put peripheral into reset */
+	reset_set_enable(periph_id, 1);
+	udelay(us_delay);
+
+	/* Remove reset */
+	reset_set_enable(periph_id, 0);
+
+	udelay(us_delay);
+}
+
+void reset_cmplx_set_enable(int cpu, int which, int reset)
+{
+	struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 mask;
+
+	/* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */
+	assert(cpu >= 0 && cpu < 2);
+	mask = which << cpu;
+
+	/* either enable or disable those reset for that CPU */
+	if (reset)
+		writel(mask, &clkrst->crc_cpu_cmplx_set);
+	else
+		writel(mask, &clkrst->crc_cpu_cmplx_clr);
+}
+
+unsigned clock_get_rate(enum clock_id clkid)
+{
+	struct clk_pll *pll;
+	u32 base;
+	u32 divm;
+	u64 parent_rate;
+	u64 rate;
+
+	parent_rate = osc_freq[clock_get_osc_freq()];
+	if (clkid == CLOCK_ID_OSC)
+		return parent_rate;
+
+	pll = get_pll(clkid);
+	base = readl(&pll->pll_base);
+
+	/* Oh for bf_unpack()... */
+	rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
+	divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+	if (clkid == CLOCK_ID_USB)
+		divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
+	else
+		divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+	do_div(rate, divm);
+	return rate;
+}
+
+/**
+ * Set the output frequency you want for each PLL clock.
+ * PLL output frequencies are programmed by setting their N, M and P values.
+ * The governing equations are:
+ *     VCO = (Fi / m) * n, Fo = VCO / (2^p)
+ *     where Fo is the output frequency from the PLL.
+ * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
+ *     216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
+ * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
+ *
+ * @param n PLL feedback divider(DIVN)
+ * @param m PLL input divider(DIVN)
+ * @param p post divider(DIVP)
+ * @param cpcon base PLL charge pump(CPCON)
+ * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
+ *		be overriden), 1 if PLL is already correct
+ */
+static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
+{
+	u32 base_reg;
+	u32 misc_reg;
+	struct clk_pll *pll;
+
+	pll = get_pll(clkid);
+
+	base_reg = readl(&pll->pll_base);
+
+	/* Set BYPASS, m, n and p to PLL_BASE */
+	base_reg &= ~PLL_DIVM_MASK;
+	base_reg |= m << PLL_DIVM_SHIFT;
+
+	base_reg &= ~PLL_DIVN_MASK;
+	base_reg |= n << PLL_DIVN_SHIFT;
+
+	base_reg &= ~PLL_DIVP_MASK;
+	base_reg |= p << PLL_DIVP_SHIFT;
+
+	if (clkid == CLOCK_ID_PERIPH) {
+		/*
+		 * If the PLL is already set up, check that it is correct
+		 * and record this info for clock_verify() to check.
+		 */
+		if (base_reg & PLL_BASE_OVRRIDE_MASK) {
+			base_reg |= PLL_ENABLE_MASK;
+			if (base_reg != readl(&pll->pll_base))
+				pllp_valid = 0;
+			return pllp_valid ? 1 : -1;
+		}
+		base_reg |= PLL_BASE_OVRRIDE_MASK;
+	}
+
+	base_reg |= PLL_BYPASS_MASK;
+	writel(base_reg, &pll->pll_base);
+
+	/* Set cpcon to PLL_MISC */
+	misc_reg = readl(&pll->pll_misc);
+	misc_reg &= ~PLL_CPCON_MASK;
+	misc_reg |= cpcon << PLL_CPCON_SHIFT;
+	writel(misc_reg, &pll->pll_misc);
+
+	/* Enable PLL */
+	base_reg |= PLL_ENABLE_MASK;
+	writel(base_reg, &pll->pll_base);
+
+	/* Disable BYPASS */
+	base_reg &= ~PLL_BYPASS_MASK;
+	writel(base_reg, &pll->pll_base);
+
+	return 0;
+}
+
+void clock_ll_start_uart(enum periph_id periph_id)
+{
+	/* Assert UART reset and enable clock */
+	reset_set_enable(periph_id, 1);
+	clock_enable(periph_id);
+	clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
+
+	/* wait for 2us */
+	udelay(2);
+
+	/* De-assert reset to UART */
+	reset_set_enable(periph_id, 0);
+}
+
+#ifdef CONFIG_OF_CONTROL
+/*
+ * Convert a device tree clock ID to our peripheral ID. They are mostly
+ * the same but we are very cautious so we check that a valid clock ID is
+ * provided.
+ *
+ * @param clk_id	Clock ID according to tegra2 device tree binding
+ * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
+ */
+static enum periph_id clk_id_to_periph_id(int clk_id)
+{
+	if (clk_id > 95)
+		return PERIPH_ID_NONE;
+
+	switch (clk_id) {
+	case 1:
+	case 2:
+	case 7:
+	case 10:
+	case 20:
+	case 30:
+	case 35:
+	case 49:
+	case 56:
+	case 74:
+	case 76:
+	case 77:
+	case 78:
+	case 79:
+	case 80:
+	case 81:
+	case 82:
+	case 83:
+	case 91:
+	case 95:
+		return PERIPH_ID_NONE;
+	default:
+		return clk_id;
+	}
+}
+
+int clock_decode_periph_id(const void *blob, int node)
+{
+	enum periph_id id;
+	u32 cell[2];
+	int err;
+
+	err = fdtdec_get_int_array(blob, node, "clocks", cell,
+				   ARRAY_SIZE(cell));
+	if (err)
+		return -1;
+	id = clk_id_to_periph_id(cell[1]);
+	assert(clock_periph_id_isvalid(id));
+	return id;
+}
+#endif /* CONFIG_OF_CONTROL */
+
+int clock_verify(void)
+{
+	struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
+	u32 reg = readl(&pll->pll_base);
+
+	if (!pllp_valid) {
+		printf("Warning: PLLP %x is not correct\n", reg);
+		return -1;
+	}
+	debug("PLLX %x is correct\n", reg);
+	return 0;
+}
+
+void clock_early_init(void)
+{
+	/*
+	 * PLLP output frequency set to 216MHz
+	 * PLLC output frequency set to 600Mhz
+	 *
+	 * TODO: Can we calculate these values instead of hard-coding?
+	 */
+	switch (clock_get_osc_freq()) {
+	case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
+		clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8);
+		clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
+		break;
+
+	case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
+		clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8);
+		clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
+		break;
+
+	case CLOCK_OSC_FREQ_13_0:
+	case CLOCK_OSC_FREQ_19_2:
+	default:
+		/*
+		 * These are not supported. It is too early to print a
+		 * message and the UART likely won't work anyway due to the
+		 * oscillator being wrong.
+		 */
+		break;
+	}
+}
+
+void clock_init(void)
+{
+	pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
+	pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
+	pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
+	pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
+	pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
+	debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+	debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
+	debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
+}
diff --git a/arch/arm/cpu/tegra2-common/funcmux.c b/arch/arm/cpu/tegra2-common/funcmux.c
new file mode 100644
index 0000000..c1d2dfe
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/funcmux.c
@@ -0,0 +1,184 @@
+/*
+ * 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
+ */
+
+/* Tegra2 high-level function multiplexing */
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pinmux.h>
+
+int funcmux_select(enum periph_id id, int config)
+{
+	int bad_config = config != FUNCMUX_DEFAULT;
+
+	switch (id) {
+	case PERIPH_ID_UART1:
+		if (config == FUNCMUX_UART1_IRRX_IRTX) {
+			pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
+			pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
+			pinmux_tristate_disable(PINGRP_IRRX);
+			pinmux_tristate_disable(PINGRP_IRTX);
+			/*
+			 * Tegra appears to boot with function UARTA pre-
+			 * selected on mux group SDB. If two mux groups are
+			 * both set to the same function, it's unclear which
+			 * group's pins drive the RX signals into the HW.
+			 * For UARTA, SDB certainly overrides group IRTX in
+			 * practice. To solve this, configure some alternative
+			 * function on SDB to avoid the conflict. Also, tri-
+			 * state the group to avoid driving any signal onto it
+			 * until we know what's connected.
+			 */
+			pinmux_tristate_enable(PINGRP_SDB);
+			pinmux_set_func(PINGRP_SDB,  PMUX_FUNC_SDIO3);
+		}
+		break;
+
+	case PERIPH_ID_UART2:
+		if (config == FUNCMUX_UART2_IRDA) {
+			pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
+			pinmux_tristate_disable(PINGRP_UAD);
+		}
+		break;
+
+	case PERIPH_ID_UART4:
+		if (config == FUNCMUX_UART4_GMC) {
+			pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
+			pinmux_tristate_disable(PINGRP_GMC);
+		}
+		break;
+
+	case PERIPH_ID_DVC_I2C:
+		/* there is only one selection, pinmux_config is ignored */
+		if (config == FUNCMUX_DVC_I2CP) {
+			pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
+			pinmux_tristate_disable(PINGRP_I2CP);
+		}
+		break;
+
+	case PERIPH_ID_I2C1:
+		/* support pinmux_config of 0 for now, */
+		if (config == FUNCMUX_I2C1_RM) {
+			pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
+			pinmux_tristate_disable(PINGRP_RM);
+		}
+		break;
+	case PERIPH_ID_I2C2: /* I2C2 */
+		switch (config) {
+		case FUNCMUX_I2C2_DDC:	/* DDC pin group, select I2C2 */
+			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
+			/* PTA to HDMI */
+			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
+			pinmux_tristate_disable(PINGRP_DDC);
+			break;
+		case FUNCMUX_I2C2_PTA:	/* PTA pin group, select I2C2 */
+			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
+			/* set DDC_SEL to RSVDx (RSVD2 works for now) */
+			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
+			pinmux_tristate_disable(PINGRP_PTA);
+			bad_config = 0;
+			break;
+		}
+		break;
+	case PERIPH_ID_I2C3: /* I2C3 */
+		/* support pinmux_config of 0 for now */
+		if (config == FUNCMUX_I2C3_DTF) {
+			pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
+			pinmux_tristate_disable(PINGRP_DTF);
+		}
+		break;
+
+	case PERIPH_ID_SDMMC2:
+		if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
+			pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
+			pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
+
+			pinmux_tristate_disable(PINGRP_DTA);
+			pinmux_tristate_disable(PINGRP_DTD);
+		}
+		break;
+
+	case PERIPH_ID_SDMMC3:
+		switch (config) {
+		case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
+			pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
+			pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
+			pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
+			pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
+
+			pinmux_tristate_disable(PINGRP_SLXA);
+			pinmux_tristate_disable(PINGRP_SLXC);
+			pinmux_tristate_disable(PINGRP_SLXD);
+			pinmux_tristate_disable(PINGRP_SLXK);
+			/* fall through */
+
+		case FUNCMUX_SDMMC3_SDB_4BIT:
+			pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
+			pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
+			pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
+
+			pinmux_tristate_disable(PINGRP_SDB);
+			pinmux_tristate_disable(PINGRP_SDC);
+			pinmux_tristate_disable(PINGRP_SDD);
+			bad_config = 0;
+			break;
+		}
+		break;
+
+	case PERIPH_ID_SDMMC4:
+		switch (config) {
+		case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
+			pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
+			pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
+
+			pinmux_tristate_disable(PINGRP_ATC);
+			pinmux_tristate_disable(PINGRP_ATD);
+			break;
+
+		case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
+			pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
+			pinmux_tristate_disable(PINGRP_GME);
+			/* fall through */
+
+		case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
+			pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
+			pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
+
+			pinmux_tristate_disable(PINGRP_ATB);
+			pinmux_tristate_disable(PINGRP_GMA);
+			bad_config = 0;
+			break;
+		}
+		break;
+
+	default:
+		debug("%s: invalid periph_id %d", __func__, id);
+		return -1;
+	}
+
+	if (bad_config) {
+		debug("%s: invalid config %d for periph_id %d", __func__,
+		      config, id);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/tegra2-common/lowlevel_init.S b/arch/arm/cpu/tegra2-common/lowlevel_init.S
new file mode 100644
index 0000000..6b86647
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/lowlevel_init.S
@@ -0,0 +1,41 @@
+/*
+ * SoC-specific setup info
+ *
+ * (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 <config.h>
+#include <version.h>
+
+	.align	5
+.global reset_cpu
+reset_cpu:
+	ldr	r1, rstctl			@ get addr for global reset
+						@ reg
+	ldr	r3, [r1]
+	orr	r3, r3, #0x10
+	str	r3, [r1]			@ force reset
+	mov	r0, r0
+_loop_forever:
+	b	_loop_forever
+rstctl:
+	.word	PRM_RSTCTRL
diff --git a/arch/arm/cpu/tegra2-common/pinmux.c b/arch/arm/cpu/tegra2-common/pinmux.c
new file mode 100644
index 0000000..b053f90
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/pinmux.c
@@ -0,0 +1,572 @@
+/*
+ * 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
+ */
+
+/* Tegra2 pin multiplexing functions */
+
+#include <asm/io.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/pinmux.h>
+#include <common.h>
+
+
+/*
+ * This defines the order of the pin mux control bits in the registers. For
+ * some reason there is no correspendence between the tristate, pin mux and
+ * pullup/pulldown registers.
+ */
+enum pmux_ctlid {
+	/* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */
+	MUXCTL_UAA,
+	MUXCTL_UAB,
+	MUXCTL_UAC,
+	MUXCTL_UAD,
+	MUXCTL_UDA,
+	MUXCTL_RESERVED5,
+	MUXCTL_ATE,
+	MUXCTL_RM,
+
+	MUXCTL_ATB,
+	MUXCTL_RESERVED9,
+	MUXCTL_ATD,
+	MUXCTL_ATC,
+	MUXCTL_ATA,
+	MUXCTL_KBCF,
+	MUXCTL_KBCE,
+	MUXCTL_SDMMC1,
+
+	/* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */
+	MUXCTL_GMA,
+	MUXCTL_GMC,
+	MUXCTL_HDINT,
+	MUXCTL_SLXA,
+	MUXCTL_OWC,
+	MUXCTL_SLXC,
+	MUXCTL_SLXD,
+	MUXCTL_SLXK,
+
+	MUXCTL_UCA,
+	MUXCTL_UCB,
+	MUXCTL_DTA,
+	MUXCTL_DTB,
+	MUXCTL_RESERVED28,
+	MUXCTL_DTC,
+	MUXCTL_DTD,
+	MUXCTL_DTE,
+
+	/* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */
+	MUXCTL_DDC,
+	MUXCTL_CDEV1,
+	MUXCTL_CDEV2,
+	MUXCTL_CSUS,
+	MUXCTL_I2CP,
+	MUXCTL_KBCA,
+	MUXCTL_KBCB,
+	MUXCTL_KBCC,
+
+	MUXCTL_IRTX,
+	MUXCTL_IRRX,
+	MUXCTL_DAP1,
+	MUXCTL_DAP2,
+	MUXCTL_DAP3,
+	MUXCTL_DAP4,
+	MUXCTL_GMB,
+	MUXCTL_GMD,
+
+	/* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */
+	MUXCTL_GME,
+	MUXCTL_GPV,
+	MUXCTL_GPU,
+	MUXCTL_SPDO,
+	MUXCTL_SPDI,
+	MUXCTL_SDB,
+	MUXCTL_SDC,
+	MUXCTL_SDD,
+
+	MUXCTL_SPIH,
+	MUXCTL_SPIG,
+	MUXCTL_SPIF,
+	MUXCTL_SPIE,
+	MUXCTL_SPID,
+	MUXCTL_SPIC,
+	MUXCTL_SPIB,
+	MUXCTL_SPIA,
+
+	/* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */
+	MUXCTL_LPW0,
+	MUXCTL_LPW1,
+	MUXCTL_LPW2,
+	MUXCTL_LSDI,
+	MUXCTL_LSDA,
+	MUXCTL_LSPI,
+	MUXCTL_LCSN,
+	MUXCTL_LDC,
+
+	MUXCTL_LSCK,
+	MUXCTL_LSC0,
+	MUXCTL_LSC1,
+	MUXCTL_LHS,
+	MUXCTL_LVS,
+	MUXCTL_LM0,
+	MUXCTL_LM1,
+	MUXCTL_LVP0,
+
+	/* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */
+	MUXCTL_LD0,
+	MUXCTL_LD1,
+	MUXCTL_LD2,
+	MUXCTL_LD3,
+	MUXCTL_LD4,
+	MUXCTL_LD5,
+	MUXCTL_LD6,
+	MUXCTL_LD7,
+
+	MUXCTL_LD8,
+	MUXCTL_LD9,
+	MUXCTL_LD10,
+	MUXCTL_LD11,
+	MUXCTL_LD12,
+	MUXCTL_LD13,
+	MUXCTL_LD14,
+	MUXCTL_LD15,
+
+	/* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */
+	MUXCTL_LD16,
+	MUXCTL_LD17,
+	MUXCTL_LHP1,
+	MUXCTL_LHP2,
+	MUXCTL_LVP1,
+	MUXCTL_LHP0,
+	MUXCTL_RESERVED102,
+	MUXCTL_LPP,
+
+	MUXCTL_LDI,
+	MUXCTL_PMC,
+	MUXCTL_CRTP,
+	MUXCTL_PTA,
+	MUXCTL_RESERVED108,
+	MUXCTL_KBCD,
+	MUXCTL_GPU7,
+	MUXCTL_DTF,
+
+	MUXCTL_NONE = -1,
+};
+
+/*
+ * And this defines the order of the pullup/pulldown controls which are again
+ * in a different order
+ */
+enum pmux_pullid {
+	/* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */
+	PUCTL_ATA,
+	PUCTL_ATB,
+	PUCTL_ATC,
+	PUCTL_ATD,
+	PUCTL_ATE,
+	PUCTL_DAP1,
+	PUCTL_DAP2,
+	PUCTL_DAP3,
+
+	PUCTL_DAP4,
+	PUCTL_DTA,
+	PUCTL_DTB,
+	PUCTL_DTC,
+	PUCTL_DTD,
+	PUCTL_DTE,
+	PUCTL_DTF,
+	PUCTL_GPV,
+
+	/* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */
+	PUCTL_RM,
+	PUCTL_I2CP,
+	PUCTL_PTA,
+	PUCTL_GPU7,
+	PUCTL_KBCA,
+	PUCTL_KBCB,
+	PUCTL_KBCC,
+	PUCTL_KBCD,
+
+	PUCTL_SPDI,
+	PUCTL_SPDO,
+	PUCTL_GPSLXAU,
+	PUCTL_CRTP,
+	PUCTL_SLXC,
+	PUCTL_SLXD,
+	PUCTL_SLXK,
+
+	/* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */
+	PUCTL_CDEV1,
+	PUCTL_CDEV2,
+	PUCTL_SPIA,
+	PUCTL_SPIB,
+	PUCTL_SPIC,
+	PUCTL_SPID,
+	PUCTL_SPIE,
+	PUCTL_SPIF,
+
+	PUCTL_SPIG,
+	PUCTL_SPIH,
+	PUCTL_IRTX,
+	PUCTL_IRRX,
+	PUCTL_GME,
+	PUCTL_RESERVED45,
+	PUCTL_XM2D,
+	PUCTL_XM2C,
+
+	/* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */
+	PUCTL_UAA,
+	PUCTL_UAB,
+	PUCTL_UAC,
+	PUCTL_UAD,
+	PUCTL_UCA,
+	PUCTL_UCB,
+	PUCTL_LD17,
+	PUCTL_LD19_18,
+
+	PUCTL_LD21_20,
+	PUCTL_LD23_22,
+	PUCTL_LS,
+	PUCTL_LC,
+	PUCTL_CSUS,
+	PUCTL_DDRC,
+	PUCTL_SDC,
+	PUCTL_SDD,
+
+	/* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */
+	PUCTL_KBCF,
+	PUCTL_KBCE,
+	PUCTL_PMCA,
+	PUCTL_PMCB,
+	PUCTL_PMCC,
+	PUCTL_PMCD,
+	PUCTL_PMCE,
+	PUCTL_CK32,
+
+	PUCTL_UDA,
+	PUCTL_SDMMC1,
+	PUCTL_GMA,
+	PUCTL_GMB,
+	PUCTL_GMC,
+	PUCTL_GMD,
+	PUCTL_DDC,
+	PUCTL_OWC,
+
+	PUCTL_NONE = -1
+};
+
+struct tegra_pingroup_desc {
+	const char *name;
+	enum pmux_func funcs[4];
+	enum pmux_func func_safe;
+	enum pmux_vddio vddio;
+	enum pmux_ctlid ctl_id;
+	enum pmux_pullid pull_id;
+};
+
+
+/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */
+#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5)
+
+/* Mask value for a tristate (within TRISTATE_REG(id)) */
+#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f))
+
+/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */
+#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4)
+
+/* Converts a PUCTL id to a shift position */
+#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f)
+
+/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */
+#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4)
+
+/* Converts a MUXCTL id to a shift position */
+#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f)
+
+/* Convenient macro for defining pin group properties */
+#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd)		\
+	{						\
+		.vddio = PMUX_VDDIO_ ## vdd,		\
+		.funcs = {				\
+			PMUX_FUNC_ ## f0,			\
+			PMUX_FUNC_ ## f1,			\
+			PMUX_FUNC_ ## f2,			\
+			PMUX_FUNC_ ## f3,			\
+		},					\
+		.func_safe = PMUX_FUNC_ ## f_safe,		\
+		.ctl_id = mux,				\
+		.pull_id = pupd				\
+	}
+
+/* A normal pin group where the mux name and pull-up name match */
+#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe)		\
+		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\
+			MUXCTL_ ## pg_name, PUCTL_ ## pg_name)
+
+/* A pin group where the pull-up name doesn't have a 1-1 mapping */
+#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd)		\
+		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\
+			MUXCTL_ ## pg_name, PUCTL_ ## pupd)
+
+/* A pin group number which is not used */
+#define PIN_RESERVED \
+	PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE)
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
+	PIN(ATA,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE),
+	PIN(ATB,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
+	PIN(ATC,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
+	PIN(ATD,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE),
+	PIN(CDEV1, AUDIO, OSC,   PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC),
+	PIN(CDEV2, AUDIO, OSC,   AHB_CLK, APB_CLK, PLLP_OUT4,    OSC),
+	PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK,
+		PLLC_OUT1),
+	PIN(DAP1, AUDIO, DAP1,   RSVD,   GMI,       SDIO2,       DAP1),
+
+	PIN(DAP2, AUDIO, DAP2,   TWC,    RSVD,      GMI,         DAP2),
+	PIN(DAP3, BB,    DAP3,   RSVD,   RSVD,      RSVD,        DAP3),
+	PIN(DAP4, UART,  DAP4,   RSVD,   GMI,       RSVD,        DAP4),
+	PIN(DTA,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD4),
+	PIN(DTB,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1),
+	PIN(DTC,  VI,    RSVD,   RSVD,   VI,        RSVD,        RSVD1),
+	PIN(DTD,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD1),
+	PIN(DTE,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1),
+
+	PINP(GPU, UART,  PWM,    UARTA,  GMI,       RSVD,        RSVD4,
+		GPSLXAU),
+	PIN(GPV,  SD,    PCIE,   RSVD,   RSVD,      RSVD,        PCIE),
+	PIN(I2CP, SYS,   I2C,    RSVD,   RSVD,      RSVD,        RSVD4),
+	PIN(IRTX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB),
+	PIN(IRRX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB),
+	PIN(KBCB, SYS,   KBC,    NAND,   SDIO2,     MIO,         KBC),
+	PIN(KBCA, SYS,   KBC,    NAND,   SDIO2,     EMC_TEST0_DLL, KBC),
+	PINP(PMC, SYS,   PWR_ON, PWR_INTR, RSVD,    RSVD,        PWR_ON, NONE),
+
+	PIN(PTA,  NAND,  I2C2,   HDMI,   GMI,       RSVD,        RSVD4),
+	PIN(RM,   UART,  I2C,    RSVD,   RSVD,      RSVD,        RSVD4),
+	PIN(KBCE, SYS,   KBC,    NAND,   OWR,       RSVD,        KBC),
+	PIN(KBCF, SYS,   KBC,    NAND,   TRACE,     MIO,         KBC),
+	PIN(GMA,  NAND,  UARTE,  SPI3,   GMI,       SDIO4,       SPI3),
+	PIN(GMC,  NAND,  UARTD,  SPI4,   GMI,       SFLASH,      SPI4),
+	PIN(SDMMC1, BB,  SDIO1,  RSVD,   UARTE,     UARTA,       RSVD2),
+	PIN(OWC,  SYS,   OWR,    RSVD,   RSVD,      RSVD,        OWR),
+
+	PIN(GME,  NAND,  RSVD,   DAP5,   GMI,       SDIO4,       GMI),
+	PIN(SDC,  SD,    PWM,    TWC,    SDIO3,     SPI3,        TWC),
+	PIN(SDD,  SD,    UARTA,  PWM,    SDIO3,     SPI3,        PWM),
+	PIN_RESERVED,
+	PINP(SLXA, SD,   PCIE,   SPI4,   SDIO3,     SPI2,        PCIE, CRTP),
+	PIN(SLXC, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4),
+	PIN(SLXD, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4),
+	PIN(SLXK, SD,    PCIE,   SPI4,   SDIO3,     SPI2,        PCIE),
+
+	PIN(SPDI, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2),
+	PIN(SPDO, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2),
+	PIN(SPIA, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
+	PIN(SPIB, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
+	PIN(SPIC, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI),
+	PIN(SPID, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI),
+	PIN(SPIE, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI),
+	PIN(SPIF, AUDIO, SPI3,   SPI1,   SPI2,      RSVD,        RSVD4),
+
+	PIN(SPIG, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT),
+	PIN(SPIH, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT),
+	PIN(UAA,  BB,    SPI3,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
+	PIN(UAB,  BB,    SPI2,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
+	PIN(UAC,  BB,    OWR,    RSVD,   RSVD,      RSVD,        RSVD4),
+	PIN(UAD,  UART,  IRDA,   SPDIF,  UARTA,     SPI4,        SPDIF),
+	PIN(UCA,  UART,  UARTC,  RSVD,   GMI,       RSVD,        RSVD4),
+	PIN(UCB,  UART,  UARTC,  PWM,    GMI,       RSVD,        RSVD4),
+
+	PIN_RESERVED,
+	PIN(ATE,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE),
+	PIN(KBCC, SYS,   KBC,    NAND,   TRACE,     EMC_TEST1_DLL, KBC),
+	PIN_RESERVED,
+	PIN_RESERVED,
+	PIN(GMB,  NAND,  IDE,    NAND,   GMI,       GMI_INT,     GMI),
+	PIN(GMD,  NAND,  RSVD,   NAND,   GMI,       SFLASH,      GMI),
+	PIN(DDC,  LCD,   I2C2,   RSVD,   RSVD,      RSVD,        RSVD4),
+
+	/* 64 */
+	PINP(LD0,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD1,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD2,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD3,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD4,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD5,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD6,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD7,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+
+	PINP(LD8,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD9,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD10, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD11, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD12, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD13, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD14, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD15, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+
+	PINP(LD16, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17),
+	PINP(LD17, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD17),
+	PINP(LHP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20),
+	PINP(LHP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18),
+	PINP(LHP2, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18),
+	PINP(LVP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LC),
+	PINP(LVP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20),
+	PINP(HDINT, LCD, HDMI,   RSVD,   RSVD,      RSVD,     HDMI , LC),
+
+	PINP(LM0,  LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LC),
+	PINP(LM1,  LCD,  DISPA,  DISPB,  RSVD,      CRT,      RSVD3, LC),
+	PINP(LVS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
+	PINP(LSC0, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
+	PINP(LSC1, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
+	PINP(LSCK, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
+	PINP(LDC,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS),
+	PINP(LCSN, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LS),
+
+	/* 96 */
+	PINP(LSPI, LCD,  DISPA,  DISPB,  XIO,       HDMI,     DISPA, LC),
+	PINP(LSDA, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
+	PINP(LSDI, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     DISPA, LS),
+	PINP(LPW0, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
+	PINP(LPW1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS),
+	PINP(LPW2, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS),
+	PINP(LDI,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22),
+	PINP(LHS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC),
+
+	PINP(LPP,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22),
+	PIN_RESERVED,
+	PIN(KBCD,  SYS,  KBC,    NAND,   SDIO2,     MIO,      KBC),
+	PIN(GPU7,  SYS,  RTCK,   RSVD,   RSVD,      RSVD,     RTCK),
+	PIN(DTF,   VI,   I2C3,   RSVD,   VI,        RSVD,     RSVD4),
+	PIN(UDA,   BB,   SPI1,   RSVD,   UARTD,     ULPI,     RSVD2),
+	PIN(CRTP,  LCD,  CRT,    RSVD,   RSVD,      RSVD,     RSVD),
+	PINP(SDB,  SD,   UARTA,  PWM,    SDIO3,     SPI2,     PWM,   NONE),
+
+	/* these pin groups only have pullup and pull down control */
+	PINALL(CK32,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(DDRC,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(PMCA,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(PMCB,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(PMCC,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(PMCD,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(PMCE,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(XM2C,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+	PINALL(XM2D,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE,
+		PUCTL_NONE),
+};
+
+void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
+{
+	struct pmux_tri_ctlr *pmt =
+			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)];
+	u32 reg;
+
+	reg = readl(tri);
+	if (enable)
+		reg |= TRISTATE_MASK(pin);
+	else
+		reg &= ~TRISTATE_MASK(pin);
+	writel(reg, tri);
+}
+
+void pinmux_tristate_enable(enum pmux_pingrp pin)
+{
+	pinmux_set_tristate(pin, 1);
+}
+
+void pinmux_tristate_disable(enum pmux_pingrp pin)
+{
+	pinmux_set_tristate(pin, 0);
+}
+
+void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
+{
+	struct pmux_tri_ctlr *pmt =
+			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id;
+	u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)];
+	u32 mask_bit;
+	u32 reg;
+	mask_bit = PULL_SHIFT(pull_id);
+
+	reg = readl(pull);
+	reg &= ~(0x3 << mask_bit);
+	reg |= pupd << mask_bit;
+	writel(reg, pull);
+}
+
+void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
+{
+	struct pmux_tri_ctlr *pmt =
+			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
+	u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
+	u32 mask_bit;
+	int i, mux = -1;
+	u32 reg;
+
+	assert(pmux_func_isvalid(func));
+
+	/* Handle special values */
+	if (func >= PMUX_FUNC_RSVD1) {
+		mux = (func - PMUX_FUNC_RSVD1) & 0x3;
+	} else {
+		/* Search for the appropriate function */
+		for (i = 0; i < 4; i++) {
+			if (tegra_soc_pingroups[pin].funcs[i] == func) {
+				mux = i;
+				break;
+			}
+		}
+	}
+	assert(mux != -1);
+
+	mask_bit = MUXCTL_SHIFT(mux_id);
+	reg = readl(muxctl);
+	reg &= ~(0x3 << mask_bit);
+	reg |= mux << mask_bit;
+	writel(reg, muxctl);
+}
+
+void pinmux_config_pingroup(struct pingroup_config *config)
+{
+	enum pmux_pingrp pin = config->pingroup;
+
+	pinmux_set_func(pin, config->func);
+	pinmux_set_pullupdown(pin, config->pull);
+	pinmux_set_tristate(pin, config->tristate);
+}
+
+void pinmux_config_table(struct pingroup_config *config, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		pinmux_config_pingroup(&config[i]);
+}
diff --git a/arch/arm/cpu/tegra2-common/sys_info.c b/arch/arm/cpu/tegra2-common/sys_info.c
new file mode 100644
index 0000000..6d11dc1
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/sys_info.c
@@ -0,0 +1,35 @@
+/*
+ * (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>
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+/* Print CPU information */
+int print_cpuinfo(void)
+{
+	puts("TEGRA2\n");
+
+	/* TBD: Add printf of major/minor rev info, stepping, etc. */
+	return 0;
+}
+#endif	/* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/tegra2-common/timer.c b/arch/arm/cpu/tegra2-common/timer.c
new file mode 100644
index 0000000..b12b12c
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/timer.c
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * (C) Copyright 2008
+ * Texas Instruments
+ *
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Syed Moahmmed Khasim <khasim@ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * 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/tegra2.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* counter runs at 1MHz */
+#define TIMER_CLK	1000000
+#define TIMER_LOAD_VAL	0xffffffff
+
+/* timer without interrupts */
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+/* delay x useconds */
+void __udelay(unsigned long usec)
+{
+	long tmo = usec * (TIMER_CLK / 1000) / 1000;
+	unsigned long now, last = timer_get_us();
+
+	while (tmo > 0) {
+		now = timer_get_us();
+		if (last > now) /* count up timer overflow */
+			tmo -= TIMER_LOAD_VAL - last + now;
+		else
+			tmo -= now - last;
+		last = now;
+	}
+}
+
+ulong get_timer_masked(void)
+{
+	ulong now;
+
+	/* current tick value */
+	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
+
+	if (now >= gd->lastinc)	/* normal mode (non roll) */
+		/* move stamp forward with absolute diff ticks */
+		gd->tbl += (now - gd->lastinc);
+	else	/* we have rollover of incrementer */
+		gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
+				- gd->lastinc) + now;
+	gd->lastinc = now;
+	return gd->tbl;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
+
+unsigned long timer_get_us(void)
+{
+	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
+
+	return readl(&timer_base->cntr_1us);
+}
diff --git a/spl/Makefile b/spl/Makefile
index ea7d475..6d3241f 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -62,6 +62,10 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
 
+ifneq ($(CONFIG_TEGRA2),)
+LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
+
 START := $(addprefix $(SPLTREE)/,$(START))
 LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-18 18:17 ` [U-Boot] [PATCH 1/1] " Allen Martin
@ 2012-04-18 22:46   ` Allen Martin
  2012-04-19 18:27     ` Simon Glass
  0 siblings, 1 reply; 8+ messages in thread
From: Allen Martin @ 2012-04-18 22:46 UTC (permalink / raw)
  To: u-boot

In preparation for splitting out the armv4t code from tegra2, move the
tegra2 SoC code to arch/arm/cpu/tegra2-common.  This code will be
compiled armv4t for the arm7tdmi and armv7 for the cortex A9.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
Resending this with "git format-patch -M" to make it more readable
and removing cover letter

This is part of an upcoming patch set to move all armv4t code out of
tegra2 u-boot and put it into an SPL, but I wanted to get some early
feedback on this patch.  This moves most of the tegra2 SoC code from
arch/arm/cpu/armv7 to a new directory arch/arm/cpu/tegra2-common.
This code will be shared between the armv7 and armv4t builds of
tegra2.

 Makefile                                           |    3 +
 arch/arm/cpu/armv7/tegra2/Makefile                 |   12 +----
 arch/arm/cpu/tegra2-common/Makefile                |   56 ++++++++++++++++++++
 .../arm/cpu/{armv7/tegra2 => tegra2-common}/ap20.c |    0
 .../arm/cpu/{armv7/tegra2 => tegra2-common}/ap20.h |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/board.c    |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/clock.c    |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/funcmux.c  |    0
 .../tegra2 => tegra2-common}/lowlevel_init.S       |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/pinmux.c   |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/sys_info.c |    0
 .../cpu/{armv7/tegra2 => tegra2-common}/timer.c    |    0
 spl/Makefile                                       |    4 ++
 13 files changed, 65 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/cpu/tegra2-common/Makefile
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/ap20.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/ap20.h (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/board.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/clock.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/funcmux.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/lowlevel_init.S (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/pinmux.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/sys_info.c (100%)
 rename arch/arm/cpu/{armv7/tegra2 => tegra2-common}/timer.c (100%)

diff --git a/Makefile b/Makefile
index 4ddf8d6..6639de0 100644
--- a/Makefile
+++ b/Makefile
@@ -319,6 +319,9 @@ endif
 ifeq ($(SOC),exynos)
 LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
 endif
+ifeq ($(SOC),tegra2)
+LIBS += $(OBJTREE)/arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
 
 LIBS := $(addprefix $(obj),$(sort $(LIBS)))
 .PHONY : $(LIBS)
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index e9ac6c9..34452c4 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -22,23 +22,15 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 # MA 02111-1307 USA
 #
-
-# The AVP is ARMv4T architecture so we must use special compiler
-# flags for any startup files it might use.
-CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t
-CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t
-
 include $(TOPDIR)/config.mk
 
 LIB	=  $(obj)lib$(SOC).o
 
-SOBJS	:= lowlevel_init.o
-COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 
 COBJS	:= $(COBJS-y)
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
 
 all:	 $(obj).depend $(LIB)
 
diff --git a/arch/arm/cpu/tegra2-common/Makefile b/arch/arm/cpu/tegra2-common/Makefile
new file mode 100644
index 0000000..8de59cf
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/Makefile
@@ -0,0 +1,56 @@
+#
+# (C) Copyright 2010,2011 Nvidia Corporation.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# 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
+
+# The AVP is ARMv4T architecture so we must use special compiler
+# flags for any startup files it might use.
+CFLAGS_arch/arm/cpu/tegra2-common/ap20.o += -march=armv4t
+CFLAGS_arch/arm/cpu/tegra2-common/clock.o += -march=armv4t
+
+LIB	= $(obj)lib$(SOC)-common.o
+
+SOBJS += lowlevel_init.o
+COBJS-y	+= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+$(obj).depend:
+	echo wtf
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/tegra2-common/ap20.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/ap20.c
rename to arch/arm/cpu/tegra2-common/ap20.c
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/cpu/tegra2-common/ap20.h
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/ap20.h
rename to arch/arm/cpu/tegra2-common/ap20.h
diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/tegra2-common/board.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/board.c
rename to arch/arm/cpu/tegra2-common/board.c
diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/tegra2-common/clock.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/clock.c
rename to arch/arm/cpu/tegra2-common/clock.c
diff --git a/arch/arm/cpu/armv7/tegra2/funcmux.c b/arch/arm/cpu/tegra2-common/funcmux.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/funcmux.c
rename to arch/arm/cpu/tegra2-common/funcmux.c
diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/tegra2-common/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/lowlevel_init.S
rename to arch/arm/cpu/tegra2-common/lowlevel_init.S
diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/tegra2-common/pinmux.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/pinmux.c
rename to arch/arm/cpu/tegra2-common/pinmux.c
diff --git a/arch/arm/cpu/armv7/tegra2/sys_info.c b/arch/arm/cpu/tegra2-common/sys_info.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/sys_info.c
rename to arch/arm/cpu/tegra2-common/sys_info.c
diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/tegra2-common/timer.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/timer.c
rename to arch/arm/cpu/tegra2-common/timer.c
diff --git a/spl/Makefile b/spl/Makefile
index ea7d475..6d3241f 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -62,6 +62,10 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
 
+ifneq ($(CONFIG_TEGRA2),)
+LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
+
 START := $(addprefix $(SPLTREE)/,$(START))
 LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-18 22:46   ` [U-Boot] [PATCH] " Allen Martin
@ 2012-04-19 18:27     ` Simon Glass
  2012-04-19 19:22       ` Allen Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Glass @ 2012-04-19 18:27 UTC (permalink / raw)
  To: u-boot

+Albert

Hi Allen,

On Wed, Apr 18, 2012 at 3:46 PM, Allen Martin <amartin@nvidia.com> wrote:
> In preparation for splitting out the armv4t code from tegra2, move the
> tegra2 SoC code to arch/arm/cpu/tegra2-common. ?This code will be
> compiled armv4t for the arm7tdmi and armv7 for the cortex A9.
>
> Signed-off-by: Allen Martin <amartin@nvidia.com>
> ---
> Resending this with "git format-patch -M" to make it more readable
> and removing cover letter
>
> This is part of an upcoming patch set to move all armv4t code out of
> tegra2 u-boot and put it into an SPL, but I wanted to get some early
> feedback on this patch. ?This moves most of the tegra2 SoC code from
> arch/arm/cpu/armv7 to a new directory arch/arm/cpu/tegra2-common.
> This code will be shared between the armv7 and armv4t builds of
> tegra2.

I am not sure whether moving things up a level is OK. It makes some
sense to me but is different from what other boards do.

Secondly, you will at some point add Tegra 3 support I suppose. In
that case much of this code will become common anyway. Should you do
that split (tegra-common, tegra2-common) now or later?

Regards,
Simon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-19 18:27     ` Simon Glass
@ 2012-04-19 19:22       ` Allen Martin
  2012-04-30 18:31         ` Simon Glass
  0 siblings, 1 reply; 8+ messages in thread
From: Allen Martin @ 2012-04-19 19:22 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 19, 2012 at 11:27:05AM -0700, Simon Glass wrote:
> >
> > This is part of an upcoming patch set to move all armv4t code out of
> > tegra2 u-boot and put it into an SPL, but I wanted to get some early
> > feedback on this patch. ?This moves most of the tegra2 SoC code from
> > arch/arm/cpu/armv7 to a new directory arch/arm/cpu/tegra2-common.
> > This code will be shared between the armv7 and armv4t builds of
> > tegra2.
> 
> I am not sure whether moving things up a level is OK. It makes some
> sense to me but is different from what other boards do.

Agreed I couldn't find any other examples, but AFAIK no other board is
trying to do what we do (sharing code between 2 different CPU
models).  The other options I contemplated were:

-Have the armv4t build reach up and over into armv7
-Move the code out to board/nvidia

Both of these seemed worse


> Secondly, you will at some point add Tegra 3 support I suppose. In
> that case much of this code will become common anyway. Should you do
> that split (tegra-common, tegra2-common) now or later?

I'd like to keep the tegra3 changes separate since that will involve
refactoring of much of this code.  For the SPL build it's mostly
hidden in the config and Makefiles.  

I thought about doing exactly what you said to reduce the amount of
code I needed to pull into the SPL build, but what I found was that
because the SPL needs to initialize some regulators, clocks, and
pinmux to bring up the A9 and UART it ends up needing much of the
tegra2 SoC code, so there's not a lot of opportunity to minize the
code set for the SPL build beyond the CONFIG options to disable
drivers that area already there.

-Allen
nvpublic

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-19 19:22       ` Allen Martin
@ 2012-04-30 18:31         ` Simon Glass
  2012-04-30 19:52           ` Allen Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Glass @ 2012-04-30 18:31 UTC (permalink / raw)
  To: u-boot

Hi Allen,

On Thu, Apr 19, 2012 at 12:22 PM, Allen Martin <amartin@nvidia.com> wrote:

> On Thu, Apr 19, 2012 at 11:27:05AM -0700, Simon Glass wrote:
> > >
> > > This is part of an upcoming patch set to move all armv4t code out of
> > > tegra2 u-boot and put it into an SPL, but I wanted to get some early
> > > feedback on this patch.  This moves most of the tegra2 SoC code from
> > > arch/arm/cpu/armv7 to a new directory arch/arm/cpu/tegra2-common.
> > > This code will be shared between the armv7 and armv4t builds of
> > > tegra2.
> >
> > I am not sure whether moving things up a level is OK. It makes some
> > sense to me but is different from what other boards do.
>
> Agreed I couldn't find any other examples, but AFAIK no other board is
> trying to do what we do (sharing code between 2 different CPU
> models).  The other options I contemplated were:
>
> -Have the armv4t build reach up and over into armv7
> -Move the code out to board/nvidia
>
> Both of these seemed worse
>

I've thought about this a bit more. To me you have a bit of a unique
problem in that you need to build the code as both ARMv4T and ARMv7. The
way it works at the moment is pretty simple - we just mark a few files that
must be build with ARMv4T and ARMv7 is happy with that also.

I believe the point of the 'cpu' directory is to separate out common code
between different architectures. It seems you want a chip which uses two
different architectures. That might be unique in the U-Boot world - I note
that other SOCs with different chips use ARMv7 for all of them.

But really, who cares what architecture you actually use? The code clearly
doesn't include ARMv7-isms otherwise it wouldn't build with current compile
options. It does work...

So my suggestion is that you just continue as now, and build the relevant
code for ARMv4T. I don't see a compelling reason to move it, least of all
into a no-man's land at the same level as 'cpu'.


>
> > Secondly, you will at some point add Tegra 3 support I suppose. In
> > that case much of this code will become common anyway. Should you do
> > that split (tegra-common, tegra2-common) now or later?
>
> I'd like to keep the tegra3 changes separate since that will involve
> refactoring of much of this code.  For the SPL build it's mostly
> hidden in the config and Makefiles.
>
> I thought about doing exactly what you said to reduce the amount of
> code I needed to pull into the SPL build, but what I found was that
> because the SPL needs to initialize some regulators, clocks, and
> pinmux to bring up the A9 and UART it ends up needing much of the
> tegra2 SoC code, so there's not a lot of opportunity to minize the
> code set for the SPL build beyond the CONFIG options to disable
> drivers that area already there.
>

OK. Please note that we do have a refactor in the Chromium tree to move
things into tegra-common and add T30 support. We hope to get this upstream
once the T20 stuff is there (NAND, keyboard and LCD are still pending).

Regards,
Simon


>
> -Allen
> nvpublic
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-30 18:31         ` Simon Glass
@ 2012-04-30 19:52           ` Allen Martin
  2012-06-10  3:16             ` Simon Glass
  0 siblings, 1 reply; 8+ messages in thread
From: Allen Martin @ 2012-04-30 19:52 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 30, 2012 at 11:31:44AM -0700, Simon Glass wrote:
> 
> -Have the armv4t build reach up and over into armv7
> -Move the code out to board/nvidia
> 
> Both of these seemed worse
> 
> I've thought about this a bit more. To me you have a bit of a unique problem in that you need to build the code as both ARMv4T and ARMv7. The way it works at the moment is pretty simple - we just mark a few files that must be build with ARMv4T and ARMv7 is happy with that also.
> 
> I believe the point of the 'cpu' directory is to separate out common code between different architectures. It seems you want a chip which uses two different architectures. That might be unique in the U-Boot world - I note that other SOCs with different chips use ARMv7 for all of them.
> 
> But really, who cares what architecture you actually use? The code clearly doesn't include ARMv7-isms otherwise it wouldn't build with current compile options. It does work...
> 
> So my suggestion is that you just continue as now, and build the relevant code for ARMv4T. I don't see a compelling reason to move it, least of all into a no-man's land at the same level as 'cpu'.
> 

The problem that pushed me over the edge on this was the patch series
to add thumb support for ARM.  The linker has to insert interworking
code for the cross ARM/thumb calls.  If it is linking armv4t and armv7
objects together it will promote them all to armv7 style interworking
which uses instructions that are illegal on armv4t.  The only fix for
this is to link armv4t objects separately or not support thumb, and we
would really like to support thumb.

Also it's not true that the code in arch/arm/cpu/armv7 doesn't include
any armv7'isms, we're just #ifdef around them for the tegra and call
them later in the boot sequence when we know we're running on the A9.
We also have to code the init sequence extremely carefully to make
sure we don't call any armv7 code on the armv4t.  It's extremely
fragile as any changes to start.S or the ordering of the init sequence
can (and have) broken us.

-Allen
--
nvpublic

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
  2012-04-30 19:52           ` Allen Martin
@ 2012-06-10  3:16             ` Simon Glass
  0 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2012-06-10  3:16 UTC (permalink / raw)
  To: u-boot

Hi Allen,

On Mon, Apr 30, 2012 at 12:52 PM, Allen Martin <amartin@nvidia.com> wrote:

> On Mon, Apr 30, 2012 at 11:31:44AM -0700, Simon Glass wrote:
> >
> > -Have the armv4t build reach up and over into armv7
> > -Move the code out to board/nvidia
> >
> > Both of these seemed worse
> >
> > I've thought about this a bit more. To me you have a bit of a unique
> problem in that you need to build the code as both ARMv4T and ARMv7. The
> way it works at the moment is pretty simple - we just mark a few files that
> must be build with ARMv4T and ARMv7 is happy with that also.
> >
> > I believe the point of the 'cpu' directory is to separate out common
> code between different architectures. It seems you want a chip which uses
> two different architectures. That might be unique in the U-Boot world - I
> note that other SOCs with different chips use ARMv7 for all of them.
> >
> > But really, who cares what architecture you actually use? The code
> clearly doesn't include ARMv7-isms otherwise it wouldn't build with current
> compile options. It does work...
> >
> > So my suggestion is that you just continue as now, and build the
> relevant code for ARMv4T. I don't see a compelling reason to move it, least
> of all into a no-man's land at the same level as 'cpu'.
> >
>
> The problem that pushed me over the edge on this was the patch series
> to add thumb support for ARM.  The linker has to insert interworking
> code for the cross ARM/thumb calls.  If it is linking armv4t and armv7
> objects together it will promote them all to armv7 style interworking
> which uses instructions that are illegal on armv4t.  The only fix for
> this is to link armv4t objects separately or not support thumb, and we
> would really like to support thumb.
>

OK I just remembered this thread...

The Thumb reason makes good sense to me. That said, you could arrange to
avoid interworked calls and have all the ARMv4 code built with the same
flags (and not allow the ARM7TDMI to enter board_init_f()).

So perhaps another way of putting it is that you are using SPL as a
convenient and existing way to allow you to built two parts of U-Boot with
separate flags.


>
> Also it's not true that the code in arch/arm/cpu/armv7 doesn't include
> any armv7'isms, we're just #ifdef around them for the tegra and call
> them later in the boot sequence when we know we're running on the A9.
> We also have to code the init sequence extremely carefully to make
> sure we don't call any armv7 code on the armv4t.  It's extremely
> fragile as any changes to start.S or the ordering of the init sequence
> can (and have) broken us.
>

See my other mail about this. I think you overstate things a little :-)
 But anyway, I think I understand the desirability for this now.


>
> -Allen
> --
> nvpublic
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-06-10  3:16 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-18 18:17 [U-Boot] [PATCH 0/1] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common Allen Martin
2012-04-18 18:17 ` [U-Boot] [PATCH 1/1] " Allen Martin
2012-04-18 22:46   ` [U-Boot] [PATCH] " Allen Martin
2012-04-19 18:27     ` Simon Glass
2012-04-19 19:22       ` Allen Martin
2012-04-30 18:31         ` Simon Glass
2012-04-30 19:52           ` Allen Martin
2012-06-10  3:16             ` Simon Glass

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.