diff --git a/MAINTAINERS b/MAINTAINERS
index d4242846e7afbc64588adedd2e9e8e7cd04804d0..54d94ca9d6e8376a2a0f579e98dae44ba6fc904b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5565,6 +5565,15 @@ W:	http://tcp-lp-mod.sourceforge.net/
 S:	Maintained
 F:	net/ipv4/tcp_lp.c
 
+TEGRA SUPPORT
+M:	Colin Cross <ccross@android.com>
+M:	Erik Gilling <konkers@android.com>
+M:	Olof Johansson <olof@lixom.net>
+L:	linux-tegra@vger.kernel.org
+T:	git git://android.git.kernel.org/kernel/tegra.git
+S:	Supported
+F:	arch/arm/mach-tegra
+
 TEHUTI ETHERNET DRIVER
 M:	Alexander Indenbaum <baum@tehutinetworks.net>
 M:	Andy Gospodarek <andy@greyhouse.net>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9e10882c81d7746e06f0908cb5ce0198e2d2654d..232f0c7582520e97b4d7779bf760d1df69a3cfbe 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -558,6 +558,18 @@ config ARCH_NUC93X
 	  Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
 	  low-power and high performance MPEG-4/JPEG multimedia controller chip.
 
+config ARCH_TEGRA
+	bool "NVIDIA Tegra"
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select ARCH_HAS_BARRIERS if CACHE_L2X0
+	help
+	  This enables support for NVIDIA Tegra based systems (Tegra APX,
+	  Tegra 6xx and Tegra 2 series).
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -907,6 +919,8 @@ source "arch/arm/mach-shmobile/Kconfig"
 
 source "arch/arm/plat-stmp3xxx/Kconfig"
 
+source "arch/arm/mach-tegra/Kconfig"
+
 source "arch/arm/mach-u300/Kconfig"
 
 source "arch/arm/mach-ux500/Kconfig"
@@ -1094,10 +1108,11 @@ config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-		 ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+		 ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
 	depends on GENERIC_CLOCKEVENTS
 	select USE_GENERIC_SMP_HELPERS
-	select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+	select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || \
+		 ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -1167,9 +1182,10 @@ config LOCAL_TIMERS
 	bool "Use local timer interrupts"
 	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
 		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-		ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+		ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
 	default y
-	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || ARCH_U8500)
+	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || \\
+		ARCH_U8500 || ARCH_TEGRA
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 63d998e8c672ef4488eb72df2cfdcce2f7ae502f..a8d4dca9da35a4310ee9a65ff08856957629f0f0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -179,6 +179,7 @@ machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
 machine-$(CONFIG_ARCH_STMP378X)		:= stmp378x
 machine-$(CONFIG_ARCH_STMP37XX)		:= stmp37xx
+machine-$(CONFIG_ARCH_TEGRA)		:= tegra
 machine-$(CONFIG_ARCH_U300)		:= u300
 machine-$(CONFIG_ARCH_U8500)		:= ux500
 machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..a57713c1954abe0ca329648d7fc398c8ac3d64f7
