[coreboot-gerrit] Patch set updated for coreboot: a9f8f6c tegra132: Enable bootblock support in tegra132 including UART support

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Fri Feb 27 23:57:06 CET 2015


Marc Jones (marc.jones at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8517

-gerrit

commit a9f8f6cab3cc5cd8535db31fd452fd07c173ffcf
Author: Furquan Shaikh <furquan at google.com>
Date:   Mon Jun 9 13:20:04 2014 -0700

    tegra132: Enable bootblock support in tegra132 including UART support
    
    BUG=None
    BRANCH=None
    TEST=Compiles successfully
    
    Original-Change-Id: Ia9420cfec5333dd5477f04cf080bdad8a37db025
    Original-Signed-off-by: Furquan Shaikh <furquan at google.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/203143
    Original-Tested-by: Furquan Shaikh <furquan at chromium.org>
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    Original-Commit-Queue: Aaron Durbin <adurbin at chromium.org>
    (cherry picked from commit a1037f203c6a07cb116eeb1632cb7200ad022cd3)
    
    This cherry-pick was modified to match the tegra124 uart.c, which
    uses the idx and base address calculations instead of Kconfig settings.
    This driver could use the 8250MEM driver when the ARM vs x86 IO
    calling convention is worked out.
    
    Change-Id: I6e439359b8bb541db4679ac144c519cf251ffed6
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
---
 src/soc/nvidia/tegra132/Kconfig             |  32 ++
 src/soc/nvidia/tegra132/Makefile.inc        |  16 +
 src/soc/nvidia/tegra132/bootblock.c         |  59 +++
 src/soc/nvidia/tegra132/bootblock_asm.S     |  89 ++++
 src/soc/nvidia/tegra132/clk_rst.h           | 551 +++++++++++++++++++++++
 src/soc/nvidia/tegra132/clock.c             | 662 ++++++++++++++++++++++++++++
 src/soc/nvidia/tegra132/flow.h              |  79 ++++
 src/soc/nvidia/tegra132/include/soc/clock.h |  43 +-
 src/soc/nvidia/tegra132/maincpu.S           |  55 +++
 src/soc/nvidia/tegra132/maincpu.h           |  29 ++
 src/soc/nvidia/tegra132/pinmux.h            | 260 +++++++++++
 src/soc/nvidia/tegra132/pmc.h               | 389 ++++++++++++++++
 src/soc/nvidia/tegra132/power.h             |  29 ++
 src/soc/nvidia/tegra132/sysctr.h            |  55 +++
 src/soc/nvidia/tegra132/uart.c              | 161 +++++++
 15 files changed, 2501 insertions(+), 8 deletions(-)

diff --git a/src/soc/nvidia/tegra132/Kconfig b/src/soc/nvidia/tegra132/Kconfig
index d90b8aa..23f7c6e 100644
--- a/src/soc/nvidia/tegra132/Kconfig
+++ b/src/soc/nvidia/tegra132/Kconfig
@@ -7,9 +7,21 @@ config SOC_NVIDIA_TEGRA132
 	select ARCH_RAMSTAGE_ARMV8_64
 	select ARM_LPAE
 	select DYNAMIC_CBMEM
+	select BOOTBLOCK_CONSOLE
+	select HAVE_UART_SPECIAL
+	select HAVE_UART_MEMORY_MAPPED
+	select ARM_BOOTBLOCK_CUSTOM
 
 if SOC_NVIDIA_TEGRA132
 
+config BOOTBLOCK_CPU_INIT
+	string
+	default "soc/nvidia/tegra132/bootblock.c"
+	help
+	  CPU/SoC-specific bootblock code. This is useful if the
+	  bootblock must load microcode or copy data from ROM before
+	  searching for the bootblock.
+
 config BOOTBLOCK_ROM_OFFSET
 	hex
 	default 0x0
@@ -22,4 +34,24 @@ config CBFS_ROM_OFFSET
 	hex "offset of CBFS data in ROM"
 	default 0x40080
 
+config BOOTBLOCK_BASE
+	hex
+	default 0x40020000
+
+config ROMSTAGE_BASE
+	hex
+	default 0x4002c000
+
+config RAMSTAGE_BASE
+	hex
+	default 0x80200000
+
+config STACK_TOP
+	hex
+	default 0x40020000
+
+config STACK_BOTTOM
+	hex
+	default 0x4001c000
+
 endif
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index b038339..5c6fe81 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -1,13 +1,29 @@
+bootblock-y += bootblock.c
+bootblock-y += bootblock_asm.S
 bootblock-y += cbfs.c
 bootblock-y += timer.c
+bootblock-y += clock.c
+bootblock-y += ../tegra/gpio.c
+bootblock-y += ../tegra/pingroup.c
+bootblock-y += ../tegra/pinmux.c
+bootblock-y += ../tegra/apbmisc.c
+ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)
+bootblock-$(CONFIG_DRIVERS_UART) += uart.c
+endif
 
 romstage-y += cbfs.c
 romstage-y += cbmem.c
 romstage-y += timer.c
+romstage-y += ../tegra/gpio.c
+romstage-y += ../tegra/pinmux.c
+romstage-$(CONFIG_DRIVERS_UART) += uart.c
 
 ramstage-y += cbfs.c
 ramstage-y += cbmem.c
 ramstage-y += timer.c
+ramstage-y += ../tegra/gpio.c
+ramstage-y += ../tegra/pinmux.c
+ramstage-$(CONFIG_DRIVERS_UART) += uart.c
 
 CPPFLAGS_common += -Isrc/soc/nvidia/tegra132/include/
 
diff --git a/src/soc/nvidia/tegra132/bootblock.c b/src/soc/nvidia/tegra132/bootblock.c
new file mode 100644
index 0000000..2d8c10f
--- /dev/null
+++ b/src/soc/nvidia/tegra132/bootblock.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/exception.h>
+#include <arch/hlt.h>
+#include <bootblock_common.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <soc/clock.h>
+#include <soc/nvidia/tegra/apbmisc.h>
+
+#include "pinmux.h"
+#include "power.h"
+
+void main(void)
+{
+	// enable pinmux clamp inputs
+	clamp_tristate_inputs();
+
+	// enable JTAG at the earliest stage
+	enable_jtag();
+
+	clock_early_uart();
+
+	// Serial out, tristate off.
+	pinmux_set_config(PINMUX_KB_ROW9_INDEX, PINMUX_KB_ROW9_FUNC_UA3);
+	// Serial in, tristate_on.
+	pinmux_set_config(PINMUX_KB_ROW10_INDEX, PINMUX_KB_ROW10_FUNC_UA3 |
+						 PINMUX_PULL_UP |
+						 PINMUX_INPUT_ENABLE);
+	// Mux some pins away from uart A.
+	pinmux_set_config(PINMUX_UART2_CTS_N_INDEX,
+			  PINMUX_UART2_CTS_N_FUNC_UB3 |
+			  PINMUX_INPUT_ENABLE);
+	pinmux_set_config(PINMUX_UART2_RTS_N_INDEX,
+			  PINMUX_UART2_RTS_N_FUNC_UB3);
+
+	if (CONFIG_BOOTBLOCK_CONSOLE) {
+		console_init();
+		exception_init();
+		printk(BIOS_INFO, "Tegra132: Bootblock here\n");
+	}
+}
diff --git a/src/soc/nvidia/tegra132/bootblock_asm.S b/src/soc/nvidia/tegra132/bootblock_asm.S
new file mode 100644
index 0000000..ebd64a7
--- /dev/null
+++ b/src/soc/nvidia/tegra132/bootblock_asm.S
@@ -0,0 +1,89 @@
+/*
+ * Early initialization code for ARM architecture.
+ *
+ * This file is based off of the OMAP3530/ARM Cortex start.S file from Das
+ * U-Boot, which itself got the file from armboot.
+ *
+ * Copyright (c) 2004	Texas Instruments <r-woodruff2 at ti.com>
+ * Copyright (c) 2001	Marius Gröger <mag at sysgo.de>
+ * Copyright (c) 2002	Alex Züpke <azu at sysgo.de>
+ * Copyright (c) 2002	Gary Jennejohn <garyj at denx.de>
+ * Copyright (c) 2003	Richard Woodruff <r-woodruff2 at ti.com>
+ * Copyright (c) 2003	Kshitij <kshitij at ti.com>
+ * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim at ti.com>
+ * Copyright (c) 2013   The Chromium OS Authors
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/asm.h>
+
+ENTRY(_start)
+	/*
+	 * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data
+	 * aborts may happen early and crash before the abort handlers are
+	 * installed, but at least the problem will show up near the code that
+	 * causes it.
+	 */
+	msr	cpsr_cxf, #0xdf
+
+	/*
+	 * Initialize the stack to a known value. This is used to check for
+	 * stack overflow later in the boot process.
+	 */
+	ldr	r0, .Stack
+	ldr	r1, .Stack_size
+	sub	r0, r0, r1
+	ldr	r1, .Stack
+	ldr	r2, =0xdeadbeef
+init_stack_loop:
+	str	r2, [r0]
+	add	r0, #4
+	cmp	r0, r1
+	bne	init_stack_loop
+
+/* Set stackpointer in internal RAM to call bootblock main() */
+call_bootblock:
+	ldr	sp, .Stack /* Set up stack pointer */
+	ldr	r0,=0x00000000
+	 /*
+	  * The current design of cpu_info places the
+	  * struct at the top of the stack. The number of
+	  * words pushed must be at least as large as that
+	  * struct.
+	  */
+	push	{r0-r2}
+	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
+	/*
+	 * Use "bl" instead of "b" even though we do not intend to return.
+	 * "bl" gets compiled to "blx" if we're transitioning from ARM to
+	 * Thumb. However, "b" will not and GCC may attempt to create a
+	 * wrapper which is currently broken.
+	 */
+	bl	main
+ENDPROC(_start)
+
+/* we do it this way because it's a 32-bit constant and
+ * in some cases too far away to be loaded as just an offset
+ * from IP
+ */
+.align 2
+.Stack:
+	.word CONFIG_STACK_TOP
+.align 2
+/* create this size the same way we do in ramstage.ld: top-bottom */
+.Stack_size:
+	.word CONFIG_STACK_TOP - CONFIG_STACK_BOTTOM
diff --git a/src/soc/nvidia/tegra132/clk_rst.h b/src/soc/nvidia/tegra132/clk_rst.h
new file mode 100644
index 0000000..9e2b33f
--- /dev/null
+++ b/src/soc/nvidia/tegra132/clk_rst.h
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TEGRA132_CLK_RST_H_
+#define _TEGRA132_CLK_RST_H_
+
+/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
+struct  __attribute__ ((__packed__)) clk_rst_ctlr {
+	u32 rst_src;			/* _RST_SOURCE,             0x000 */
+	u32 rst_dev_l;			/* _RST_DEVICES_L,          0x004 */
+	u32 rst_dev_h;			/* _RST_DEVICES_H,          0x008 */
+	u32 rst_dev_u;			/* _RST_DEVICES_U,          0x00c */
+	u32 clk_out_enb_l;		/* _CLK_OUT_ENB_L,          0x010 */
+	u32 clk_out_enb_h;		/* _CLK_OUT_ENB_H,          0x014 */
+	u32 clk_out_enb_u;		/* _CLK_OUT_ENB_U,          0x018 */
+	u32 _rsv0;			/*                          0x01c */
+	u32 cclk_brst_pol;		/* _CCLK_BURST_POLICY,      0x020 */
+	u32 super_cclk_div;		/* _SUPER_CCLK_DIVIDER,     0x024 */
+	u32 sclk_brst_pol;		/* _SCLK_BURST_POLICY,      0x028 */
+	u32 super_sclk_div;		/* _SUPER_SCLK_DIVIDER,     0x02C */
+	u32 clk_sys_rate;		/* _CLK_SYSTEM_RATE,        0x030 */
+	u32 _rsv1[3];			/*                      0x034-03c */
+	u32 cop_clk_skip_plcy;		/* _COP_CLK_SKIP_POLICY,    0x040 */
+	u32 clk_mask_arm;		/* _CLK_MASK_ARM,           0x044 */
+	u32 misc_clk_enb;		/* _MISC_CLK_ENB,           0x048 */
+	u32 clk_cpu_cmplx;		/* _CLK_CPU_CMPLX,          0x04C */
+	u32 osc_ctrl;			/* _OSC_CTRL,               0x050 */
+	u32 pll_lfsr;			/* _PLL_LFSR,               0x054 */
+	u32 osc_freq_det;		/* _OSC_FREQ_DET,           0x058 */
+	u32 osc_freq_det_stat;		/* _OSC_FREQ_DET_STATUS,    0x05C */
+	u32 _rsv2[8];			/*                      0x060-07C */
+	u32 pllc_base;			/* _PLLC_BASE,              0x080 */
+	u32 pllc_out;			/* _PLLC_OUT,               0x084 */
+	u32 pllc_misc2;			/* _PLLC_MISC2,             0x088 */
+	u32 pllc_misc;			/* _PLLC_MISC,              0x08c */
+	u32 pllm_base;			/* _PLLM_BASE,              0x090 */
+	u32 pllm_out;			/* _PLLM_OUT,               0x094 */
+	u32 pllm_misc1;			/* _PLLM_MISC1,             0x098 */
+	u32 pllm_misc2;			/* _PLLM_MISC2,             0x09c */
+	u32 pllp_base;			/* _PLLP_BASE,              0x0a0 */
+	u32 pllp_outa;			/* _PLLP_OUTA,              0x0a4 */
+	u32 pllp_outb;			/* _PLLP_OUTB,              0x0a8 */
+	u32 pllp_misc;			/* _PLLP_MISC,              0x0ac */
+	u32 plla_base;			/* _PLLA_BASE,              0x0b0 */
+	u32 plla_out;			/* _PLLA_OUT,               0x0b4 */
+	u32 _rsv3;			/*                          0x0b8 */
+	u32 plla_misc;			/* _PLLA_MISC,              0x0bc */
+	u32 pllu_base;			/* _PLLU_BASE,              0x0c0 */
+	u32 _rsv4[2];			/*                      0x0c4-0c8 */
+	u32 pllu_misc;			/* _PLLU_MISC,              0x0cc */
+	u32 plld_base;			/* _PLLD_BASE,              0x0d0 */
+	u32 _rsv5[2];			/*                      0x0d4-0d8 */
+	u32 plld_misc;			/* _PLLD_MISC,              0x0dc */
+	u32 pllx_base;			/* _PLLX_BASE,              0x0e0 */
+	u32 pllx_misc;			/* _PLLX_MISC,              0x0e4 */
+	u32 plle_base;			/* _PLLE_BASE,              0x0e8 */
+	u32 plle_misc;			/* _PLLE_MISC,              0x0ec */
+	u32 plls_base;			/* _PLLS_BASE,              0x0f0 */
+	u32 plls_misc;			/* _PLLS_MISC,              0x0f4 */
+	u32 _rsv6[2];			/*                      0x0f8-0fc */
+        u32 clk_src_i2s1;		/* _CLK_SOURCE_I2S1,        0x100 */
+        u32 clk_src_i2s2;		/* _CLK_SOURCE_I2S2,        0x104 */
+        u32 clk_src_spdif_out;		/* _CLK_SOURCE_SPDIF_OUT,   0x108 */
+        u32 clk_src_spdif_in;		/* _CLK_SOURCE_SPDIF_IN,    0x10c */
+        u32 clk_src_pwm;		/* _CLK_SOURCE_PWM,         0x110 */
+        u32 _rsv7;			/*                          0x114 */
+        u32 clk_src_sbc2;		/* _CLK_SOURCE_SBC2,        0x118 */
+        u32 clk_src_sbc3;		/* _CLK_SOURCE_SBC3,        0x11c */
+        u32 _rsv8;			/*                          0x120 */
+        u32 clk_src_i2c1;		/* _CLK_SOURCE_I2C1,        0x124 */
+        u32 clk_src_i2c5;		/* _CLK_SOURCE_I2C5,        0x128 */
+        u32 _rsv9[2];			/*                      0x12c-130 */
+        u32 clk_src_sbc1;		/* _CLK_SOURCE_SBC1,        0x134 */
+        u32 clk_src_disp1;		/* _CLK_SOURCE_DISP1,       0x138 */
+        u32 clk_src_disp2;		/* _CLK_SOURCE_DISP2,       0x13c */
+        u32 _rsv10[2];			/*                      0x140-144 */
+        u32 clk_src_vi;			/* _CLK_SOURCE_VI,          0x148 */
+        u32 _rsv11;			/*                          0x14c */
+        u32 clk_src_sdmmc1;		/* _CLK_SOURCE_SDMMC1,      0x150 */
+        u32 clk_src_sdmmc2;		/* _CLK_SOURCE_SDMMC2,      0x154 */
+        u32 clk_src_g3d;		/* _CLK_SOURCE_G3D,         0x158 */
+        u32 clk_src_g2d;		/* _CLK_SOURCE_G2D,         0x15c */
+        u32 clk_src_ndflash;		/* _CLK_SOURCE_NDFLASH,     0x160 */
+        u32 clk_src_sdmmc4;		/* _CLK_SOURCE_SDMMC4,      0x164 */
+        u32 clk_src_vfir;		/* _CLK_SOURCE_VFIR,        0x168 */
+        u32 clk_src_epp;		/* _CLK_SOURCE_EPP,         0x16c */
+        u32 clk_src_mpe;		/* _CLK_SOURCE_MPE,         0x170 */
+        u32 clk_src_hsi;		/* _CLK_SOURCE_HSI,         0x174 */
+        u32 clk_src_uarta;		/* _CLK_SOURCE_UARTA,       0x178 */
+        u32 clk_src_uartb;		/* _CLK_SOURCE_UARTB,       0x17c */
+        u32 clk_src_host1x;		/* _CLK_SOURCE_HOST1X,      0x180 */
+        u32 _rsv12[2];			/*                      0x184-188 */
+        u32 clk_src_hdmi;		/* _CLK_SOURCE_HDMI,        0x18c */
+        u32 _rsv13[2];			/*                      0x190-194 */
+        u32 clk_src_i2c2;		/* _CLK_SOURCE_I2C2,        0x198 */
+        u32 clk_src_emc;		/* _CLK_SOURCE_EMC,         0x19c */
+        u32 clk_src_uartc;		/* _CLK_SOURCE_UARTC,       0x1a0 */
+	u32 _rsv14;			/*                          0x1a4 */
+        u32 clk_src_vi_sensor;		/* _CLK_SOURCE_VI_SENSOR,   0x1a8 */
+        u32 _rsv15[2];			/*                      0x1ac-1b0 */
+        u32 clk_src_sbc4;		/* _CLK_SOURCE_SBC4,        0x1b4 */
+        u32 clk_src_i2c3;		/* _CLK_SOURCE_I2C3,        0x1b8 */
+        u32 clk_src_sdmmc3;		/* _CLK_SOURCE_SDMMC3,      0x1bc */
+        u32 clk_src_uartd;		/* _CLK_SOURCE_UARTD,       0x1c0 */
+        u32 clk_src_uarte;		/* _CLK_SOURCE_UARTE,       0x1c4 */
+        u32 clk_src_vde;		/* _CLK_SOURCE_VDE,         0x1c8 */
+        u32 clk_src_owr;		/* _CLK_SOURCE_OWR,         0x1cc */
+        u32 clk_src_nor;		/* _CLK_SOURCE_NOR,         0x1d0 */
+        u32 clk_src_csite;		/* _CLK_SOURCE_CSITE,       0x1d4 */
+        u32 clk_src_i2s0;		/* _CLK_SOURCE_I2S0,        0x1d8 */
+        u32 clk_src_dtv;		/* _CLK_SOURCE_DTV,         0x1dc */
+        u32 _rsv16[4];			/*                      0x1e0-1ec */
+        u32 clk_src_msenc;		/* _CLK_SOURCE_MSENC,       0x1f0 */
+        u32 clk_src_tsec;		/* _CLK_SOURCE_TSEC,        0x1f4 */
+	u32 _rsv17;			/*                          0x1f8 */
+        u32 clk_src_osc;		/* _CLK_SOURCE_OSC,         0x1fc */
+	u32 _rsv18[32];			/*                      0x200-27c */
+	u32 clk_out_enb_x;		/* _CLK_OUT_ENB_X_0,        0x280 */
+	u32 clk_enb_x_set;		/* _CLK_ENB_X_SET_0,        0x284 */
+	u32 clk_enb_x_clr;		/* _CLK_ENB_X_CLR_0,        0x288 */
+	u32 rst_devices_x;		/* _RST_DEVICES_X_0,        0x28c */
+	u32 rst_dev_x_set;		/* _RST_DEV_X_SET_0,        0x290 */
+	u32 rst_dev_x_clr;		/* _RST_DEV_X_CLR_0,        0x294 */
+	u32 _rsv19[23];			/*                      0x298-2f0 */
+	u32 dfll_base;			/* _DFLL_BASE_0,            0x2f4 */
+	u32 _rsv20[2];			/*                      0x2f8-2fc */
+	u32 rst_dev_l_set;		/* _RST_DEV_L_SET           0x300 */
+	u32 rst_dev_l_clr;		/* _RST_DEV_L_CLR           0x304 */
+	u32 rst_dev_h_set;		/* _RST_DEV_H_SET           0x308 */
+	u32 rst_dev_h_clr;		/* _RST_DEV_H_CLR           0x30c */
+	u32 rst_dev_u_set;		/* _RST_DEV_U_SET           0x310 */
+	u32 rst_dev_u_clr;		/* _RST_DEV_U_CLR           0x314 */
+	u32 _rsv21[2];			/*                      0x318-31c */
+	u32 clk_enb_l_set;		/* _CLK_ENB_L_SET           0x320 */
+	u32 clk_enb_l_clr;		/* _CLK_ENB_L_CLR           0x324 */
+	u32 clk_enb_h_set;		/* _CLK_ENB_H_SET           0x328 */
+	u32 clk_enb_h_clr;		/* _CLK_ENB_H_CLR           0x32c */
+	u32 clk_enb_u_set;		/* _CLK_ENB_U_SET           0x330 */
+	u32 clk_enb_u_clk;		/* _CLK_ENB_U_CLR           0x334 */
+	u32 _rsv22;			/*                          0x338 */
+	u32 ccplex_pg_sm_ovrd;		/* _CCPLEX_PG_SM_OVRD,      0x33c */
+	u32 rst_cpu_cmplx_set;		/* _RST_CPU_CMPLX_SET,      0x340 */
+	u32 rst_cpu_cmplx_clr;		/* _RST_CPU_CMPLX_CLR,      0x344 */
+	u32 clk_cpu_cmplx_set;		/* _CLK_CPU_CMPLX_SET,      0x348 */
+	u32 clk_cpu_cmplx_clr;		/* _CLK_CPU_CMPLX_SET,      0x34c */
+	u32 _rsv23[2];			/*                      0x350-354 */
+	u32 rst_dev_v;			/* _RST_DEVICES_V,          0x358 */
+	u32 rst_dev_w;			/* _RST_DEVICES_W,          0x35c */
+	u32 clk_out_enb_v;		/* _CLK_OUT_ENB_V,          0x360 */
+	u32 clk_out_enb_w;		/* _CLK_OUT_ENB_W,          0x364 */
+	u32 cclkg_brst_pol;		/* _CCLKG_BURST_POLICY,     0x368 */
+	u32 super_cclkg_div;		/* _SUPER_CCLKG_DIVIDER,    0x36c */
+	u32 cclklp_brst_pol;		/* _CCLKLP_BURST_POLICY,    0x370 */
+	u32 super_cclkp_div;		/* _SUPER_CCLKLP_DIVIDER,   0x374 */
+	u32 clk_cpug_cmplx;		/* _CLK_CPUG_CMPLX,         0x378 */
+	u32 clk_cpulp_cmplx;		/* _CLK_CPULP_CMPLX,        0x37c */
+	u32 cpu_softrst_ctrl;		/* _CPU_SOFTRST_CTRL,       0x380 */
+	u32 cpu_softrst_ctrl1;		/* _CPU_SOFTRST_CTRL1,      0x384 */
+	u32 cpu_softrst_ctrl2;		/* _CPU_SOFTRST_CTRL2,      0x388 */
+	u32 _rsv24[9];			/*                      0x38c-3ac */
+	u32 clk_src_g3d2;		/* _CLK_SOURCE_G3D2,        0x3b0 */
+	u32 clk_src_mselect;		/* _CLK_SOURCE_MSELECT,     0x3b4 */
+	u32 clk_src_tsensor;		/* _CLK_SOURCE_TSENSOR,     0x3b8 */
+	u32 clk_src_i2s3;		/* _CLK_SOURCE_I2S3,        0x3bc */
+	u32 clk_src_i2s4;		/* _CLK_SOURCE_I2S4,        0x3c0 */
+	u32 clk_src_i2c4;		/* _CLK_SOURCE_I2C4,        0x3c4 */
+	u32 clk_src_sbc5;		/* _CLK_SOURCE_SBC5,        0x3c8 */
+	u32 clk_src_sbc6;		/* _CLK_SOURCE_SBC6,        0x3cc */
+	u32 clk_src_audio;		/* _CLK_SOURCE_AUDIO,       0x3d0 */
+	u32 _rsv25;			/*                          0x3d4 */
+	u32 clk_src_dam0;		/* _CLK_SOURCE_DAM0,        0x3d8 */
+	u32 clk_src_dam1;		/* _CLK_SOURCE_DAM1,        0x3dc */
+	u32 clk_src_dam2;		/* _CLK_SOURCE_DAM2,        0x3e0 */
+	u32 clk_src_hda2codec_2x;	/* _CLK_SOURCE_HDA2CODEC_2X,0x3e4 */
+	u32 clk_src_actmon;		/* _CLK_SOURCE_ACTMON,      0x3e8 */
+	u32 clk_src_extperiph1;		/* _CLK_SOURCE_EXTPERIPH1,  0x3ec */
+	u32 clk_src_extperiph2;		/* _CLK_SOURCE_EXTPERIPH2,  0x3f0 */
+	u32 clk_src_extperiph3;		/* _CLK_SOURCE_EXTPERIPH3,  0x3f4 */
+	u32 clk_src_nand_speed;		/* _CLK_SOURCE_NAND_SPEED,  0x3f8 */
+	u32 clk_src_i2c_slow;		/* _CLK_SOURCE_I2C_SLOW,    0x3fc */
+	u32 clk_src_sys;		/* _CLK_SOURCE_SYS,         0x400 */
+	u32 _rsv26[4];			/*                      0x404-410 */
+	u32 clk_src_sor;		/* _CLK_SOURCE_SOR_0,       0x414 */
+	u32 _rsv261[2];			/*                      0x404-410 */
+	u32 clk_src_sata_oob;		/* _CLK_SOURCE_SATA_OOB,    0x420 */
+	u32 clk_src_sata;		/* _CLK_SOURCE_SATA,        0x424 */
+	u32 clk_src_hda;		/* _CLK_SOURCE_HDA,         0x428 */
+	u32 _rsv27;			/*                          0x42c */
+	u32 rst_dev_v_set;		/* _RST_DEV_V_SET,          0x430 */
+	u32 rst_dev_v_clr;		/* _RST_DEV_V_CLR,          0x434 */
+	u32 rst_dev_w_set;		/* _RST_DEV_W_SET,          0x438 */
+	u32 rst_dev_w_clr;		/* _RST_DEV_W_CLR,          0x43c */
+	u32 clk_enb_v_set;		/* _CLK_ENB_V_SET,          0x440 */
+	u32 clk_enb_v_clr;		/* _CLK_ENB_V_CLR,          0x444 */
+	u32 clk_enb_w_set;		/* _CLK_ENB_W_SET,          0x448 */
+	u32 clk_enb_w_clr;		/* _CLK_ENB_W_CLR,          0x44c */
+	u32 rst_cpug_cmplx_set;		/* _RST_CPUG_CMPLX_SET,     0x450 */
+	u32 rst_cpug_cmplx_clr;		/* _RST_CPUG_CMPLX_CLR,     0x454 */
+	u32 rst_cpulp_cmplx_set;	/* _RST_CPULP_CMPLX_SET,    0x458 */
+	u32 rst_cpulp_cmplx_clr;	/* _RST_CPULP_CMPLX_CLR,    0x45C */
+	u32 clk_cpug_cmplx_set;		/* _CLK_CPUG_CMPLX_SET,     0x460 */
+	u32 clk_cpug_cmplx_clr;		/* _CLK_CPUG_CMPLX_CLR,     0x464 */
+	u32 clk_cpulp_cmplx_set;	/* _CLK_CPULP_CMPLX_SET,    0x468 */
+	u32 clk_cpulp_cmplx_clr;	/* _CLK_CPULP_CMPLX_CLR,    0x46c */
+	u32 cpu_cmplx_status;		/* _CPU_CMPLX_STATUS,       0x470 */
+	u32 _rsv28;			/*                          0x474 */
+	u32 intstatus;			/* _INTSTATUS,              0x478 */
+	u32 intmask;			/* _INTMASK,                0x47c */
+	u32 utmip_pll_cfg0;		/* _UTMIP_PLL_CFG0,         0x480 */
+	u32 utmip_pll_cfg1;		/* _UTMIP_PLL_CFG1,         0x484 */
+	u32 utmip_pll_cfg2;		/* _UTMIP_PLL_CFG2,         0x488 */
+	u32 plle_aux;			/* _PLLE_AUX,               0x48c */
+	u32 sata_pll_cfg0;		/* _SATA_PLL_CFG0,          0x490 */
+	u32 sata_pll_cfg1;		/* _SATA_PLL_CFG1,          0x494 */
+	u32 pcie_pll_cfg0;		/* _PCIE_PLL_CFG0,          0x498 */
+	u32 prog_audio_dly_clk;		/* _PROG_AUDIO_DLY_CLK,     0x49c */
+	u32 audio_sync_clk_i2s0;	/* _AUDIO_SYNC_CLK_I2S0,    0x4a0 */
+	u32 audio_sync_clk_i2s1;	/* _AUDIO_SYNC_CLK_I2S1,    0x4a4 */
+	u32 audio_sync_clk_i2s2;	/* _AUDIO_SYNC_CLK_I2S2,    0x4a8 */
+	u32 audio_sync_clk_i2s3;	/* _AUDIO_SYNC_CLK_I2S3,    0x4ac */
+	u32 audio_sync_clk_i2s4;	/* _AUDIO_SYNC_CLK_I2S4,    0x4b0 */
+	u32 audio_sync_clk_spdif;	/* _AUDIO_SYNC_CLK_SPDIF,   0x4b4 */
+	u32 plld2_base;			/* _PLLD2_BASE,             0x4b8 */
+	u32 plld2_misc;			/* _PLLD2_MISC,             0x4bc */
+	u32 utmip_pll_cfg3;		/* _UTMIP_PLL_CFG3,         0x4c0 */
+	u32 pllrefe_base;		/* _PLLREFE_BASE,           0x4c4 */
+	u32 pllrefe_misc;		/* _PLLREFE_MISC,           0x4c8 */
+	u32 _rsv29[7];			/*                      0x4cc-4e4 */
+	u32 pllc2_base;			/* _PLLC2_BASE,             0x4e8 */
+	u32 pllc2_misc0;		/* _PLLC2_MISC_0,           0x4ec */
+	u32 pllc2_misc1;		/* _PLLC2_MISC_1,           0x4f0 */
+	u32 pllc2_misc2;		/* _PLLC2_MISC_2,           0x4f4 */
+	u32 pllc2_misc3;		/* _PLLC2_MISC_3,           0x4f8 */
+	u32 pllc3_base;			/* _PLLC3_BASE,             0x4fc */
+	u32 pllc3_misc0;		/* _PLLC3_MISC_0,           0x500 */
+	u32 pllc3_misc1;		/* _PLLC3_MISC_1,           0x504 */
+	u32 pllc3_misc2;		/* _PLLC3_MISC_2,           0x508 */
+	u32 pllc3_misc3;		/* _PLLC3_MISC_3,           0x50c */
+	u32 pllx_misc1;			/* _PLLX_MISC_1,            0x510 */
+	u32 pllx_misc2;			/* _PLLX_MISC_2,            0x514 */
+	u32 pllx_misc3;			/* _PLLX_MISC_3,            0x518 */
+	u32 xusbio_pll_cfg0;		/* _XUSBIO_PLL_CFG0,        0x51c */
+	u32 xusbio_pll_cfg1;		/* _XUSBIO_PLL_CFG1,        0x520 */
+	u32 plle_aux1;			/* _PLLE_AUX1,              0x524 */
+	u32 pllp_reshift;		/* _PLLP_RESHIFT,           0x528 */
+	u32 utmipll_hw_pwrdn_cfg0;	/* _UTMIPLL_HW_PWRDN_CFG0,  0x52c */
+	u32 pllu_hw_pwrdn_cfg0;		/* _PLLU_HW_PWRDN_CFG0,     0x530 */
+	u32 xusb_pll_cfg0;		/* _XUSB_PLL_CFG0,          0x534 */
+	u32 _rsv30;			/*                          0x538 */
+	u32 clk_cpu_misc;		/* _CLK_CPU_MISC,           0x53c */
+	u32 clk_cpug_misc;		/* _CLK_CPUG_MISC,          0x540 */
+	u32 clk_cpulp_misc;		/* _CLK_CPULP_MISC,         0x544 */
+	u32 pllx_hw_ctrl_cfg;		/* _PLLX_HW_CTRL_CFG,       0x548 */
+	u32 pllx_sw_ramp_cfg;		/* _PLLX_SW_RAMP_CFG,       0x54c */
+	u32 pllx_hw_ctrl_status;	/* _PLLX_HW_CTRL_STATUS,    0x550 */
+	u32 _rsv31;			/*                          0x554 */
+	u32 super_gr3d_clk_div;		/* _SUPER_GR3D_CLK_DIVIDER, 0x558 */
+	u32 spare_reg0;			/* _SPARE_REG0,             0x55c */
+	u32 _rsv32[4];                  /*                    0x560-0x56c */
+	u32 plld2_ss_cfg;               /* _PLLD2_SS_CFG            0x570 */
+	u32 _rsv32_1[7];			/*                      0x574-58c */
+	u32 plldp_base;			/* _PLLDP_BASE,             0x590 */
+	u32 plldp_misc;			/* _PLLDP_MISC,             0x594 */
+	u32 plldp_ss_cfg;		/* _PLLDP_SS_CFG,           0x598 */
+	u32 _rsrv32_2[25];
+	u32 clk_src_xusb_core_host;	/* _CLK_SOURCE_XUSB_CORE_HOST 0x600 */
+	u32 clk_src_xusb_falcon;	/* _CLK_SOURCE_XUSB_FALCON  0x604 */
+	u32 clk_src_xusb_fs;		/* _CLK_SOURCE_XUSB_FS      0x608 */
+	u32 clk_src_xusb_core_dev;	/* _CLK_SOURCE_XUSB_CORE_DEV 0x60c */
+	u32 clk_src_xusb_ss;		/* _CLK_SOURCE_XUSB_SS      0x610 */
+	u32 clk_src_cilab;		/* _CLK_SOURCE_CILAB        0x614 */
+	u32 clk_src_cilcd;		/* _CLK_SOURCE_CILCD        0x618 */
+	u32 clk_src_cile;		/* _CLK_SOURCE_CILE         0x61c */
+	u32 clk_src_dsia_lp;		/* _CLK_SOURCE_DSIA_LP      0x620 */
+	u32 clk_src_dsib_lp;		/* _CLK_SOURCE_DSIB_LP      0x624 */
+	u32 clk_src_entropy;		/* _CLK_SOURCE_ENTROPY      0x628 */
+	u32 clk_src_dvfs_ref;		/* _CLK_SOURCE_DVFS_REF     0x62c */
+	u32 clk_src_dvfs_soc;		/* _CLK_SOURCE_DVFS_SOC     0x630 */
+	u32 clk_src_traceclkin;		/* _CLK_SOURCE_TRACECLKIN   0x634 */
+	u32 clk_src_adx0;		/* _CLK_SOURCE_ADX0         0x638 */
+	u32 clk_src_amx0;		/* _CLK_SOURCE_AMX0         0x63c */
+	u32 clk_src_emc_latency;	/* _CLK_SOURCE_EMC_LATENCY  0x640 */
+	u32 clk_src_soc_therm;		/* _CLK_SOURCE_SOC_THERM    0x644 */
+};
+check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644);
+
+#define TEGRA_DEV_L			0
+#define TEGRA_DEV_H			1
+#define TEGRA_DEV_U			2
+#define TEGRA_DEV_V			0
+#define TEGRA_DEV_W			1
+
+#define SIMPLE_PLLX		(CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
+
+/* Bits to enable/reset modules */
+#define CLK_ENB_CPU			(1 << 0)
+#define SWR_TRIG_SYS_RST		(1 << 2)
+#define SWR_CSITE_RST			(1 << 9)
+#define CLK_ENB_CSITE			(1 << 9)
+
+/* CRC_SUPER_CCLK_DIVIDER_0 0x24 */
+#define SUPER_CDIV_ENB_ENABLE		(1 << 31)
+
+/* CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 */
+#define EN_PPSB_STOPCLK			(1 << 0)
+
+/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 (0x4C) */
+#define CPU3_CLK_STP_SHIFT		11
+#define CPU2_CLK_STP_SHIFT		10
+#define CPU1_CLK_STP_SHIFT		9
+#define CPU0_CLK_STP_SHIFT		8
+#define CPU0_CLK_STP_MASK		(1U << CPU0_CLK_STP_SHIFT)
+
+/* CRC_OSC_CTRL_0 0x50 */
+#define OSC_FREQ_SHIFT			28
+#define OSC_FREQ_MASK			(0xf << OSC_FREQ_SHIFT)
+#define OSC_PREDIV_SHIFT		26
+#define OSC_PREDIV_MASK			(0x3 << OSC_PREDIV_SHIFT)
+#define OSC_XOFS_SHIFT			4
+#define OSC_XOFS_MASK			(0x3F << OSC_XOFS_SHIFT)
+#define OSC_DRIVE_STRENGTH		7
+#define OSC_XOBP			(1 << 1)
+#define OSC_XOE				(1 << 0)
+
+enum {
+	OSC_FREQ_12	= 8,	/* 12.0MHz */
+	OSC_FREQ_13	= 0,	/* 13.0MHz */
+	OSC_FREQ_16P8	= 1,	/* 16.8MHz */
+	OSC_FREQ_19P2	= 4,	/* 19.2MHz */
+	OSC_FREQ_26	= 12,	/* 26.0MHz */
+	OSC_FREQ_38P4	= 5,	/* 38.4MHz */
+	OSC_FREQ_48	= 9,	/* 48.0MHz */
+};
+
+/* CLK_RST_CONTROLLER_PLL*_BASE_0 */
+#define PLL_BASE_BYPASS			(1U << 31)
+#define PLL_BASE_ENABLE			(1U << 30)
+#define PLL_BASE_REF_DIS		(1U << 29)
+#define PLL_BASE_OVRRIDE		(1U << 28)
+#define PLL_BASE_LOCK			(1U << 27)
+
+#define PLL_BASE_DIVP_SHIFT		20
+#define PLL_BASE_DIVP_MASK		(7U << PLL_BASE_DIVP_SHIFT)
+
+#define PLL_BASE_DIVN_SHIFT		8
+#define PLL_BASE_DIVN_MASK		(0x3ffU << PLL_BASE_DIVN_SHIFT)
+
+#define PLL_BASE_DIVM_SHIFT		0
+#define PLL_BASE_DIVM_MASK		(0x1f << PLL_BASE_DIVM_SHIFT)
+
+/* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */
+#define PLLCX_BASE_DIVP_MASK		(0xfU << PLL_BASE_DIVP_SHIFT)
+#define PLLM_BASE_DIVP_MASK		(0x1U << PLL_BASE_DIVP_SHIFT)
+#define PLLCMX_BASE_DIVN_MASK		(0xffU << PLL_BASE_DIVN_SHIFT)
+#define PLLCMX_BASE_DIVM_MASK		(0xffU << PLL_BASE_DIVM_SHIFT)
+
+/* PLLM specific registers */
+#define PLLM_MISC1_SETUP_SHIFT			0
+#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT		28
+#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT		29
+#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT	30
+#define PLLM_MISC2_KCP_SHIFT			1
+#define PLLM_MISC2_KVCO_SHIFT			0
+#define PLLM_OUT1_RSTN_RESET_DISABLE		(1 << 0)
+
+/* Generic, indiscriminate divisor mask. May catch some innocent bystander bits
+ * on the side that we don't particularly care about. */
+#define PLL_BASE_DIV_MASK		(0xffffff)
+
+/* CLK_RST_CONTROLLER_PLL*_OUT*_0 */
+#define PLL_OUT_RSTN			(1 << 0)
+#define PLL_OUT_CLKEN			(1 << 1)
+#define PLL_OUT_OVR			(1 << 2)
+
+#define PLL_OUT_RATIO_SHIFT		8
+#define PLL_OUT_RATIO_MASK		(0xffU << PLL_OUT_RATIO_SHIFT)
+
+#define PLL_OUT1_SHIFT			0
+#define PLL_OUT2_SHIFT			16
+#define PLL_OUT3_SHIFT			0
+#define PLL_OUT4_SHIFT			16
+
+/* CLK_RST_CONTROLLER_PLL*_MISC_0 */
+#define PLL_MISC_DCCON			(1 << 20)
+
+#define PLL_MISC_CPCON_SHIFT		8
+#define PLL_MISC_CPCON_MASK		(0xfU << PLL_MISC_CPCON_SHIFT)
+
+#define PLL_MISC_LFCON_SHIFT		4
+#define PLL_MISC_LFCON_MASK		(0xfU << PLL_MISC_LFCON_SHIFT)
+
+/* This bit is different all over the place. Oh joy... */
+#define PLLDPD2_MISC_LOCK_ENABLE	(1 << 30)
+#define PLLC_MISC_LOCK_ENABLE		(1 << 24)
+#define PLLUD_MISC_LOCK_ENABLE		(1 << 22)
+#define PLLD_MISC_CLK_ENABLE		(1 << 30)
+#define PLLPAXS_MISC_LOCK_ENABLE	(1 << 18)
+#define PLLE_MISC_LOCK_ENABLE		(1 << 9)
+
+#define PLLU_MISC_VCO_FREQ		(1 << 20)
+
+/* PLLX_BASE_0 0xe0 */
+#define PLLX_BASE_PLLX_ENABLE		(1 << 30)
+
+/* CLK_RST_CONTROLLER_PLLX_MISC_3 */
+#define PLLX_IDDQ_SHIFT			3
+#define PLLX_IDDQ_MASK			(1U << PLLX_IDDQ_SHIFT)
+
+#define CLK_DIVISOR_MASK		(0xffff)
+
+#define CLK_SOURCE_SHIFT		29
+#define CLK_SOURCE_MASK			(0x7 << CLK_SOURCE_SHIFT)
+
+#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16)
+
+#define CLK_UART_DIV_OVERRIDE		(1 << 24)
+
+/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */
+#define SCLK_SYS_STATE_SHIFT		28U
+#define SCLK_SYS_STATE_MASK		(15U << SCLK_SYS_STATE_SHIFT)
+enum {
+	SCLK_SYS_STATE_STDBY,
+	SCLK_SYS_STATE_IDLE,
+	SCLK_SYS_STATE_RUN,
+	SCLK_SYS_STATE_IRQ = 4U,
+	SCLK_SYS_STATE_FIQ = 8U,
+};
+#define SCLK_COP_FIQ_MASK		(1 << 27)
+#define SCLK_CPU_FIQ_MASK		(1 << 26)
+#define SCLK_COP_IRQ_MASK		(1 << 25)
+#define SCLK_CPU_IRQ_MASK		(1 << 24)
+
+#define SCLK_FIQ_SHIFT			12
+#define SCLK_FIQ_MASK			(7 << SCLK_FIQ_SHIFT)
+#define SCLK_IRQ_SHIFT			8
+#define SCLK_IRQ_MASK			(7 << SCLK_FIQ_SHIFT)
+#define SCLK_RUN_SHIFT			4
+#define SCLK_RUN_MASK			(7 << SCLK_FIQ_SHIFT)
+#define SCLK_IDLE_SHIFT			0
+#define SCLK_IDLE_MASK			(7 << SCLK_FIQ_SHIFT)
+enum {
+	SCLK_SOURCE_CLKM,
+	SCLK_SOURCE_PLLC_OUT1,
+	SCLK_SOURCE_PLLP_OUT4,
+	SCLK_SOURCE_PLLP_OUT3,
+	SCLK_SOURCE_PLLP_OUT2,
+	SCLK_SOURCE_PLLC_OUT0,
+	SCLK_SOURCE_CLKS,
+	SCLK_SOURCE_PLLM_OUT1,
+};
+
+/* CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2c */
+#define SCLK_DIV_ENB			(1 << 31)
+#define SCLK_DIVIDEND_SHIFT		8
+#define SCLK_DIVIDEND_MASK		(0xff << SCLK_DIVIDEND_SHIFT)
+#define SCLK_DIVISOR_SHIFT		0
+#define SCLK_DIVISOR_MASK		(0xff << SCLK_DIVISOR_SHIFT)
+
+/* CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 */
+#define HCLK_DISABLE 			(1 << 7)
+#define HCLK_DIVISOR_SHIFT    		4
+#define HCLK_DIVISOR_MASK     		(3 << AHB_RATE_SHIFT)
+#define PCLK_DISABLE 			(1 << 3)
+#define PCLK_DIVISOR_SHIFT    		0
+#define PCLK_DIVISOR_MASK     		(3 << AHB_RATE_SHIFT)
+
+/* CRC_CLK_SOURCE_MSELECT_0 0x3b4 */
+#define MSELECT_CLK_SRC_PLLP_OUT0	(0 << 29)
+
+/* CRC_CLK_ENB_V_SET_0 0x440 */
+#define SET_CLK_ENB_CPUG_ENABLE		(1 << 0)
+#define SET_CLK_ENB_CPULP_ENABLE	(1 << 1)
+#define SET_CLK_ENB_MSELECT_ENABLE	(1 << 3)
+
+/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 0x484 */
+#define PLLU_POWERDOWN			(1 << 16)
+#define PLL_ENABLE_POWERDOWN		(1 << 14)
+#define PLL_ACTIVE_POWERDOWN		(1 << 12)
+
+/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG2_0 0x488 */
+#define UTMIP_FORCE_PD_SAMP_C_POWERDOWN	(1 << 4)
+#define UTMIP_FORCE_PD_SAMP_B_POWERDOWN	(1 << 2)
+#define UTMIP_FORCE_PD_SAMP_A_POWERDOWN	(1 << 0)
+
+// CCLK_BRST_POL
+enum {
+	CRC_CCLK_BRST_POL_PLLX_OUT0 = 0x8,
+	CRC_CCLK_BRST_POL_CPU_STATE_RUN = 0x2
+};
+
+// SUPER_CCLK_DIVIDER
+enum {
+	CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31
+};
+
+// CLK_CPU_CMPLX_CLR
+enum {
+	CRC_CLK_CLR_CPU0_STP = 0x1 << 8,
+	CRC_CLK_CLR_CPU1_STP = 0x1 << 9,
+	CRC_CLK_CLR_CPU2_STP = 0x1 << 10,
+	CRC_CLK_CLR_CPU3_STP = 0x1 << 11
+};
+
+// RST_CPUG_CMPLX_CLR
+enum {
+	CRC_RST_CPUG_CLR_CPU0 = 0x1 << 0,
+	CRC_RST_CPUG_CLR_CPU1 = 0x1 << 1,
+	CRC_RST_CPUG_CLR_CPU2 = 0x1 << 2,
+	CRC_RST_CPUG_CLR_CPU3 = 0x1 << 3,
+	CRC_RST_CPUG_CLR_DBG0 = 0x1 << 12,
+	CRC_RST_CPUG_CLR_DBG1 = 0x1 << 13,
+	CRC_RST_CPUG_CLR_DBG2 = 0x1 << 14,
+	CRC_RST_CPUG_CLR_DBG3 = 0x1 << 15,
+	CRC_RST_CPUG_CLR_CORE0 = 0x1 << 16,
+	CRC_RST_CPUG_CLR_CORE1 = 0x1 << 17,
+	CRC_RST_CPUG_CLR_CORE2 = 0x1 << 18,
+	CRC_RST_CPUG_CLR_CORE3 = 0x1 << 19,
+	CRC_RST_CPUG_CLR_CX0 = 0x1 << 20,
+	CRC_RST_CPUG_CLR_CX1 = 0x1 << 21,
+	CRC_RST_CPUG_CLR_CX2 = 0x1 << 22,
+	CRC_RST_CPUG_CLR_CX3 = 0x1 << 23,
+	CRC_RST_CPUG_CLR_L2 = 0x1 << 24,
+	CRC_RST_CPUG_CLR_NONCPU = 0x1 << 29,
+	CRC_RST_CPUG_CLR_PDBG = 0x1 << 30,
+};
+
+// RST_CPULP_CMPLX_CLR
+enum {
+	CRC_RST_CPULP_CLR_CPU0 = 0x1 << 0,
+	CRC_RST_CPULP_CLR_DBG0 = 0x1 << 12,
+	CRC_RST_CPULP_CLR_CORE0 = 0x1 << 16,
+	CRC_RST_CPULP_CLR_CX0 = 0x1 << 20,
+	CRC_RST_CPULP_CLR_L2 = 0x1 << 24,
+	CRC_RST_CPULP_CLR_NONCPU = 0x1 << 29,
+	CRC_RST_CPULP_CLR_PDBG = 0x1 << 30,
+};
+
+#endif	/* _TEGRA132_CLK_RST_H_ */
diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c
new file mode 100644
index 0000000..5237712
--- /dev/null
+++ b/src/soc/nvidia/tegra132/clock.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <console/console.h>
+#include <delay.h>
+#include <arch/io.h>
+#include <soc/addressmap.h>
+#include <soc/clock.h>
+#include <stdlib.h>
+#include "clk_rst.h"
+#include "flow.h"
+#include "maincpu.h"
+#include "pmc.h"
+#include "sysctr.h"
+
+static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
+static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE;
+static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE;
+static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE;
+
+struct pll_dividers {
+	u32	n : 10;
+	u32	m : 8;
+	u32	p : 4;
+	u32	cpcon : 4;
+	u32	lfcon : 4;
+	u32	: 2;
+};
+
+/* Some PLLs have more restrictive divider bit lengths or are missing some
+ * fields. Make sure to use the right struct in the osc_table definition to get
+ * compile-time checking, but keep the bits aligned with struct pll_dividers so
+ * they can be used interchangeably at run time. Add new formats as required. */
+struct pllcx_dividers {
+	u32	n : 8;
+	u32	: 2;
+	u32	m : 8;
+	u32	p : 4;
+	u32	: 10;
+};
+struct pllpad_dividers {
+	u32	n : 10;
+	u32	m : 5;
+	u32	: 3;
+	u32	p : 3;
+	u32	: 1;
+	u32	cpcon : 4;
+	u32	: 6;
+};
+struct pllu_dividers {
+	u32	n : 10;
+	u32	m : 5;
+	u32	: 3;
+	u32	p : 1;
+	u32	: 3;
+	u32	cpcon : 4;
+	u32	lfcon : 4;
+	u32	: 2;
+};
+
+union __attribute__((transparent_union)) pll_fields {
+	u32 raw;
+	struct pll_dividers div;
+	struct pllcx_dividers cx;
+	struct pllpad_dividers pad;
+	struct pllu_dividers u;
+};
+
+/* This table defines the frequency dividers for every PLL to turn the external
+ * OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h.
+ * All PLLs have three dividers (n, m and p), with the governing formula for
+ * the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p).
+ * All divisor configurations must meet the PLL's constraints for VCO and CF:
+ * PLLX:  12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz
+ * PLLC:  12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz
+ * PLLM:  12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz
+ * PLLP:   1 MHz < CF <  6 MHz, 200 MHz < VCO <  700 MHz
+ * PLLD:   1 MHz < CF <  6 MHz, 500 MHz < VCO < 1000 MHz
+ * PLLU:   1 MHz < CF <  6 MHz, 480 MHz < VCO <  960 MHz
+ * PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz
+ * (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */
+struct {
+	int khz;
+	struct pllcx_dividers	pllx;	/* target:  CONFIG_PLLX_KHZ */
+	struct pllcx_dividers	pllc;	/* target:  600 MHz */
+	/* PLLM is set up dynamically by clock_sdram(). */
+	/* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */
+	struct pllu_dividers	pllu;	/* target;  960 MHz */
+	struct pllcx_dividers	plldp;	/* target;  270 MHz */
+	/* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */
+} static const osc_table[16] = {
+	[OSC_FREQ_12]{
+		.khz = 12000,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m =  1, .p = 0},
+		.pllc = {.n =  50, .m =  1, .p = 0},
+		.pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2},
+		.plldp = {.n = 90, .m =  1, .p = 3},
+	},
+	[OSC_FREQ_13]{
+		.khz = 13000,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m =  1, .p = 0},
+		.pllc = {.n =  46, .m =  1, .p = 0},		 /* 598.0 MHz */
+		.pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2},
+		.plldp = {.n = 83, .m =  1, .p = 3},		 /* 269.8 MHz */
+	},
+	[OSC_FREQ_16P8]{
+		.khz = 16800,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m =  1, .p = 0},
+		.pllc = {.n =  71, .m =  1, .p = 1},		 /* 596.4 MHz */
+		.pllu = {.n = 400, .m =  7, .p = 0, .cpcon = 5, .lfcon = 2},
+		.plldp = {.n = 64, .m =  1, .p = 3},		 /* 268.8 MHz */
+	},
+	[OSC_FREQ_19P2]{
+		.khz = 19200,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m =  1, .p = 0},
+		.pllc = {.n =  62, .m =  1, .p = 1},		 /* 595.2 MHz */
+		.pllu = {.n = 200, .m =  4, .p = 0, .cpcon = 3, .lfcon = 2},
+		.plldp = {.n = 56, .m =  1, .p = 3},		 /* 268.8 MHz */
+	},
+	[OSC_FREQ_26]{
+		.khz = 26000,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m =  1, .p = 0},
+		.pllc = {.n =  23, .m =  1, .p = 0},		 /* 598.0 MHz */
+		.pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2},
+		.plldp = {.n = 83, .m =  2, .p = 3},		 /* 269.8 MHz */
+	},
+	/* These oscillators get predivided as PLL inputs... n/m/p divisors for
+	 * 38.4 should always match 19.2, and 48 should always match 12. */
+	[OSC_FREQ_38P4]{
+		.khz = 38400,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m =  1, .p = 0},
+		.pllc = {.n =  62, .m =  1, .p = 1},		 /* 595.2 MHz */
+		.pllu = {.n = 200, .m =  4, .p = 0, .cpcon = 3, .lfcon = 2},
+		.plldp = {.n = 56, .m =  1, .p = 3},		 /* 268.8 MHz */
+	},
+	[OSC_FREQ_48]{
+		.khz = 48000,
+		.pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m =  1, .p = 0},
+		.pllc = {.n =  50, .m =  1, .p = 0},
+		.pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2},
+		.plldp = {.n = 90, .m =  1, .p = 3},
+	},
+};
+
+/* Get the oscillator frequency, from the corresponding hardware
+ * configuration field. This is actually a per-soc thing. Avoid the
+ * temptation to make it common.
+ */
+static u32 clock_get_osc_bits(void)
+{
+	return (readl(&clk_rst->osc_ctrl) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+}
+
+int clock_get_osc_khz(void)
+{
+	return osc_table[clock_get_osc_bits()].khz;
+}
+
+int clock_get_pll_input_khz(void)
+{
+	u32 osc_ctrl = readl(&clk_rst->osc_ctrl);
+	u32 osc_bits = (osc_ctrl & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+	u32 pll_ref_div = (osc_ctrl & OSC_PREDIV_MASK) >> OSC_PREDIV_SHIFT;
+	return osc_table[osc_bits].khz >> pll_ref_div;
+}
+
+void clock_init_arm_generic_timer(void)
+{
+	uint32_t freq = clock_get_osc_khz() * 1000;
+	// Set the cntfrq register.
+	__asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq));
+
+	// Record the system timer frequency.
+	write32(freq, &sysctr->cntfid0);
+	// Enable the system counter.
+	uint32_t cntcr = read32(&sysctr->cntcr);
+	cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG;
+	write32(cntcr, &sysctr->cntcr);
+}
+
+#define SOR0_CLK_SEL0			(1 << 14)
+#define SOR0_CLK_SEL1			(1 << 15)
+
+void sor_clock_stop(void)
+{
+	/* The Serial Output Resource clock has to be off
+	 * before we start the plldp. Learned the hard way.
+	 * FIXME: this has to be cleaned up a bit more.
+	 * Waiting on some new info from Nvidia.
+	 */
+	clrbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0 | SOR0_CLK_SEL1);
+}
+
+void sor_clock_start(void)
+{
+	/* uses PLLP, has a non-standard bit layout. */
+	setbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0);
+}
+
+static void init_pll(u32 *base, u32 *misc, const union pll_fields pll, u32 lock)
+{
+	u32 dividers =  pll.div.n << PLL_BASE_DIVN_SHIFT |
+			pll.div.m << PLL_BASE_DIVM_SHIFT |
+			pll.div.p << PLL_BASE_DIVP_SHIFT;
+	u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT |
+		       pll.div.lfcon << PLL_MISC_LFCON_SHIFT;
+
+	/* Write dividers but BYPASS the PLL while we're messing with it. */
+	writel(dividers | PLL_BASE_BYPASS, base);
+	/*
+	 * Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't
+	 * exist for this PLL)
+	 */
+	writel(lock | misc_con, misc);
+
+	/* Enable PLL and take it back out of BYPASS */
+	writel(dividers | PLL_BASE_ENABLE, base);
+
+	/* Wait for lock ready */
+	while (!(readl(base) & PLL_BASE_LOCK));
+}
+
+static void init_utmip_pll(void)
+{
+	int khz = clock_get_pll_input_khz();
+
+	/* Shut off PLL crystal clock while we mess with it */
+	clrbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */
+	udelay(1);
+
+	write32(80 << 16 |			/* (rst) phy_divn */
+		1 << 8 |			/* (rst) phy_divm */
+		0, &clk_rst->utmip_pll_cfg0);	/* 960MHz * 1 / 80 == 12 MHz */
+
+	write32(div_round_up(khz, 8000) << 27 |	/* pllu_enbl_cnt / 8 (1us) */
+		0 << 16 |			/* PLLU pwrdn */
+		0 << 14 |			/* pll_enable pwrdn */
+		0 << 12 |			/* pll_active pwrdn */
+		div_round_up(khz, 102) << 0 |	/* phy_stbl_cnt / 256 (2.5ms) */
+		0, &clk_rst->utmip_pll_cfg1);
+
+	/* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */
+	write32(0 << 24 |			/* SAMP_D/XDEV pwrdn */
+		div_round_up(khz, 3200) << 18 |	/* phy_actv_cnt / 16 (5us) */
+		div_round_up(khz, 256) << 6 |	/* pllu_stbl_cnt / 256 (1ms) */
+		0 << 4 |			/* SAMP_C/USB3 pwrdn */
+		0 << 2 |			/* SAMP_B/XHOST pwrdn */
+		0 << 0 |			/* SAMP_A/USBD pwrdn */
+		0, &clk_rst->utmip_pll_cfg2);
+
+	setbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */
+}
+
+/* Graphics just has to be different. There's a few more bits we
+ * need to set in here, but it makes sense just to restrict all the
+ * special bits to this one function.
+ */
+static void graphics_pll(void)
+{
+	int osc = clock_get_osc_bits();
+	u32 *cfg = &clk_rst->plldp_ss_cfg;
+	/* the vendor code sets the dither bit (28)
+	 * an undocumented bit (24)
+	 * and clamp while we mess with it (22)
+	 * Dither is pretty important to display port
+	 * so we really do need to handle these bits.
+	 * I'm not willing to not clamp it, even if
+	 * it might "mostly work" with it not set,
+	 * I don't want to find out in a few months
+	 * that it is needed.
+	 */
+	u32 scfg = (1<<28) | (1<<24) | (1<<22);
+	writel(scfg, cfg);
+	init_pll(&clk_rst->plldp_base, &clk_rst->plldp_misc,
+		osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE);
+	/* leave dither and undoc bits set, release clamp */
+	scfg = (1<<28) | (1<<24);
+	writel(scfg, cfg);
+
+	/* disp1 will be set when panel information (pixel clock) is
+	 * retrieved (clock_display).
+	 */
+}
+
+/* Init PLLD clock source. */
+int
+clock_display(u32 frequency)
+{
+	/**
+	 * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz
+	 *           = (cf * n) >> p, where 1MHz < cf < 6MHz
+	 *           = ((ref / m) * n) >> p
+	 *
+	 * Iterate the possible values of p (3 bits, 2^7) to find out a minimum
+	 * safe vco, then find best (m, n). since m has only 5 bits, we can
+	 * iterate all possible values.  Note Tegra 124 supports 11 bits for n,
+	 * but our pll_fields has only 10 bits for n.
+	 *
+	 * Note values undershoot or overshoot target output frequency may not
+	 * work if the values are not in "safe" range by panel specification.
+	 */
+	struct pllpad_dividers plld = { 0 };
+	u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0;
+	u32 cf, vco;
+	u32 diff, best_diff;
+	const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3,
+		  mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz,
+		  min_cf = 1 * mhz, max_cf = 6 * mhz;
+
+	for (vco = frequency; vco < min_vco && p < max_p; p++)
+		vco <<= 1;
+
+	if (vco < min_vco || vco > max_vco) {
+		printk(BIOS_ERR, "%s: Cannot find out a supported VCO"
+			" for Frequency (%u).\n", __func__, frequency);
+		return -1;
+	}
+
+	plld.p = p;
+	best_diff = vco;
+
+	for (m = 1; m < max_m && best_diff; m++) {
+		cf = ref / m;
+		if (cf < min_cf)
+			break;
+		if (cf > max_cf)
+			continue;
+
+		n = vco / cf;
+		if (n >= max_n)
+			continue;
+
+		diff = vco - n * cf;
+		if (n + 1 < max_n && diff > cf / 2) {
+			n++;
+			diff = cf - diff;
+		}
+
+		if (diff >= best_diff)
+			continue;
+
+		best_diff = diff;
+		plld.m = m;
+		plld.n = n;
+	}
+
+	if (plld.n < 50)
+		plld.cpcon = 2;
+	else if (plld.n < 300)
+		plld.cpcon = 3;
+	else if (plld.n < 600)
+		plld.cpcon = 8;
+	else
+		plld.cpcon = 12;
+
+	if (best_diff) {
+		printk(BIOS_ERR, "%s: Failed to match output frequency %u, "
+		       "best difference is %u.\n", __func__, frequency,
+		       best_diff);
+	}
+
+	printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n",
+	       __func__, (ref / plld.m * plld.n) >> plld.p, ref, plld.m, plld.n,
+	       plld.p, plld.cpcon);
+
+	init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, plld,
+		 (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE));
+	return 0;
+}
+
+/* Initialize the UART and put it on CLK_M so we can use it during clock_init().
+ * Will later move it to PLLP in clock_config(). The divisor must be very small
+ * to accomodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1
+ * CLK_SOURCE divider to get more precision. (This might still not be enough for
+ * some OSCs... if you use 13KHz, be prepared to have a bad time.) The 1900 has
+ * been determined through trial and error (must lead to div 13 at 24MHz). */
+void clock_early_uart(void)
+{
+	write32(CLK_M << CLK_SOURCE_SHIFT | CLK_UART_DIV_OVERRIDE |
+		CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900), &clk_rst->clk_src_uarta);
+	setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_UARTA);
+	udelay(2);
+	clrbits_le32(&clk_rst->rst_dev_l, CLK_L_UARTA);
+}
+
+/* Enable output clock (CLK1~3) for external peripherals. */
+void clock_external_output(int clk_id)
+{
+	switch (clk_id) {
+	case 1:
+		setbits_le32(&pmc->clk_out_cntrl, 1 << 2);
+		break;
+	case 2:
+		setbits_le32(&pmc->clk_out_cntrl, 1 << 10);
+		break;
+	case 3:
+		setbits_le32(&pmc->clk_out_cntrl, 1 << 18);
+		break;
+	default:
+		printk(BIOS_CRIT, "ERROR: Unknown output clock id %d\n",
+		       clk_id);
+		break;
+	}
+}
+
+/* Start PLLM for SDRAM. */
+void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
+		 u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source,
+		 u32 same_freq)
+{
+	u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) |
+		     (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) |
+		     (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) |
+		     (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)),
+	    misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) |
+		     (kcp << PLLM_MISC2_KCP_SHIFT)),
+	    base;
+
+	if (same_freq)
+		emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
+	else
+		emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
+
+	/*
+	 * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and
+	 * PLLM_BASE.ENABLE must be in DISABLE state (both are the default
+	 * values after coldboot reset).
+	 */
+
+	writel(misc1, &clk_rst->pllm_misc1);
+	writel(misc2, &clk_rst->pllm_misc2);
+
+	/* PLLM.BASE needs BYPASS=0, different from general init_pll */
+	base = readl(&clk_rst->pllm_base);
+	base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK |
+		  PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS);
+	base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) |
+		 (p << PLL_BASE_DIVP_SHIFT));
+	writel(base, &clk_rst->pllm_base);
+
+	setbits_le32(&clk_rst->pllm_base, PLL_BASE_ENABLE);
+	/* stable_time is required, before we can start to check lock. */
+	udelay(stable_time);
+
+	while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) {
+		udelay(1);
+	}
+	/*
+	 * After PLLM reports being locked, we have to delay 10us before
+	 * enabling PLLM_OUT.
+	 */
+	udelay(10);
+
+	/* Put OUT1 out of reset state (start to output). */
+	setbits_le32(&clk_rst->pllm_out, PLLM_OUT1_RSTN_RESET_DISABLE);
+
+	/* Enable and start MEM(MC) and EMC. */
+	clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0);
+	writel(emc_source, &clk_rst->clk_src_emc);
+	udelay(IO_STABILIZATION_DELAY);
+}
+
+void clock_cpu0_config_and_reset(void *entry)
+{
+	void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100;
+
+	write32(CONFIG_STACK_TOP, &maincpu_stack_pointer);
+	write32((uintptr_t)entry, &maincpu_entry_point);
+	write32((uintptr_t)&maincpu_setup, evp_cpu_reset);
+
+	/* Set active CPU cluster to G */
+	clrbits_le32(&flow->cluster_control, 1);
+
+	// Set up cclk_brst and divider.
+	write32((CRC_CCLK_BRST_POL_PLLX_OUT0 << 0) |
+		(CRC_CCLK_BRST_POL_PLLX_OUT0 << 4) |
+		(CRC_CCLK_BRST_POL_PLLX_OUT0 << 8) |
+		(CRC_CCLK_BRST_POL_PLLX_OUT0 << 12) |
+		(CRC_CCLK_BRST_POL_CPU_STATE_RUN << 28),
+		&clk_rst->cclk_brst_pol);
+	write32(CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB,
+		&clk_rst->super_cclk_div);
+
+	// Enable the clocks for CPUs 0-3.
+	uint32_t cpu_cmplx_clr = read32(&clk_rst->clk_cpu_cmplx_clr);
+	cpu_cmplx_clr |= CRC_CLK_CLR_CPU0_STP | CRC_CLK_CLR_CPU1_STP |
+			 CRC_CLK_CLR_CPU2_STP | CRC_CLK_CLR_CPU3_STP;
+	write32(cpu_cmplx_clr, &clk_rst->clk_cpu_cmplx_clr);
+
+	// Enable other CPU related clocks.
+	setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU);
+	setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG);
+	setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP);
+
+	// Disable the reset on the non-CPU parts of the fast cluster.
+	write32(CRC_RST_CPUG_CLR_NONCPU,
+		&clk_rst->rst_cpug_cmplx_clr);
+	// Disable the various resets on the CPUs.
+	write32(CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_CPU1 |
+		CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_CPU3 |
+		CRC_RST_CPUG_CLR_DBG0 | CRC_RST_CPUG_CLR_DBG1 |
+		CRC_RST_CPUG_CLR_DBG2 | CRC_RST_CPUG_CLR_DBG3 |
+		CRC_RST_CPUG_CLR_CORE0 | CRC_RST_CPUG_CLR_CORE1 |
+		CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CORE3 |
+		CRC_RST_CPUG_CLR_CX0 | CRC_RST_CPUG_CLR_CX1 |
+		CRC_RST_CPUG_CLR_CX2 | CRC_RST_CPUG_CLR_CX3 |
+		CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG,
+		&clk_rst->rst_cpug_cmplx_clr);
+
+	// Disable the reset on the non-CPU parts of the slow cluster.
+	write32(CRC_RST_CPULP_CLR_NONCPU,
+		&clk_rst->rst_cpulp_cmplx_clr);
+	// Disable the various resets on the LP CPU.
+	write32(CRC_RST_CPULP_CLR_CPU0 | CRC_RST_CPULP_CLR_DBG0 |
+		CRC_RST_CPULP_CLR_CORE0 | CRC_RST_CPULP_CLR_CX0 |
+		CRC_RST_CPULP_CLR_L2 | CRC_RST_CPULP_CLR_PDBG,
+		&clk_rst->rst_cpulp_cmplx_clr);
+}
+
+void clock_halt_avp(void)
+{
+	for (;;) {
+		write32(FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ |
+			FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT,
+			&flow->halt_cop_events);
+	}
+}
+
+void clock_init(void)
+{
+	u32 osc = clock_get_osc_bits();
+
+	/* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */
+	writel(0x2b << 17 | 0xb << 9, &clk_rst->pllc_misc2);
+
+	/* Max out the AVP clock before everything else (need PLLC for that). */
+	init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc,
+		osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE);
+
+	/* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA
+	 * features section in the TRM). */
+	write32(1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT,
+		&clk_rst->clk_sys_rate);	/* pclk = hclk = sclk/2 */
+	write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT |
+		PLL_OUT_CLKEN | PLL_OUT_RSTN, &clk_rst->pllc_out);
+	write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT |
+		SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT,
+		&clk_rst->sclk_brst_pol);		/* sclk = 300 MHz */
+
+	/* Change the oscillator drive strength (from U-Boot -- why?) */
+	clrsetbits_le32(&clk_rst->osc_ctrl, OSC_XOFS_MASK,
+			OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT);
+
+	/*
+	 * Ambiguous quote from u-boot. TODO: what's this mean?
+	 * "should update same value in PMC_OSC_EDPD_OVER XOFS
+	 * field for warmboot "
+	 */
+	clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK,
+			OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT);
+
+	/* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */
+	clrbits_le32(&clk_rst->pllx_misc3, PLLX_IDDQ_MASK);
+
+	/* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */
+	write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT |
+		 PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT |
+		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT |
+		 PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT,
+		&clk_rst->pllp_outa);
+	write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT |
+		 PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT |
+		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT |
+		 PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT,
+		&clk_rst->pllp_outb);
+
+	/* init pllx */
+	init_pll(&clk_rst->pllx_base, &clk_rst->pllx_misc,
+		osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE);
+
+	/* init pllu */
+	init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc,
+		osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE);
+
+	init_utmip_pll();
+	graphics_pll();
+}
+
+void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x)
+{
+	if (l) writel(l, &clk_rst->clk_enb_l_set);
+	if (h) writel(h, &clk_rst->clk_enb_h_set);
+	if (u) writel(u, &clk_rst->clk_enb_u_set);
+	if (v) writel(v, &clk_rst->clk_enb_v_set);
+	if (w) writel(w, &clk_rst->clk_enb_w_set);
+	if (x) writel(x, &clk_rst->clk_enb_x_set);
+
+	/* Give clocks time to stabilize. */
+	udelay(IO_STABILIZATION_DELAY);
+
+	if (l) writel(l, &clk_rst->rst_dev_l_clr);
+	if (h) writel(h, &clk_rst->rst_dev_h_clr);
+	if (u) writel(u, &clk_rst->rst_dev_u_clr);
+	if (v) writel(v, &clk_rst->rst_dev_v_clr);
+	if (w) writel(w, &clk_rst->rst_dev_w_clr);
+	if (x) writel(x, &clk_rst->rst_dev_x_clr);
+}
+
+void clock_reset_l(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_l_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_l_clr);
+}
+
+void clock_reset_h(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_h_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_h_clr);
+}
+
+void clock_reset_u(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_u_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_u_clr);
+}
+
+void clock_reset_v(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_v_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_v_clr);
+}
+
+void clock_reset_w(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_w_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_w_clr);
+}
+
+void clock_reset_x(u32 bit)
+{
+	writel(bit, &clk_rst->rst_dev_x_set);
+	udelay(1);
+	writel(bit, &clk_rst->rst_dev_x_clr);
+}
diff --git a/src/soc/nvidia/tegra132/flow.h b/src/soc/nvidia/tegra132/flow.h
new file mode 100644
index 0000000..01dbc14
--- /dev/null
+++ b/src/soc/nvidia/tegra132/flow.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TEGRA132_FLOW_H_
+#define _TEGRA132_FLOW_H_
+
+struct flow_ctlr {
+	u32 halt_cpu_events;	/* offset 0x00 */
+	u32 halt_cop_events;	/* offset 0x04 */
+	u32 cpu_csr;		/* offset 0x08 */
+	u32 cop_csr;		/* offset 0x0c */
+	u32 xrq_events;		/* offset 0x10 */
+	u32 halt_cpu1_events;	/* offset 0x14 */
+	u32 cpu1_csr;		/* offset 0x18 */
+	u32 halt_cpu2_events;	/* offset 0x1c */
+	u32 cpu2_csr;		/* offset 0x20 */
+	u32 halt_cpu3_events;	/* offset 0x24 */
+	u32 cpu3_csr;		/* offset 0x28 */
+	u32 cluster_control;	/* offset 0x2c */
+	u32 halt_cop1_events;	/* offset 0x30 */
+	u32 halt_cop1_csr;	/* offset 0x34 */
+	u32 cpu_pwr_csr;	/* offset 0x38 */
+	u32 mpid;		/* offset 0x3c */
+	u32 ram_repair;		/* offset 0x40 */
+};
+check_member(flow_ctlr, ram_repair, 0x40);
+
+enum {
+	FLOW_MODE_SHIFT = 29,
+	FLOW_MODE_MASK = 0x7 << FLOW_MODE_SHIFT,
+
+	FLOW_MODE_NONE = 0 << FLOW_MODE_SHIFT,
+	FLOW_MODE_RUN_AND_INT = 1 << FLOW_MODE_SHIFT,
+	FLOW_MODE_WAITEVENT = 2 << FLOW_MODE_SHIFT,
+	FLOW_MODE_WAITEVENT_AND_INT = 3 << FLOW_MODE_SHIFT,
+	FLOW_MODE_STOP_UNTIL_IRQ = 4 << FLOW_MODE_SHIFT,
+	FLOW_MODE_STOP_UNTIL_IRQ_AND_INT = 5 << FLOW_MODE_SHIFT,
+	FLOW_MODE_STOP_UNTIL_EVENT_AND_IRQ = 6 << FLOW_MODE_SHIFT,
+};
+
+/* HALT_COP_EVENTS_0, 0x04 */
+enum {
+	FLOW_EVENT_GIC_FIQ = 1 << 8,
+	FLOW_EVENT_GIC_IRQ = 1 << 9,
+	FLOW_EVENT_LIC_FIQ = 1 << 10,
+	FLOW_EVENT_LIC_IRQ = 1 << 11,
+	FLOW_EVENT_IBF = 1 << 12,
+	FLOW_EVENT_IBE = 1 << 13,
+	FLOW_EVENT_OBF = 1 << 14,
+	FLOW_EVENT_OBE = 1 << 15,
+	FLOW_EVENT_XRQ_A = 1 << 16,
+	FLOW_EVENT_XRQ_B = 1 << 17,
+	FLOW_EVENT_XRQ_C = 1 << 18,
+	FLOW_EVENT_XRQ_D = 1 << 19,
+	FLOW_EVENT_SMP30 = 1 << 20,
+	FLOW_EVENT_SMP31 = 1 << 21,
+	FLOW_EVENT_X_RDY = 1 << 22,
+	FLOW_EVENT_SEC = 1 << 23,
+	FLOW_EVENT_MSEC = 1 << 24,
+	FLOW_EVENT_USEC = 1 << 25,
+	FLOW_EVENT_X32K = 1 << 26,
+	FLOW_EVENT_SCLK = 1 << 27,
+	FLOW_EVENT_JTAG = 1 << 28
+};
+
+#endif	/*  _TEGRA132_FLOW_H_ */
diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h
index 5fc10c3..6f69fef 100644
--- a/src/soc/nvidia/tegra132/include/soc/clock.h
+++ b/src/soc/nvidia/tegra132/include/soc/clock.h
@@ -18,7 +18,12 @@
 #ifndef __SOC_NVIDIA_TEGRA132_CLOCK_H__
 #define __SOC_NVIDIA_TEGRA132_CLOCK_H__
 
+#include <arch/hlt.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <soc/nvidia/tegra132/clk_rst.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 enum {
 	CLK_L_CPU = 0x1 << 0,
@@ -174,6 +179,7 @@ enum {
 #define CLOCK_PLL_STABLE_DELAY_US 300
 
 #define IO_STABILIZATION_DELAY (2)
+
 /* Calculate clock fractional divider value from ref and target frequencies.
  * This is for a U7.1 format. This is not well written up in the book and
  * there have been some questions about this macro, so here we go.
@@ -195,7 +201,7 @@ enum {
  * and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you
  * will assign this to a u8, it gets nicely truncated for you.
  */
-#define CLK_DIVIDER(REF, FREQ)	((((REF) * 2) / (FREQ)) - 2)
+#define CLK_DIVIDER(REF, FREQ)	(div_round_up(((REF) * 2), (FREQ)) - 2)
 
 /* Calculate clock frequency value from reference and clock divider value
  * The discussion in the book is pretty lacking.
@@ -216,11 +222,23 @@ enum {
  */
 #define CLK_FREQUENCY(REF, REG)	(((REF) * 2) / ((REG) + 2))
 
+static inline void _clock_set_div(u32 *reg, const char *name, u32 div,
+				  u32 div_mask, u32 src)
+{
+	// The I2C and UART divisors are 16 bit while all the others are 8 bit.
+	// The I2C clocks are handled by the specialized macro below, but the
+	// UART clocks aren't. Don't use this function on UART clocks.
+	if (div & ~div_mask) {
+		printk(BIOS_ERR, "%s clock divisor overflow!", name);
+		hlt();
+	}
+	clrsetbits_le32(reg, CLK_SOURCE_MASK | CLK_DIVISOR_MASK,
+			src << CLK_SOURCE_SHIFT | div);
+}
+
 #define clock_configure_irregular_source(device, src, freq, src_id) \
-	clrsetbits_le32(&clk_rst->clk_src_##device, \
-		CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \
-		src_id << CLK_SOURCE_SHIFT | \
-		CLK_DIVIDER(TEGRA_##src##_KHZ, freq))
+	_clock_set_div(&clk_rst->clk_src_##device, #device, \
+		CLK_DIVIDER(TEGRA_##src##_KHZ, freq), 0xff, src_id)
 
 /* Warning: Some devices just use different bits for the same sources for no
  * apparent reason. *Always* double-check the TRM before trusting this macro. */
@@ -232,11 +250,12 @@ enum {
  * We can deal with those here and make it easier to select what the actual
  * bus frequency will be. The 0x19 value is the default divisor in the
  * clk_divisor register in the controller, and 8 is just a magic number in the
- * documentation. Multiplying by 2 compensates for the different format of the
- * divisor.
+ * documentation.
  */
 #define clock_configure_i2c_scl_freq(device, src, freq) \
-	clock_configure_source(device, src, (freq) * (0x19 + 1) * 8 * 2)
+	_clock_set_div(&clk_rst->clk_src_##device, #device, \
+		div_round_up(TEGRA_##src##_KHZ, (freq) * (0x19 + 1) * 8) - 1, \
+		0xffff, src)
 
 enum clock_source {  /* Careful: Not true for all sources, always check TRM! */
 	PLLP = 0,
@@ -259,6 +278,8 @@ enum clock_source {  /* Careful: Not true for all sources, always check TRM! */
 #define TEGRA_PLLU_KHZ   (960000)
 
 int clock_get_osc_khz(void);
+int clock_get_pll_input_khz(void);
+int clock_display(u32 frequency);
 void clock_early_uart(void);
 void clock_external_output(int clk_id);
 void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
@@ -267,6 +288,12 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
 void clock_cpu0_config_and_reset(void * entry);
 void clock_halt_avp(void);
 void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x);
+void clock_reset_l(u32 l);
+void clock_reset_h(u32 h);
+void clock_reset_u(u32 u);
+void clock_reset_v(u32 v);
+void clock_reset_w(u32 w);
+void clock_reset_x(u32 x);
 void clock_init(void);
 void clock_init_arm_generic_timer(void);
 void sor_clock_stop(void);
diff --git a/src/soc/nvidia/tegra132/maincpu.S b/src/soc/nvidia/tegra132/maincpu.S
new file mode 100644
index 0000000..898d821
--- /dev/null
+++ b/src/soc/nvidia/tegra132/maincpu.S
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <arch/asm.h>
+
+ENTRY(maincpu_setup)
+	/*
+	 * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data
+	 * aborts may happen early and crash before the abort handlers are
+	 * installed, but at least the problem will show up near the code that
+	 * causes it.
+	 */
+	msr	cpsr, #0xdf
+
+	ldr	sp, maincpu_stack_pointer
+	eor	lr, lr
+	ldr	r0, maincpu_entry_point
+	bx	r0
+ENDPROC(maincpu_setup)
+
+	.align 2
+
+	.global maincpu_stack_pointer
+maincpu_stack_pointer:
+	.word 0
+
+	.global maincpu_entry_point
+maincpu_entry_point:
+	.word 0
diff --git a/src/soc/nvidia/tegra132/maincpu.h b/src/soc/nvidia/tegra132/maincpu.h
new file mode 100644
index 0000000..1f795df
--- /dev/null
+++ b/src/soc/nvidia/tegra132/maincpu.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_NVIDIA_TEGRA132_MAINCPU_H__
+#define __SOC_NVIDIA_TEGRA132_MAINCPU_H__
+
+#include <stdint.h>
+
+extern u32 maincpu_stack_pointer;
+extern u32 maincpu_entry_point;
+void maincpu_setup(void);
+
+#endif	/* __SOC_NVIDIA_TEGRA132_MAINCPU_H__ */
diff --git a/src/soc/nvidia/tegra132/pinmux.h b/src/soc/nvidia/tegra132/pinmux.h
new file mode 100644
index 0000000..2bed253
--- /dev/null
+++ b/src/soc/nvidia/tegra132/pinmux.h
@@ -0,0 +1,260 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_NVIDIA_TEGRA132_PINMUX_H__
+#define __SOC_NVIDIA_TEGRA132_PINMUX_H__
+
+#include <soc/nvidia/tegra/pinmux.h>
+#include <stdint.h>
+
+#define PINMUX_CONSTANTS(index, name, gpio, func0, func1, func2, func3) \
+	PINMUX_##name##_INDEX = index, \
+	PINMUX_##name##_FUNC_##func0 = 0, \
+	PINMUX_##name##_FUNC_##func1 = 1, \
+	PINMUX_##name##_FUNC_##func2 = 2, \
+	PINMUX_##name##_FUNC_##func3 = 3, \
+	PINMUX_GPIO_##gpio = PINMUX_##name##_INDEX
+
+enum {
+	PINMUX_CONSTANTS(0, ULPI_DATA0, O1, SPI3, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(1, ULPI_DATA1, O2, SPI3, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(2, ULPI_DATA2, O3, SPI3, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(3, ULPI_DATA3, O4, SPI3, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(4, ULPI_DATA4, O5, SPI2, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(5, ULPI_DATA5, O6, SPI2, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(6, ULPI_DATA6, O7, SPI2, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(7, ULPI_DATA7, O0, SPI2, HSI, UA3, ULPI),
+	PINMUX_CONSTANTS(8, ULPI_CLK, Y0, SPI1, SPI5, UD3, ULPI),
+	PINMUX_CONSTANTS(9, ULPI_DIR, Y1, SPI1, SPI5, UD3, ULPI),
+	PINMUX_CONSTANTS(10, ULPI_NXT, Y2, SPI1, SPI5, UD3, ULPI),
+	PINMUX_CONSTANTS(11, ULPI_STP, Y3, SPI1, SPI5, UD3, ULPI),
+	PINMUX_CONSTANTS(12, DAP3_FS, P0, I2S2, SPI5, DCA, DCB),
+	PINMUX_CONSTANTS(13, DAP3_DIN, P1, I2S2, SPI5, DCA, DCB),
+	PINMUX_CONSTANTS(14, DAP3_DOUT, P2, I2S2, SPI5, DCA, RES3),
+	PINMUX_CONSTANTS(15, DAP3_SCLK, P3, I2S2, SPI5, RES2, DCB),
+	PINMUX_CONSTANTS(16, GPIO_PV0, V0, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(17, GPIO_PV1, V1, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(18, SDMMC1_CLK, Z0, SDMMC1, CLK12M, RES2, RES3),
+	PINMUX_CONSTANTS(19, SDMMC1_CMD, Z1, SDMMC1, SPDIF, SPI4, UA3),
+	PINMUX_CONSTANTS(20, SDMMC1_DAT3, Y4, SDMMC1, SPDIF, SPI4, UA3),
+	PINMUX_CONSTANTS(21, SDMMC1_DAT2, Y5, SDMMC1, PWM0, SPI4, UA3),
+	PINMUX_CONSTANTS(22, SDMMC1_DAT1, Y6, SDMMC1, PWM1, SPI4, UA3),
+	PINMUX_CONSTANTS(23, SDMMC1_DAT0, Y7, SDMMC1, RES1, SPI4, UA3),
+	PINMUX_CONSTANTS(26, CLK2_OUT, W5, EXTPERIPH2, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(27, CLK2_REQ, CC5, DAP, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(68, HDMI_INT, N7, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(69, DDC_SCL, V4, I2C4, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(70, DDC_SDA, V5, I2C4, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(89, UART2_RXD, C3, IR3, SPDIF, UA3, SPI4),
+	PINMUX_CONSTANTS(90, UART2_TXD, C2, IR3, SPDIF, UA3, SPI4),
+	PINMUX_CONSTANTS(91, UART2_RTS_N, J6, UA3, UB3, NOR, SPI4),
+	PINMUX_CONSTANTS(92, UART2_CTS_N, J5, UA3, UB3, NOR, SPI4),
+	PINMUX_CONSTANTS(93, UART3_TXD, W6, UC3, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(94, UART3_RXD, W7, UC3, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(95, UART3_CTS_N, A1, UC3, SDMMC1, DTV, NOR),
+	PINMUX_CONSTANTS(96, UART3_RTS_N, C0, UC3, PWM0, DTV, NOR),
+	PINMUX_CONSTANTS(97, GPIO_PU0, U0, OWR, UA3, NOR, RES3),
+	PINMUX_CONSTANTS(98, GPIO_PU1, U1, RES0, UA3, NOR, RES3),
+	PINMUX_CONSTANTS(99, GPIO_PU2, U2, RES0, UA3, NOR, RES3),
+	PINMUX_CONSTANTS(100, GPIO_PU3, U3, PWM0, UA3, NOR, DCB),
+	PINMUX_CONSTANTS(101, GPIO_PU4, U4, PWM1, UA3, NOR, DCB),
+	PINMUX_CONSTANTS(102, GPIO_PU5, U5, PWM2, UA3, NOR, DCB),
+	PINMUX_CONSTANTS(103, GPIO_PU6, U6, PWM3, UA3, RES2, NOR),
+	PINMUX_CONSTANTS(104, GEN1_I2C_SDA, C5, I2C1, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(105, GEN1_I2C_SCL, C4, I2C1, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(106, DAP4_FS, P4, I2S3, NOR, DTV, RES3),
+	PINMUX_CONSTANTS(107, DAP4_DIN, P5, I2S3, NOR, RES2, RES3),
+	PINMUX_CONSTANTS(108, DAP4_DOUT, P6, I2S3, NOR, DTV, RES3),
+	PINMUX_CONSTANTS(109, DAP4_SCLK, P7, I2S3, NOR, RES2, RES3),
+	PINMUX_CONSTANTS(110, CLK3_OUT, EE0, EXTPERIPH3, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(111, CLK3_REQ, EE1, DEV3, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(112, GPIO_PC7, C7, RES0, RES1, NOR_WP_N, NOR_INT1),
+	PINMUX_CONSTANTS(113, GPIO_PI5, I5, SDMMC2, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(114, GPIO_PI7, I7, RES0, TRACE, NOR, DTV),
+	PINMUX_CONSTANTS(115, GPIO_PK0, K0, RES0, SDMMC3, NOR, SOC_THERM),
+	PINMUX_CONSTANTS(116, GPIO_PK1, K1, SDMMC2, TRACE, NOR, RES3),
+	PINMUX_CONSTANTS(117, GPIO_PJ0, J0, RES0, RES1, NOR, USB),
+	PINMUX_CONSTANTS(118, GPIO_PJ2, J2, RES0, RES1, NOR, SOC_THERM),
+	PINMUX_CONSTANTS(119, GPIO_PK3, K3, SDMMC2, TRACE, NOR, CCLA),
+	PINMUX_CONSTANTS(120, GPIO_PK4, K4, SDMMC2, RES1, NOR_AD22, NOR_INT1),
+	PINMUX_CONSTANTS(121, GPIO_PK2, K2, RES0, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(122, GPIO_PI3, I3, RES0, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(123, GPIO_PI6, I6, RES0, RES1, NOR, SDMMC2),
+	PINMUX_CONSTANTS(124, GPIO_PG0, G0, RES0, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(125, GPIO_PG1, G1, RES0, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(126, GPIO_PG2, G2, RES0, TRACE, NOR, RES3),
+	PINMUX_CONSTANTS(127, GPIO_PG3, G3, RES0, TRACE, NOR, RES3),
+	PINMUX_CONSTANTS(128, GPIO_PG4, G4, RES0, TMDS, NOR, SPI4),
+	PINMUX_CONSTANTS(129, GPIO_PG5, G5, RES0, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(130, GPIO_PG6, G6, RES0, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(131, GPIO_PG7, G7, RES0, RES1, NOR, SPI4),
+	PINMUX_CONSTANTS(132, GPIO_PH0, H0, PWM0, TRACE, NOR, DTV),
+	PINMUX_CONSTANTS(133, GPIO_PH1, H1, PWM1, TMDS, NOR, DCA),
+	PINMUX_CONSTANTS(134, GPIO_PH2, H2, PWM2, TDMS, NOR, CLDVFS),
+	PINMUX_CONSTANTS(135, GPIO_PH3, H3, PWM3, SPI4, NOR, CLDVFS),
+	PINMUX_CONSTANTS(136, GPIO_PH4, H4, SDMMC2, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(137, GPIO_PH5, H5, SDMMC2, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(138, GPIO_PH6, H6, SDMMC2, TRACE, NOR, DTV),
+	PINMUX_CONSTANTS(139, GPIO_PH7, H7, SDMMC2, TRACE, NOR, DTV),
+	PINMUX_CONSTANTS(140, GPIO_PJ7, J7, UD3, RES1, NOR_AD16, NOR_INT2),
+	PINMUX_CONSTANTS(141, GPIO_PB0, B0, UD3, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(142, GPIO_PB1, B1, UD3, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(143, GPIO_PK7, K7, UD3, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(144, GPIO_PI0, I0, RES0, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(145, GPIO_PI1, I1, RES0, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(146, GPIO_PI2, I2, SDMMC2, TRACE, NOR, RES3),
+	PINMUX_CONSTANTS(147, GPIO_PI4, I4, SPI4, TRACE, NOR, DCA),
+	PINMUX_CONSTANTS(148, GEN2_I2C_SCL, T5, I2C2, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(149, GEN2_I2C_SDA, T6, I2C2, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(150, SDMMC4_CLK, CC4, SDMMC4, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(151, SDMMC4_CMD, T7, SDMMC4, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(152, SDMMC4_DAT0, AA0, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(153, SDMMC4_DAT1, AA1, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(154, SDMMC4_DAT2, AA2, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(155, SDMMC4_DAT3, AA3, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(156, SDMMC4_DAT4, AA4, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(157, SDMMC4_DAT5, AA5, SDMMC4, SPI3, RES2, RES3),
+	PINMUX_CONSTANTS(158, SDMMC4_DAT6, AA6, SDMMC4, SPI3, NOR, RES3),
+	PINMUX_CONSTANTS(159, SDMMC4_DAT7, AA7, SDMMC4, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(161, CAM_MCLK, CC0, VIMCLK_PRI, VIMCLK_ALT1,
+			 VIMCLK_ALT3, SDMMC2),
+	PINMUX_CONSTANTS(162, GPIO_PCC1, CC1, I2S4, RES1, RES2, SDMMC2),
+	PINMUX_CONSTANTS(163, GPIO_PBB0, BB0, VGP6, VIMCLK2_PRI, SDMMC2,
+			 VIMCLK2_ALT3),
+	PINMUX_CONSTANTS(164, CAM_I2C_SCL, BB1, VGP1, I2C3, RES2, SDMMC2),
+	PINMUX_CONSTANTS(165, CAM_I2C_SDA, BB2, VGP2, I2C3, RES2, SDMMC2),
+	PINMUX_CONSTANTS(166, GPIO_PBB3, BB3, VGP3, DCA, DCB, SDMMC2),
+	PINMUX_CONSTANTS(167, GPIO_PBB4, BB4, VGP4, DCA, DCB, SDMMC2),
+	PINMUX_CONSTANTS(168, GPIO_PBB5, BB5, VGP5, DCA, RES2, SDMMC2),
+	PINMUX_CONSTANTS(169, GPIO_PBB6, BB6, I2S4, RES1, DCB, SDMMC2),
+	PINMUX_CONSTANTS(170, GPIO_PBB7, BB7, I2S4, RES1, RES2, SDMMC2),
+	PINMUX_CONSTANTS(171, GPIO_PCC2, CC2, I2S4, RES1, SDMMC3, SDMMC2),
+	PINMUX_CONSTANTS(172, JTAG_RTCK, NONE172, RTCK, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(173, PWR_I2C_SCL, Z6, I2CPMU, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(174, PWR_I2C_SDA, Z7, I2CPMU, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(175, KB_ROW0, R0, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(176, KB_ROW1, R1, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(177, KB_ROW2, R2, RES0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(178, KB_ROW3, R3, RES0, DCA, SYS_CLK, DCB),
+	PINMUX_CONSTANTS(179, KB_ROW4, R4, RES0, DCA, RES2, DCB),
+	PINMUX_CONSTANTS(180, KB_ROW5, R5, RES0, DCA, RES2, DCB),
+	PINMUX_CONSTANTS(181, KB_ROW6, R6, RES0, DCA_LSC0, DCA_LSPII, DCB),
+	PINMUX_CONSTANTS(182, KB_ROW7, R7, RES0, RES1, CLDVFS, UA3),
+	PINMUX_CONSTANTS(183, KB_ROW8, S0, RES0, RES1, CLDVFS, UA3),
+	PINMUX_CONSTANTS(184, KB_ROW9, S1, RES0, RES1, RES2, UA3),
+	PINMUX_CONSTANTS(185, KB_ROW10, S2, RES0, RES1, RES2, UA3),
+	PINMUX_CONSTANTS(186, KB_ROW11, S3, RES0, RES1, RES2, IR3),
+	PINMUX_CONSTANTS(187, KB_ROW12, S4, RES0, RES1, RES2, IR3),
+	PINMUX_CONSTANTS(188, KB_ROW13, S5, RES0, RES1, SPI2, RES3),
+	PINMUX_CONSTANTS(189, KB_ROW14, S6, RES0, RES1, SPI2, RES3),
+	PINMUX_CONSTANTS(190, KB_ROW15, S7, RES0, SOC_THERM, RES2, RES3),
+	PINMUX_CONSTANTS(191, KB_COL0, Q0, RES0, RES1, SPI2, RES3),
+	PINMUX_CONSTANTS(192, KB_COL1, Q1, RES0, RES1, SPI2, RES3),
+	PINMUX_CONSTANTS(193, KB_COL2, Q2, RES0, RES1, SPI2, RES3),
+	PINMUX_CONSTANTS(194, KB_COL3, Q3, RES0, DCA, PWM2, UA3),
+	PINMUX_CONSTANTS(195, KB_COL4, Q4, RES0, OWR, SDMMC3, UA3),
+	PINMUX_CONSTANTS(196, KB_COL5, Q5, RES0, RES1, SDMMC3, RES3),
+	PINMUX_CONSTANTS(197, KB_COL6, Q6, RES0, RES1, SPI2, UD3),
+	PINMUX_CONSTANTS(198, KB_COL7, Q7, RES0, RES1, SPI2, UD3),
+	PINMUX_CONSTANTS(199, CLK_32K_OUT, A0, BLINK, SOC_THERM, RES2, RES3),
+	PINMUX_CONSTANTS(201, CORE_PWR_REQ, NONE201, PWRON, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(202, CPU_PWR_REQ, NONE202, CPU, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(203, PWR_INT_N, NONE203, PMICINTR, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(204, CLK_32K_IN, NONE204, CLK_32K_IN, RES1, RES2,
+			 RES3),
+	PINMUX_CONSTANTS(205, OWR, NONE205, OWR, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(206, DAP1_FS, N0, I2S0, DAP1, NOR, RES3),
+	PINMUX_CONSTANTS(207, DAP1_DIN, N1, I2S0, DAP1, NOR, RES3),
+	PINMUX_CONSTANTS(208, DAP1_DOUT, N2, I2S0, DAP1, NOR, SATA),
+	PINMUX_CONSTANTS(209, DAP1_SCLK, N3, I2S0, DAP1, NOR, RES3),
+	PINMUX_CONSTANTS(210, DAP_MCLK1_REQ, EE2, DAP, DAP1, SATA, RES3),
+	PINMUX_CONSTANTS(211, DAP_MCLK1, W4, EXTPERIPH1, DAP2, RES2, RES3),
+	PINMUX_CONSTANTS(212, SPDIF_IN, K6, SPDIF, RES1, RES2, I2C3),
+	PINMUX_CONSTANTS(213, SPDIF_OUT, K5, SPDIF, RES1, RES2, I2C3),
+	PINMUX_CONSTANTS(214, DAP2_FS, A2, I2S1, DAP2, NOR, RES3),
+	PINMUX_CONSTANTS(215, DAP2_DIN, A4, I2S1, DAP2, NOR, RES3),
+	PINMUX_CONSTANTS(216, DAP2_DOUT, A5, I2S1, DAP2, NOR, RES3),
+	PINMUX_CONSTANTS(217, DAP2_SCLK, A3, I2S1, SAP2, NOR, RES3),
+	PINMUX_CONSTANTS(218, DVFS_PWM, X0, SPI6, CLDVFS, NOR, RES3),
+	PINMUX_CONSTANTS(219, GPIO_X1_AUD, X1, SPI6, RES1, NOR, RES3),
+	PINMUX_CONSTANTS(220, GPIO_X3_AUD, X3, SPI6, SPI1, NOR, RES3),
+	PINMUX_CONSTANTS(221, DVFS_CLK, X2, SPI6, CLDVFS_CLK, NOR, RES3),
+	PINMUX_CONSTANTS(222, GPIO_X4_AUD, X4, NOR, SPI1, SPI2, DAP2),
+	PINMUX_CONSTANTS(223, GPIO_X5_AUD, X5, NOR, SPI1, SPI2, RES3),
+	PINMUX_CONSTANTS(224, GPIO_X6_AUD, X6, SPI6, SPI1, SPI2, NOR),
+	PINMUX_CONSTANTS(225, GPIO_X7_AUD, X7, RES0, SPI1, SPI2, RES3),
+	PINMUX_CONSTANTS(228, SDMMC3_CLK, A6, SDMMC3, RES1, RES2, SPI3),
+	PINMUX_CONSTANTS(229, SDMMC3_CMD, A7, SDMMC3, PWM3, UA3, SPI3),
+	PINMUX_CONSTANTS(230, SDMMC3_DAT0, B7, SDMMC3, RES1, RES2, SPI3),
+	PINMUX_CONSTANTS(231, SDMMC3_DAT1, B6, SDMMC3, PWM2, UA3, SPI3),
+	PINMUX_CONSTANTS(232, SDMMC3_DAT2, B5, SDMMC3, PWM1, DCA, SPI3),
+	PINMUX_CONSTANTS(233, SDMMC3_DAT3, B4, SDMMC3, PWM0, DCB, SPI3),
+	PINMUX_CONSTANTS(239, PEX_L0_RST_N, DD1, PE0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(240, PEX_L0_CLKREQ_N, DD2, PE0, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(241, PEX_WAKE_N, DD3, PE, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(243, PEX_L1_RST_N, DD5, PE1, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(244, PEX_L1_CLKREQ_N, DD6, PE1, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(248, HDMI_CEC, EE3, CEC, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(249, SDMMC1_WP_N, V3, SDMMC1, CLK12M, SPI4, UA3),
+	PINMUX_CONSTANTS(250, SDMMC3_CD_N, V2, SDMMC3, OWR, RES2, RES3),
+	PINMUX_CONSTANTS(251, GPIO_W2_AUD, W2, SPI6, RES1, SPI2, I2C1),
+	PINMUX_CONSTANTS(252, GPIO_W3_AUD, W3, SPI6, SPI1, SPI2, I2C1),
+	PINMUX_CONSTANTS(253, USB_VBUS_EN0, N4, USB, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(254, USB_VBUS_EN1, N5, USB, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(255, SDMMC3_CLK_LB_IN, EE5, SDMMC3, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(256, SDMMC3_CLK_LB_OUT, EE4, SDMMC3, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(258, RESET_OUT_N, NONE258, RES0, RES1, RES2, RESET),
+	PINMUX_CONSTANTS(259, KB_ROW16, T0, RES0, RES1, RES2, UC3),
+	PINMUX_CONSTANTS(260, KB_ROW17, T1, RES0, RES1, RES2, UC3),
+	PINMUX_CONSTANTS(261, USB_VBUS_EN2, FF1, USB, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(262, GPIO_PFF2, FF2, SATA, RES1, RES2, RES3),
+	PINMUX_CONSTANTS(268, DP_HPD, FF0, DP, RES1, RES2, RES3),
+
+	// Where do these go?
+	/*
+	PINMUX_JTAG_TRST_N_JTAG_TRST_N = 0,
+
+	PINMUX_JTAG_TDO_JTAG_TDO = 0,
+
+	PINMUX_JTAG_TMS_JTAG_TMS = 0,
+
+	PINMUX_JTAG_TCK_JTAG_TCK = 0,
+	// What do functions 1 and 2 do?
+
+	PINMUX_JTAG_TDI_JTAG_TDI = 0,
+	PINMUX_JTAG_TDI_PWR_BREAK = 1,
+
+	PINMUX_TEST_MODE_EN_TEST_MODE_EN = 0,
+	PINMUX_TEST_MODE_EN_VIMCLK_PRI = 1,
+	PINMUX_TEST_MODE_EN_VIMCLK_ALT1 = 2,
+	PINMUX_TEST_MODE_EN_VIMCLK_ALT3 = 3,
+
+	PINMUX_DP_AUX_CH0_P_I2C_CLK = 0,
+	PINMUX_DP_AUX_CH0_P_SDMMC3_DAT3 = 1,
+	PINMUX_DP_AUX_CH0_P_PM3_PWM0 = 2,
+	PINMUX_DP_AUX_CH0_P_DCB_LPM0 = 3,
+
+	PINMUX_DP_AUX_CH0_N_I2C6_DAT = 0,
+	PINMUX_DP_AUX_CH0_N_SDMMC3_DAT2 = 1,
+	PINMUX_DP_AUX_CH0_N_PM3_PWM1 = 2,
+	PINMUX_DP_AUX_CH0_N_DCA_LPM0 = 3,
+	*/
+};
+
+#endif	/* __SOC_NVIDIA_TEGRA132_PINMUX_H__ */
diff --git a/src/soc/nvidia/tegra132/pmc.h b/src/soc/nvidia/tegra132/pmc.h
new file mode 100644
index 0000000..e9fbcd6
--- /dev/null
+++ b/src/soc/nvidia/tegra132/pmc.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2010 - 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TEGRA132_PMC_H_
+#define _TEGRA132_PMC_H_
+
+#include <stdint.h>
+
+enum {
+	POWER_PARTID_CRAIL = 0,
+	POWER_PARTID_TD = 1,
+	POWER_PARTID_VE = 2,
+	POWER_PARTID_VDE = 4,
+	POWER_PARTID_L2C = 5,
+	POWER_PARTID_MPE = 6,
+	POWER_PARTID_HEG = 7,
+	POWER_PARTID_CE1 = 9,
+	POWER_PARTID_CE2 = 10,
+	POWER_PARTID_CE3 = 11,
+	POWER_PARTID_CELP = 12,
+	POWER_PARTID_CE0 = 14,
+	POWER_PARTID_C0NC = 15,
+	POWER_PARTID_C1NC = 16,
+	POWER_PARTID_DIS = 18,
+	POWER_PARTID_DISB = 19,
+	POWER_PARTID_XUSBA = 20,
+	POWER_PARTID_XUSBB = 21,
+	POWER_PARTID_XUSBC = 22
+};
+
+struct tegra_pmc_regs {
+	u32 cntrl;
+	u32 sec_disable;
+	u32 pmc_swrst;
+	u32 wake_mask;
+	u32 wake_lvl;
+	u32 wake_status;
+	u32 sw_wake_status;
+	u32 dpd_pads_oride;
+	u32 dpd_sample;
+	u32 dpd_enable;
+	u32 pwrgate_timer_off;
+	u32 clamp_status;
+	u32 pwrgate_toggle;
+	u32 remove_clamping_cmd;
+	u32 pwrgate_status;
+	u32 pwrgood_timer;
+	u32 blink_timer;
+	u32 no_iopower;
+	u32 pwr_det;
+	u32 pwr_det_latch;
+	u32 scratch0;
+	u32 scratch1;
+	u32 scratch2;
+	u32 scratch3;
+	u32 scratch4;
+	u32 scratch5;
+	u32 scratch6;
+	u32 scratch7;
+	u32 scratch8;
+	u32 scratch9;
+	u32 scratch10;
+	u32 scratch11;
+	u32 scratch12;
+	u32 scratch13;
+	u32 scratch14;
+	u32 scratch15;
+	u32 scratch16;
+	u32 scratch17;
+	u32 scratch18;
+	u32 scratch19;
+	u32 odmdata;
+	u32 scratch21;
+	u32 scratch22;
+	u32 scratch23;
+	u32 secure_scratch0;
+	u32 secure_scratch1;
+	u32 secure_scratch2;
+	u32 secure_scratch3;
+	u32 secure_scratch4;
+	u32 secure_scratch5;
+	u32 cpupwrgood_timer;
+	u32 cpupwroff_timer;
+	u32 pg_mask;
+	u32 pg_mask_1;
+	u32 auto_wake_lvl;
+	u32 auto_wake_lvl_mask;
+	u32 wake_delay;
+	u32 pwr_det_val;
+	u32 ddr_pwr;
+	u32 usb_debounce_del;
+	u32 usb_a0;
+	u32 crypto_op;
+	u32 pllp_wb0_override;
+	u32 scratch24;
+	u32 scratch25;
+	u32 scratch26;
+	u32 scratch27;
+	u32 scratch28;
+	u32 scratch29;
+	u32 scratch30;
+	u32 scratch31;
+	u32 scratch32;
+	u32 scratch33;
+	u32 scratch34;
+	u32 scratch35;
+	u32 scratch36;
+	u32 scratch37;
+	u32 scratch38;
+	u32 scratch39;
+	u32 scratch40;
+	u32 scratch41;
+	u32 scratch42;
+	u32 bondout_mirror[3];
+	u32 sys_33v_en;
+	u32 bondout_mirror_access;
+	u32 gate;
+	u32 wake2_mask;
+	u32 wake2_lvl;
+	u32 wake2_status;
+	u32 sw_wake2_status;
+	u32 auto_wake2_lvl_mask;
+	u32 pg_mask_2;
+	u32 pg_mask_ce1;
+	u32 pg_mask_ce2;
+	u32 pg_mask_ce3;
+	u32 pwrgate_timer_ce[7];
+	u32 pcx_edpd_cntrl;
+	u32 osc_edpd_over;
+	u32 clk_out_cntrl;
+	u32 sata_pwrgt;
+	u32 sensor_ctrl;
+	u32 rst_status;
+	u32 io_dpd_req;
+	u32 io_dpd_status;
+	u32 io_dpd2_req;
+	u32 io_dpd2_status;
+	u32 sel_dpd_tim;
+	u32 vddp_sel;
+	u32 ddr_cfg;
+	u32 e_no_vttgen;
+	u8 _rsv0[4];
+	u32 pllm_wb0_override_freq;
+	u32 test_pwrgate;
+	u32 pwrgate_timer_mult;
+	u32 dis_sel_dpd;
+	u32 utmip_uhsic_triggers;
+	u32 utmip_uhsic_saved_state;
+	u32 utmip_pad_cfg;
+	u32 utmip_term_pad_cfg;
+	u32 utmip_uhsic_sleep_cfg;
+	u32 utmip_uhsic_sleepwalk_cfg;
+	u32 utmip_sleepwalk_p[3];
+	u32 uhsic_sleepwalk_p0;
+	u32 utmip_uhsic_status;
+	u32 utmip_uhsic_fake;
+	u32 bondout_mirror3[5 - 3];
+	u32 secure_scratch6;
+	u32 secure_scratch7;
+	u32 scratch43;
+	u32 scratch44;
+	u32 scratch45;
+	u32 scratch46;
+	u32 scratch47;
+	u32 scratch48;
+	u32 scratch49;
+	u32 scratch50;
+	u32 scratch51;
+	u32 scratch52;
+	u32 scratch53;
+	u32 scratch54;
+	u32 scratch55;
+	u32 scratch0_eco;
+	u32 por_dpd_ctrl;
+	u32 scratch2_eco;
+	u32 utmip_uhsic_line_wakeup;
+	u32 utmip_bias_master_cntrl;
+	u32 utmip_master_config;
+	u32 td_pwrgate_inter_part_timer;
+	u32 utmip_uhsic2_triggers;
+	u32 utmip_uhsic2_saved_state;
+	u32 utmip_uhsic2_sleep_cfg;
+	u32 utmip_uhsic2_sleepwalk_cfg;
+	u32 uhsic2_sleepwalk_p1;
+	u32 utmip_uhsic2_status;
+	u32 utmip_uhsic2_fake;
+	u32 utmip_uhsic2_line_wakeup;
+	u32 utmip_master2_config;
+	u32 utmip_uhsic_rpd_cfg;
+	u32 pg_mask_ce0;
+	u32 pg_mask3[5 - 3];
+	u32 pllm_wb0_override2;
+	u32 tsc_mult;
+	u32 cpu_vsense_override;
+	u32 glb_amap_cfg;
+	u32 sticky_bits;
+	u32 sec_disable2;
+	u32 weak_bias;
+	u32 reg_short;
+	u32 pg_mask_andor;
+	u8 _rsv1[0x2c];
+	u32 secure_scratch8;
+	u32 secure_scratch9;
+	u32 secure_scratch10;
+	u32 secure_scratch11;
+	u32 secure_scratch12;
+	u32 secure_scratch13;
+	u32 secure_scratch14;
+	u32 secure_scratch15;
+	u32 secure_scratch16;
+	u32 secure_scratch17;
+	u32 secure_scratch18;
+	u32 secure_scratch19;
+	u32 secure_scratch20;
+	u32 secure_scratch21;
+	u32 secure_scratch22;
+	u32 secure_scratch23;
+	u32 secure_scratch24;
+	u32 secure_scratch25;
+	u32 secure_scratch26;
+	u32 secure_scratch27;
+	u32 secure_scratch28;
+	u32 secure_scratch29;
+	u32 secure_scratch30;
+	u32 secure_scratch31;
+	u32 secure_scratch32;
+	u32 secure_scratch33;
+	u32 secure_scratch34;
+	u32 secure_scratch35;
+	u8 _rsv2[0xd0];
+	u32 cntrl2;
+	u8 _rsv3[0x18];
+	u32 io_dpd3_req;
+	u32 io_dqd3_status;
+	u32 strapping_opt_a;
+	u8 _rsv4[0x198];
+	u32 scratch56;
+	u32 scratch57;
+	u32 scratch58;
+	u32 scratch59;
+	u32 scratch60;
+	u32 scratch61;
+	u32 scratch62;
+	u32 scratch63;
+	u32 scratch64;
+	u32 scratch65;
+	u32 scratch66;
+	u32 scratch67;
+	u32 scratch68;
+	u32 scratch69;
+	u32 scratch70;
+	u32 scratch71;
+	u32 scratch72;
+	u32 scratch73;
+	u32 scratch74;
+	u32 scratch75;
+	u32 scratch76;
+	u32 scratch77;
+	u32 scratch78;
+	u32 scratch79;
+	u32 scratch80;
+	u32 scratch81;
+	u32 scratch82;
+	u32 scratch83;
+	u32 scratch84;
+	u32 scratch85;
+	u32 scratch86;
+	u32 scratch87;
+	u32 scratch88;
+	u32 scratch89;
+	u32 scratch90;
+	u32 scratch91;
+	u32 scratch92;
+	u32 scratch93;
+	u32 scratch94;
+	u32 scratch95;
+	u32 scratch96;
+	u32 scratch97;
+	u32 scratch98;
+	u32 scratch99;
+	u32 scratch100;
+	u32 scratch101;
+	u32 scratch102;
+	u32 scratch103;
+	u32 scratch104;
+	u32 scratch105;
+	u32 scratch106;
+	u32 scratch107;
+	u32 scratch108;
+	u32 scratch109;
+	u32 scratch110;
+	u32 scratch111;
+	u32 scratch112;
+	u32 scratch113;
+	u32 scratch114;
+	u32 scratch115;
+	u32 scratch116;
+	u32 scratch117;
+	u32 scratch118;
+	u32 scratch119;
+};
+
+check_member(tegra_pmc_regs, scratch119, 0x6fc);
+
+enum {
+	PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f,
+	PMC_PWRGATE_TOGGLE_PARTID_SHIFT = 0,
+	PMC_PWRGATE_TOGGLE_START = 0x1 << 8
+};
+
+enum {
+	PMC_CNTRL_KBC_CLK_DIS = 0x1 << 0,
+	PMC_CNTRL_RTC_CLK_DIS = 0x1 << 1,
+	PMC_CNTRL_RTC_RST = 0x1 << 2,
+	PMC_CNTRL_KBC_RST = 0x1 << 3,
+	PMC_CNTRL_MAIN_RST = 0x1 << 4,
+	PMC_CNTRL_LATCHWAKE_EN = 0x1 << 5,
+	PMC_CNTRL_GLITCHDET_DIS = 0x1 << 6,
+	PMC_CNTRL_BLINK_EN = 0x1 << 7,
+	PMC_CNTRL_PWRREQ_POLARITY = 0x1 << 8,
+	PMC_CNTRL_PWRREQ_OE = 0x1 << 9,
+	PMC_CNTRL_SYSCLK_POLARITY = 0x1 << 10,
+	PMC_CNTRL_SYSCLK_OE = 0x1 << 11,
+	PMC_CNTRL_PWRGATE_DIS = 0x1 << 12,
+	PMC_CNTRL_AOINIT = 0x1 << 13,
+	PMC_CNTRL_SIDE_EFFECT_LP0 = 0x1 << 14,
+	PMC_CNTRL_CPUPWRREQ_POLARITY = 0x1 << 15,
+	PMC_CNTRL_CPUPWRREQ_OE = 0x1 << 16,
+	PMC_CNTRL_INTR_POLARITY = 0x1 << 17,
+	PMC_CNTRL_FUSE_OVERRIDE = 0x1 << 18,
+	PMC_CNTRL_CPUPWRGOOD_EN = 0x1 << 19,
+	PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT = 20,
+	PMC_CNTRL_CPUPWRGOOD_SEL_MASK =
+		0x3 << PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT
+};
+
+enum {
+	PMC_DDR_PWR_EMMC_MASK = 1 << 1,
+	PMC_DDR_PWR_VAL_MASK = 1 << 0,
+};
+
+enum {
+	PMC_DDR_CFG_PKG_MASK = 1 << 0,
+	PMC_DDR_CFG_IF_MASK = 1 << 1,
+	PMC_DDR_CFG_XM0_RESET_TRI_MASK = 1 << 12,
+	PMC_DDR_CFG_XM0_RESET_DPDIO_MASK = 1 << 13,
+};
+
+enum {
+	PMC_NO_IOPOWER_MEM_MASK = 1 << 7,
+	PMC_NO_IOPOWER_MEM_COMP_MASK = 1 << 16,
+};
+
+enum {
+	PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK = 1 << 0,
+	PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK = 1 << 1,
+	PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK = 1 << 31,
+};
+
+enum {
+	PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12
+};
+
+enum {
+	PMC_OSC_EDPD_OVER_XOFS_SHIFT = 1,
+	PMC_OSC_EDPD_OVER_XOFS_MASK =
+		0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT
+};
+
+enum {
+	PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT = 4,
+	PMC_STRAPPING_OPT_A_RAM_CODE_MASK =
+		0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT,
+};
+
+#endif	/* _TEGRA132_PMC_H_ */
diff --git a/src/soc/nvidia/tegra132/power.h b/src/soc/nvidia/tegra132/power.h
new file mode 100644
index 0000000..9283b55
--- /dev/null
+++ b/src/soc/nvidia/tegra132/power.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_NVIDIA_TEGRA132_POWER_H__
+#define __SOC_NVIDIA_TEGRA132_POWER_H__
+
+// This function does not enable the external power to the rail, it enables
+// the rail itself internal to the SOC.
+void power_enable_cpu_rail(void);
+
+void power_ungate_cpu(void);
+
+#endif	/* __SOC_NVIDIA_TEGRA132_POWER_H__ */
diff --git a/src/soc/nvidia/tegra132/sysctr.h b/src/soc/nvidia/tegra132/sysctr.h
new file mode 100644
index 0000000..ea9746d
--- /dev/null
+++ b/src/soc/nvidia/tegra132/sysctr.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_NVIDIA_TEGRA132_SYSCTR_H__
+#define __SOC_NVIDIA_TEGRA132_SYSCTR_H__
+
+#include <stdint.h>
+
+enum {
+	SYSCTR_CNTCR_EN = 1 << 0,
+	SYSCTR_CNTCR_HDBG = 1 << 1,
+	SYSCTR_CNTCR_FCREQ = 1 << 8
+};
+
+struct sysctr_regs {
+	uint32_t cntcr;
+	uint32_t cntsr;
+	uint32_t cntcv0;
+	uint32_t cntcv1;
+	uint8_t _rsv0[0x10];
+	uint32_t cntfid0;
+	uint32_t cntfid1;
+	uint8_t _rsv1[0xfa8];
+	uint32_t counterid4;
+	uint32_t counterid5;
+	uint32_t counterid6;
+	uint32_t counterid7;
+	uint32_t counterid0;
+	uint32_t counterid1;
+	uint32_t counterid2;
+	uint32_t counterid3;
+	uint32_t counterid8;
+	uint32_t counterid9;
+	uint32_t counterid10;
+	uint32_t counterid11;
+};
+check_member(sysctr_regs, counterid11, 0xffc);
+
+#endif	/* __SOC_NVIDIA_TEGRA132_SYSCTR_H__ */
diff --git a/src/soc/nvidia/tegra132/uart.c b/src/soc/nvidia/tegra132/uart.c
new file mode 100644
index 0000000..80328af
--- /dev/null
+++ b/src/soc/nvidia/tegra132/uart.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/uart.h>
+#include <arch/io.h>
+#include <boot/coreboot_tables.h>
+#include <console/console.h>	/* for __console definition */
+#include <stdint.h>
+#include <drivers/uart/uart8250reg.h>
+
+/*
+ * TODO: Use DRIVERS_UART_8250MEM driver instead.
+ * There is an issue in the IO call functions where x86 and ARM
+ * ordering is reversed. This 8250MEM driver uses the x86 convention.
+ * This driver can be replaced once the IO calls are sorted.
+ */
+struct tegra132_uart {
+	union {
+		uint32_t thr; // Transmit holding register.
+		uint32_t rbr; // Receive buffer register.
+		uint32_t dll; // Divisor latch lsb.
+	};
+	union {
+		uint32_t ier; // Interrupt enable register.
+		uint32_t dlm; // Divisor latch msb.
+	};
+	union {
+		uint32_t iir; // Interrupt identification register.
+		uint32_t fcr; // FIFO control register.
+	};
+	uint32_t lcr; // Line control register.
+	uint32_t mcr; // Modem control register.
+	uint32_t lsr; // Line status register.
+	uint32_t msr; // Modem status register.
+} __attribute__ ((packed));
+
+static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr);
+static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr);
+
+static void tegra132_uart_init(struct tegra132_uart *uart_ptr)
+{
+	const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1
+
+	uint16_t divisor = (u16) uart_baudrate_divisor(default_baudrate(),
+		uart_platform_refclk(), 16);
+
+	tegra132_uart_tx_flush(uart_ptr);
+
+	// Disable interrupts.
+	write8(0, &uart_ptr->ier);
+	// Force DTR and RTS to high.
+	write8(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr);
+	// Set line configuration, access divisor latches.
+	write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr);
+	// Set the divisor.
+	write8(divisor & 0xff, &uart_ptr->dll);
+	write8((divisor >> 8) & 0xff, &uart_ptr->dlm);
+	// Hide the divisor latches.
+	write8(line_config, &uart_ptr->lcr);
+	// Enable FIFOs, and clear receive and transmit.
+	write8(UART8250_FCR_FIFO_EN |
+		UART8250_FCR_CLEAR_RCVR |
+		UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr);
+}
+
+static unsigned char tegra132_uart_rx_byte(struct tegra132_uart *uart_ptr)
+{
+	if (!tegra132_uart_tst_byte(uart_ptr))
+		return 0;
+	return read8(&uart_ptr->rbr);
+}
+
+static void tegra132_uart_tx_byte(struct tegra132_uart *uart_ptr, unsigned char data)
+{
+	while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE));
+	write8(data, &uart_ptr->thr);
+}
+
+static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr)
+{
+	while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT));
+}
+
+static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr)
+{
+	return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR;
+}
+
+/* FIXME: Add mainboard override */
+unsigned int uart_platform_refclk(void)
+{
+	return 408000000;
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+	/* Default to UART A */
+	unsigned int base = 0x70006000;
+	/* UARTs A - E are mapped as index 0 - 4 */
+	if ((idx < 5) && (idx >= 0)) {
+		if (idx != 1) { /* Not UART B */
+			base += idx * 0x100;
+		} else {
+			base += 0x40;
+		}
+	}
+	return base;
+}
+
+void uart_init(int idx)
+{
+	struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+	tegra132_uart_init(uart_ptr);
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+	struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+	return tegra132_uart_rx_byte(uart_ptr);
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+	struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+	tegra132_uart_tx_byte(uart_ptr, data);
+}
+
+void uart_tx_flush(int idx)
+{
+	struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+	tegra132_uart_tx_flush(uart_ptr);
+}
+
+#ifndef __PRE_RAM__
+void uart_fill_lb(void *data)
+{
+	struct lb_serial serial;
+	serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
+	serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+	serial.baud = default_baudrate();
+	lb_add_serial(&serial, data);
+
+	lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
+}
+#endif



More information about the coreboot-gerrit mailing list