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

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Tue Feb 24 01:38:38 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 9ff163e70d6432fc07fe9847362ef57c5afec03f
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.
    
    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              | 148 +++++++
 15 files changed, 2488 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..10479b0 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_CONSOLE_SERIAL) += 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_CONSOLE_SERIAL) += 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_CONSOLE_SERIAL) += 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..41a9c73
--- /dev/null
+++ b/src/soc/nvidia/tegra132/uart.c
@@ -0,0 +1,148 @@
+/*
+ * 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>
+
+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)
+{
+	// Use a hardcoded divisor for now.
+	const unsigned divisor = 221;
+	const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1
+
+	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;
+}
+
+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