--- /dev/null
+++ b/arch/arm/mach-tegra/Kconfig
@@ -0,0 +1,50 @@
+if ARCH_TEGRA
+
+comment "NVIDIA Tegra options"
+
+choice
+	prompt "Select Tegra processor family for target system"
+
+config ARCH_TEGRA_2x_SOC
+	bool "Tegra 2 family"
+	select CPU_V7
+	select ARM_GIC
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
+	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
+
+endchoice
+
+comment "Tegra board type"
+
+config MACH_HARMONY
+       bool "Harmony board"
+       help
+         Support for nVidia Harmony development platform
+
+choice
+        prompt "Low-level debug console UART"
+        default TEGRA_DEBUG_UART_NONE
+
+config TEGRA_DEBUG_UART_NONE
+        bool "None"
+
+config TEGRA_DEBUG_UARTA
+        bool "UART-A"
+
+config TEGRA_DEBUG_UARTB
+        bool "UART-B"
+
+config TEGRA_DEBUG_UARTC
+        bool "UART-C"
+
+config TEGRA_DEBUG_UARTD
+        bool "UART-D"
+
+config TEGRA_DEBUG_UARTE
+        bool "UART-E"
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..51e9370eed99bb4ffb23323610fff4e5f3cd9787
--- /dev/null
+++ b/arch/arm/mach-tegra/Makefile
@@ -0,0 +1,14 @@
+obj-y                                   += common.o
+obj-y                                   += io.o
+obj-y                                   += irq.o
+obj-y                                   += clock.o
+obj-y                                   += timer.o
+obj-y                                   += gpio.o
+obj-y                                   += pinmux.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
+
+obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
new file mode 100644
index 0000000000000000000000000000000000000000..db52d61a73860cb0b4c19fa6c488303cbe15c210
--- /dev/null
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00008000
+params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
+initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
new file mode 100644
index 0000000000000000000000000000000000000000..50b15d500cacc73817258202178b0b79fc42478b
--- /dev/null
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -0,0 +1,144 @@
+/*
+ * arch/arm/mach-tegra/board-harmony-pinmux.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <mach/pinmux.h>
+
+#include "board-harmony.h"
+
+static struct tegra_pingroup_config harmony_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_UARTD,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+};
+
+void harmony_pinmux_init(void)
+{
+	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
+}
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
new file mode 100644
index 0000000000000000000000000000000000000000..05e78dd9b50ca22ef7b20e91f8a21e6e92c8021d
--- /dev/null
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-harmony.h"
+#include "clock.h"
+
+/* NVidia bootloader tags */
+#define ATAG_NVIDIA		0x41000801
+
+#define ATAG_NVIDIA_RM			0x1
+#define ATAG_NVIDIA_DISPLAY		0x2
+#define ATAG_NVIDIA_FRAMEBUFFER		0x3
+#define ATAG_NVIDIA_CHIPSHMOO		0x4
+#define ATAG_NVIDIA_CHIPSHMOOPHYS	0x5
+#define ATAG_NVIDIA_PRESERVED_MEM_0	0x10000
+#define ATAG_NVIDIA_PRESERVED_MEM_N	2
+#define ATAG_NVIDIA_FORCE_32		0x7fffffff
+
+struct tag_tegra {
+	__u32 bootarg_key;
+	__u32 bootarg_len;
+	char bootarg[1];
+};
+
+static int __init parse_tag_nvidia(const struct tag *tag)
+{
+
+	return 0;
+}
+__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
+		.mapbase	= TEGRA_UARTD_BASE,
+		.irq		= INT_UARTD,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = debug_uart_platform_data,
+	},
+};
+
+static struct platform_device *harmony_devices[] __initdata = {
+	&debug_uart,
+};
+
+static void __init tegra_harmony_fixup(struct machine_desc *desc,
+	struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 2;
+	mi->bank[0].start = PHYS_OFFSET;
+	mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET);
+	mi->bank[0].size = 448 * SZ_1M;
+	mi->bank[1].start = SZ_512M;
+	mi->bank[1].node = PHYS_TO_NID(SZ_512M);
+	mi->bank[1].size = SZ_512M;
+}
+
+static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uartd",	"pll_p",	216000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+static void __init tegra_harmony_init(void)
+{
+	tegra_common_init();
+
+	tegra_clk_init_from_table(harmony_clk_init_table);
+
+	harmony_pinmux_init();
+
+	platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
+}
+
+MACHINE_START(HARMONY, "harmony")
+	.boot_params  = 0x00000100,
+	.phys_io        = IO_APB_PHYS,
+	.io_pg_offst    = ((IO_APB_VIRT) >> 18) & 0xfffc,
+	.fixup		= tegra_harmony_fixup,
+	.init_irq       = tegra_init_irq,
+	.init_machine   = tegra_harmony_init,
+	.map_io         = tegra_map_common_io,
+	.timer          = &tegra_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h
new file mode 100644
index 0000000000000000000000000000000000000000..09ca7755dd5558b966833be98ea75c18e5b6efd0
--- /dev/null
+++ b/arch/arm/mach-tegra/board-harmony.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_HARMONY_H
+#define _MACH_TEGRA_BOARD_HARMONY_H
+
+void harmony_pinmux_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d06354136f2663ff2f80cdbfa9b441671dc4146
--- /dev/null
+++ b/arch/arm/mach-tegra/board.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-tegra/board.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_BOARD_H
+#define __MACH_TEGRA_BOARD_H
+
+#include <linux/types.h>
+
+void __init tegra_common_init(void);
+void __init tegra_map_common_io(void);
+void __init tegra_init_irq(void);
+void __init tegra_init_clock(void);
+
+extern struct sys_timer tegra_timer;
+#endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
new file mode 100644
index 0000000000000000000000000000000000000000..03ad578349b98aa55e89f8639ff49663dd0f8d6d
--- /dev/null
+++ b/arch/arm/mach-tegra/clock.c
@@ -0,0 +1,488 @@
+/*
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <asm/clkdev.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+
+static DEFINE_SPINLOCK(clock_lock);
+
+struct clk *tegra_get_clock_by_name(const char *name)
+{
+	struct clk *c;
+	struct clk *ret = NULL;
+	unsigned long flags;
+	spin_lock_irqsave(&clock_lock, flags);
+	list_for_each_entry(c, &clocks, node) {
+		if (strcmp(c->name, name) == 0) {
+			ret = c;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&clock_lock, flags);
+	return ret;
+}
+
+int clk_reparent(struct clk *c, struct clk *parent)
+{
+	pr_debug("%s: %s\n", __func__, c->name);
+	if (c->refcnt && c->parent)
+		clk_disable_locked(c->parent);
+	c->parent = parent;
+	if (c->refcnt && c->parent)
+		clk_enable_locked(c->parent);
+	list_del(&c->sibling);
+	list_add_tail(&c->sibling, &parent->children);
+	return 0;
+}
+
+static void propagate_rate(struct clk *c)
+{
+	struct clk *clkp;
+	pr_debug("%s: %s\n", __func__, c->name);
+	list_for_each_entry(clkp, &c->children, sibling) {
+		pr_debug("   %s\n", clkp->name);
+		if (clkp->ops->recalculate_rate)
+			clkp->ops->recalculate_rate(clkp);
+		propagate_rate(clkp);
+	}
+}
+
+void clk_init(struct clk *c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_lock, flags);
+
+	INIT_LIST_HEAD(&c->children);
+	INIT_LIST_HEAD(&c->sibling);
+
+	if (c->ops && c->ops->init)
+		c->ops->init(c);
+
+	list_add(&c->node, &clocks);
+
+	if (c->parent)
+		list_add_tail(&c->sibling, &c->parent->children);
+
+	spin_unlock_irqrestore(&clock_lock, flags);
+}
+
+int clk_enable_locked(struct clk *c)
+{
+	int ret;
+	pr_debug("%s: %s\n", __func__, c->name);
+	if (c->refcnt == 0) {
+		if (c->parent) {
+			ret = clk_enable_locked(c->parent);
+			if (ret)
+				return ret;
+		}
+
+		if (c->ops && c->ops->enable) {
+			ret = c->ops->enable(c);
+			if (ret) {
+				if (c->parent)
+					clk_disable_locked(c->parent);
+				return ret;
+			}
+			c->state = ON;
+#ifdef CONFIG_DEBUG_FS
+			c->set = 1;
+#endif
+		}
+	}
+	c->refcnt++;
+
+	return 0;
+}
+
+int clk_enable(struct clk *c)
+{
+	int ret;
+	unsigned long flags;
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = clk_enable_locked(c);
+	spin_unlock_irqrestore(&clock_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable_locked(struct clk *c)
+{
+	pr_debug("%s: %s\n", __func__, c->name);
+	if (c->refcnt == 0) {
+		WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
+		return;
+	}
+	if (c->refcnt == 1) {
+		if (c->ops && c->ops->disable)
+			c->ops->disable(c);
+
+		if (c->parent)
+			clk_disable_locked(c->parent);
+
+		c->state = OFF;
+	}
+	c->refcnt--;
+}
+
+void clk_disable(struct clk *c)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&clock_lock, flags);
+	clk_disable_locked(c);
+	spin_unlock_irqrestore(&clock_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_set_parent_locked(struct clk *c, struct clk *parent)
+{
+	int ret;
+
+	pr_debug("%s: %s\n", __func__, c->name);
+
+	if (!c->ops || !c->ops->set_parent)
+		return -ENOSYS;
+
+	ret = c->ops->set_parent(c, parent);
+
+	if (ret)
+		return ret;
+
+	propagate_rate(c);
+
+	return 0;
+}
+
+int clk_set_parent(struct clk *c, struct clk *parent)
+{
+	int ret;
+	unsigned long flags;
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = clk_set_parent_locked(c, parent);
+	spin_unlock_irqrestore(&clock_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *c)
+{
+	return c->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_lock, flags);
+
+	pr_debug("%s: %s\n", __func__, c->name);
+
+	if (c->ops && c->ops->set_rate)
+		ret = c->ops->set_rate(c, rate);
+	else
+		ret = -ENOSYS;
+
+	propagate_rate(c);
+
+	spin_unlock_irqrestore(&clock_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+unsigned long clk_get_rate(struct clk *c)
+{
+	unsigned long flags;
+	unsigned long ret;
+
+	spin_lock_irqsave(&clock_lock, flags);
+
+	pr_debug("%s: %s\n", __func__, c->name);
+
+	ret = c->rate;
+
+	spin_unlock_irqrestore(&clock_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
+{
+	struct clk *c;
+	struct clk *p;
+
+	int ret = 0;
+
+	c = tegra_get_clock_by_name(table->name);
+
+	if (!c) {
+		pr_warning("Unable to initialize clock %s\n",
+			table->name);
+		return -ENODEV;
+	}
+
+	if (table->parent) {
+		p = tegra_get_clock_by_name(table->parent);
+		if (!p) {
+			pr_warning("Unable to find parent %s of clock %s\n",
+				table->parent, table->name);
+			return -ENODEV;
+		}
+
+		if (c->parent != p) {
+			ret = clk_set_parent(c, p);
+			if (ret) {
+				pr_warning("Unable to set parent %s of clock %s: %d\n",
+					table->parent, table->name, ret);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (table->rate && table->rate != clk_get_rate(c)) {
+		ret = clk_set_rate(c, table->rate);
+		if (ret) {
+			pr_warning("Unable to set clock %s to rate %lu: %d\n",
+				table->name, table->rate, ret);
+			return -EINVAL;
+		}
+	}
+
+	if (table->enabled) {
+		ret = clk_enable(c);
+		if (ret) {
+			pr_warning("Unable to enable clock %s: %d\n",
+				table->name, ret);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
+{
+	for (; table->name; table++)
+		tegra_clk_init_one_from_table(table);
+}
+EXPORT_SYMBOL(tegra_clk_init_from_table);
+
+void tegra_periph_reset_deassert(struct clk *c)
+{
+	tegra2_periph_reset_deassert(c);
+}
+EXPORT_SYMBOL(tegra_periph_reset_deassert);
+
+void tegra_periph_reset_assert(struct clk *c)
+{
+	tegra2_periph_reset_assert(c);
+}
+EXPORT_SYMBOL(tegra_periph_reset_assert);
+
+int __init tegra_init_clock(void)
+{
+	tegra2_init_clocks();
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *clk_debugfs_root;
+
+
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+	struct clk *child;
+	struct clk *safe;
+	const char *state = "uninit";
+	char div[5] = {0};
+
+	if (c->state == ON)
+		state = "on";
+	else if (c->state == OFF)
+		state = "off";
+
+	if (c->mul != 0 && c->div != 0) {
+		BUG_ON(c->mul > 2);
+		if (c->mul > c->div)
+			snprintf(div, sizeof(div), "x%d", c->mul / c->div);
+		else
+			snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
+				(c->div % c->mul) ? ".5" : "");
+	}
+
+	seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
+		level * 3 + 1, c->set ? "" : "*",
+		30 - level * 3, c->name,
+		state, c->refcnt, div, c->rate);
+	list_for_each_entry_safe(child, safe, &c->children, sibling) {
+		clock_tree_show_one(s, child, level + 1);
+	}
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+	struct clk *c;
+	unsigned long flags;
+	seq_printf(s, " clock                          state  ref div   rate      \n");
+	seq_printf(s, "-----------------------------------------------------------\n");
+	spin_lock_irqsave(&clock_lock, flags);
+	list_for_each_entry(c, &clocks, node)
+		if (c->parent == NULL)
+			clock_tree_show_one(s, c, 0);
+	spin_unlock_irqrestore(&clock_lock, flags);
+	return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+	.open		= clock_tree_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int possible_parents_show(struct seq_file *s, void *data)
+{
+	struct clk *c = s->private;
+	int i;
+
+	for (i = 0; c->inputs[i].input; i++) {
+		char *first = (i == 0) ? "" : " ";
+		seq_printf(s, "%s%s", first, c->inputs[i].input->name);
+	}
+	seq_printf(s, "\n");
+	return 0;
+}
+
+static int possible_parents_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, possible_parents_show, inode->i_private);
+}
+
+static const struct file_operations possible_parents_fops = {
+	.open		= possible_parents_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+	struct dentry *d, *child, *child_tmp;
+
+	d = debugfs_create_dir(c->name, clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	c->dent = d;
+
+	d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+	if (!d)
+		goto err_out;
+
+	if (c->inputs) {
+		d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
+			c, &possible_parents_fops);
+		if (!d)
+			goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	d = c->dent;
+	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(c->dent);
+	return -ENOMEM;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->parent;
+
+	if (pa && !pa->dent) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dent) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err = -ENOMEM;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+		&clock_tree_fops);
+	if (!d)
+		goto err_out;
+
+	list_for_each_entry(c, &clocks, node) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+
+late_initcall(clk_debugfs_init);
+#endif
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
new file mode 100644
index 0000000000000000000000000000000000000000..af7c70e2a3baf4a29c8860ccc0ca51cd026cb1cd
--- /dev/null
+++ b/arch/arm/mach-tegra/clock.h
@@ -0,0 +1,147 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clock.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_CLOCK_H
+#define __MACH_TEGRA_CLOCK_H
+
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
+#define DIV_BUS			(1 << 0)
+#define DIV_U71			(1 << 1)
+#define DIV_U71_FIXED		(1 << 2)
+#define DIV_2			(1 << 3)
+#define PLL_FIXED		(1 << 4)
+#define PLL_HAS_CPCON		(1 << 5)
+#define MUX			(1 << 6)
+#define PLLD			(1 << 7)
+#define PERIPH_NO_RESET		(1 << 8)
+#define PERIPH_NO_ENB		(1 << 9)
+#define PERIPH_EMC_ENB		(1 << 10)
+#define PERIPH_MANUAL_RESET	(1 << 11)
+#define PLL_ALT_MISC_REG	(1 << 12)
+#define ENABLE_ON_INIT		(1 << 28)
+
+struct clk;
+
+struct clk_mux_sel {
+	struct clk	*input;
+	u32		value;
+};
+
+struct clk_pll_table {
+	unsigned long	input_rate;
+	unsigned long	output_rate;
+	u16		n;
+	u16		m;
+	u8		p;
+	u8		cpcon;
+};
+
+struct clk_ops {
+	void		(*init)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	void		(*recalc)(struct clk *);
+	int		(*set_parent)(struct clk *, struct clk *);
+	int		(*set_rate)(struct clk *, unsigned long);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	unsigned long	(*recalculate_rate)(struct clk *);
+};
+
+enum clk_state {
+	UNINITIALIZED = 0,
+	ON,
+	OFF,
+};
+
+struct clk {
+	/* node for master clocks list */
+	struct list_head		node;
+	struct list_head		children;	/* list of children */
+	struct list_head		sibling;	/* node for children */
+#ifdef CONFIG_DEBUG_FS
+	struct dentry			*dent;
+	struct dentry			*parent_dent;
+#endif
+	struct clk_ops			*ops;
+	struct clk			*parent;
+	struct clk_lookup		lookup;
+	unsigned long			rate;
+	u32				flags;
+	u32				refcnt;
+	const char			*name;
+	u32				reg;
+	u32				reg_shift;
+	unsigned int			clk_num;
+	enum clk_state			state;
+#ifdef CONFIG_DEBUG_FS
+	bool				set;
+#endif
+
+	/* PLL */
+	unsigned long			input_min;
+	unsigned long			input_max;
+	unsigned long			cf_min;
+	unsigned long			cf_max;
+	unsigned long			vco_min;
+	unsigned long			vco_max;
+	u32				m;
+	u32				n;
+	u32				p;
+	u32				cpcon;
+	const struct clk_pll_table	*pll_table;
+
+	/* DIV */
+	u32				div;
+	u32				mul;
+
+	/* MUX */
+	const struct clk_mux_sel	*inputs;
+	u32				sel;
+	u32				reg_mask;
+};
+
+
+struct clk_duplicate {
+	const char *name;
+	struct clk_lookup lookup;
+};
+
+struct tegra_clk_init_table {
+	const char *name;
+	const char *parent;
+	unsigned long rate;
+	bool enabled;
+};
+
+void tegra2_init_clocks(void);
+void tegra2_periph_reset_deassert(struct clk *c);
+void tegra2_periph_reset_assert(struct clk *c);
+void clk_init(struct clk *clk);
+struct clk *tegra_get_clock_by_name(const char *name);
+unsigned long clk_measure_input_freq(void);
+void clk_disable_locked(struct clk *c);
+int clk_enable_locked(struct clk *c);
+int clk_set_parent_locked(struct clk *c, struct clk *parent);
+int clk_reparent(struct clk *c, struct clk *parent);
+void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
+
+#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
new file mode 100644
index 0000000000000000000000000000000000000000..039a514b61ef1e5f0c9142a4aa81ccf021c96c95
--- /dev/null
+++ b/arch/arm/mach-tegra/common.c
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/iomap.h>
+
+#include "board.h"
+#include "clock.h"
+
+static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "clk_m",	NULL,		0,		true },
+	{ "pll_p",	"clk_m",	216000000,	true },
+	{ "pll_p_out1",	"pll_p",	28800000,	true },
+	{ "pll_p_out2",	"pll_p",	48000000,	true },
+	{ "pll_p_out3",	"pll_p",	72000000,	true },
+	{ "pll_p_out4",	"pll_p",	108000000,	true },
+	{ "sys",	"pll_p_out4",	108000000,	true },
+	{ "hclk",	"sys",		108000000,	true },
+	{ "pclk",	"hclk",		54000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+void __init tegra_init_cache(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
+
+	writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
+	writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
+
+	l2x0_init(p, 0x6C080001, 0x8200c3fe);
+#endif
+}
+
+void __init tegra_common_init(void)
+{
+	tegra_init_clock();
+	tegra_clk_init_from_table(common_clk_init_table);
+	tegra_init_cache();
+}
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
new file mode 100644
index 0000000000000000000000000000000000000000..f28220a641b20a88338720f9604c318b37b0636d
--- /dev/null
+++ b/arch/arm/mach-tegra/gpio-names.h
@@ -0,0 +1,247 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio-names.h
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_TEGRA_GPIO_NAMES_H
+#define __MACH_TEGRA_GPIO_NAMES_H
+
+#define TEGRA_GPIO_PA0		0
+#define TEGRA_GPIO_PA1		1
+#define TEGRA_GPIO_PA2		2
+#define TEGRA_GPIO_PA3		3
+#define TEGRA_GPIO_PA4		4
+#define TEGRA_GPIO_PA5		5
+#define TEGRA_GPIO_PA6		6
+#define TEGRA_GPIO_PA7		7
+#define TEGRA_GPIO_PB0		8
+#define TEGRA_GPIO_PB1		9
+#define TEGRA_GPIO_PB2		10
+#define TEGRA_GPIO_PB3		11
+#define TEGRA_GPIO_PB4		12
+#define TEGRA_GPIO_PB5		13
+#define TEGRA_GPIO_PB6		14
+#define TEGRA_GPIO_PB7		15
+#define TEGRA_GPIO_PC0		16
+#define TEGRA_GPIO_PC1		17
+#define TEGRA_GPIO_PC2		18
+#define TEGRA_GPIO_PC3		19
+#define TEGRA_GPIO_PC4		20
+#define TEGRA_GPIO_PC5		21
+#define TEGRA_GPIO_PC6		22
+#define TEGRA_GPIO_PC7		23
+#define TEGRA_GPIO_PD0		24
+#define TEGRA_GPIO_PD1		25
+#define TEGRA_GPIO_PD2		26
+#define TEGRA_GPIO_PD3		27
+#define TEGRA_GPIO_PD4		28
+#define TEGRA_GPIO_PD5		29
+#define TEGRA_GPIO_PD6		30
+#define TEGRA_GPIO_PD7		31
+#define TEGRA_GPIO_PE0		32
+#define TEGRA_GPIO_PE1		33
+#define TEGRA_GPIO_PE2		34
+#define TEGRA_GPIO_PE3		35
+#define TEGRA_GPIO_PE4		36
+#define TEGRA_GPIO_PE5		37
+#define TEGRA_GPIO_PE6		38
+#define TEGRA_GPIO_PE7		39
+#define TEGRA_GPIO_PF0		40
+#define TEGRA_GPIO_PF1		41
+#define TEGRA_GPIO_PF2		42
+#define TEGRA_GPIO_PF3		43
+#define TEGRA_GPIO_PF4		44
+#define TEGRA_GPIO_PF5		45
+#define TEGRA_GPIO_PF6		46
+#define TEGRA_GPIO_PF7		47
+#define TEGRA_GPIO_PG0		48
+#define TEGRA_GPIO_PG1		49
+#define TEGRA_GPIO_PG2		50
+#define TEGRA_GPIO_PG3		51
+#define TEGRA_GPIO_PG4		52
+#define TEGRA_GPIO_PG5		53
+#define TEGRA_GPIO_PG6		54
+#define TEGRA_GPIO_PG7		55
+#define TEGRA_GPIO_PH0		56
+#define TEGRA_GPIO_PH1		57
+#define TEGRA_GPIO_PH2		58
+#define TEGRA_GPIO_PH3		59
+#define TEGRA_GPIO_PH4		60
+#define TEGRA_GPIO_PH5		61
+#define TEGRA_GPIO_PH6		62
+#define TEGRA_GPIO_PH7		63
+#define TEGRA_GPIO_PI0		64
+#define TEGRA_GPIO_PI1		65
+#define TEGRA_GPIO_PI2		66
+#define TEGRA_GPIO_PI3		67
+#define TEGRA_GPIO_PI4		68
+#define TEGRA_GPIO_PI5		69
+#define TEGRA_GPIO_PI6		70
+#define TEGRA_GPIO_PI7		71
+#define TEGRA_GPIO_PJ0		72
+#define TEGRA_GPIO_PJ1		73
+#define TEGRA_GPIO_PJ2		74
+#define TEGRA_GPIO_PJ3		75
+#define TEGRA_GPIO_PJ4		76
+#define TEGRA_GPIO_PJ5		77
+#define TEGRA_GPIO_PJ6		78
+#define TEGRA_GPIO_PJ7		79
+#define TEGRA_GPIO_PK0		80
+#define TEGRA_GPIO_PK1		81
+#define TEGRA_GPIO_PK2		82
+#define TEGRA_GPIO_PK3		83
+#define TEGRA_GPIO_PK4		84
+#define TEGRA_GPIO_PK5		85
+#define TEGRA_GPIO_PK6		86
+#define TEGRA_GPIO_PK7		87
+#define TEGRA_GPIO_PL0		88
+#define TEGRA_GPIO_PL1		89
+#define TEGRA_GPIO_PL2		90
+#define TEGRA_GPIO_PL3		91
+#define TEGRA_GPIO_PL4		92
+#define TEGRA_GPIO_PL5		93
+#define TEGRA_GPIO_PL6		94
+#define TEGRA_GPIO_PL7		95
+#define TEGRA_GPIO_PM0		96
+#define TEGRA_GPIO_PM1		97
+#define TEGRA_GPIO_PM2		98
+#define TEGRA_GPIO_PM3		99
+#define TEGRA_GPIO_PM4		100
+#define TEGRA_GPIO_PM5		101
+#define TEGRA_GPIO_PM6		102
+#define TEGRA_GPIO_PM7		103
+#define TEGRA_GPIO_PN0		104
+#define TEGRA_GPIO_PN1		105
+#define TEGRA_GPIO_PN2		106
+#define TEGRA_GPIO_PN3		107
+#define TEGRA_GPIO_PN4		108
+#define TEGRA_GPIO_PN5		109
+#define TEGRA_GPIO_PN6		110
+#define TEGRA_GPIO_PN7		111
+#define TEGRA_GPIO_PO0		112
+#define TEGRA_GPIO_PO1		113
+#define TEGRA_GPIO_PO2		114
+#define TEGRA_GPIO_PO3		115
+#define TEGRA_GPIO_PO4		116
+#define TEGRA_GPIO_PO5		117
+#define TEGRA_GPIO_PO6		118
+#define TEGRA_GPIO_PO7		119
+#define TEGRA_GPIO_PP0		120
+#define TEGRA_GPIO_PP1		121
+#define TEGRA_GPIO_PP2		122
+#define TEGRA_GPIO_PP3		123
+#define TEGRA_GPIO_PP4		124
+#define TEGRA_GPIO_PP5		125
+#define TEGRA_GPIO_PP6		126
+#define TEGRA_GPIO_PP7		127
+#define TEGRA_GPIO_PQ0		128
+#define TEGRA_GPIO_PQ1		129
+#define TEGRA_GPIO_PQ2		130
+#define TEGRA_GPIO_PQ3		131
+#define TEGRA_GPIO_PQ4		132
+#define TEGRA_GPIO_PQ5		133
+#define TEGRA_GPIO_PQ6		134
+#define TEGRA_GPIO_PQ7		135
+#define TEGRA_GPIO_PR0		136
+#define TEGRA_GPIO_PR1		137
+#define TEGRA_GPIO_PR2		138
+#define TEGRA_GPIO_PR3		139
+#define TEGRA_GPIO_PR4		140
+#define TEGRA_GPIO_PR5		141
+#define TEGRA_GPIO_PR6		142
+#define TEGRA_GPIO_PR7		143
+#define TEGRA_GPIO_PS0		144
+#define TEGRA_GPIO_PS1		145
+#define TEGRA_GPIO_PS2		146
+#define TEGRA_GPIO_PS3		147
+#define TEGRA_GPIO_PS4		148
+#define TEGRA_GPIO_PS5		149
+#define TEGRA_GPIO_PS6		150
+#define TEGRA_GPIO_PS7		151
+#define TEGRA_GPIO_PT0		152
+#define TEGRA_GPIO_PT1		153
+#define TEGRA_GPIO_PT2		154
+#define TEGRA_GPIO_PT3		155
+#define TEGRA_GPIO_PT4		156
+#define TEGRA_GPIO_PT5		157
+#define TEGRA_GPIO_PT6		158
+#define TEGRA_GPIO_PT7		159
+#define TEGRA_GPIO_PU0		160
+#define TEGRA_GPIO_PU1		161
+#define TEGRA_GPIO_PU2		162
+#define TEGRA_GPIO_PU3		163
+#define TEGRA_GPIO_PU4		164
+#define TEGRA_GPIO_PU5		165
+#define TEGRA_GPIO_PU6		166
+#define TEGRA_GPIO_PU7		167
+#define TEGRA_GPIO_PV0		168
+#define TEGRA_GPIO_PV1		169
+#define TEGRA_GPIO_PV2		170
+#define TEGRA_GPIO_PV3		171
+#define TEGRA_GPIO_PV4		172
+#define TEGRA_GPIO_PV5		173
+#define TEGRA_GPIO_PV6		174
+#define TEGRA_GPIO_PV7		175
+#define TEGRA_GPIO_PW0		176
+#define TEGRA_GPIO_PW1		177
+#define TEGRA_GPIO_PW2		178
+#define TEGRA_GPIO_PW3		179
+#define TEGRA_GPIO_PW4		180
+#define TEGRA_GPIO_PW5		181
+#define TEGRA_GPIO_PW6		182
+#define TEGRA_GPIO_PW7		183
+#define TEGRA_GPIO_PX0		184
+#define TEGRA_GPIO_PX1		185
+#define TEGRA_GPIO_PX2		186
+#define TEGRA_GPIO_PX3		187
+#define TEGRA_GPIO_PX4		188
+#define TEGRA_GPIO_PX5		189
+#define TEGRA_GPIO_PX6		190
+#define TEGRA_GPIO_PX7		191
+#define TEGRA_GPIO_PY0		192
+#define TEGRA_GPIO_PY1		193
+#define TEGRA_GPIO_PY2		194
+#define TEGRA_GPIO_PY3		195
+#define TEGRA_GPIO_PY4		196
+#define TEGRA_GPIO_PY5		197
+#define TEGRA_GPIO_PY6		198
+#define TEGRA_GPIO_PY7		199
+#define TEGRA_GPIO_PZ0		200
+#define TEGRA_GPIO_PZ1		201
+#define TEGRA_GPIO_PZ2		202
+#define TEGRA_GPIO_PZ3		203
+#define TEGRA_GPIO_PZ4		204
+#define TEGRA_GPIO_PZ5		205
+#define TEGRA_GPIO_PZ6		206
+#define TEGRA_GPIO_PZ7		207
+#define TEGRA_GPIO_PAA0		208
+#define TEGRA_GPIO_PAA1		209
+#define TEGRA_GPIO_PAA2		210
+#define TEGRA_GPIO_PAA3		211
+#define TEGRA_GPIO_PAA4		212
+#define TEGRA_GPIO_PAA5		213
+#define TEGRA_GPIO_PAA6		214
+#define TEGRA_GPIO_PAA7		215
+#define TEGRA_GPIO_PBB0		216
+#define TEGRA_GPIO_PBB1		217
+#define TEGRA_GPIO_PBB2		218
+#define TEGRA_GPIO_PBB3		219
+#define TEGRA_GPIO_PBB4		220
+#define TEGRA_GPIO_PBB5		221
+#define TEGRA_GPIO_PBB6		222
+#define TEGRA_GPIO_PBB7		223
+
+#endif
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe78fba25f3c7c39fdc494f3519ed956e76cbb5a
--- /dev/null
+++ b/arch/arm/mach-tegra/gpio.c
@@ -0,0 +1,348 @@
+/*
+ * arch/arm/mach-tegra/gpio.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/iomap.h>
+
+#define GPIO_BANK(x)		((x) >> 5)
+#define GPIO_PORT(x)		(((x) >> 3) & 0x3)
+#define GPIO_BIT(x)		((x) & 0x7)
+
+#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
+				 GPIO_BANK(x) * 0x80 +		\
+				 GPIO_PORT(x) * 4)
+
+#define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
+#define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
+#define GPIO_OUT(x)		(GPIO_REG(x) + 0X20)
+#define GPIO_IN(x)		(GPIO_REG(x) + 0x30)
+#define GPIO_INT_STA(x)		(GPIO_REG(x) + 0x40)
+#define GPIO_INT_ENB(x)		(GPIO_REG(x) + 0x50)
+#define GPIO_INT_LVL(x)		(GPIO_REG(x) + 0x60)
+#define GPIO_INT_CLR(x)		(GPIO_REG(x) + 0x70)
+
+#define GPIO_MSK_CNF(x)		(GPIO_REG(x) + 0x800)
+#define GPIO_MSK_OE(x)		(GPIO_REG(x) + 0x810)
+#define GPIO_MSK_OUT(x)		(GPIO_REG(x) + 0X820)
+#define GPIO_MSK_INT_STA(x)	(GPIO_REG(x) + 0x840)
+#define GPIO_MSK_INT_ENB(x)	(GPIO_REG(x) + 0x850)
+#define GPIO_MSK_INT_LVL(x)	(GPIO_REG(x) + 0x860)
+
+#define GPIO_INT_LVL_MASK		0x010101
+#define GPIO_INT_LVL_EDGE_RISING	0x000101
+#define GPIO_INT_LVL_EDGE_FALLING	0x000100
+#define GPIO_INT_LVL_EDGE_BOTH		0x010100
+#define GPIO_INT_LVL_LEVEL_HIGH		0x000001
+#define GPIO_INT_LVL_LEVEL_LOW		0x000000
+
+struct tegra_gpio_bank {
+	int bank;
+	int irq;
+	spinlock_t lvl_lock[4];
+};
+
+
+static struct tegra_gpio_bank tegra_gpio_banks[] = {
+	{.bank = 0, .irq = INT_GPIO1},
+	{.bank = 1, .irq = INT_GPIO2},
+	{.bank = 2, .irq = INT_GPIO3},
+	{.bank = 3, .irq = INT_GPIO4},
+	{.bank = 4, .irq = INT_GPIO5},
+	{.bank = 5, .irq = INT_GPIO6},
+	{.bank = 6, .irq = INT_GPIO7},
+};
+
+static int tegra_gpio_compose(int bank, int port, int bit)
+{
+	return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
+}
+
+static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
+{
+	u32 val;
+
+	val = 0x100 << GPIO_BIT(gpio);
+	if (value)
+		val |= 1 << GPIO_BIT(gpio);
+	__raw_writel(val, reg);
+}
+
+void tegra_gpio_enable(int gpio)
+{
+	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
+}
+
+void tegra_gpio_disable(int gpio)
+{
+	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
+}
+
+static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
+}
+
+static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+}
+
+static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
+	return 0;
+}
+
+static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	tegra_gpio_set(chip, offset, value);
+	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
+	return 0;
+}
+
+
+
+static struct gpio_chip tegra_gpio_chip = {
+	.label			= "tegra-gpio",
+	.direction_input	= tegra_gpio_direction_input,
+	.get			= tegra_gpio_get,
+	.direction_output	= tegra_gpio_direction_output,
+	.set			= tegra_gpio_set,
+	.base			= 0,
+	.ngpio			= ARCH_NR_GPIOS,
+};
+
+static void tegra_gpio_irq_ack(unsigned int irq)
+{
+	int gpio = irq - INT_GPIO_BASE;
+
+	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+}
+
+static void tegra_gpio_irq_mask(unsigned int irq)
+{
+	int gpio = irq - INT_GPIO_BASE;
+
+	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
+}
+
+static void tegra_gpio_irq_unmask(unsigned int irq)
+{
+	int gpio = irq - INT_GPIO_BASE;
+
+	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
+}
+
+static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+	int gpio = irq - INT_GPIO_BASE;
+	struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+	int port = GPIO_PORT(gpio);
+	int lvl_type;
+	int val;
+	unsigned long flags;
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_RISING:
+		lvl_type = GPIO_INT_LVL_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		lvl_type = GPIO_INT_LVL_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		lvl_type = GPIO_INT_LVL_EDGE_BOTH;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		lvl_type = GPIO_INT_LVL_LEVEL_LOW;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&bank->lvl_lock[port], flags);
+
+	val = __raw_readl(GPIO_INT_LVL(gpio));
+	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
+	val |= lvl_type << GPIO_BIT(gpio);
+	__raw_writel(val, GPIO_INT_LVL(gpio));
+
+	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		__set_irq_handler_unlocked(irq, handle_level_irq);
+	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		__set_irq_handler_unlocked(irq, handle_edge_irq);
+
+	return 0;
+}
+
+static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct tegra_gpio_bank *bank;
+	int port;
+	int pin;
+	int unmasked = 0;
+
+	desc->chip->ack(irq);
+
+	bank = get_irq_data(irq);
+
+	for (port = 0; port < 4; port++) {
+		int gpio = tegra_gpio_compose(bank->bank, port, 0);
+		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
+			__raw_readl(GPIO_INT_ENB(gpio));
+		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+
+		for_each_set_bit(pin, &sta, 8) {
+			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+
+			/* if gpio is edge triggered, clear condition
+			 * before executing the hander so that we don't
+			 * miss edges
+			 */
+			if (lvl & (0x100 << pin)) {
+				unmasked = 1;
+				desc->chip->unmask(irq);
+			}
+
+			generic_handle_irq(gpio_to_irq(gpio + pin));
+		}
+	}
+
+	if (!unmasked)
+		desc->chip->unmask(irq);
+
+}
+
+
+static struct irq_chip tegra_gpio_irq_chip = {
+	.name		= "GPIO",
+	.ack		= tegra_gpio_irq_ack,
+	.mask		= tegra_gpio_irq_mask,
+	.unmask		= tegra_gpio_irq_unmask,
+	.set_type	= tegra_gpio_irq_set_type,
+};
+
+
+/* This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int __init tegra_gpio_init(void)
+{
+	struct tegra_gpio_bank *bank;
+	int i;
+	int j;
+
+	for (i = 0; i < 7; i++) {
+		for (j = 0; j < 4; j++) {
+			int gpio = tegra_gpio_compose(i, j, 0);
+			__raw_writel(0x00, GPIO_INT_ENB(gpio));
+		}
+	}
+
+	gpiochip_add(&tegra_gpio_chip);
+
+	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+
+		lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
+		set_irq_chip_data(i, bank);
+		set_irq_chip(i, &tegra_gpio_irq_chip);
+		set_irq_handler(i, handle_simple_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+		bank = &tegra_gpio_banks[i];
+
+		set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
+		set_irq_data(bank->irq, bank);
+
+		for (j = 0; j < 4; j++)
+			spin_lock_init(&bank->lvl_lock[j]);
+	}
+
+	return 0;
+}
+
+postcore_initcall(tegra_gpio_init);
+
+#ifdef	CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int dbg_gpio_show(struct seq_file *s, void *unused)
+{
+	int i;
+	int j;
+
+	for (i = 0; i < 7; i++) {
+		for (j = 0; j < 4; j++) {
+			int gpio = tegra_gpio_compose(i, j, 0);
+			seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+			       i, j,
+			       __raw_readl(GPIO_CNF(gpio)),
+			       __raw_readl(GPIO_OE(gpio)),
+			       __raw_readl(GPIO_OUT(gpio)),
+			       __raw_readl(GPIO_IN(gpio)),
+			       __raw_readl(GPIO_INT_STA(gpio)),
+			       __raw_readl(GPIO_INT_ENB(gpio)),
+			       __raw_readl(GPIO_INT_LVL(gpio)));
+		}
+	}
+	return 0;
+}
+
+static int dbg_gpio_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dbg_gpio_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= dbg_gpio_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init tegra_gpio_debuginit(void)
+{
+	(void) debugfs_create_file("tegra_gpio", S_IRUGO,
+					NULL, NULL, &debug_fops);
+	return 0;
+}
+late_initcall(tegra_gpio_debuginit);
+#endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
new file mode 100644
index 0000000000000000000000000000000000000000..b5349b2f13d296893f6737e39d544b93e89472d3
--- /dev/null
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -0,0 +1,61 @@
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+        .section ".text.head", "ax"
+	__CPUINIT
+
+/*
+ * Tegra specific entry point for secondary CPUs.
+ *   The secondary kernel init calls v7_flush_dcache_all before it enables
+ *   the L1; however, the L1 comes out of reset in an undefined state, so
+ *   the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ *   of cache lines with uninitialized data and uninitialized tags to get
+ *   written out to memory, which does really unpleasant things to the main
+ *   processor.  We fix this by performing an invalidate, rather than a
+ *   clean + invalidate, before jumping into the kernel.
+ */
+ENTRY(v7_invalidate_l1)
+        mov     r0, #0
+        mcr     p15, 2, r0, c0, c0, 0
+        mrc     p15, 1, r0, c0, c0, 0
+
+        ldr     r1, =0x7fff
+        and     r2, r1, r0, lsr #13
+
+        ldr     r1, =0x3ff
+
+        and     r3, r1, r0, lsr #3  @ NumWays - 1
+        add     r2, r2, #1          @ NumSets
+
+        and     r0, r0, #0x7
+        add     r0, r0, #4          @ SetShift
+
+        clz     r1, r3              @ WayShift
+        add     r4, r3, #1          @ NumWays
+1:      sub     r2, r2, #1          @ NumSets--
+        mov     r3, r4              @ Temp = NumWays
+2:      subs    r3, r3, #1          @ Temp--
+        mov     r5, r3, lsl r1
+        mov     r6, r2, lsl r0
+        orr     r5, r5, r6          @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+        mcr     p15, 0, r5, c7, c6, 2
+        bgt     2b
+        cmp     r2, #0
+        bgt     1b
+        dsb
+        isb
+        mov     pc, lr
+ENDPROC(v7_invalidate_l1)
+
+ENTRY(tegra_secondary_startup)
+	msr	cpsr_fsxc, #0xd3
+        bl      v7_invalidate_l1
+	mrc	p15, 0, r0, c0, c0, 5
+        and	r0, r0, #15
+        ldr     r1, =0x6000f100
+        str     r0, [r1]
+1:      ldr     r2, [r1]
+        cmp     r0, r2
+        beq     1b
+        b       secondary_startup
+ENDPROC(tegra_secondary_startup)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e7f115aa21e8b33c11c1a889d7aa2634445bd84
--- /dev/null
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -0,0 +1,140 @@
+/*
+ *  linux/arch/arm/mach-realview/hotplug.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, #0x04\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0)
+	  : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, #0x04\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  :
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		/*if (pen_release == cpu) {*/
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		/*}*/
+
+		/*
+		 * getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * The trouble is, letting people know about this is not really
+		 * possible, since we are currently running incoherently, and
+		 * therefore cannot safely call printk() or anything else
+		 */
+#ifdef DEBUG
+		printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
+#endif
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+	unsigned int this_cpu = hard_smp_processor_id();
+
+	if (cpu != this_cpu) {
+		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+			   this_cpu, cpu);
+		BUG();
+	}
+#endif
+
+	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+	complete(&cpu_killed);
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc115174899bdf4253471065134a90a658f3a5d6
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/barriers.h
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-realview/include/mach/barriers.h
+ *
+ * Copyright (C) 2010 ARM Ltd.
+ * Written by Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MACH_BARRIERS_H
+#define __MACH_BARRIERS_H
+
+#include <asm/outercache.h>
+
+#define rmb()		dmb()
+#define wmb()		do { dsb(); outer_sync(); } while (0)
+#define mb()		wmb()
+
+#endif	/* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
new file mode 100644
index 0000000000000000000000000000000000000000..2896f25ebfb57f0ce29cc43a4965763284166422
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clk.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_CLK_H
+#define __MACH_CLK_H
+
+void tegra_periph_reset_deassert(struct clk *c);
+void tegra_periph_reset_assert(struct clk *c);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h
new file mode 100644
index 0000000000000000000000000000000000000000..412f5c63e65adabc23eab9bf520acaccccd7f399
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/clkdev.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clkdev.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk)
+{
+	return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
new file mode 100644
index 0000000000000000000000000000000000000000..55a39564b43c476e2002b806a8bdff6f6e7c6f44
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-tegra/include/mach/debug-macro.S
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <mach/io.h>
+
+	.macro  addruart,rx, tmp
+        mrc     p15, 0, \rx, c1, c0
+        tst     \rx, #1                 @ MMU enabled?
+        ldreq   \rx, =IO_APB_PHYS       @ physical
+        ldrne   \rx, =IO_APB_VIRT        @ virtual
+#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
+#error "A debug UART must be selected in the kernel config to use DEBUG_LL"
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
+        orr     \rx, \rx, #0x6000
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+	ldr	\tmp, =0x6040
+        orr     \rx, \rx, \tmp
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+        orr     \rx, \rx, #0x6200
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+        orr     \rx, \rx, #0x6300
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+        orr     \rx, \rx, #0x6400
+#endif
+	.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
+
diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S
new file mode 100644
index 0000000000000000000000000000000000000000..2ba9e5c9d2f6f711aecae8bda9506c7008d406a0
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/entry-macro.S
@@ -0,0 +1,118 @@
+/* arch/arm/mach-tegra/include/mach/entry-macro.S
+ *
+ * Copyright (C) 2009 Palm, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <mach/iomap.h>
+#include <mach/io.h>
+
+#if defined(CONFIG_ARM_GIC)
+
+#include <asm/hardware/gic.h>
+
+	/* Uses the GIC interrupt controller built into the cpu */
+#define ICTRL_BASE (IO_CPU_VIRT + 0x100)
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	movw \base, #(ICTRL_BASE & 0x0000ffff)
+	movt \base, #((ICTRL_BASE & 0xffff0000) >> 16)
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	/*
+	 * The interrupt numbering scheme is defined in the
+	 * interrupt controller spec.  To wit:
+	 *
+	 * Interrupts 0-15 are IPI
+	 * 16-28 are reserved
+	 * 29-31 are local.  We allow 30 to be used for the watchdog.
+	 * 32-1020 are global
+	 * 1021-1022 are reserved
+	 * 1023 is "spurious" (no interrupt)
+	 *
+	 * For now, we ignore all local interrupts so only return an interrupt
+	 * if it's between 30 and 1020.  The test_for_ipi routine below will
+	 * pick up on IPIs.
+	 *
+	 * A simple read from the controller will tell us the number of the
+	 * highest priority enabled interrupt.  We then just need to check
+	 * whether it is in the valid range for an IRQ (30-1020 inclusive).
+	 */
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	/* bits 12-10 = src CPU, 9-0 = int # */
+	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+
+	ldr		\tmp, =1021
+
+	bic     \irqnr, \irqstat, #0x1c00
+
+	cmp     \irqnr, #29
+	cmpcc	\irqnr, \irqnr
+	cmpne	\irqnr, \tmp
+	cmpcs	\irqnr, \irqnr
+
+	.endm
+
+	/* We assume that irqstat (the raw value of the IRQ acknowledge
+	 * register) is preserved from the macro above.
+	 * If there is an IPI, we immediately signal end of interrupt on the
+	 * controller, since this requires the original irqstat value which
+	 * we won't easily be able to recreate later.
+	 */
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	cmp	\irqnr, #16
+	strcc	\irqstat, [\base, #GIC_CPU_EOI]
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+	/* As above, this assumes that irqstat and base are preserved.. */
+
+	.macro test_for_ltirq, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	mov 	\tmp, #0
+	cmp	\irqnr, #29
+	moveq	\tmp, #1
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	cmp	\tmp, #0
+	.endm
+
+#else
+	/* legacy interrupt controller for AP16 */
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	@ enable imprecise aborts
+	cpsie	a
+	@ EVP base at 0xf010f000
+	mov \base, #0xf0000000
+	orr \base, #0x00100000
+	orr \base, #0x0000f000
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr \irqnr, [\base, #0x20]	@ EVT_IRQ_STS
+	cmp \irqnr, #0x80
+	.endm
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..540e822e50f7c15c0afa4799f060d5c33c638fb3
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -0,0 +1,53 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_GPIO_H
+#define __MACH_TEGRA_GPIO_H
+
+#include <mach/irqs.h>
+
+#define ARCH_NR_GPIOS		INT_GPIO_NR
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value		__gpio_get_value
+#define gpio_set_value		__gpio_set_value
+#define gpio_cansleep		__gpio_cansleep
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE)
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+	if (gpio < ARCH_NR_GPIOS)
+		return INT_GPIO_BASE + gpio;
+	return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
+		return irq - INT_GPIO_BASE;
+	return -EINVAL;
+}
+
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h
new file mode 100644
index 0000000000000000000000000000000000000000..6014edf60d9353d53ecea8fe08b0d5c7838b4719
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/hardware.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/include/mach/hardware.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_HARDWARE_H
+#define __MACH_TEGRA_HARDWARE_H
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
new file mode 100644
index 0000000000000000000000000000000000000000..35edfc32ffc9d96280f43f47da841d63ff0fdc32
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -0,0 +1,79 @@
+/*
+ * arch/arm/mach-tegra/include/mach/io.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IO_H
+#define __MACH_TEGRA_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* On TEGRA, many peripherals are very closely packed in
+ * two 256MB io windows (that actually only use about 64KB
+ * at the start of each).
+ *
+ * We will just map the first 1MB of each window (to minimize
+ * pt entries needed) and provide a macro to transform physical
+ * io addresses to an appropriate void __iomem *.
+ *
+ */
+
+#define IO_CPU_PHYS     0x50040000
+#define IO_CPU_VIRT     0xFE000000
+#define IO_CPU_SIZE	SZ_16K
+
+#define IO_PPSB_PHYS	0x60000000
+#define IO_PPSB_VIRT	0xFE200000
+#define IO_PPSB_SIZE	SZ_1M
+
+#define IO_APB_PHYS	0x70000000
+#define IO_APB_VIRT	0xFE300000
+#define IO_APB_SIZE	SZ_1M
+
+#define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
+#define IO_TO_VIRT_XLATE(p, pst, vst)	(((p) - (pst) + (vst)))
+
+#define IO_TO_VIRT(n) ( \
+	IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :	\
+	IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :	\
+	IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
+	0)
+
+#ifndef __ASSEMBLER__
+
+#define __arch_ioremap(p, s, t)	tegra_ioremap(p, s, t)
+#define __arch_iounmap(v)	tegra_iounmap(v)
+
+void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
+void tegra_iounmap(volatile void __iomem *addr);
+
+#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+
+static inline void __iomem *__io(unsigned long addr)
+{
+	return (void __iomem *)addr;
+}
+#define __io(a)         __io(a)
+#define __mem_pci(a)    (a)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
new file mode 100644
index 0000000000000000000000000000000000000000..1741f7dd7a9b71183c98b53cab88e688aa16b031
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -0,0 +1,203 @@
+/*
+ * arch/arm/mach-tegra/include/mach/iomap.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IOMAP_H
+#define __MACH_TEGRA_IOMAP_H
+
+#include <asm/sizes.h>
+
+#define TEGRA_ARM_PERIF_BASE		0x50040000
+#define TEGRA_ARM_PERIF_SIZE		SZ_8K
+
+#define TEGRA_ARM_INT_DIST_BASE		0x50041000
+#define TEGRA_ARM_INT_DIST_SIZE		SZ_4K
+
+#define TEGRA_DISPLAY_BASE		0x54200000
+#define TEGRA_DISPLAY_SIZE		SZ_256K
+
+#define TEGRA_DISPLAY2_BASE		0x54240000
+#define TEGRA_DISPLAY2_SIZE		SZ_256K
+
+#define TEGRA_PRIMARY_ICTLR_BASE	0x60004000
+#define TEGRA_PRIMARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_SECONDARY_ICTLR_BASE	0x60004100
+#define TEGRA_SECONDARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_TERTIARY_ICTLR_BASE	0x60004200
+#define TEGRA_TERTIARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_QUATERNARY_ICTLR_BASE	0x60004300
+#define TEGRA_QUATERNARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_TMR1_BASE			0x60005000
+#define TEGRA_TMR1_SIZE			SZ_8
+
+#define TEGRA_TMR2_BASE			0x60005008
+#define TEGRA_TMR2_SIZE			SZ_8
+
+#define TEGRA_TMRUS_BASE		0x60005010
+#define TEGRA_TMRUS_SIZE		SZ_64
+
+#define TEGRA_TMR3_BASE			0x60005050
+#define TEGRA_TMR3_SIZE			SZ_8
+
+#define TEGRA_TMR4_BASE			0x60005058
+#define TEGRA_TMR4_SIZE			SZ_8
+
+#define TEGRA_CLK_RESET_BASE		0x60006000
+#define TEGRA_CLK_RESET_SIZE		SZ_4K
+
+#define TEGRA_FLOW_CTRL_BASE		0x60007000
+#define TEGRA_FLOW_CTRL_SIZE		20
+
+#define TEGRA_STATMON_BASE		0x6000C4000
+#define TEGRA_STATMON_SIZE		SZ_1K
+
+#define TEGRA_GPIO_BASE			0x6000D000
+#define TEGRA_GPIO_SIZE			SZ_4K
+
+#define TEGRA_EXCEPTION_VECTORS_BASE    0x6000F000
+#define TEGRA_EXCEPTION_VECTORS_SIZE    SZ_4K
+
+#define TEGRA_APB_MISC_BASE		0x70000000
+#define TEGRA_APB_MISC_SIZE		SZ_4K
+
+#define TEGRA_AC97_BASE			0x70002000
+#define TEGRA_AC97_SIZE			SZ_512
+
+#define TEGRA_SPDIF_BASE		0x70002400
+#define TEGRA_SPDIF_SIZE		SZ_512
+
+#define TEGRA_I2S1_BASE			0x70002800
+#define TEGRA_I2S1_SIZE			SZ_256
+
+#define TEGRA_I2S2_BASE			0x70002A00
+#define TEGRA_I2S2_SIZE			SZ_256
+
+#define TEGRA_UARTA_BASE		0x70006000
+#define TEGRA_UARTA_SIZE		SZ_64
+
+#define TEGRA_UARTB_BASE		0x70006040
+#define TEGRA_UARTB_SIZE		SZ_64
+
+#define TEGRA_UARTC_BASE		0x70006200
+#define TEGRA_UARTC_SIZE		SZ_256
+
+#define TEGRA_UARTD_BASE		0x70006300
+#define TEGRA_UARTD_SIZE		SZ_256
+
+#define TEGRA_UARTE_BASE		0x70006400
+#define TEGRA_UARTE_SIZE		SZ_256
+
+#define TEGRA_NAND_BASE			0x70008000
+#define TEGRA_NAND_SIZE			SZ_256
+
+#define TEGRA_HSMMC_BASE		0x70008500
+#define TEGRA_HSMMC_SIZE		SZ_256
+
+#define TEGRA_SNOR_BASE			0x70009000
+#define TEGRA_SNOR_SIZE			SZ_4K
+
+#define TEGRA_PWFM_BASE			0x7000A000
+#define TEGRA_PWFM_SIZE			SZ_256
+
+#define TEGRA_MIPI_BASE			0x7000B000
+#define TEGRA_MIPI_SIZE			SZ_256
+
+#define TEGRA_I2C_BASE			0x7000C000
+#define TEGRA_I2C_SIZE			SZ_256
+
+#define TEGRA_TWC_BASE			0x7000C100
+#define TEGRA_TWC_SIZE			SZ_256
+
+#define TEGRA_SPI_BASE			0x7000C380
+#define TEGRA_SPI_SIZE			48
+
+#define TEGRA_I2C2_BASE			0x7000C400
+#define TEGRA_I2C2_SIZE			SZ_256
+
+#define TEGRA_I2C3_BASE			0x7000C500
+#define TEGRA_I2C3_SIZE			SZ_256
+
+#define TEGRA_OWR_BASE			0x7000D000
+#define TEGRA_OWR_SIZE			80
+
+#define TEGRA_DVC_BASE			0x7000D000
+#define TEGRA_DVC_SIZE			SZ_512
+
+#define TEGRA_SPI1_BASE			0x7000D400
+#define TEGRA_SPI1_SIZE			SZ_512
+
+#define TEGRA_SPI2_BASE			0x7000D600
+#define TEGRA_SPI2_SIZE			SZ_512
+
+#define TEGRA_SPI3_BASE			0x7000D800
+#define TEGRA_SPI3_SIZE			SZ_512
+
+#define TEGRA_SPI4_BASE			0x7000DA00
+#define TEGRA_SPI4_SIZE			SZ_512
+
+#define TEGRA_RTC_BASE			0x7000E000
+#define TEGRA_RTC_SIZE			SZ_256
+
+#define TEGRA_KBC_BASE			0x7000E200
+#define TEGRA_KBC_SIZE			SZ_256
+
+#define TEGRA_PMC_BASE			0x7000E400
+#define TEGRA_PMC_SIZE			SZ_256
+
+#define TEGRA_MC_BASE			0x7000F000
+#define TEGRA_MC_SIZE			SZ_1K
+
+#define TEGRA_EMC_BASE			0x7000F400
+#define TEGRA_EMC_SIZE			SZ_1K
+
+#define TEGRA_FUSE_BASE			0x7000F800
+#define TEGRA_FUSE_SIZE			SZ_1K
+
+#define TEGRA_KFUSE_BASE		0x7000FC00
+#define TEGRA_KFUSE_SIZE		SZ_1K
+
+#define TEGRA_CSITE_BASE		0x70040000
+#define TEGRA_CSITE_SIZE		SZ_256K
+
+#define TEGRA_USB_BASE			0xC5000000
+#define TEGRA_USB_SIZE			SZ_16K
+
+#define TEGRA_USB1_BASE			0xC5004000
+#define TEGRA_USB1_SIZE			SZ_16K
+
+#define TEGRA_USB2_BASE			0xC5008000
+#define TEGRA_USB2_SIZE			SZ_16K
+
+#define TEGRA_SDMMC1_BASE		0xC8000000
+#define TEGRA_SDMMC1_SIZE		SZ_512
+
+#define TEGRA_SDMMC2_BASE		0xC8000200
+#define TEGRA_SDMMC2_SIZE		SZ_512
+
+#define TEGRA_SDMMC3_BASE		0xC8000400
+#define TEGRA_SDMMC3_SIZE		SZ_512
+
+#define TEGRA_SDMMC4_BASE		0xC8000600
+#define TEGRA_SDMMC4_SIZE		SZ_512
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
new file mode 100644
index 0000000000000000000000000000000000000000..20f640edaa0d31e0247681db1dc68ca53125cb79
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/irqs.h
@@ -0,0 +1,173 @@
+/*
+ * arch/arm/mach-tegra/include/mach/irqs.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IRQS_H
+#define __MACH_TEGRA_IRQS_H
+
+#define INT_GIC_BASE			0
+
+#define IRQ_LOCALTIMER                  29
+
+/* Primary Interrupt Controller */
+#define INT_PRI_BASE			(INT_GIC_BASE + 32)
+#define INT_TMR1			(INT_PRI_BASE + 0)
+#define INT_TMR2			(INT_PRI_BASE + 1)
+#define INT_RTC				(INT_PRI_BASE + 2)
+#define INT_I2S2			(INT_PRI_BASE + 3)
+#define INT_SHR_SEM_INBOX_IBF		(INT_PRI_BASE + 4)
+#define INT_SHR_SEM_INBOX_IBE		(INT_PRI_BASE + 5)
+#define INT_SHR_SEM_OUTBOX_IBF		(INT_PRI_BASE + 6)
+#define INT_SHR_SEM_OUTBOX_IBE		(INT_PRI_BASE + 7)
+#define INT_VDE_UCQ_ERROR		(INT_PRI_BASE + 8)
+#define INT_VDE_SYNC_TOKEN		(INT_PRI_BASE + 9)
+#define INT_VDE_BSE_V			(INT_PRI_BASE + 10)
+#define INT_VDE_BSE_A			(INT_PRI_BASE + 11)
+#define INT_VDE_SXE			(INT_PRI_BASE + 12)
+#define INT_I2S1			(INT_PRI_BASE + 13)
+#define INT_SDMMC1			(INT_PRI_BASE + 14)
+#define INT_SDMMC2			(INT_PRI_BASE + 15)
+#define INT_XIO				(INT_PRI_BASE + 16)
+#define INT_VDE				(INT_PRI_BASE + 17)
+#define INT_AVP_UCQ			(INT_PRI_BASE + 18)
+#define INT_SDMMC3			(INT_PRI_BASE + 19)
+#define INT_USB				(INT_PRI_BASE + 20)
+#define INT_USB2			(INT_PRI_BASE + 21)
+#define INT_PRI_RES_22			(INT_PRI_BASE + 22)
+#define INT_EIDE			(INT_PRI_BASE + 23)
+#define INT_NANDFLASH			(INT_PRI_BASE + 24)
+#define INT_VCP				(INT_PRI_BASE + 25)
+#define INT_APB_DMA			(INT_PRI_BASE + 26)
+#define INT_AHB_DMA			(INT_PRI_BASE + 27)
+#define INT_GNT_0			(INT_PRI_BASE + 28)
+#define INT_GNT_1			(INT_PRI_BASE + 29)
+#define INT_OWR				(INT_PRI_BASE + 30)
+#define INT_SDMMC4			(INT_PRI_BASE + 31)
+
+/* Secondary Interrupt Controller */
+#define INT_SEC_BASE			(INT_PRI_BASE + 32)
+#define INT_GPIO1			(INT_SEC_BASE + 0)
+#define INT_GPIO2			(INT_SEC_BASE + 1)
+#define INT_GPIO3			(INT_SEC_BASE + 2)
+#define INT_GPIO4			(INT_SEC_BASE + 3)
+#define INT_UARTA			(INT_SEC_BASE + 4)
+#define INT_UARTB			(INT_SEC_BASE + 5)
+#define INT_I2C				(INT_SEC_BASE + 6)
+#define INT_SPI				(INT_SEC_BASE + 7)
+#define INT_TWC				(INT_SEC_BASE + 8)
+#define INT_TMR3			(INT_SEC_BASE + 9)
+#define INT_TMR4			(INT_SEC_BASE + 10)
+#define INT_FLOW_RSM0			(INT_SEC_BASE + 11)
+#define INT_FLOW_RSM1			(INT_SEC_BASE + 12)
+#define INT_SPDIF			(INT_SEC_BASE + 13)
+#define INT_UARTC			(INT_SEC_BASE + 14)
+#define INT_MIPI			(INT_SEC_BASE + 15)
+#define INT_EVENTA			(INT_SEC_BASE + 16)
+#define INT_EVENTB			(INT_SEC_BASE + 17)
+#define INT_EVENTC			(INT_SEC_BASE + 18)
+#define INT_EVENTD			(INT_SEC_BASE + 19)
+#define INT_VFIR			(INT_SEC_BASE + 20)
+#define INT_DVC				(INT_SEC_BASE + 21)
+#define INT_SYS_STATS_MON		(INT_SEC_BASE + 22)
+#define INT_GPIO5			(INT_SEC_BASE + 23)
+#define INT_CPU0_PMU_INTR		(INT_SEC_BASE + 24)
+#define INT_CPU2_PMU_INTR		(INT_SEC_BASE + 25)
+#define INT_SEC_RES_26			(INT_SEC_BASE + 26)
+#define INT_S_LINK1			(INT_SEC_BASE + 27)
+#define INT_APB_DMA_COP			(INT_SEC_BASE + 28)
+#define INT_AHB_DMA_COP			(INT_SEC_BASE + 29)
+#define INT_DMA_TX			(INT_SEC_BASE + 30)
+#define INT_DMA_RX			(INT_SEC_BASE + 31)
+
+/* Tertiary Interrupt Controller */
+#define INT_TRI_BASE			(INT_SEC_BASE + 32)
+#define INT_HOST1X_COP_SYNCPT		(INT_TRI_BASE + 0)
+#define INT_HOST1X_MPCORE_SYNCPT	(INT_TRI_BASE + 1)
+#define INT_HOST1X_COP_GENERAL		(INT_TRI_BASE + 2)
+#define INT_HOST1X_MPCORE_GENERAL	(INT_TRI_BASE + 3)
+#define INT_MPE_GENERAL			(INT_TRI_BASE + 4)
+#define INT_VI_GENERAL			(INT_TRI_BASE + 5)
+#define INT_EPP_GENERAL			(INT_TRI_BASE + 6)
+#define INT_ISP_GENERAL			(INT_TRI_BASE + 7)
+#define INT_2D_GENERAL			(INT_TRI_BASE + 8)
+#define INT_DISPLAY_GENERAL		(INT_TRI_BASE + 9)
+#define INT_DISPLAY_B_GENERAL		(INT_TRI_BASE + 10)
+#define INT_HDMI			(INT_TRI_BASE + 11)
+#define INT_TVO_GENERAL			(INT_TRI_BASE + 12)
+#define INT_MC_GENERAL			(INT_TRI_BASE + 13)
+#define INT_EMC_GENERAL			(INT_TRI_BASE + 14)
+#define INT_TRI_RES_15			(INT_TRI_BASE + 15)
+#define INT_TRI_RES_16			(INT_TRI_BASE + 16)
+#define INT_AC97			(INT_TRI_BASE + 17)
+#define INT_SPI_2			(INT_TRI_BASE + 18)
+#define INT_SPI_3			(INT_TRI_BASE + 19)
+#define INT_I2C2			(INT_TRI_BASE + 20)
+#define INT_KBC				(INT_TRI_BASE + 21)
+#define INT_EXTERNAL_PMU		(INT_TRI_BASE + 22)
+#define INT_GPIO6			(INT_TRI_BASE + 23)
+#define INT_TVDAC			(INT_TRI_BASE + 24)
+#define INT_GPIO7			(INT_TRI_BASE + 25)
+#define INT_UARTD			(INT_TRI_BASE + 26)
+#define INT_UARTE			(INT_TRI_BASE + 27)
+#define INT_I2C3			(INT_TRI_BASE + 28)
+#define INT_SPI_4			(INT_TRI_BASE + 29)
+#define INT_TRI_RES_30			(INT_TRI_BASE + 30)
+#define INT_SW_RESERVED			(INT_TRI_BASE + 31)
+
+/* Quaternary Interrupt Controller */
+#define INT_QUAD_BASE			(INT_TRI_BASE + 32)
+#define INT_SNOR			(INT_QUAD_BASE + 0)
+#define INT_USB3			(INT_QUAD_BASE + 1)
+#define INT_PCIE_INTR			(INT_QUAD_BASE + 2)
+#define INT_PCIE_MSI			(INT_QUAD_BASE + 3)
+#define INT_QUAD_RES_4			(INT_QUAD_BASE + 4)
+#define INT_QUAD_RES_5			(INT_QUAD_BASE + 5)
+#define INT_QUAD_RES_6			(INT_QUAD_BASE + 6)
+#define INT_QUAD_RES_7			(INT_QUAD_BASE + 7)
+#define INT_APB_DMA_CH0			(INT_QUAD_BASE + 8)
+#define INT_APB_DMA_CH1			(INT_QUAD_BASE + 9)
+#define INT_APB_DMA_CH2			(INT_QUAD_BASE + 10)
+#define INT_APB_DMA_CH3			(INT_QUAD_BASE + 11)
+#define INT_APB_DMA_CH4			(INT_QUAD_BASE + 12)
+#define INT_APB_DMA_CH5			(INT_QUAD_BASE + 13)
+#define INT_APB_DMA_CH6			(INT_QUAD_BASE + 14)
+#define INT_APB_DMA_CH7			(INT_QUAD_BASE + 15)
+#define INT_APB_DMA_CH8			(INT_QUAD_BASE + 16)
+#define INT_APB_DMA_CH9			(INT_QUAD_BASE + 17)
+#define INT_APB_DMA_CH10		(INT_QUAD_BASE + 18)
+#define INT_APB_DMA_CH11		(INT_QUAD_BASE + 19)
+#define INT_APB_DMA_CH12		(INT_QUAD_BASE + 20)
+#define INT_APB_DMA_CH13		(INT_QUAD_BASE + 21)
+#define INT_APB_DMA_CH14		(INT_QUAD_BASE + 22)
+#define INT_APB_DMA_CH15		(INT_QUAD_BASE + 23)
+#define INT_QUAD_RES_24			(INT_QUAD_BASE + 24)
+#define INT_QUAD_RES_25			(INT_QUAD_BASE + 25)
+#define INT_QUAD_RES_26			(INT_QUAD_BASE + 26)
+#define INT_QUAD_RES_27			(INT_QUAD_BASE + 27)
+#define INT_QUAD_RES_28			(INT_QUAD_BASE + 28)
+#define INT_QUAD_RES_29			(INT_QUAD_BASE + 29)
+#define INT_QUAD_RES_30			(INT_QUAD_BASE + 30)
+#define INT_QUAD_RES_31			(INT_QUAD_BASE + 31)
+
+#define INT_GPIO_BASE			(INT_QUAD_BASE + 32)
+#define INT_GPIO_NR			(28 * 8)
+
+#define NR_IRQS				(INT_GPIO_BASE + INT_GPIO_NR)
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h
new file mode 100644
index 0000000000000000000000000000000000000000..6151bab62af207078960e8df6518ed6f55fd85f9
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/memory.h
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-tegra/include/mach/memory.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_MEMORY_H
+#define __MACH_TEGRA_MEMORY_H
+
+/* physical offset of RAM */
+#define PHYS_OFFSET		UL(0)
+
+#endif
+
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
new file mode 100644
index 0000000000000000000000000000000000000000..41c8ce5b7c27564b7621397a86fe0b2722a1e48f
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/pinmux.h
@@ -0,0 +1,348 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/pinmux.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_PINMUX_H
+#define __MACH_TEGRA_PINMUX_H
+
+enum tegra_pingroup {
+	TEGRA_PINGROUP_ATA = 0,
+	TEGRA_PINGROUP_ATB,
+	TEGRA_PINGROUP_ATC,
+	TEGRA_PINGROUP_ATD,
+	TEGRA_PINGROUP_ATE,
+	TEGRA_PINGROUP_CDEV1,
+	TEGRA_PINGROUP_CDEV2,
+	TEGRA_PINGROUP_CRTP,
+	TEGRA_PINGROUP_CSUS,
+	TEGRA_PINGROUP_DAP1,
+	TEGRA_PINGROUP_DAP2,
+	TEGRA_PINGROUP_DAP3,
+	TEGRA_PINGROUP_DAP4,
+	TEGRA_PINGROUP_DDC,
+	TEGRA_PINGROUP_DTA,
+	TEGRA_PINGROUP_DTB,
+	TEGRA_PINGROUP_DTC,
+	TEGRA_PINGROUP_DTD,
+	TEGRA_PINGROUP_DTE,
+	TEGRA_PINGROUP_DTF,
+	TEGRA_PINGROUP_GMA,
+	TEGRA_PINGROUP_GMB,
+	TEGRA_PINGROUP_GMC,
+	TEGRA_PINGROUP_GMD,
+	TEGRA_PINGROUP_GME,
+	TEGRA_PINGROUP_GPU,
+	TEGRA_PINGROUP_GPU7,
+	TEGRA_PINGROUP_GPV,
+	TEGRA_PINGROUP_HDINT,
+	TEGRA_PINGROUP_I2CP,
+	TEGRA_PINGROUP_IRRX,
+	TEGRA_PINGROUP_IRTX,
+	TEGRA_PINGROUP_KBCA,
+	TEGRA_PINGROUP_KBCB,
+	TEGRA_PINGROUP_KBCC,
+	TEGRA_PINGROUP_KBCD,
+	TEGRA_PINGROUP_KBCE,
+	TEGRA_PINGROUP_KBCF,
+	TEGRA_PINGROUP_LCSN,
+	TEGRA_PINGROUP_LD0,
+	TEGRA_PINGROUP_LD1,
+	TEGRA_PINGROUP_LD10,
+	TEGRA_PINGROUP_LD11,
+	TEGRA_PINGROUP_LD12,
+	TEGRA_PINGROUP_LD13,
+	TEGRA_PINGROUP_LD14,
+	TEGRA_PINGROUP_LD15,
+	TEGRA_PINGROUP_LD16,
+	TEGRA_PINGROUP_LD17,
+	TEGRA_PINGROUP_LD2,
+	TEGRA_PINGROUP_LD3,
+	TEGRA_PINGROUP_LD4,
+	TEGRA_PINGROUP_LD5,
+	TEGRA_PINGROUP_LD6,
+	TEGRA_PINGROUP_LD7,
+	TEGRA_PINGROUP_LD8,
+	TEGRA_PINGROUP_LD9,
+	TEGRA_PINGROUP_LDC,
+	TEGRA_PINGROUP_LDI,
+	TEGRA_PINGROUP_LHP0,
+	TEGRA_PINGROUP_LHP1,
+	TEGRA_PINGROUP_LHP2,
+	TEGRA_PINGROUP_LHS,
+	TEGRA_PINGROUP_LM0,
+	TEGRA_PINGROUP_LM1,
+	TEGRA_PINGROUP_LPP,
+	TEGRA_PINGROUP_LPW0,
+	TEGRA_PINGROUP_LPW1,
+	TEGRA_PINGROUP_LPW2,
+	TEGRA_PINGROUP_LSC0,
+	TEGRA_PINGROUP_LSC1,
+	TEGRA_PINGROUP_LSCK,
+	TEGRA_PINGROUP_LSDA,
+	TEGRA_PINGROUP_LSDI,
+	TEGRA_PINGROUP_LSPI,
+	TEGRA_PINGROUP_LVP0,
+	TEGRA_PINGROUP_LVP1,
+	TEGRA_PINGROUP_LVS,
+	TEGRA_PINGROUP_OWC,
+	TEGRA_PINGROUP_PMC,
+	TEGRA_PINGROUP_PTA,
+	TEGRA_PINGROUP_RM,
+	TEGRA_PINGROUP_SDB,
+	TEGRA_PINGROUP_SDC,
+	TEGRA_PINGROUP_SDD,
+	TEGRA_PINGROUP_SDIO1,
+	TEGRA_PINGROUP_SLXA,
+	TEGRA_PINGROUP_SLXC,
+	TEGRA_PINGROUP_SLXD,
+	TEGRA_PINGROUP_SLXK,
+	TEGRA_PINGROUP_SPDI,
+	TEGRA_PINGROUP_SPDO,
+	TEGRA_PINGROUP_SPIA,
+	TEGRA_PINGROUP_SPIB,
+	TEGRA_PINGROUP_SPIC,
+	TEGRA_PINGROUP_SPID,
+	TEGRA_PINGROUP_SPIE,
+	TEGRA_PINGROUP_SPIF,
+	TEGRA_PINGROUP_SPIG,
+	TEGRA_PINGROUP_SPIH,
+	TEGRA_PINGROUP_UAA,
+	TEGRA_PINGROUP_UAB,
+	TEGRA_PINGROUP_UAC,
+	TEGRA_PINGROUP_UAD,
+	TEGRA_PINGROUP_UCA,
+	TEGRA_PINGROUP_UCB,
+	TEGRA_PINGROUP_UDA,
+	/* these pin groups only have pullup and pull down control */
+	TEGRA_PINGROUP_CK32,
+	TEGRA_PINGROUP_DDRC,
+	TEGRA_PINGROUP_PMCA,
+	TEGRA_PINGROUP_PMCB,
+	TEGRA_PINGROUP_PMCC,
+	TEGRA_PINGROUP_PMCD,
+	TEGRA_PINGROUP_PMCE,
+	TEGRA_PINGROUP_XM2C,
+	TEGRA_PINGROUP_XM2D,
+	TEGRA_MAX_PINGROUP,
+};
+
+enum tegra_mux_func {
+	TEGRA_MUX_RSVD = 0x8000,
+	TEGRA_MUX_RSVD1 = 0x8000,
+	TEGRA_MUX_RSVD2 = 0x8001,
+	TEGRA_MUX_RSVD3 = 0x8002,
+	TEGRA_MUX_RSVD4 = 0x8003,
+	TEGRA_MUX_NONE = -1,
+	TEGRA_MUX_AHB_CLK,
+	TEGRA_MUX_APB_CLK,
+	TEGRA_MUX_AUDIO_SYNC,
+	TEGRA_MUX_CRT,
+	TEGRA_MUX_DAP1,
+	TEGRA_MUX_DAP2,
+	TEGRA_MUX_DAP3,
+	TEGRA_MUX_DAP4,
+	TEGRA_MUX_DAP5,
+	TEGRA_MUX_DISPLAYA,
+	TEGRA_MUX_DISPLAYB,
+	TEGRA_MUX_EMC_TEST0_DLL,
+	TEGRA_MUX_EMC_TEST1_DLL,
+	TEGRA_MUX_GMI,
+	TEGRA_MUX_GMI_INT,
+	TEGRA_MUX_HDMI,
+	TEGRA_MUX_I2C,
+	TEGRA_MUX_I2C2,
+	TEGRA_MUX_I2C3,
+	TEGRA_MUX_IDE,
+	TEGRA_MUX_IRDA,
+	TEGRA_MUX_KBC,
+	TEGRA_MUX_MIO,
+	TEGRA_MUX_MIPI_HS,
+	TEGRA_MUX_NAND,
+	TEGRA_MUX_OSC,
+	TEGRA_MUX_OWR,
+	TEGRA_MUX_PCIE,
+	TEGRA_MUX_PLLA_OUT,
+	TEGRA_MUX_PLLC_OUT1,
+	TEGRA_MUX_PLLM_OUT1,
+	TEGRA_MUX_PLLP_OUT2,
+	TEGRA_MUX_PLLP_OUT3,
+	TEGRA_MUX_PLLP_OUT4,
+	TEGRA_MUX_PWM,
+	TEGRA_MUX_PWR_INTR,
+	TEGRA_MUX_PWR_ON,
+	TEGRA_MUX_RTCK,
+	TEGRA_MUX_SDIO1,
+	TEGRA_MUX_SDIO2,
+	TEGRA_MUX_SDIO3,
+	TEGRA_MUX_SDIO4,
+	TEGRA_MUX_SFLASH,
+	TEGRA_MUX_SPDIF,
+	TEGRA_MUX_SPI1,
+	TEGRA_MUX_SPI2,
+	TEGRA_MUX_SPI2_ALT,
+	TEGRA_MUX_SPI3,
+	TEGRA_MUX_SPI4,
+	TEGRA_MUX_TRACE,
+	TEGRA_MUX_TWC,
+	TEGRA_MUX_UARTA,
+	TEGRA_MUX_UARTB,
+	TEGRA_MUX_UARTC,
+	TEGRA_MUX_UARTD,
+	TEGRA_MUX_UARTE,
+	TEGRA_MUX_ULPI,
+	TEGRA_MUX_VI,
+	TEGRA_MUX_VI_SENSOR_CLK,
+	TEGRA_MUX_XIO,
+	TEGRA_MAX_MUX,
+};
+
+enum tegra_pullupdown {
+	TEGRA_PUPD_NORMAL = 0,
+	TEGRA_PUPD_PULL_DOWN,
+	TEGRA_PUPD_PULL_UP,
+};
+
+enum tegra_tristate {
+	TEGRA_TRI_NORMAL = 0,
+	TEGRA_TRI_TRISTATE = 1,
+};
+
+struct tegra_pingroup_config {
+	enum tegra_pingroup	pingroup;
+	enum tegra_mux_func	func;
+	enum tegra_pullupdown	pupd;
+	enum tegra_tristate	tristate;
+};
+
+enum tegra_slew {
+	TEGRA_SLEW_FASTEST = 0,
+	TEGRA_SLEW_FAST,
+	TEGRA_SLEW_SLOW,
+	TEGRA_SLEW_SLOWEST,
+	TEGRA_MAX_SLEW,
+};
+
+enum tegra_pull_strength {
+	TEGRA_PULL_0 = 0,
+	TEGRA_PULL_1,
+	TEGRA_PULL_2,
+	TEGRA_PULL_3,
+	TEGRA_PULL_4,
+	TEGRA_PULL_5,
+	TEGRA_PULL_6,
+	TEGRA_PULL_7,
+	TEGRA_PULL_8,
+	TEGRA_PULL_9,
+	TEGRA_PULL_10,
+	TEGRA_PULL_11,
+	TEGRA_PULL_12,
+	TEGRA_PULL_13,
+	TEGRA_PULL_14,
+	TEGRA_PULL_15,
+	TEGRA_PULL_16,
+	TEGRA_PULL_17,
+	TEGRA_PULL_18,
+	TEGRA_PULL_19,
+	TEGRA_PULL_20,
+	TEGRA_PULL_21,
+	TEGRA_PULL_22,
+	TEGRA_PULL_23,
+	TEGRA_PULL_24,
+	TEGRA_PULL_25,
+	TEGRA_PULL_26,
+	TEGRA_PULL_27,
+	TEGRA_PULL_28,
+	TEGRA_PULL_29,
+	TEGRA_PULL_30,
+	TEGRA_PULL_31,
+	TEGRA_MAX_PULL,
+};
+
+enum tegra_drive_pingroup {
+	TEGRA_DRIVE_PINGROUP_AO1 = 0,
+	TEGRA_DRIVE_PINGROUP_AO2,
+	TEGRA_DRIVE_PINGROUP_AT1,
+	TEGRA_DRIVE_PINGROUP_AT2,
+	TEGRA_DRIVE_PINGROUP_CDEV1,
+	TEGRA_DRIVE_PINGROUP_CDEV2,
+	TEGRA_DRIVE_PINGROUP_CSUS,
+	TEGRA_DRIVE_PINGROUP_DAP1,
+	TEGRA_DRIVE_PINGROUP_DAP2,
+	TEGRA_DRIVE_PINGROUP_DAP3,
+	TEGRA_DRIVE_PINGROUP_DAP4,
+	TEGRA_DRIVE_PINGROUP_DBG,
+	TEGRA_DRIVE_PINGROUP_LCD1,
+	TEGRA_DRIVE_PINGROUP_LCD2,
+	TEGRA_DRIVE_PINGROUP_SDMMC2,
+	TEGRA_DRIVE_PINGROUP_SDMMC3,
+	TEGRA_DRIVE_PINGROUP_SPI,
+	TEGRA_DRIVE_PINGROUP_UAA,
+	TEGRA_DRIVE_PINGROUP_UAB,
+	TEGRA_DRIVE_PINGROUP_UART2,
+	TEGRA_DRIVE_PINGROUP_UART3,
+	TEGRA_DRIVE_PINGROUP_VI1,
+	TEGRA_DRIVE_PINGROUP_VI2,
+	TEGRA_DRIVE_PINGROUP_XM2A,
+	TEGRA_DRIVE_PINGROUP_XM2C,
+	TEGRA_DRIVE_PINGROUP_XM2D,
+	TEGRA_DRIVE_PINGROUP_XM2CLK,
+	TEGRA_DRIVE_PINGROUP_MEMCOMP,
+	TEGRA_MAX_DRIVE_PINGROUP,
+};
+
+enum tegra_drive {
+	TEGRA_DRIVE_DIV_8 = 0,
+	TEGRA_DRIVE_DIV_4,
+	TEGRA_DRIVE_DIV_2,
+	TEGRA_DRIVE_DIV_1,
+	TEGRA_MAX_DRIVE,
+};
+
+enum tegra_hsm {
+	TEGRA_HSM_DISABLE = 0,
+	TEGRA_HSM_ENABLE,
+};
+
+enum tegra_schmitt {
+	TEGRA_SCHMITT_DISABLE = 0,
+	TEGRA_SCHMITT_ENABLE,
+};
+
+struct tegra_drive_pingroup_config {
+	enum tegra_drive_pingroup pingroup;
+	enum tegra_hsm hsm;
+	enum tegra_schmitt schmitt;
+	enum tegra_drive drive;
+	enum tegra_pull_strength pull_down;
+	enum tegra_pull_strength pull_up;
+	enum tegra_slew slew_rising;
+	enum tegra_slew slew_falling;
+};
+
+int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func);
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate);
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd);
+
+void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
+	enum tegra_mux_func func, enum tegra_pullupdown pupd,
+	enum tegra_tristate tristate);
+
+void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len);
+
+void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
+	int len);
+
+#endif
+
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b42dab79a70ca17499b55c0ba9042e278428de5
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/smp.h
@@ -0,0 +1,30 @@
+#ifndef ASMARM_ARCH_SMP_H
+#define ASMARM_ARCH_SMP_H
+
+
+#include <asm/hardware/gic.h>
+
+#define hard_smp_processor_id()			\
+	({						\
+		unsigned int cpunum;			\
+		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
+			: "=r" (cpunum));		\
+		cpunum &= 0x0F;				\
+	})
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+	gic_raise_softirq(mask, 1);
+}
+
+/*
+ * Do nothing on MPcore.
+ */
+static inline void smp_cross_call_done(cpumask_t callmap)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h
new file mode 100644
index 0000000000000000000000000000000000000000..84d5d46113f7457b4e6bf8d7bfcb54ec8f4a0a20
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/system.h
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-tegra/include/mach/system.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_SYSTEM_H
+#define __MACH_TEGRA_SYSTEM_H
+
+#include <mach/hardware.h>
+#include <mach/iomap.h>
+
+static inline void arch_idle(void)
+{
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
+	u32 reg = readl(reset);
+	reg |= 0x04;
+	writel(reg, reset);
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/timex.h b/arch/arm/mach-tegra/include/mach/timex.h
new file mode 100644
index 0000000000000000000000000000000000000000..a44ccbdb7dbf0d1e72485f0fe8b3058707d71ad6
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/timex.h
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-tegra/include/mach/timex.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_TIMEX_H
+#define __MACH_TEGRA_TIMEX_H
+
+#define CLOCK_TICK_RATE		1000000
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c4dd815abd7670e0df8d2980a8d28342ba9bd54
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-tegra/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_UNCOMPRESS_H
+#define __MACH_TEGRA_UNCOMPRESS_H
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <mach/iomap.h>
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+#define DEBUG_UART_BASE TEGRA_UARTA_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+#define DEBUG_UART_BASE TEGRA_UARTB_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+#define DEBUG_UART_BASE TEGRA_UARTC_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+#define DEBUG_UART_BASE TEGRA_UARTD_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+#define DEBUG_UART_BASE TEGRA_UARTE_BASE
+#else
+#define DEBUG_UART_BASE NULL
+#endif
+
+static void putc(int c)
+{
+	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	int shift = 2;
+
+	if (uart == NULL)
+		return;
+
+	while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
+		barrier();
+	uart[UART_TX << shift] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static inline void arch_decomp_setup(void)
+{
+	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	int shift = 2;
+
+	if (uart == NULL)
+		return;
+
+	uart[UART_LCR << shift] |= UART_LCR_DLAB;
+	uart[UART_DLL << shift] = 0x75;
+	uart[UART_DLM << shift] = 0x0;
+	uart[UART_LCR << shift] = 3;
+}
+
+static inline void arch_decomp_wdog(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/vmalloc.h b/arch/arm/mach-tegra/include/mach/vmalloc.h
new file mode 100644
index 0000000000000000000000000000000000000000..267a141730d9c94fa59a7c0acbd5bbc6426e79d2
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/vmalloc.h
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-tegra/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_VMALLOC_H
+#define __MACH_TEGRA_VMALLOC_H
+
+#include <asm/sizes.h>
+
+#define VMALLOC_END        0xFE000000
+
+#endif
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fe2c5c683d471e96e794a86be2061d9a46694a8
--- /dev/null
+++ b/arch/arm/mach-tegra/io.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-tegra/io.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+
+#include "board.h"
+
+static struct map_desc tegra_io_desc[] __initdata = {
+	{
+		.virtual = IO_PPSB_VIRT,
+		.pfn = __phys_to_pfn(IO_PPSB_PHYS),
+		.length = IO_PPSB_SIZE,
+		.type = MT_DEVICE,
+	},
+	{
+		.virtual = IO_APB_VIRT,
+		.pfn = __phys_to_pfn(IO_APB_PHYS),
+		.length = IO_APB_SIZE,
+		.type = MT_DEVICE,
+	},
+	{
+		.virtual = IO_CPU_VIRT,
+		.pfn = __phys_to_pfn(IO_CPU_PHYS),
+		.length = IO_CPU_SIZE,
+		.type = MT_DEVICE,
+	},
+};
+
+void __init tegra_map_common_io(void)
+{
+	iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc));
+}
+
+/*
+ * Intercept ioremap() requests for addresses in our fixed mapping regions.
+ */
+void __iomem *tegra_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+	void __iomem *v = IO_ADDRESS(p);
+	if (v == NULL)
+		v = __arm_ioremap(p, size, type);
+	return v;
+}
+EXPORT_SYMBOL(tegra_ioremap);
+
+void tegra_iounmap(volatile void __iomem *addr)
+{
+	unsigned long virt = (unsigned long)addr;
+
+	if (virt >= VMALLOC_START && virt < VMALLOC_END)
+		__iounmap(addr);
+}
+EXPORT_SYMBOL(tegra_iounmap);
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
new file mode 100644
index 0000000000000000000000000000000000000000..1fdbe708d43d12b5bc73ddf1c553461700932677
--- /dev/null
+++ b/arch/arm/mach-tegra/irq.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/gic.h>
+
+#include <mach/iomap.h>
+
+#include "board.h"
+
+void __init tegra_init_irq(void)
+{
+	gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
+	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+}
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c
new file mode 100644
index 0000000000000000000000000000000000000000..f81ca7cbbc1f7279aea08174896aec401725fa54
--- /dev/null
+++ b/arch/arm/mach-tegra/localtimer.c
@@ -0,0 +1,25 @@
+/*
+ *  arch/arm/mach-tegra/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/clockchips.h>
+#include <asm/irq.h>
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
+}
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
new file mode 100644
index 0000000000000000000000000000000000000000..13ae10237e84688565af92668975a2c11e58171a
--- /dev/null
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -0,0 +1,945 @@
+/*
+ * linux/arch/arm/mach-tegra/pinmux.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+
+
+#define TEGRA_TRI_STATE(x)	(0x14 + (4 * (x)))
+#define TEGRA_PP_MUX_CTL(x)	(0x80 + (4 * (x)))
+#define TEGRA_PP_PU_PD(x)	(0xa0 + (4 * (x)))
+
+#define REG_A 0
+#define REG_B 1
+#define REG_C 2
+#define REG_D 3
+#define REG_E 4
+#define REG_F 5
+#define REG_G 6
+
+#define REG_N -1
+
+#define HSM_EN(reg)	(((reg) >> 2) & 0x1)
+#define SCHMT_EN(reg)	(((reg) >> 3) & 0x1)
+#define LPMD(reg)	(((reg) >> 4) & 0x3)
+#define DRVDN(reg)	(((reg) >> 12) & 0x1f)
+#define DRVUP(reg)	(((reg) >> 20) & 0x1f)
+#define SLWR(reg)	(((reg) >> 28) & 0x3)
+#define SLWF(reg)	(((reg) >> 30) & 0x3)
+
+struct tegra_pingroup_desc {
+	const char *name;
+	int funcs[4];
+	s8 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
+	s8 tri_bit; 	/* offset into the TRISTATE_REG_* register bit */
+	s8 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
+	s8 mux_bit;	/* offset into the PIN_MUX_CTL_* register bit */
+	s8 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
+	s8 pupd_bit;	/* offset into the PULL_UPDOWN_REG_* register bit */
+};
+
+#define PINGROUP(pg_name, f0, f1, f2, f3,			\
+		 tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)	\
+	[TEGRA_PINGROUP_ ## pg_name] = {			\
+		.name = #pg_name,				\
+		.funcs = {					\
+			TEGRA_MUX_ ## f0,			\
+			TEGRA_MUX_ ## f1,			\
+			TEGRA_MUX_ ## f2,			\
+			TEGRA_MUX_ ## f3,			\
+		},						\
+		.tri_reg = REG_ ## tri_r,			\
+		.tri_bit = tri_b,				\
+		.mux_reg = REG_ ## mux_r,			\
+		.mux_bit = mux_b,				\
+		.pupd_reg = REG_ ## pupd_r,			\
+		.pupd_bit = pupd_b,				\
+	}
+
+static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = {
+	PINGROUP(ATA,   IDE,       NAND,      GMI,       RSVD,          A, 0,  A, 24, A, 0),
+	PINGROUP(ATB,   IDE,       NAND,      GMI,       SDIO4,         A, 1,  A, 16, A, 2),
+	PINGROUP(ATC,   IDE,       NAND,      GMI,       SDIO4,         A, 2,  A, 22, A, 4),
+	PINGROUP(ATD,   IDE,       NAND,      GMI,       SDIO4,         A, 3,  A, 20, A, 6),
+	PINGROUP(ATE,   IDE,       NAND,      GMI,       RSVD,          B, 25, A, 12, A, 8),
+	PINGROUP(CDEV1, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    A, 4,  C, 2,  C, 0),
+	PINGROUP(CDEV2, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     A, 5,  C, 4,  C, 2),
+	PINGROUP(CRTP,  CRT,       RSVD,      RSVD,      RSVD,          D, 14, G, 20, B, 24),
+	PINGROUP(CSUS,  PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6,  C, 6,  D, 24),
+	PINGROUP(DAP1,  DAP1,      RSVD,      GMI,       SDIO2,         A, 7,  C, 20, A, 10),
+	PINGROUP(DAP2,  DAP2,      TWC,       RSVD,      GMI,           A, 8,  C, 22, A, 12),
+	PINGROUP(DAP3,  DAP3,      RSVD,      RSVD,      RSVD,          A, 9,  C, 24, A, 14),
+	PINGROUP(DAP4,  DAP4,      RSVD,      GMI,       RSVD,          A, 10, C, 26, A, 16),
+	PINGROUP(DDC,   I2C2,      RSVD,      RSVD,      RSVD,          B, 31, C, 0,  E, 28),
+	PINGROUP(DTA,   RSVD,      SDIO2,     VI,        RSVD,          A, 11, B, 20, A, 18),
+	PINGROUP(DTB,   RSVD,      RSVD,      VI,        SPI1,          A, 12, B, 22, A, 20),
+	PINGROUP(DTC,   RSVD,      RSVD,      VI,        RSVD,          A, 13, B, 26, A, 22),
+	PINGROUP(DTD,   RSVD,      SDIO2,     VI,        RSVD,          A, 14, B, 28, A, 24),
+	PINGROUP(DTE,   RSVD,      RSVD,      VI,        SPI1,          A, 15, B, 30, A, 26),
+	PINGROUP(DTF,   I2C3,      RSVD,      VI,        RSVD,          D, 12, G, 30, A, 28),
+	PINGROUP(GMA,   UARTE,     SPI3,      GMI,       SDIO4,         A, 28, B, 0,  E, 20),
+	PINGROUP(GMB,   IDE,       NAND,      GMI,       GMI_INT,       B, 29, C, 28, E, 22),
+	PINGROUP(GMC,   UARTD,     SPI4,      GMI,       SFLASH,        A, 29, B, 2,  E, 24),
+	PINGROUP(GMD,   RSVD,      NAND,      GMI,       SFLASH,        B, 30, C, 30, E, 26),
+	PINGROUP(GME,   RSVD,      DAP5,      GMI,       SDIO4,         B, 0,  D, 0,  C, 24),
+	PINGROUP(GPU,   PWM,       UARTA,     GMI,       RSVD,          A, 16, D, 4,  B, 20),
+	PINGROUP(GPU7,  RTCK,      RSVD,      RSVD,      RSVD,          D, 11, G, 28, B, 6),
+	PINGROUP(GPV,   PCIE,      RSVD,      RSVD,      RSVD,          A, 17, D, 2,  A, 30),
+	PINGROUP(HDINT, HDMI,      RSVD,      RSVD,      RSVD,          C, 23, B, 4,  D, 22),
+	PINGROUP(I2CP,  I2C,       RSVD,      RSVD,      RSVD,          A, 18, C, 8,  B, 2),
+	PINGROUP(IRRX,  UARTA,     UARTB,     GMI,       SPI4,          A, 20, C, 18, C, 22),
+	PINGROUP(IRTX,  UARTA,     UARTB,     GMI,       SPI4,          A, 19, C, 16, C, 20),
+	PINGROUP(KBCA,  KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, A, 22, C, 10, B, 8),
+	PINGROUP(KBCB,  KBC,       NAND,      SDIO2,     MIO,           A, 21, C, 12, B, 10),
+	PINGROUP(KBCC,  KBC,       NAND,      TRACE,     EMC_TEST1_DLL, B, 26, C, 14, B, 12),
+	PINGROUP(KBCD,  KBC,       NAND,      SDIO2,     MIO,           D, 10, G, 26, B, 14),
+	PINGROUP(KBCE,  KBC,       NAND,      OWR,       RSVD,          A, 26, A, 28, E, 2),
+	PINGROUP(KBCF,  KBC,       NAND,      TRACE,     MIO,           A, 27, A, 26, E, 0),
+	PINGROUP(LCSN,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 31, E, 12, D, 20),
+	PINGROUP(LD0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 0,  F, 0,  D, 12),
+	PINGROUP(LD1,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 1,  F, 2,  D, 12),
+	PINGROUP(LD10,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 10, F, 20, D, 12),
+	PINGROUP(LD11,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 11, F, 22, D, 12),
+	PINGROUP(LD12,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 12, F, 24, D, 12),
+	PINGROUP(LD13,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 13, F, 26, D, 12),
+	PINGROUP(LD14,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 14, F, 28, D, 12),
+	PINGROUP(LD15,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 15, F, 30, D, 12),
+	PINGROUP(LD16,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 16, G, 0,  D, 12),
+	PINGROUP(LD17,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 17, G, 2,  D, 12),
+	PINGROUP(LD2,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 2,  F, 4,  D, 12),
+	PINGROUP(LD3,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 3,  F, 6,  D, 12),
+	PINGROUP(LD4,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 4,  F, 8,  D, 12),
+	PINGROUP(LD5,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 5,  F, 10, D, 12),
+	PINGROUP(LD6,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 6,  F, 12, D, 12),
+	PINGROUP(LD7,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 7,  F, 14, D, 12),
+	PINGROUP(LD8,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 8,  F, 16, D, 12),
+	PINGROUP(LD9,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 9,  F, 18, D, 12),
+	PINGROUP(LDC,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 30, E, 14, D, 20),
+	PINGROUP(LDI,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 6,  G, 16, D, 18),
+	PINGROUP(LHP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 18, G, 10, D, 16),
+	PINGROUP(LHP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 19, G, 4,  D, 14),
+	PINGROUP(LHP2,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 20, G, 6,  D, 14),
+	PINGROUP(LHS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          D, 7,  E, 22, D, 22),
+	PINGROUP(LM0,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 24, E, 26, D, 22),
+	PINGROUP(LM1,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           C, 25, E, 28, D, 22),
+	PINGROUP(LPP,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 8,  G, 14, D, 18),
+	PINGROUP(LPW0,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 3,  E, 0,  D, 20),
+	PINGROUP(LPW1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 4,  E, 2,  D, 20),
+	PINGROUP(LPW2,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 5,  E, 4,  D, 20),
+	PINGROUP(LSC0,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 27, E, 18, D, 22),
+	PINGROUP(LSC1,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 28, E, 20, D, 20),
+	PINGROUP(LSCK,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 29, E, 16, D, 20),
+	PINGROUP(LSDA,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 1,  E, 8,  D, 20),
+	PINGROUP(LSDI,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          D, 2,  E, 6,  D, 20),
+	PINGROUP(LSPI,  DISPLAYA,  DISPLAYB,  XIO,       HDMI,          D, 0,  E, 10, D, 22),
+	PINGROUP(LVP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 21, E, 30, D, 22),
+	PINGROUP(LVP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 22, G, 8,  D, 16),
+	PINGROUP(LVS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 26, E, 24, D, 22),
+	PINGROUP(OWC,   OWR,       RSVD,      RSVD,      RSVD,          A, 31, B, 8,  E, 30),
+	PINGROUP(PMC,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          A, 23, G, 18, N, -1),
+	PINGROUP(PTA,   I2C2,      HDMI,      GMI,       RSVD,          A, 24, G, 22, B, 4),
+	PINGROUP(RM,    I2C,       RSVD,      RSVD,      RSVD,          A, 25, A, 14, B, 0),
+	PINGROUP(SDB,   UARTA,     PWM,       SDIO3,     SPI2,          D, 15, D, 10, N, -1),
+	PINGROUP(SDC,   PWM,       TWC,       SDIO3,     SPI3,          B, 1,  D, 12, D, 28),
+	PINGROUP(SDD,   UARTA,     PWM,       SDIO3,     SPI3,          B, 2,  D, 14, D, 30),
+	PINGROUP(SDIO1, SDIO1,     RSVD,      UARTE,     UARTA,         A, 30, A, 30, E, 18),
+	PINGROUP(SLXA,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 3,  B, 6,  B, 22),
+	PINGROUP(SLXC,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 5,  B, 10, B, 26),
+	PINGROUP(SLXD,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 6,  B, 12, B, 28),
+	PINGROUP(SLXK,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 7,  B, 14, B, 30),
+	PINGROUP(SPDI,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 8,  D, 8,  B, 16),
+	PINGROUP(SPDO,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 9,  D, 6,  B, 18),
+	PINGROUP(SPIA,  SPI1,      SPI2,      SPI3,      GMI,           B, 10, D, 30, C, 4),
+	PINGROUP(SPIB,  SPI1,      SPI2,      SPI3,      GMI,           B, 11, D, 28, C, 6),
+	PINGROUP(SPIC,  SPI1,      SPI2,      SPI3,      GMI,           B, 12, D, 26, C, 8),
+	PINGROUP(SPID,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 13, D, 24, C, 10),
+	PINGROUP(SPIE,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 14, D, 22, C, 12),
+	PINGROUP(SPIF,  SPI3,      SPI1,      SPI2,      RSVD,          B, 15, D, 20, C, 14),
+	PINGROUP(SPIG,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 16, D, 18, C, 16),
+	PINGROUP(SPIH,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 17, D, 16, C, 18),
+	PINGROUP(UAA,   SPI3,      MIPI_HS,   UARTA,     ULPI,          B, 18, A, 0,  D, 0),
+	PINGROUP(UAB,   SPI2,      MIPI_HS,   UARTA,     ULPI,          B, 19, A, 2,  D, 2),
+	PINGROUP(UAC,   OWR,       RSVD,      RSVD,      RSVD,          B, 20, A, 4,  D, 4),
+	PINGROUP(UAD,   IRDA,      SPDIF,     UARTA,     SPI4,          B, 21, A, 6,  D, 6),
+	PINGROUP(UCA,   UARTC,     RSVD,      GMI,       RSVD,          B, 22, B, 16, D, 8),
+	PINGROUP(UCB,   UARTC,     PWM,       GMI,       RSVD,          B, 23, B, 18, D, 10),
+	PINGROUP(UDA,   SPI1,      RSVD,      UARTD,     ULPI,          D, 13, A, 8,  E, 16),
+	/* these pin groups only have pullup and pull down control */
+	PINGROUP(CK32,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 14),
+	PINGROUP(DDRC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  D, 26),
+	PINGROUP(PMCA,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 4),
+	PINGROUP(PMCB,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 6),
+	PINGROUP(PMCC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 8),
+	PINGROUP(PMCD,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 10),
+	PINGROUP(PMCE,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 12),
+	PINGROUP(XM2C,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 30),
+	PINGROUP(XM2D,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 28),
+};
+
+static char *tegra_mux_names[TEGRA_MAX_MUX] = {
+	[TEGRA_MUX_AHB_CLK] = "AHB_CLK",
+	[TEGRA_MUX_APB_CLK] = "APB_CLK",
+	[TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC",
+	[TEGRA_MUX_CRT] = "CRT",
+	[TEGRA_MUX_DAP1] = "DAP1",
+	[TEGRA_MUX_DAP2] = "DAP2",
+	[TEGRA_MUX_DAP3] = "DAP3",
+	[TEGRA_MUX_DAP4] = "DAP4",
+	[TEGRA_MUX_DAP5] = "DAP5",
+	[TEGRA_MUX_DISPLAYA] = "DISPLAYA",
+	[TEGRA_MUX_DISPLAYB] = "DISPLAYB",
+	[TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL",
+	[TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL",
+	[TEGRA_MUX_GMI] = "GMI",
+	[TEGRA_MUX_GMI_INT] = "GMI_INT",
+	[TEGRA_MUX_HDMI] = "HDMI",
+	[TEGRA_MUX_I2C] = "I2C",
+	[TEGRA_MUX_I2C2] = "I2C2",
+	[TEGRA_MUX_I2C3] = "I2C3",
+	[TEGRA_MUX_IDE] = "IDE",
+	[TEGRA_MUX_IRDA] = "IRDA",
+	[TEGRA_MUX_KBC] = "KBC",
+	[TEGRA_MUX_MIO] = "MIO",
+	[TEGRA_MUX_MIPI_HS] = "MIPI_HS",
+	[TEGRA_MUX_NAND] = "NAND",
+	[TEGRA_MUX_OSC] = "OSC",
+	[TEGRA_MUX_OWR] = "OWR",
+	[TEGRA_MUX_PCIE] = "PCIE",
+	[TEGRA_MUX_PLLA_OUT] = "PLLA_OUT",
+	[TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1",
+	[TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1",
+	[TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2",
+	[TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3",
+	[TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4",
+	[TEGRA_MUX_PWM] = "PWM",
+	[TEGRA_MUX_PWR_INTR] = "PWR_INTR",
+	[TEGRA_MUX_PWR_ON] = "PWR_ON",
+	[TEGRA_MUX_RTCK] = "RTCK",
+	[TEGRA_MUX_SDIO1] = "SDIO1",
+	[TEGRA_MUX_SDIO2] = "SDIO2",
+	[TEGRA_MUX_SDIO3] = "SDIO3",
+	[TEGRA_MUX_SDIO4] = "SDIO4",
+	[TEGRA_MUX_SFLASH] = "SFLASH",
+	[TEGRA_MUX_SPDIF] = "SPDIF",
+	[TEGRA_MUX_SPI1] = "SPI1",
+	[TEGRA_MUX_SPI2] = "SPI2",
+	[TEGRA_MUX_SPI2_ALT] = "SPI2_ALT",
+	[TEGRA_MUX_SPI3] = "SPI3",
+	[TEGRA_MUX_SPI4] = "SPI4",
+	[TEGRA_MUX_TRACE] = "TRACE",
+	[TEGRA_MUX_TWC] = "TWC",
+	[TEGRA_MUX_UARTA] = "UARTA",
+	[TEGRA_MUX_UARTB] = "UARTB",
+	[TEGRA_MUX_UARTC] = "UARTC",
+	[TEGRA_MUX_UARTD] = "UARTD",
+	[TEGRA_MUX_UARTE] = "UARTE",
+	[TEGRA_MUX_ULPI] = "ULPI",
+	[TEGRA_MUX_VI] = "VI",
+	[TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
+	[TEGRA_MUX_XIO] = "XIO",
+};
+
+struct tegra_drive_pingroup_desc {
+	const char *name;
+	s16 reg;
+};
+
+#define DRIVE_PINGROUP(pg_name, r)				\
+	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
+		.name = #pg_name,				\
+		.reg = r					\
+	}
+
+static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = {
+	DRIVE_PINGROUP(AO1,		0x868),
+	DRIVE_PINGROUP(AO2,		0x86c),
+	DRIVE_PINGROUP(AT1,		0x870),
+	DRIVE_PINGROUP(AT2,		0x874),
+	DRIVE_PINGROUP(CDEV1,		0x878),
+	DRIVE_PINGROUP(CDEV2,		0x87c),
+	DRIVE_PINGROUP(CSUS,		0x880),
+	DRIVE_PINGROUP(DAP1,		0x884),
+	DRIVE_PINGROUP(DAP2,		0x888),
+	DRIVE_PINGROUP(DAP3,		0x88c),
+	DRIVE_PINGROUP(DAP4,		0x890),
+	DRIVE_PINGROUP(DBG,		0x894),
+	DRIVE_PINGROUP(LCD1,		0x898),
+	DRIVE_PINGROUP(LCD2,		0x89c),
+	DRIVE_PINGROUP(SDMMC2,	0x8a0),
+	DRIVE_PINGROUP(SDMMC3,	0x8a4),
+	DRIVE_PINGROUP(SPI,		0x8a8),
+	DRIVE_PINGROUP(UAA,		0x8ac),
+	DRIVE_PINGROUP(UAB,		0x8b0),
+	DRIVE_PINGROUP(UART2,		0x8b4),
+	DRIVE_PINGROUP(UART3,		0x8b8),
+	DRIVE_PINGROUP(VI1,		0x8bc),
+	DRIVE_PINGROUP(VI2,		0x8c0),
+	DRIVE_PINGROUP(XM2A,		0x8c4),
+	DRIVE_PINGROUP(XM2C,		0x8c8),
+	DRIVE_PINGROUP(XM2D,		0x8cc),
+	DRIVE_PINGROUP(XM2CLK,	0x8d0),
+	DRIVE_PINGROUP(MEMCOMP,	0x8d4),
+};
+
+static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
+	[TEGRA_DRIVE_DIV_8] = "DIV_8",
+	[TEGRA_DRIVE_DIV_4] = "DIV_4",
+	[TEGRA_DRIVE_DIV_2] = "DIV_2",
+	[TEGRA_DRIVE_DIV_1] = "DIV_1",
+};
+
+static const char *tegra_slew_names[TEGRA_MAX_SLEW] = {
+	[TEGRA_SLEW_FASTEST] = "FASTEST",
+	[TEGRA_SLEW_FAST] = "FAST",
+	[TEGRA_SLEW_SLOW] = "SLOW",
+	[TEGRA_SLEW_SLOWEST] = "SLOWEST",
+};
+
+static DEFINE_SPINLOCK(mux_lock);
+
+static const char *pingroup_name(enum tegra_pingroup pg)
+{
+	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+		return "<UNKNOWN>";
+
+	return pingroups[pg].name;
+}
+
+static const char *func_name(enum tegra_mux_func func)
+{
+	if (func == TEGRA_MUX_RSVD1)
+		return "RSVD1";
+
+	if (func == TEGRA_MUX_RSVD2)
+		return "RSVD2";
+
+	if (func == TEGRA_MUX_RSVD3)
+		return "RSVD3";
+
+	if (func == TEGRA_MUX_RSVD4)
+		return "RSVD4";
+
+	if (func == TEGRA_MUX_NONE)
+		return "NONE";
+
+	if (func < 0 || func >=  TEGRA_MAX_MUX)
+		return "<UNKNOWN>";
+
+	return tegra_mux_names[func];
+}
+
+
+static const char *tri_name(unsigned long val)
+{
+	return val ? "TRISTATE" : "NORMAL";
+}
+
+static const char *pupd_name(unsigned long val)
+{
+	switch (val) {
+	case 0:
+		return "NORMAL";
+
+	case 1:
+		return "PULL_DOWN";
+
+	case 2:
+		return "PULL_UP";
+
+	default:
+		return "RSVD";
+	}
+}
+
+
+static inline unsigned long pg_readl(unsigned long offset)
+{
+	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+static inline void pg_writel(unsigned long value, unsigned long offset)
+{
+	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
+{
+	int mux = -1;
+	int i;
+	unsigned long reg;
+	unsigned long flags;
+
+	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+		return -ERANGE;
+
+	if (pingroups[pg].mux_reg == REG_N)
+		return -EINVAL;
+
+	if (func < 0)
+		return -ERANGE;
+
+	if (func & TEGRA_MUX_RSVD) {
+		mux = func & 0x3;
+	} else {
+		for (i = 0; i < 4; i++) {
+			if (pingroups[pg].funcs[i] == func) {
+				mux = i;
+				break;
+			}
+		}
+	}
+
+	if (mux < 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+	reg &= ~(0x3 << pingroups[pg].mux_bit);
+	reg |= mux << pingroups[pg].mux_bit;
+	pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
+	enum tegra_tristate tristate)
+{
+	unsigned long reg;
+	unsigned long flags;
+
+	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+		return -ERANGE;
+
+	if (pingroups[pg].tri_reg == REG_N)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+	reg &= ~(0x1 << pingroups[pg].tri_bit);
+	if (tristate)
+		reg |= 1 << pingroups[pg].tri_bit;
+	pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
+	enum tegra_pullupdown pupd)
+{
+	unsigned long reg;
+	unsigned long flags;
+
+	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+		return -ERANGE;
+
+	if (pingroups[pg].pupd_reg == REG_N)
+		return -EINVAL;
+
+	if (pupd != TEGRA_PUPD_NORMAL &&
+	    pupd != TEGRA_PUPD_PULL_DOWN &&
+	    pupd != TEGRA_PUPD_PULL_UP)
+		return -EINVAL;
+
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+	reg &= ~(0x3 << pingroups[pg].pupd_bit);
+	reg |= pupd << pingroups[pg].pupd_bit;
+	pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
+				 enum tegra_mux_func func,
+				 enum tegra_pullupdown pupd,
+				 enum tegra_tristate tristate)
+{
+	int err;
+
+	if (pingroups[pingroup].mux_reg != REG_N) {
+		err = tegra_pinmux_set_func(pingroup, func);
+		if (err < 0)
+			pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
+			       pingroup_name(pingroup), func_name(func), err);
+	}
+
+	if (pingroups[pingroup].pupd_reg != REG_N) {
+		err = tegra_pinmux_set_pullupdown(pingroup, pupd);
+		if (err < 0)
+			pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
+			       pingroup_name(pingroup), pupd_name(pupd), err);
+	}
+
+	if (pingroups[pingroup].tri_reg != REG_N) {
+		err = tegra_pinmux_set_tristate(pingroup, tristate);
+		if (err < 0)
+			pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
+			       pingroup_name(pingroup), tri_name(func), err);
+	}
+}
+
+
+
+void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		tegra_pinmux_config_pingroup(config[i].pingroup,
+					     config[i].func,
+					     config[i].pupd,
+					     config[i].tristate);
+}
+
+static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
+{
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return "<UNKNOWN>";
+
+	return drive_pingroups[pg].name;
+}
+
+static const char *enable_name(unsigned long val)
+{
+	return val ? "ENABLE" : "DISABLE";
+}
+
+static const char *drive_name(unsigned long val)
+{
+	if (val >= TEGRA_MAX_DRIVE)
+		return "<UNKNOWN>";
+
+	return tegra_drive_names[val];
+}
+
+static const char *slew_name(unsigned long val)
+{
+	if (val >= TEGRA_MAX_SLEW)
+		return "<UNKNOWN>";
+
+	return tegra_slew_names[val];
+}
+
+static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
+	enum tegra_hsm hsm)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (hsm != TEGRA_HSM_ENABLE && hsm != TEGRA_HSM_DISABLE)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	if (hsm == TEGRA_HSM_ENABLE)
+		reg |= (1 << 2);
+	else
+		reg &= ~(1 << 2);
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
+	enum tegra_schmitt schmitt)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (schmitt != TEGRA_SCHMITT_ENABLE && schmitt != TEGRA_SCHMITT_DISABLE)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	if (schmitt == TEGRA_SCHMITT_ENABLE)
+		reg |= (1 << 3);
+	else
+		reg &= ~(1 << 3);
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
+	enum tegra_drive drive)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (drive < 0 || drive >= TEGRA_MAX_DRIVE)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	reg &= ~(0x3 << 4);
+	reg |= drive << 4;
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
+	enum tegra_pull_strength pull_down)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (pull_down < 0 || pull_down >= TEGRA_MAX_PULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	reg &= ~(0x1f << 12);
+	reg |= pull_down << 12;
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
+	enum tegra_pull_strength pull_up)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (pull_up < 0 || pull_up >= TEGRA_MAX_PULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	reg &= ~(0x1f << 12);
+	reg |= pull_up << 12;
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
+	enum tegra_slew slew_rising)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (slew_rising < 0 || slew_rising >= TEGRA_MAX_SLEW)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	reg &= ~(0x3 << 28);
+	reg |= slew_rising << 28;
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
+	enum tegra_slew slew_falling)
+{
+	unsigned long flags;
+	u32 reg;
+	if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+		return -ERANGE;
+
+	if (slew_falling < 0 || slew_falling >= TEGRA_MAX_SLEW)
+		return -EINVAL;
+
+	spin_lock_irqsave(&mux_lock, flags);
+
+	reg = pg_readl(drive_pingroups[pg].reg);
+	reg &= ~(0x3 << 30);
+	reg |= slew_falling << 30;
+	pg_writel(reg, drive_pingroups[pg].reg);
+
+	spin_unlock_irqrestore(&mux_lock, flags);
+
+	return 0;
+}
+
+static void tegra_drive_pinmux_config_pingroup(enum tegra_drive_pingroup pingroup,
+					  enum tegra_hsm hsm,
+					  enum tegra_schmitt schmitt,
+					  enum tegra_drive drive,
+					  enum tegra_pull_strength pull_down,
+					  enum tegra_pull_strength pull_up,
+					  enum tegra_slew slew_rising,
+					  enum tegra_slew slew_falling)
+{
+	int err;
+
+	err = tegra_drive_pinmux_set_hsm(pingroup, hsm);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s hsm to %s: %d\n",
+			drive_pinmux_name(pingroup),
+			enable_name(hsm), err);
+
+	err = tegra_drive_pinmux_set_schmitt(pingroup, schmitt);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s schmitt to %s: %d\n",
+			drive_pinmux_name(pingroup),
+			enable_name(schmitt), err);
+
+	err = tegra_drive_pinmux_set_drive(pingroup, drive);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s drive to %s: %d\n",
+			drive_pinmux_name(pingroup),
+			drive_name(drive), err);
+
+	err = tegra_drive_pinmux_set_pull_down(pingroup, pull_down);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s pull down to %d: %d\n",
+			drive_pinmux_name(pingroup),
+			pull_down, err);
+
+	err = tegra_drive_pinmux_set_pull_up(pingroup, pull_up);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s pull up to %d: %d\n",
+			drive_pinmux_name(pingroup),
+			pull_up, err);
+
+	err = tegra_drive_pinmux_set_slew_rising(pingroup, slew_rising);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s rising slew to %s: %d\n",
+			drive_pinmux_name(pingroup),
+			slew_name(slew_rising), err);
+
+	err = tegra_drive_pinmux_set_slew_falling(pingroup, slew_falling);
+	if (err < 0)
+		pr_err("pinmux: can't set pingroup %s falling slew to %s: %d\n",
+			drive_pinmux_name(pingroup),
+			slew_name(slew_falling), err);
+}
+
+void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
+	int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		tegra_drive_pinmux_config_pingroup(config[i].pingroup,
+						     config[i].hsm,
+						     config[i].schmitt,
+						     config[i].drive,
+						     config[i].pull_down,
+						     config[i].pull_up,
+						     config[i].slew_rising,
+						     config[i].slew_falling);
+}
+
+
+#ifdef	CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static void dbg_pad_field(struct seq_file *s, int len)
+{
+	seq_putc(s, ',');
+
+	while (len-- > -1)
+		seq_putc(s, ' ');
+}
+
+static int dbg_pinmux_show(struct seq_file *s, void *unused)
+{
+	int i;
+	int len;
+
+	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		unsigned long tri;
+		unsigned long mux;
+		unsigned long pupd;
+
+		seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name);
+		len = strlen(pingroups[i].name);
+		dbg_pad_field(s, 5 - len);
+
+		if (pingroups[i].mux_reg == REG_N) {
+			seq_printf(s, "TEGRA_MUX_NONE");
+			len = strlen("NONE");
+		} else {
+			mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >>
+			       pingroups[i].mux_bit) & 0x3;
+			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
+				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
+				len = 5;
+			} else {
+				seq_printf(s, "TEGRA_MUX_%s",
+					   tegra_mux_names[pingroups[i].funcs[mux]]);
+				len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]);
+			}
+		}
+		dbg_pad_field(s, 13-len);
+
+		if (pingroups[i].mux_reg == REG_N) {
+			seq_printf(s, "TEGRA_PUPD_NORMAL");
+			len = strlen("NORMAL");
+		} else {
+			pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >>
+				pingroups[i].pupd_bit) & 0x3;
+			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
+			len = strlen(pupd_name(pupd));
+		}
+		dbg_pad_field(s, 9 - len);
+
+		if (pingroups[i].tri_reg == REG_N) {
+			seq_printf(s, "TEGRA_TRI_NORMAL");
+		} else {
+			tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >>
+			       pingroups[i].tri_bit) & 0x1;
+
+			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
+		}
+		seq_printf(s, "},\n");
+	}
+	return 0;
+}
+
+static int dbg_pinmux_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dbg_pinmux_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= dbg_pinmux_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
+{
+	int i;
+	int len;
+
+	for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+		u32 reg;
+
+		seq_printf(s, "\t{TEGRA_DRIVE_PINGROUP_%s",
+			drive_pingroups[i].name);
+		len = strlen(drive_pingroups[i].name);
+		dbg_pad_field(s, 7 - len);
+
+
+		reg = pg_readl(drive_pingroups[i].reg);
+		if (HSM_EN(reg)) {
+			seq_printf(s, "TEGRA_HSM_ENABLE");
+			len = 16;
+		} else {
+			seq_printf(s, "TEGRA_HSM_DISABLE");
+			len = 17;
+		}
+		dbg_pad_field(s, 17 - len);
+
+		if (SCHMT_EN(reg)) {
+			seq_printf(s, "TEGRA_SCHMITT_ENABLE");
+			len = 21;
+		} else {
+			seq_printf(s, "TEGRA_SCHMITT_DISABLE");
+			len = 22;
+		}
+		dbg_pad_field(s, 22 - len);
+
+		seq_printf(s, "TEGRA_DRIVE_%s", drive_name(LPMD(reg)));
+		len = strlen(drive_name(LPMD(reg)));
+		dbg_pad_field(s, 5 - len);
+
+		seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg));
+		len = DRVDN(reg) < 10 ? 1 : 2;
+		dbg_pad_field(s, 2 - len);
+
+		seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg));
+		len = DRVUP(reg) < 10 ? 1 : 2;
+		dbg_pad_field(s, 2 - len);
+
+		seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg)));
+		len = strlen(slew_name(SLWR(reg)));
+		dbg_pad_field(s, 7 - len);
+
+		seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg)));
+
+		seq_printf(s, "},\n");
+	}
+	return 0;
+}
+
+static int dbg_drive_pinmux_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dbg_drive_pinmux_show, &inode->i_private);
+}
+
+static const struct file_operations debug_drive_fops = {
+	.open		= dbg_drive_pinmux_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init tegra_pinmux_debuginit(void)
+{
+	(void) debugfs_create_file("tegra_pinmux", S_IRUGO,
+					NULL, NULL, &debug_fops);
+	(void) debugfs_create_file("tegra_pinmux_drive", S_IRUGO,
+					NULL, NULL, &debug_drive_fops);
+	return 0;
+}
+late_initcall(tegra_pinmux_debuginit);
+#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
new file mode 100644
index 0000000000000000000000000000000000000000..1c0fd92cab39e44779a3823e89d5248997163a72
--- /dev/null
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -0,0 +1,156 @@
+/*
+ *  linux/arch/arm/mach-tegra/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ *  Copyright (C) 2009 Palm
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/localtimer.h>
+#include <asm/smp_scu.h>
+
+#include <mach/iomap.h>
+
+extern void tegra_secondary_startup(void);
+
+static DEFINE_SPINLOCK(boot_lock);
+static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
+
+#define EVP_CPU_RESET_VECTOR \
+	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
+#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
+	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
+#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
+	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	trace_hardirqs_off();
+
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long old_boot_vector;
+	unsigned long boot_vector;
+	unsigned long timeout;
+	u32 reg;
+
+	/*
+	 * set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+
+	/* set the reset vector to point to the secondary_startup routine */
+
+	boot_vector = virt_to_phys(tegra_secondary_startup);
+	old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
+	writel(boot_vector, EVP_CPU_RESET_VECTOR);
+
+	/* enable cpu clock on cpu1 */
+	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+
+	reg = (1<<13) | (1<<9) | (1<<5) | (1<<1);
+	writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+
+	smp_wmb();
+	flush_cache_all();
+
+	/* unhalt the cpu */
+	writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
+			break;
+		udelay(10);
+	}
+
+	/* put the old boot vector back */
+	writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i, ncores = scu_get_core_count(scu_base);
+
+	for (i = 0; i < ncores; i++)
+		cpu_set(i, cpu_possible_map);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int ncores = scu_get_core_count(scu_base);
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	smp_store_cpu_info(cpu);
+
+	/*
+	 * are we trying to boot more cores than exist?
+	 */
+	if (max_cpus > ncores)
+		max_cpus = ncores;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	/*
+	 * Initialise the SCU if there are more than one CPU and let
+	 * them know where to start. Note that, on modern versions of
+	 * MILO, the "poke" doesn't actually do anything until each
+	 * individual core is sent a soft interrupt to get it out of
+	 * WFI
+	 */
+	if (max_cpus > 1) {
+		percpu_timer_setup();
+		scu_enable(scu_base);
+	}
+}
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
new file mode 100644
index 0000000000000000000000000000000000000000..426163231fff155cdd9c1a9094e33d3ac6fa7217
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -0,0 +1,1359 @@
+/*
+ * arch/arm/mach-tegra/tegra2_clocks.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/hrtimer.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/iomap.h>
+
+#include "clock.h"
+
+#define RST_DEVICES			0x004
+#define RST_DEVICES_SET			0x300
+#define RST_DEVICES_CLR			0x304
+
+#define CLK_OUT_ENB			0x010
+#define CLK_OUT_ENB_SET			0x320
+#define CLK_OUT_ENB_CLR			0x324
+
+#define OSC_CTRL			0x50
+#define OSC_CTRL_OSC_FREQ_MASK		(3<<30)
+#define OSC_CTRL_OSC_FREQ_13MHZ		(0<<30)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
+#define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
+#define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
+
+#define OSC_FREQ_DET			0x58
+#define OSC_FREQ_DET_TRIG		(1<<31)
+
+#define OSC_FREQ_DET_STATUS		0x5C
+#define OSC_FREQ_DET_BUSY		(1<<31)
+#define OSC_FREQ_DET_CNT_MASK		0xFFFF
+
+#define PERIPH_CLK_SOURCE_MASK		(3<<30)
+#define PERIPH_CLK_SOURCE_SHIFT		30
+#define PERIPH_CLK_SOURCE_ENABLE	(1<<28)
+#define PERIPH_CLK_SOURCE_DIV_MASK	0xFF
+#define PERIPH_CLK_SOURCE_DIV_SHIFT	0
+
+#define PLL_BASE			0x0
+#define PLL_BASE_BYPASS			(1<<31)
+#define PLL_BASE_ENABLE			(1<<30)
+#define PLL_BASE_REF_ENABLE		(1<<29)
+#define PLL_BASE_OVERRIDE		(1<<28)
+#define PLL_BASE_LOCK			(1<<27)
+#define PLL_BASE_DIVP_MASK		(0x7<<20)
+#define PLL_BASE_DIVP_SHIFT		20
+#define PLL_BASE_DIVN_MASK		(0x3FF<<8)
+#define PLL_BASE_DIVN_SHIFT		8
+#define PLL_BASE_DIVM_MASK		(0x1F)
+#define PLL_BASE_DIVM_SHIFT		0
+
+#define PLL_OUT_RATIO_MASK		(0xFF<<8)
+#define PLL_OUT_RATIO_SHIFT		8
+#define PLL_OUT_OVERRIDE		(1<<2)
+#define PLL_OUT_CLKEN			(1<<1)
+#define PLL_OUT_RESET_DISABLE		(1<<0)
+
+#define PLL_MISC(c)			(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_DCCON_SHIFT		20
+#define PLL_MISC_LOCK_ENABLE		(1<<18)
+#define PLL_MISC_CPCON_SHIFT		8
+#define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
+#define PLL_MISC_LFCON_SHIFT		4
+#define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
+#define PLL_MISC_VCOCON_SHIFT		0
+#define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
+
+#define PLLD_MISC_CLKENABLE		(1<<30)
+#define PLLD_MISC_DIV_RST		(1<<23)
+#define PLLD_MISC_DCCON_SHIFT		12
+
+#define PERIPH_CLK_TO_ENB_REG(c)	((c->clk_num / 32) * 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->clk_num / 32) * 8)
+#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->clk_num % 32))
+
+#define SUPER_CLK_MUX			0x00
+#define SUPER_STATE_SHIFT		28
+#define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
+#define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
+#define SUPER_SOURCE_MASK		0xF
+#define	SUPER_FIQ_SOURCE_SHIFT		12
+#define	SUPER_IRQ_SOURCE_SHIFT		8
+#define	SUPER_RUN_SOURCE_SHIFT		4
+#define	SUPER_IDLE_SOURCE_SHIFT		0
+
+#define SUPER_CLK_DIVIDER		0x04
+
+#define BUS_CLK_DISABLE			(1<<3)
+#define BUS_CLK_DIV_MASK		0x3
+
+static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+
+#define clk_writel(value, reg) \
+	__raw_writel(value, (u32)reg_clk_base + (reg))
+#define clk_readl(reg) \
+	__raw_readl((u32)reg_clk_base + (reg))
+
+unsigned long clk_measure_input_freq(void)
+{
+	u32 clock_autodetect;
+	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
+	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
+	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
+	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
+		return 12000000;
+	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
+		return 13000000;
+	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
+		return 19200000;
+	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
+		return 26000000;
+	} else {
+		pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect);
+		BUG();
+		return 0;
+	}
+}
+
+static int clk_div71_get_divider(struct clk *c, unsigned long rate)
+{
+	unsigned long divider_u71;
+
+	divider_u71 = DIV_ROUND_UP(c->rate * 2, rate);
+
+	if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0)
+		return -EINVAL;
+
+	return divider_u71 - 2;
+}
+
+static unsigned long tegra2_clk_recalculate_rate(struct clk *c)
+{
+	unsigned long rate;
+	rate = c->parent->rate;
+
+	if (c->mul != 0 && c->div != 0)
+		c->rate = rate * c->mul / c->div;
+	else
+		c->rate = rate;
+	return c->rate;
+}
+
+
+/* clk_m functions */
+static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
+{
+	u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;
+
+	c->rate = clk_measure_input_freq();
+	switch (c->rate) {
+	case 12000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
+		break;
+	case 13000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
+		break;
+	case 19200000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
+		break;
+	case 26000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
+		break;
+	default:
+		pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
+		BUG();
+	}
+	clk_writel(auto_clock_control, OSC_CTRL);
+	return c->rate;
+}
+
+static void tegra2_clk_m_init(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+	tegra2_clk_m_autodetect_rate(c);
+}
+
+static int tegra2_clk_m_enable(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+	return 0;
+}
+
+static void tegra2_clk_m_disable(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+	BUG();
+}
+
+static struct clk_ops tegra_clk_m_ops = {
+	.init		= tegra2_clk_m_init,
+	.enable		= tegra2_clk_m_enable,
+	.disable	= tegra2_clk_m_disable,
+};
+
+/* super clock functions */
+/* "super clocks" on tegra have two-stage muxes and a clock skipping
+ * super divider.  We will ignore the clock skipping divider, since we
+ * can't lower the voltage when using the clock skip, but we can if we
+ * lower the PLL frequency.
+ */
+static void tegra2_super_clk_init(struct clk *c)
+{
+	u32 val;
+	int source;
+	int shift;
+	const struct clk_mux_sel *sel;
+	val = clk_readl(c->reg + SUPER_CLK_MUX);
+	c->state = ON;
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+	source = (val >> shift) & SUPER_SOURCE_MASK;
+	for (sel = c->inputs; sel->input != NULL; sel++) {
+		if (sel->value == source)
+			break;
+	}
+	BUG_ON(sel->input == NULL);
+	c->parent = sel->input;
+	tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_super_clk_enable(struct clk *c)
+{
+	clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
+	return 0;
+}
+
+static void tegra2_super_clk_disable(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	/* oops - don't disable the CPU clock! */
+	BUG();
+}
+
+static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
+{
+	u32 val;
+	const struct clk_mux_sel *sel;
+	int shift;
+	val = clk_readl(c->reg + SUPER_CLK_MUX);;
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+	for (sel = c->inputs; sel->input != NULL; sel++) {
+		if (sel->input == p) {
+			clk_reparent(c, p);
+			val &= ~(SUPER_SOURCE_MASK << shift);
+			val |= sel->value << shift;
+			clk_writel(val, c->reg);
+			c->rate = c->parent->rate;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct clk_ops tegra_super_ops = {
+	.init			= tegra2_super_clk_init,
+	.enable			= tegra2_super_clk_enable,
+	.disable		= tegra2_super_clk_disable,
+	.set_parent		= tegra2_super_clk_set_parent,
+	.recalculate_rate	= tegra2_clk_recalculate_rate,
+};
+
+/* bus clock functions */
+static void tegra2_bus_clk_init(struct clk *c)
+{
+	u32 val = clk_readl(c->reg);
+	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
+	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
+	c->mul = 1;
+	tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_bus_clk_enable(struct clk *c)
+{
+	u32 val = clk_readl(c->reg);
+	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
+	clk_writel(val, c->reg);
+	return 0;
+}
+
+static void tegra2_bus_clk_disable(struct clk *c)
+{
+	u32 val = clk_readl(c->reg);
+	val |= BUS_CLK_DISABLE << c->reg_shift;
+	clk_writel(val, c->reg);
+}
+
+static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	u32 val = clk_readl(c->reg);
+	unsigned long parent_rate = c->parent->rate;
+	int i;
+	for (i = 1; i <= 4; i++) {
+		if (rate == parent_rate / i) {
+			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
+			val |= (i - 1) << c->reg_shift;
+			clk_writel(val, c->reg);
+			c->div = i;
+			c->mul = 1;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct clk_ops tegra_bus_ops = {
+	.init			= tegra2_bus_clk_init,
+	.enable			= tegra2_bus_clk_enable,
+	.disable		= tegra2_bus_clk_disable,
+	.set_rate		= tegra2_bus_clk_set_rate,
+	.recalculate_rate	= tegra2_clk_recalculate_rate,
+};
+
+/* PLL Functions */
+static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c)
+{
+	u64 rate;
+	rate = c->parent->rate;
+	rate *= c->n;
+	do_div(rate, c->m);
+	if (c->p == 2)
+		rate >>= 1;
+	c->rate = rate;
+	return c->rate;
+}
+
+static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+{
+	ktime_t before;
+
+	before = ktime_get();
+	while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
+		if (ktime_us_delta(ktime_get(), before) > 5000) {
+			pr_err("Timed out waiting for lock bit on pll %s",
+				c->name);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static void tegra2_pll_clk_init(struct clk *c)
+{
+	u32 val = clk_readl(c->reg + PLL_BASE);
+
+	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
+
+	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
+		pr_warning("Clock %s has unknown fixed frequency\n", c->name);
+		c->n = 1;
+		c->m = 0;
+		c->p = 1;
+	} else if (val & PLL_BASE_BYPASS) {
+		c->n = 1;
+		c->m = 1;
+		c->p = 1;
+	} else {
+		c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+		c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+		c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+	}
+
+	val = clk_readl(c->reg + PLL_MISC(c));
+	if (c->flags & PLL_HAS_CPCON)
+		c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT;
+
+	tegra2_pll_clk_recalculate_rate(c);
+}
+
+static int tegra2_pll_clk_enable(struct clk *c)
+{
+	u32 val;
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	val = clk_readl(c->reg + PLL_BASE);
+	val &= ~PLL_BASE_BYPASS;
+	val |= PLL_BASE_ENABLE;
+	clk_writel(val, c->reg + PLL_BASE);
+
+	val = clk_readl(c->reg + PLL_MISC(c));
+	val |= PLL_MISC_LOCK_ENABLE;
+	clk_writel(val, c->reg + PLL_MISC(c));
+
+	tegra2_pll_clk_wait_for_lock(c);
+
+	return 0;
+}
+
+static void tegra2_pll_clk_disable(struct clk *c)
+{
+	u32 val;
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	val = clk_readl(c->reg);
+	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	clk_writel(val, c->reg);
+}
+
+static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	u32 val;
+	unsigned long input_rate;
+	const struct clk_pll_table *sel;
+
+	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+	BUG_ON(c->refcnt != 0);
+
+	input_rate = c->parent->rate;
+	for (sel = c->pll_table; sel->input_rate != 0; sel++) {
+		if (sel->input_rate == input_rate && sel->output_rate == rate) {
+			c->n = sel->n;
+			c->m = sel->m;
+			c->p = sel->p;
+			c->cpcon = sel->cpcon;
+
+			val = clk_readl(c->reg + PLL_BASE);
+			if (c->flags & PLL_FIXED)
+				val |= PLL_BASE_OVERRIDE;
+			val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
+				 PLL_BASE_DIVM_MASK);
+			val |= (c->m << PLL_BASE_DIVM_SHIFT) |
+				(c->n << PLL_BASE_DIVN_SHIFT);
+			BUG_ON(c->p > 2);
+			if (c->p == 2)
+				val |= 1 << PLL_BASE_DIVP_SHIFT;
+			clk_writel(val, c->reg + PLL_BASE);
+
+			if (c->flags & PLL_HAS_CPCON) {
+				val = c->cpcon << PLL_MISC_CPCON_SHIFT;
+				val |= PLL_MISC_LOCK_ENABLE;
+				clk_writel(val, c->reg + PLL_MISC(c));
+			}
+
+			if (c->state == ON)
+				tegra2_pll_clk_enable(c);
+
+			c->rate = rate;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct clk_ops tegra_pll_ops = {
+	.init			= tegra2_pll_clk_init,
+	.enable			= tegra2_pll_clk_enable,
+	.disable		= tegra2_pll_clk_disable,
+	.set_rate		= tegra2_pll_clk_set_rate,
+	.recalculate_rate	= tegra2_pll_clk_recalculate_rate,
+};
+
+/* Clock divider ops */
+static void tegra2_pll_div_clk_init(struct clk *c)
+{
+	u32 val = clk_readl(c->reg);
+	u32 divu71;
+	val >>= c->reg_shift;
+	c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
+	if (!(val & PLL_OUT_RESET_DISABLE))
+		c->state = OFF;
+
+	if (c->flags & DIV_U71) {
+		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
+		c->div = (divu71 + 2);
+		c->mul = 2;
+	} else if (c->flags & DIV_2) {
+		c->div = 2;
+		c->mul = 1;
+	} else {
+		c->div = 1;
+		c->mul = 1;
+	}
+
+	tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_pll_div_clk_enable(struct clk *c)
+{
+	u32 val;
+	u32 new_val;
+
+	pr_debug("%s: %s\n", __func__, c->name);
+	if (c->flags & DIV_U71) {
+		val = clk_readl(c->reg);
+		new_val = val >> c->reg_shift;
+		new_val &= 0xFFFF;
+
+		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+
+		val &= ~(0xFFFF << c->reg_shift);
+		val |= new_val << c->reg_shift;
+		clk_writel(val, c->reg);
+		return 0;
+	} else if (c->flags & DIV_2) {
+		BUG_ON(!(c->flags & PLLD));
+		val = clk_readl(c->reg);
+		val &= ~PLLD_MISC_DIV_RST;
+		clk_writel(val, c->reg);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static void tegra2_pll_div_clk_disable(struct clk *c)
+{
+	u32 val;
+	u32 new_val;
+
+	pr_debug("%s: %s\n", __func__, c->name);
+	if (c->flags & DIV_U71) {
+		val = clk_readl(c->reg);
+		new_val = val >> c->reg_shift;
+		new_val &= 0xFFFF;
+
+		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
+
+		val &= ~(0xFFFF << c->reg_shift);
+		val |= new_val << c->reg_shift;
+		clk_writel(val, c->reg);
+	} else if (c->flags & DIV_2) {
+		BUG_ON(!(c->flags & PLLD));
+		val = clk_readl(c->reg);
+		val |= PLLD_MISC_DIV_RST;
+		clk_writel(val, c->reg);
+	}
+}
+
+static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	u32 val;
+	u32 new_val;
+	int divider_u71;
+	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+	if (c->flags & DIV_U71) {
+		divider_u71 = clk_div71_get_divider(c->parent, rate);
+		if (divider_u71 >= 0) {
+			val = clk_readl(c->reg);
+			new_val = val >> c->reg_shift;
+			new_val &= 0xFFFF;
+			if (c->flags & DIV_U71_FIXED)
+				new_val |= PLL_OUT_OVERRIDE;
+			new_val &= ~PLL_OUT_RATIO_MASK;
+			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
+
+			val &= ~(0xFFFF << c->reg_shift);
+			val |= new_val << c->reg_shift;
+			clk_writel(val, c->reg);
+			c->div = divider_u71 + 2;
+			c->mul = 2;
+			tegra2_clk_recalculate_rate(c);
+			return 0;
+		}
+	} else if (c->flags & DIV_2) {
+		if (c->parent->rate == rate * 2) {
+			c->rate = rate;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+
+static struct clk_ops tegra_pll_div_ops = {
+	.init			= tegra2_pll_div_clk_init,
+	.enable			= tegra2_pll_div_clk_enable,
+	.disable		= tegra2_pll_div_clk_disable,
+	.set_rate		= tegra2_pll_div_clk_set_rate,
+	.recalculate_rate	= tegra2_clk_recalculate_rate,
+};
+
+/* Periph clk ops */
+
+static void tegra2_periph_clk_init(struct clk *c)
+{
+	u32 val = clk_readl(c->reg);
+	const struct clk_mux_sel *mux = 0;
+	const struct clk_mux_sel *sel;
+	if (c->flags & MUX) {
+		for (sel = c->inputs; sel->input != NULL; sel++) {
+			if (val >> PERIPH_CLK_SOURCE_SHIFT == sel->value)
+				mux = sel;
+		}
+		BUG_ON(!mux);
+
+		c->parent = mux->input;
+	} else {
+		c->parent = c->inputs[0].input;
+	}
+
+	if (c->flags & DIV_U71) {
+		u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK;
+		c->div = divu71 + 2;
+		c->mul = 2;
+	} else {
+		c->div = 1;
+		c->mul = 1;
+	}
+
+	c->state = ON;
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+	if (!(c->flags & PERIPH_NO_RESET))
+		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
+				PERIPH_CLK_TO_ENB_BIT(c))
+			c->state = OFF;
+	tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_periph_clk_enable(struct clk *c)
+{
+	u32 val;
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
+		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+	if (c->flags & PERIPH_EMC_ENB) {
+		/* The EMC peripheral clock has 2 extra enable bits */
+		/* FIXME: Do they need to be disabled? */
+		val = clk_readl(c->reg);
+		val |= 0x3 << 24;
+		clk_writel(val, c->reg);
+	}
+	return 0;
+}
+
+static void tegra2_periph_clk_disable(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+void tegra2_periph_reset_deassert(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+	if (!(c->flags & PERIPH_NO_RESET))
+		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+void tegra2_periph_reset_assert(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+	if (!(c->flags & PERIPH_NO_RESET))
+		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+			RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+
+static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
+{
+	u32 val;
+	const struct clk_mux_sel *sel;
+	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+	for (sel = c->inputs; sel->input != NULL; sel++) {
+		if (sel->input == p) {
+			clk_reparent(c, p);
+			val = clk_readl(c->reg);
+			val &= ~PERIPH_CLK_SOURCE_MASK;
+			val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+			clk_writel(val, c->reg);
+			c->rate = c->parent->rate;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	u32 val;
+	int divider_u71;
+	pr_debug("%s: %lu\n", __func__, rate);
+	if (c->flags & DIV_U71) {
+		divider_u71 = clk_div71_get_divider(c->parent, rate);
+		if (divider_u71 >= 0) {
+			val = clk_readl(c->reg);
+			val &= ~PERIPH_CLK_SOURCE_DIV_MASK;
+			val |= divider_u71;
+			clk_writel(val, c->reg);
+			c->div = divider_u71 + 2;
+			c->mul = 2;
+			tegra2_clk_recalculate_rate(c);
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct clk_ops tegra_periph_clk_ops = {
+	.init			= &tegra2_periph_clk_init,
+	.enable			= &tegra2_periph_clk_enable,
+	.disable		= &tegra2_periph_clk_disable,
+	.set_parent		= &tegra2_periph_clk_set_parent,
+	.set_rate		= &tegra2_periph_clk_set_rate,
+	.recalculate_rate	= &tegra2_clk_recalculate_rate,
+};
+
+/* Clock doubler ops */
+static void tegra2_clk_double_init(struct clk *c)
+{
+	c->mul = 2;
+	c->div = 1;
+	c->state = ON;
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+	tegra2_clk_recalculate_rate(c);
+};
+
+static struct clk_ops tegra_clk_double_ops = {
+	.init			= &tegra2_clk_double_init,
+	.enable			= &tegra2_periph_clk_enable,
+	.disable		= &tegra2_periph_clk_disable,
+	.recalculate_rate	= &tegra2_clk_recalculate_rate,
+};
+
+/* Clock definitions */
+static struct clk tegra_clk_32k = {
+	.name = "clk_32k",
+	.rate = 32678,
+	.ops  = NULL,
+};
+
+static struct clk_pll_table tegra_pll_s_table[] = {
+	{32768, 12000000, 366, 1, 1, 0},
+	{32768, 13000000, 397, 1, 1, 0},
+	{32768, 19200000, 586, 1, 1, 0},
+	{32768, 26000000, 793, 1, 1, 0},
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct clk tegra_pll_s = {
+	.name      = "pll_s",
+	.flags     = PLL_ALT_MISC_REG,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xf0,
+	.input_min = 32768,
+	.input_max = 32768,
+	.parent    = &tegra_clk_32k,
+	.cf_min    = 0, /* FIXME */
+	.cf_max    = 0, /* FIXME */
+	.vco_min   = 12000000,
+	.vco_max   = 26000000,
+	.pll_table = tegra_pll_s_table,
+};
+
+static struct clk_mux_sel tegra_clk_m_sel[] = {
+	{ .input = &tegra_clk_32k, .value = 0},
+	{ .input = &tegra_pll_s,  .value = 1},
+	{ 0, 0},
+};
+static struct clk tegra_clk_m = {
+	.name      = "clk_m",
+	.flags     = ENABLE_ON_INIT,
+	.ops       = &tegra_clk_m_ops,
+	.inputs    = tegra_clk_m_sel,
+	.reg       = 0x1fc,
+	.reg_mask  = (1<<28),
+	.reg_shift = 28,
+};
+
+static struct clk_pll_table tegra_pll_c_table[] = {
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_c = {
+	.name      = "pll_c",
+	.flags	   = PLL_HAS_CPCON,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0x80,
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 20000000,
+	.vco_max   = 1400000000,
+	.pll_table = tegra_pll_c_table,
+};
+
+static struct clk tegra_pll_c_out1 = {
+	.name      = "pll_c_out1",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = DIV_U71,
+	.parent    = &tegra_pll_c,
+	.reg       = 0x84,
+	.reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_m_table[] = {
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_m = {
+	.name      = "pll_m",
+	.flags     = PLL_HAS_CPCON,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0x90,
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 20000000,
+	.vco_max   = 1200000000,
+	.pll_table = tegra_pll_m_table,
+};
+
+static struct clk tegra_pll_m_out1 = {
+	.name      = "pll_m_out1",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = DIV_U71,
+	.parent    = &tegra_pll_m,
+	.reg       = 0x94,
+	.reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_p_table[] = {
+	{ 12000000, 216000000, 432, 12, 2, 8},
+	{ 13000000, 216000000, 432, 13, 2, 8},
+	{ 19200000, 216000000, 90,   4, 2, 1},
+	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 12000000, 432000000, 432, 12, 1, 8},
+	{ 13000000, 432000000, 432, 13, 1, 8},
+	{ 19200000, 432000000, 90,   4, 1, 1},
+	{ 26000000, 432000000, 432, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_p = {
+	.name      = "pll_p",
+	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xa0,
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 20000000,
+	.vco_max   = 1400000000,
+	.pll_table = tegra_pll_p_table,
+};
+
+static struct clk tegra_pll_p_out1 = {
+	.name      = "pll_p_out1",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+	.parent    = &tegra_pll_p,
+	.reg       = 0xa4,
+	.reg_shift = 0,
+};
+
+static struct clk tegra_pll_p_out2 = {
+	.name      = "pll_p_out2",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+	.parent    = &tegra_pll_p,
+	.reg       = 0xa4,
+	.reg_shift = 16,
+};
+
+static struct clk tegra_pll_p_out3 = {
+	.name      = "pll_p_out3",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+	.parent    = &tegra_pll_p,
+	.reg       = 0xa8,
+	.reg_shift = 0,
+};
+
+static struct clk tegra_pll_p_out4 = {
+	.name      = "pll_p_out4",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+	.parent    = &tegra_pll_p,
+	.reg       = 0xa8,
+	.reg_shift = 16,
+};
+
+static struct clk_pll_table tegra_pll_a_table[] = {
+	{ 28800000, 56448000, 49, 25, 1, 1},
+	{ 28800000, 73728000, 64, 25, 1, 1},
+	{ 28800000, 11289600, 49, 25, 1, 1},
+	{ 28800000, 12288000, 64, 25, 1, 1},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_a = {
+	.name      = "pll_a",
+	.flags     = PLL_HAS_CPCON,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xb0,
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.parent    = &tegra_pll_p_out1,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 20000000,
+	.vco_max   = 1400000000,
+	.pll_table = tegra_pll_a_table,
+};
+
+static struct clk tegra_pll_a_out0 = {
+	.name      = "pll_a_out0",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = DIV_U71,
+	.parent    = &tegra_pll_a,
+	.reg       = 0xb4,
+	.reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_d_table[] = {
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_d = {
+	.name      = "pll_d",
+	.flags     = PLL_HAS_CPCON | PLLD,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xd0,
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 40000000,
+	.vco_max   = 1000000000,
+	.pll_table = tegra_pll_d_table,
+};
+
+static struct clk tegra_pll_d_out0 = {
+	.name      = "pll_d_out0",
+	.ops       = &tegra_pll_div_ops,
+	.flags     = DIV_2 | PLLD,
+	.parent    = &tegra_pll_d,
+};
+
+static struct clk_pll_table tegra_pll_u_table[] = {
+	{ 12000000, 480000000, 960, 12, 1, 0},
+	{ 13000000, 480000000, 960, 13, 1, 0},
+	{ 19200000, 480000000, 200, 4,  1, 0},
+	{ 26000000, 480000000, 960, 26, 1, 0},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_u = {
+	.name      = "pll_u",
+	.flags     = 0,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xc0,
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 480000000,
+	.vco_max   = 960000000,
+	.pll_table = tegra_pll_u_table,
+};
+
+static struct clk_pll_table tegra_pll_x_table[] = {
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+	{ 12000000, 750000000,  750,  12, 1, 12},
+	{ 13000000, 750000000,  750,  13, 1, 12},
+	{ 19200000, 750000000,  625,  16, 1, 8},
+	{ 26000000, 750000000,  750,  26, 1, 12},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_x = {
+	.name      = "pll_x",
+	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
+	.ops       = &tegra_pll_ops,
+	.reg       = 0xe0,
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.parent    = &tegra_clk_m,
+	.cf_min    = 1000000,
+	.cf_max    = 6000000,
+	.vco_min   = 20000000,
+	.vco_max   = 1200000000,
+	.pll_table = tegra_pll_x_table,
+};
+
+static struct clk tegra_clk_d = {
+	.name      = "clk_d",
+	.flags     = PERIPH_NO_RESET,
+	.ops       = &tegra_clk_double_ops,
+	.clk_num   = 90,
+	.reg       = 0x34,
+	.reg_shift = 12,
+	.parent    = &tegra_clk_m,
+};
+
+/* FIXME: need tegra_audio
+static struct clk tegra_clk_audio_2x = {
+	.name      = "clk_d",
+	.flags     = PERIPH_NO_RESET,
+	.ops       = &tegra_clk_double_ops,
+	.clk_num   = 89,
+	.reg       = 0x34,
+	.reg_shift = 8,
+	.parent    = &tegra_audio,
+}
+*/
+
+static struct clk_mux_sel mux_cclk[] = {
+	{ .input = &tegra_clk_m,	.value = 0},
+	{ .input = &tegra_pll_c,	.value = 1},
+	{ .input = &tegra_clk_32k,	.value = 2},
+	{ .input = &tegra_pll_m,	.value = 3},
+	{ .input = &tegra_pll_p,	.value = 4},
+	{ .input = &tegra_pll_p_out4,	.value = 5},
+	{ .input = &tegra_pll_p_out3,	.value = 6},
+	{ .input = &tegra_clk_d,	.value = 7},
+	{ .input = &tegra_pll_x,	.value = 8},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_sclk[] = {
+	{ .input = &tegra_clk_m,	.value = 0},
+	{ .input = &tegra_pll_c_out1,	.value = 1},
+	{ .input = &tegra_pll_p_out4,	.value = 2},
+	{ .input = &tegra_pll_p_out3,	.value = 3},
+	{ .input = &tegra_pll_p_out2,	.value = 4},
+	{ .input = &tegra_clk_d,	.value = 5},
+	{ .input = &tegra_clk_32k,	.value = 6},
+	{ .input = &tegra_pll_m_out1,	.value = 7},
+	{ 0, 0},
+};
+
+static struct clk tegra_clk_cpu = {
+	.name	= "cpu",
+	.inputs	= mux_cclk,
+	.reg	= 0x20,
+	.ops	= &tegra_super_ops,
+};
+
+static struct clk tegra_clk_sys = {
+	.name	= "sys",
+	.inputs	= mux_sclk,
+	.reg	= 0x28,
+	.ops	= &tegra_super_ops,
+};
+
+static struct clk tegra_clk_hclk = {
+	.name		= "hclk",
+	.flags		= DIV_BUS,
+	.parent		= &tegra_clk_sys,
+	.reg		= 0x30,
+	.reg_shift	= 4,
+	.ops		= &tegra_bus_ops,
+};
+
+static struct clk tegra_clk_pclk = {
+	.name		= "pclk",
+	.flags		= DIV_BUS,
+	.parent		= &tegra_clk_hclk,
+	.reg		= 0x30,
+	.reg_shift	= 0,
+	.ops		= &tegra_bus_ops,
+};
+
+static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
+	{ .input = &tegra_pll_m, .value = 0},
+	{ .input = &tegra_pll_c, .value = 1},
+	{ .input = &tegra_pll_p, .value = 2},
+	{ .input = &tegra_pll_a_out0, .value = 3},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
+	{ .input = &tegra_pll_m, .value = 0},
+	{ .input = &tegra_pll_c, .value = 1},
+	{ .input = &tegra_pll_p, .value = 2},
+	{ .input = &tegra_clk_m, .value = 3},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
+	{ .input = &tegra_pll_p, .value = 0},
+	{ .input = &tegra_pll_c, .value = 1},
+	{ .input = &tegra_pll_m, .value = 2},
+	{ .input = &tegra_clk_m, .value = 3},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = {
+	{.input = &tegra_pll_a, .value = 0},
+	/* FIXME: no mux defined for tegra_audio
+	{.input = &tegra_audio, .value = 1},*/
+	{.input = &tegra_pll_p, .value = 2},
+	{.input = &tegra_clk_m, .value = 3},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
+	{.input = &tegra_pll_p, .value = 0},
+	{.input = &tegra_pll_d_out0, .value = 1},
+	{.input = &tegra_pll_c, .value = 2},
+	{.input = &tegra_clk_m, .value = 3},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
+	{.input = &tegra_pll_p,     .value = 0},
+	{.input = &tegra_pll_c,     .value = 1},
+	/* FIXME: no mux defined for tegra_audio
+	{.input = &tegra_audio,     .value = 2},*/
+	{.input = &tegra_clk_m,     .value = 3},
+	{.input = &tegra_clk_32k,   .value = 4},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
+	{.input = &tegra_pll_p,     .value = 0},
+	{.input = &tegra_pll_c,     .value = 1},
+	{.input = &tegra_pll_m,     .value = 2},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_m[] = {
+	{ .input = &tegra_clk_m, .value = 0},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_out3[] = {
+	{ .input = &tegra_pll_p_out3, .value = 0},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_plld[] = {
+	{ .input = &tegra_pll_d, .value = 0},
+	{ 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_32k[] = {
+	{ .input = &tegra_clk_32k, .value = 0},
+	{ 0, 0},
+};
+
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \
+	{						\
+		.name      = _name,			\
+		.lookup    = {				\
+			.dev_id    = _dev,		\
+			.con_id	   = _con,		\
+		},					\
+		.ops       = &tegra_periph_clk_ops,	\
+		.clk_num   = _clk_num,			\
+		.reg       = _reg,			\
+		.inputs    = _inputs,			\
+		.flags     = _flags,			\
+	}
+
+struct clk tegra_periph_clks[] = {
+	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	mux_clk_32k,			PERIPH_NO_RESET),
+	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	mux_clk_m,			0),
+	PERIPH_CLK("i2s1",	"i2s.0",		NULL,	11,	0x100,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2s2",	"i2s.1",		NULL,	18,	0x104,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
+	/* FIXME: spdif has 2 clocks but 1 enable */
+	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	mux_pllp_pllc_pllm,		MUX | DIV_U71),
+	PERIPH_CLK("pwm",	"pwm",			NULL,	17,	0x110,	mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71),
+	PERIPH_CLK("spi",	"spi",			NULL,	43,	0x114,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("xio",	"xio",			NULL,	45,	0x120,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("twc",	"twc",			NULL,	16,	0x12c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	/* FIXME: vfir shares an enable with uartb */
+	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x160,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	/* FIXME: what is la? */
+	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("owr",	"owr",			NULL,	71,	0x1cc,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("dvc",	"tegra-i2c.3",		NULL,	47,	0x128,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2c1_i2c",	"tegra-i2c.0",		"i2c",	0,	0,	mux_pllp_out3,			0),
+	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	mux_pllp_out3,			0),
+	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	mux_pllp_out3,			0),
+	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	mux_pllp_out3,			0),
+	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET),
+	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	/* FIXME: vi and vi_sensor share an enable */
+	PERIPH_CLK("vi",	"vi",			NULL,	20,	0x148,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("vi_sensor",	"vi_sensor",		NULL,	20,	0x1a8,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	/* FIXME: cve and tvo share an enable	*/
+	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("disp1",	"tegrafb.0",		NULL,	27,	0x138,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("disp2",	"tegrafb.1",		NULL,	26,	0x13c,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	mux_clk_m,			0),
+	PERIPH_CLK("usb2",	"usb.1",		NULL,	58,	0,	mux_clk_m,			0),
+	PERIPH_CLK("usb3",	"usb.2",		NULL,	59,	0,	mux_clk_m,			0),
+	PERIPH_CLK("emc",	"emc",			NULL,	57,	0x19c,	mux_pllm_pllc_pllp_clkm,	MUX | DIV_U71 | PERIPH_EMC_ENB),
+	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	mux_plld,			0),
+};
+
+#define CLK_DUPLICATE(_name, _dev, _con)		\
+	{						\
+		.name	= _name,			\
+		.lookup	= {				\
+			.dev_id	= _dev,			\
+			.con_id		= _con,		\
+		},					\
+	}
+
+/* Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+struct clk_duplicate tegra_clk_duplicates[] = {
+	CLK_DUPLICATE("uarta",	"tegra_uart.0",	NULL),
+	CLK_DUPLICATE("uartb",	"tegra_uart.1",	NULL),
+	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
+	CLK_DUPLICATE("uartd",	"tegra_uart.3",	NULL),
+	CLK_DUPLICATE("uarte",	"tegra_uart.4",	NULL),
+};
+
+#define CLK(dev, con, ck)	\
+	{			\
+		.dev_id = dev,	\
+		.con_id = con,	\
+		.clk = ck,	\
+	}
+
+struct clk_lookup tegra_clk_lookups[] = {
+	/* external root sources */
+	CLK(NULL,	"32k_clk",	&tegra_clk_32k),
+	CLK(NULL,	"pll_s",	&tegra_pll_s),
+	CLK(NULL,	"clk_m",	&tegra_clk_m),
+	CLK(NULL,	"pll_m",	&tegra_pll_m),
+	CLK(NULL,	"pll_m_out1",	&tegra_pll_m_out1),
+	CLK(NULL,	"pll_c",	&tegra_pll_c),
+	CLK(NULL,	"pll_c_out1",	&tegra_pll_c_out1),
+	CLK(NULL,	"pll_p",	&tegra_pll_p),
+	CLK(NULL,	"pll_p_out1",	&tegra_pll_p_out1),
+	CLK(NULL,	"pll_p_out2",	&tegra_pll_p_out2),
+	CLK(NULL,	"pll_p_out3",	&tegra_pll_p_out3),
+	CLK(NULL,	"pll_p_out4",	&tegra_pll_p_out4),
+	CLK(NULL,	"pll_a",	&tegra_pll_a),
+	CLK(NULL,	"pll_a_out0",	&tegra_pll_a_out0),
+	CLK(NULL,	"pll_d",	&tegra_pll_d),
+	CLK(NULL,	"pll_d_out0",	&tegra_pll_d_out0),
+	CLK(NULL,	"pll_u",	&tegra_pll_u),
+	CLK(NULL,	"pll_x",	&tegra_pll_x),
+	CLK(NULL,	"cpu",		&tegra_clk_cpu),
+	CLK(NULL,	"sys",		&tegra_clk_sys),
+	CLK(NULL,	"hclk",		&tegra_clk_hclk),
+	CLK(NULL,	"pclk",		&tegra_clk_pclk),
+	CLK(NULL,	"clk_d",	&tegra_clk_d),
+};
+
+void __init tegra2_init_clocks(void)
+{
+	int i;
+	struct clk_lookup *cl;
+	struct clk *c;
+	struct clk_duplicate *cd;
+
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) {
+		cl = &tegra_clk_lookups[i];
+		clk_init(cl->clk);
+		clkdev_add(cl);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) {
+		c = &tegra_periph_clks[i];
+		cl = &c->lookup;
+		cl->clk = c;
+
+		clk_init(cl->clk);
+		clkdev_add(cl);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
+		cd = &tegra_clk_duplicates[i];
+		c = tegra_get_clock_by_name(cd->name);
+		if (c) {
+			cl = &cd->lookup;
+			cl->clk = c;
+			clkdev_add(cl);
+		} else {
+			pr_err("%s: Unknown duplicate clock %s\n", __func__,
+				cd->name);
+		}
+	}
+}
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f420210d4069cbfd299d7413cd527e4540a742b
--- /dev/null
+++ b/arch/arm/mach-tegra/timer.c
@@ -0,0 +1,187 @@
+/*
+ * arch/arch/mach-tegra/timer.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cnt32_to_63.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/time.h>
+#include <asm/localtimer.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "clock.h"
+
+#define TIMERUS_CNTR_1US 0x10
+#define TIMERUS_USEC_CFG 0x14
+#define TIMERUS_CNTR_FREEZE 0x4c
+
+#define TIMER1_BASE 0x0
+#define TIMER2_BASE 0x8
+#define TIMER3_BASE 0x50
+#define TIMER4_BASE 0x58
+
+#define TIMER_PTV 0x0
+#define TIMER_PCR 0x4
+
+struct tegra_timer;
+
+static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
+
+#define timer_writel(value, reg) \
+	__raw_writel(value, (u32)timer_reg_base + (reg))
+#define timer_readl(reg) \
+	__raw_readl((u32)timer_reg_base + (reg))
+
+static int tegra_timer_set_next_event(unsigned long cycles,
+					 struct clock_event_device *evt)
+{
+	u32 reg;
+
+	reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0);
+	timer_writel(reg, TIMER3_BASE + TIMER_PTV);
+
+	return 0;
+}
+
+static void tegra_timer_set_mode(enum clock_event_mode mode,
+				    struct clock_event_device *evt)
+{
+	u32 reg;
+
+	timer_writel(0, TIMER3_BASE + TIMER_PTV);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		reg = 0xC0000000 | ((1000000/HZ)-1);
+		timer_writel(reg, TIMER3_BASE + TIMER_PTV);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static cycle_t tegra_clocksource_read(struct clocksource *cs)
+{
+	return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US));
+}
+
+static struct clock_event_device tegra_clockevent = {
+	.name		= "timer0",
+	.rating		= 300,
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+	.set_next_event	= tegra_timer_set_next_event,
+	.set_mode	= tegra_timer_set_mode,
+};
+
+static struct clocksource tegra_clocksource = {
+	.name	= "timer_us",
+	.rating	= 300,
+	.read	= tegra_clocksource_read,
+	.mask	= 0x7FFFFFFFFFFFFFFFULL,
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+unsigned long long sched_clock(void)
+{
+	return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource),
+		tegra_clocksource.mult, tegra_clocksource.shift);
+}
+
+static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+	timer_writel(1<<30, TIMER3_BASE + TIMER_PCR);
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction tegra_timer_irq = {
+	.name		= "timer0",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
+	.handler	= tegra_timer_interrupt,
+	.dev_id		= &tegra_clockevent,
+	.irq		= INT_TMR3,
+};
+
+static void __init tegra_init_timer(void)
+{
+	unsigned long rate = clk_measure_input_freq();
+	int ret;
+
+#ifdef CONFIG_HAVE_ARM_TWD
+	twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
+#endif
+
+	switch (rate) {
+	case 12000000:
+		timer_writel(0x000b, TIMERUS_USEC_CFG);
+		break;
+	case 13000000:
+		timer_writel(0x000c, TIMERUS_USEC_CFG);
+		break;
+	case 19200000:
+		timer_writel(0x045f, TIMERUS_USEC_CFG);
+		break;
+	case 26000000:
+		timer_writel(0x0019, TIMERUS_USEC_CFG);
+		break;
+	default:
+		WARN(1, "Unknown clock rate");
+	}
+
+	if (clocksource_register_hz(&tegra_clocksource, 1000000)) {
+		printk(KERN_ERR "Failed to register clocksource\n");
+		BUG();
+	}
+
+	ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
+	if (ret) {
+		printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret);
+		BUG();
+	}
+
+	clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5);
+	tegra_clockevent.max_delta_ns =
+		clockevent_delta2ns(0x1fffffff, &tegra_clockevent);
+	tegra_clockevent.min_delta_ns =
+		clockevent_delta2ns(0x1, &tegra_clockevent);
+	tegra_clockevent.cpumask = cpu_all_mask;
+	tegra_clockevent.irq = tegra_timer_irq.irq;
+	clockevents_register_device(&tegra_clockevent);
+
+	return;
+}
+
+struct sys_timer tegra_timer = {
+	.init = tegra_init_timer,
+};
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 87ec141fcaa6e5ad0d5d7eef0e1a8249ac2bdcc3..e1fd98fff8fac03c58282841191b8e7cff03e807 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -771,7 +771,8 @@ config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
-		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+		   ARCH_TEGRA
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC