summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7/tegra2/Makefile10
-rw-r--r--arch/arm/cpu/armv7/tegra2/ap20.c6
-rw-r--r--arch/arm/cpu/armv7/tegra2/warmboot.c448
-rw-r--r--arch/arm/cpu/armv7/tegra2/warmboot_avp.S402
-rw-r--r--arch/arm/cpu/armv7/tegra2/warmboot_avp.h161
-rw-r--r--arch/arm/include/asm/arch-tegra2/emc.h66
-rw-r--r--arch/arm/include/asm/arch-tegra2/gp_padctrl.h65
-rw-r--r--arch/arm/include/asm/arch-tegra2/sdram_param.h149
-rw-r--r--arch/arm/include/asm/arch-tegra2/tegra2.h8
-rw-r--r--arch/arm/include/asm/arch-tegra2/warmboot.h81
-rw-r--r--arch/arm/lib/board.c1
-rw-r--r--board/nvidia/common/board.c7
12 files changed, 1399 insertions, 5 deletions
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index 06035f48ee2..f9b81a4208e 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -32,10 +32,16 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
-SOBJS := lowlevel_init.o
-COBJS := ap20.o board.o clock.o display.o pinmux.o power.o pwfm.o \
+SOBJS-y := lowlevel_init.o
+COBJS-y := ap20.o board.o clock.o display.o pinmux.o power.o pwfm.o \
sys_info.o timer.o
+SOBJS-$(CONFIG_TEGRA2_LP0) += warmboot_avp.o
+COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o
+
+SOBJS := $(SOBJS-y)
+COBJS := $(COBJS-y)
+
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
index 4fec9f8dd11..abcfa977ab8 100644
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -31,6 +31,7 @@
#include <asm/arch/pinmux.h>
#include <asm/arch/scu.h>
#include <common.h>
+#include <asm/arch/warmboot.h>
#include "../../../../../board/nvidia/common/board.h"
struct clk_pll_table {
@@ -340,6 +341,11 @@ void init_pmc_scratch(void)
/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+
+#ifdef CONFIG_TEGRA2_LP0
+ /* save Sdram params to PMC 2, 4, and 24 for WB0 */
+ warmboot_save_sdram_params();
+#endif
}
void tegra2_start(void)
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c
new file mode 100644
index 00000000000..dfa51e4aecd
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot.c
@@ -0,0 +1,448 @@
+/*
+ * (C) Copyright 2010 - 2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/bitfield.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/fuse.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/warmboot.h>
+#include <asm/arch/sdram_param.h>
+#include "ap20.h"
+
+#define BCT_OFFSET 0x100 /* BCT starts at 0x100 */
+#define BCT_SDRAM_PARAMS_OFFSET (BCT_OFFSET + 0x88)
+#define SDRAM_PARAMS_BASE (AP20_BASE_PA_SRAM + BCT_SDRAM_PARAMS_OFFSET)
+
+union osc_ctrl_reg {
+ struct {
+ u32 xoe:1;
+ u32 xobp:1;
+ u32 reserved0:2;
+ u32 xofs:6;
+ u32 reserved1:2;
+ u32 xods:5;
+ u32 reserved2:3;
+ u32 oscfi_spare:8;
+ u32 pll_ref_div:2;
+ u32 osc_freq:2;
+ };
+ u32 word;
+};
+
+union pll_base_reg {
+ struct {
+ u32 pll_divm:5;
+ u32 reserved0:3;
+ u32 pll_divn:10;
+ u32 reserved1:2;
+ u32 pll_divp:3;
+ u32 reserved2:4;
+ u32 pll_lock:1;
+ u32 reserved3:1;
+ u32 pll_ref_dis:1;
+ u32 pll_enable:1;
+ u32 pll_bypass:1;
+ };
+ u32 word;
+};
+
+union pll_misc_reg {
+ struct {
+ u32 pll_vcocon:4;
+ u32 pll_lfcon:4;
+ u32 pll_cpcon:4;
+ u32 pll_lock_sel:6;
+ u32 reserved0:1;
+ u32 pll_lock_enable:1;
+ u32 reserved1:1;
+ u32 pll_dccon:1;
+ u32 pll_pts:2;
+ u32 reserved2:6;
+ u32 pll_out1_div_byp:1;
+ u32 pll_out1_inv_clk:1;
+ };
+ u32 word;
+};
+
+union xm2cfga_reg {
+ struct {
+ u32 reserved0:2;
+ u32 hsm_en:1;
+ u32 reserved1:2;
+ u32 preemp_en:1;
+ u32 vref_en:1;
+ u32 reserved2:5;
+ u32 cal_drvdn:5;
+ u32 reserved3:3;
+ u32 cal_drvup:5;
+ u32 reserved4:3;
+ u32 cal_drvdn_slwr:2;
+ u32 cal_drvup_slwf:2;
+ };
+ u32 word;
+};
+
+union xm2cfgd_reg {
+ struct {
+ u32 reserved0:2;
+ u32 hsm_en:1;
+ u32 schmt_en:1;
+ u32 lpmd:2;
+ u32 vref_en:1;
+ u32 reserved1:5;
+ u32 cal_drvdn:5;
+ u32 reserved2:3;
+ u32 cal_drvup:5;
+ u32 reserved3:3;
+ u32 cal_drvdn_slwr:2;
+ u32 cal_drvup_slwf:2;
+ };
+ u32 word;
+};
+
+union fbio_spare_reg {
+ struct {
+ u32 reserved:24;
+ u32 cfg_wb0:8;
+ };
+ u32 word;
+};
+
+union scratch2_reg {
+ struct {
+ u32 pllm_base_divm:5;
+ u32 pllm_base_divn:10;
+ u32 pllm_base_divp:3;
+ u32 pllm_misc_lfcon:4;
+ u32 pllm_misc_cpcon:4;
+ u32 gp_xm2cfga_padctrl_preemp:1;
+ u32 gp_xm2cfgd_padctrl_schmt:1;
+ u32 osc_ctrl_xobp:1;
+ u32 memory_type:3;
+ };
+ u32 word;
+};
+
+union scratch4_reg {
+ struct {
+ u32 emc_clock_divider:8;
+ u32 pllm_stable_time:8;
+ u32 pllx_stable_time:8;
+ u32 emc_fbio_spare_cfg_wb0:8;
+ };
+ u32 word;
+};
+
+union scratch24_reg {
+ struct {
+ u32 emc_auto_cal_wait:8;
+ u32 emc_pin_program_wait:8;
+ u32 warmboot_wait:8;
+ u32 reserved:8;
+ };
+ u32 word;
+};
+
+void warmboot_save_sdram_params(void)
+{
+ u32 ram_code;
+ struct sdram_params sdram;
+ struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+ struct apb_misc_gp_ctlr *gp =
+ (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+ struct emc_ctlr *emc = (struct emc_ctlr *)NV_PA_EMC_BASE;
+ union osc_ctrl_reg osc_ctrl;
+ union pll_base_reg pllm_base;
+ union pll_misc_reg pllm_misc;
+ union scratch2_reg scratch2;
+ union scratch4_reg scratch4;
+ union scratch24_reg scratch24;
+ union xm2cfga_reg xm2cfga;
+ union xm2cfgd_reg xm2cfgd;
+ union fbio_spare_reg fbio_spare;
+
+ /* get ram code that is used as index to array sdram_params in BCT */
+ ram_code = bf_readl(STRAP_OPT_A_RAM_CODE, &pmt->pmt_strap_opt_a) & 3;
+ memcpy(&sdram,
+ (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code),
+ sizeof(sdram));
+
+ osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
+ pllm_base.word = readl(&clkrst->crc_pll[CLOCK_ID_MEMORY].pll_base);
+ pllm_misc.word = readl(&clkrst->crc_pll[CLOCK_ID_MEMORY].pll_misc);
+ xm2cfga.word = readl(&gp->xm2cfga);
+ xm2cfgd.word = readl(&gp->xm2cfgd);
+
+ scratch2.word = 0;
+ scratch2.osc_ctrl_xobp = osc_ctrl.xobp;
+ scratch2.pllm_base_divm = pllm_base.pll_divm;
+ scratch2.pllm_base_divn = pllm_base.pll_divn;
+ scratch2.pllm_base_divp = pllm_base.pll_divp;
+ scratch2.pllm_misc_cpcon = pllm_misc.pll_cpcon;
+ scratch2.pllm_misc_lfcon = pllm_misc.pll_lfcon;
+ scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en;
+ scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en;
+ scratch2.memory_type = sdram.memory_type;
+ writel(scratch2.word, &pmc->pmc_scratch2);
+
+ /* collect data from various sources for pmc_scratch4 */
+ fbio_spare.word = readl(&emc->fbio_spare);
+ scratch4.word = 0;
+ scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0;
+ scratch4.emc_clock_divider = sdram.emc_clock_divider;
+ scratch4.pllm_stable_time = -1;
+ scratch4.pllx_stable_time = -1;
+ writel(scratch4.word, &pmc->pmc_scratch4);
+
+ /* collect various data from sdram for pmc_scratch24 */
+ scratch24.word = 0;
+ scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait;
+ scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait;
+ scratch24.warmboot_wait = sdram.warm_boot_wait;
+ writel(scratch24.word, &pmc->pmc_scratch24);
+}
+
+/*
+ * NOTE: If more than one of the following is enabled, only one of them will
+ * actually be used. RANDOM takes precedence over PATTERN and ZERO, and
+ * PATTERN takes precedence overy ZERO.
+ *
+ * RANDOM_AES_BLOCK_IS_PATTERN is to define a 32-bit PATTERN.
+ */
+#define RANDOM_AES_BLOCK_IS_RANDOM /* to randomize the header */
+#undef RANDOM_AES_BLOCK_IS_PATTERN /* to patternize the header */
+#undef RANDOM_AES_BLOCK_IS_ZERO /* to clear the header */
+
+static u32 get_major_version(void)
+{
+ u32 major_id;
+ struct apb_misc_gp_ctlr *gp =
+ (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+
+ major_id = bf_readl(HIDREV_MAJORPREV, &gp->hidrev);
+ return major_id;
+}
+
+static int is_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+ return readl(&fuse->production_mode);
+}
+
+static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+ return readl(&fuse->security_mode);
+}
+
+static int is_failure_analysis_mode(struct fuse_regs *fuse)
+{
+ return readl(&fuse->fa);
+}
+
+static int ap20_is_odm_production_mode(void)
+{
+ struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
+
+ if (!is_failure_analysis_mode(fuse) &&
+ is_odm_production_mode_fuse_set(fuse))
+ return 1;
+ else
+ return 0;
+}
+
+static int ap20_is_production_mode(void)
+{
+ struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
+
+ if (get_major_version() == 0)
+ return 1;
+
+ if (!is_failure_analysis_mode(fuse) &&
+ is_production_mode_fuse_set(fuse) &&
+ !is_odm_production_mode_fuse_set(fuse))
+ return 1;
+ else
+ return 0;
+}
+
+static enum fuse_operating_mode fuse_get_operation_mode(void)
+{
+ u32 chip_id;
+ struct apb_misc_gp_ctlr *gp =
+ (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+
+ chip_id = bf_readl(HIDREV_CHIPID, &gp->hidrev);
+ if (chip_id == CHIPID_TEGRA2) {
+ if (ap20_is_odm_production_mode()) {
+ printf("!! odm_production_mode is not supported !!\n");
+ return MODE_UNDEFINED;
+ } else
+ if (ap20_is_production_mode())
+ return MODE_PRODUCTION;
+ else
+ return MODE_UNDEFINED;
+ }
+ return MODE_UNDEFINED;
+}
+
+/* Currently, this routine returns a 32-bit all 0 seed. */
+static u32 query_random_seed(void)
+{
+ return 0;
+}
+
+static void determine_crypto_options(int *is_encrypted, int *is_signed,
+ int *use_zero_key)
+{
+ switch (fuse_get_operation_mode()) {
+ case MODE_PRODUCTION:
+ *is_encrypted = 0;
+ *is_signed = 1;
+ *use_zero_key = 1;
+ break;
+ case MODE_UNDEFINED:
+ default:
+ *is_encrypted = 0;
+ *is_signed = 0;
+ *use_zero_key = 0;
+ break;
+ }
+}
+
+static int sign_wb_code(u32 start, u32 length, int use_zero_key)
+{
+ int err;
+ u8 *source; /* Pointer to source */
+ u8 *hash;
+
+ /* Calculate AES block parameters. */
+ source = (u8 *)(start + offsetof(struct wb_header, random_aes_block));
+ length -= offsetof(struct wb_header, random_aes_block);
+ hash = (u8 *)(start + offsetof(struct wb_header, hash));
+ err = sign_data_block(source, length, hash);
+
+ return err;
+}
+
+int warmboot_prepare_code(u32 seg_address, u32 seg_length)
+{
+ int err = 0;
+ u32 start; /* start of the actual code */
+ u32 length; /* length of the signed/encrypt code */
+ struct wb_header *src_header; /* Pointer to src WB header */
+ struct wb_header *dst_header; /* Pointer to dest WB header */
+ int is_encrypted; /* Segment is encrypted */
+ int is_signed; /* Segment is signed */
+ int use_zero_key; /* Use key of all zeros */
+
+ /* Determine crypto options. */
+ determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
+
+ /* Get the actual code limits. */
+ start = (u32)wb_start;
+ length = roundup(((u32)wb_end - start), 16);
+
+ /*
+ * The region specified by seg_address must not be in IRAM and must be
+ * nonzero in length.
+ */
+ if ((seg_length == 0) || (seg_address == 0) ||
+ (seg_address >= AP20_BASE_PA_SRAM)) {
+ err = -EFAULT;
+ goto fail;
+ }
+
+ /* Things must be 16-byte aligned. */
+ if ((seg_length & 0xF) || (seg_address & 0xF)) {
+ err = -EINVAL;
+ goto fail;
+ }
+
+ /* Will the code fit? */
+ if (seg_length < length) {
+ err = -EINVAL;
+ goto fail;
+ }
+
+ /* Get a pointers to the source and destination region header. */
+ src_header = (struct wb_header *)start;
+ dst_header = (struct wb_header *)seg_address;
+
+ /* Populate the random_aes_block as requested. */
+ {
+ u32 *aes_block = (u32 *)&(src_header->random_aes_block);
+ u32 *end = (u32 *)(((u32)aes_block) +
+ sizeof(src_header->random_aes_block));
+
+ do {
+#if defined(RANDOM_AES_BLOCK_IS_RANDOM)
+ *aes_block++ = query_random_seed();
+#elif defined(RANDOM_AES_BLOCK_IS_PATTERN)
+ *aes_block++ = RANDOM_AES_BLOCK_IS_PATTERN;
+#elif defined(RANDOM_AES_BLOCK_IS_ZERO)
+ *aes_block++ = 0;
+#else
+ printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; ");
+ printf("Default to pattern 0.\n");
+ *aes_block++ = 0;
+#endif
+ } while (aes_block < end);
+ }
+
+ /* Populate the header. */
+ src_header->length_in_secure = length;
+ src_header->length_secure = length;
+ src_header->destination = AP20_WB_RUN_ADDRESS;
+ src_header->entry_point = AP20_WB_RUN_ADDRESS;
+ src_header->code_length = length - sizeof(struct wb_header);
+
+ if (is_encrypted) {
+ printf("!!!! Encryption is not supported !!!!\n");
+ dst_header->length_in_secure = 0;
+ err = -EACCES;
+ goto fail;
+ } else
+ /* No, just copy the code directly. */
+ memcpy(dst_header, src_header, length);
+
+ /* Clear the signature in the destination code segment. */
+ memset(&(dst_header->hash), 0, sizeof(dst_header->hash));
+
+ if (is_signed)
+ err = sign_wb_code(seg_address, length, use_zero_key);
+
+fail:
+ if (err)
+ printf("WB code not copied to LP0 location! (error=%d)\n", err);
+
+ return err;
+}
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.S b/arch/arm/cpu/armv7/tegra2/warmboot_avp.S
new file mode 100644
index 00000000000..3f712acb7d8
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot_avp.S
@@ -0,0 +1,402 @@
+/*
+ * (C) Copyright 2010 - 2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm/arch/tegra2.h>
+#include "warmboot_avp.h"
+
+/* Set non-zero to skip resetting CoreSight */
+#define DEBUG_DO_NOT_RESET_CORESIGHT 0
+
+ .section .text
+ .align 4
+
+/* ------------------------------------------------------
+ * void wb_start(void)
+ *
+ * Input:
+ *
+ * Output:
+ * None
+ *
+ * Registers Used:
+ * ALL
+ *
+ * Description:
+ * This function restarts the CPU and then waits for the AVP driver to
+ * tell it where to transfer control to finish restoration of the AVP state.
+ * ---------------------------------------------------------------------------
+ */
+
+ .globl wb_start
+wb_start:
+
+ .word 0, 0, 0, 0
+ .word 0, 0, 0, 0
+ .word 0, 0, 0, 0
+ .word 0, 0, 0, 0
+
+start:
+ ldr r0, =NV_PA_APB_MISC_BASE /* R0 = MISC PA base address */
+ ldr r1, =APB_MISC_PP_CONFIG_CTL_JTAG_ENABLE \
+ | APB_MISC_PP_CONFIG_CTL_TBE_ENABLE
+ str r1, [r0, #APB_MISC_PP_CONFIG_CTL_OFFSET]
+
+ /* -----------------------------------------------------------------
+ * Load up the base addresses for the register blocks.
+ * -----------------------------------------------------------------
+ */
+ ldr r5, =NV_PA_PMC_BASE /* R5 = PMC PA base address */
+ ldr r6, =NV_PA_FLOW_BASE /* R6 = FLOW PA base address */
+ ldr r7, =NV_PA_TMRUS_BASE /* R7 = TIMERUS PA base address */
+ ldr r8, =NV_PA_CLK_RST_BASE /* R8 = CLK PA base address */
+ ldr r9, =NV_PA_EVP_BASE /* R9 = EVP PA base address */
+ ldr r10,=NV_PA_CSITE_BASE /* R10 = CSITE base address */
+
+ /* -----------------------------------------------------------------
+ * Are we running where we're supposed to be?
+ * -----------------------------------------------------------------
+ */
+
+ ldr r0, =AP20_WB_RUN_ADDRESS /* R0 = expected load address */
+ add r1, pc, #here-(.+8) /* R1 = &here */
+
+here:
+ sub r1, r1, #(here-start) /* R1 = actual load address */
+ ldr r2, =NV_PA_PG_UP_BASE /* R2 = PG PA base address */
+ ldr r3, [r2, #PG_UP_TAG_OFFSET] /* R3 = processor tag */
+ ldr r2, =PG_UP_TAG_AVP /* R2 = AVP processor tag */
+ cmp r0, r1 /* Addresses match? */
+ cmpeq r2, r3 /* Processor tags match? */
+ bne do_reset /* No -- reset the chip */
+
+
+ /* -----------------------------------------------------------------
+ * Get a snapshot of the Usec count. This is a good indicator of
+ * the overhead of BOOTROM after a wake-up event.
+ * -----------------------------------------------------------------
+ */
+
+ ldr r11, [r7, #TIMERUS_CNTR_1US_OFFSET]
+
+ /* ==================================================================
+ * BEGIN CPU COMPLEX INITIALIZATON
+ * ==================================================================
+ */
+
+#if !DEBUG_DO_NOT_RESET_CORESIGHT
+
+ /* ----------------------------------------------------------------
+ * Assert CoreSight reset.
+ * ----------------------------------------------------------------
+ */
+
+ mov r1, #CLK_RST_DEV_U_SET_SET_CSITE_RST
+ str r1, [r8, #CLK_RST_CTLR_RST_DEV_U_SET_OFFSET]
+
+#endif /*!DEBUG_DO_NOT_RESET_CORESIGHT */
+
+ /* Set the drive strength */
+ ldr r1, [r8, #CLK_RST_CTLR_OSC_CTRL_OFFSET]
+ ldr r3, =CLK_RST_CTLR_OSC_CTRL_XOFS_MASK \
+ | CLK_RST_CTLR_OSC_CTRL_XOE_MASK
+ bic r1, r1, r3
+ ldr r3, =CLK_RST_CTLR_OSC_CTRL_XOFS_VAL_4 \
+ | CLK_RST_CTLR_OSC_CTRL_XOE_ENABLE
+ orr r3, r1, r3
+ str r3, [r8, #CLK_RST_CTLR_OSC_CTRL_OFFSET]
+
+ /* -----------------------------------------------------------------
+ * Power up the CPU complex if necessary.
+ * -----------------------------------------------------------------
+ */
+
+ ldr r3, [r5, #PMC_PWRGATE_STATUS_OFFSET]
+ tst r3, #PMC_PWRGATE_STATUS_CPU_MASK
+
+ ldreq r2, =PMC_PWRGATE_TOGGLE_PARTID_CPU \
+ | PMC_PWRGATE_TOGGLE_START_ENABLE
+ streq r2, [r5, #PMC_PWRGATE_TOGGLE_OFFSET]
+
+is_cpu_on:
+ ldr r3, [r5, #PMC_PWRGATE_STATUS_OFFSET]
+ tst r3, #PMC_PWRGATE_STATUS_CPU_MASK
+ beq is_cpu_on
+
+ /* -----------------------------------------------------------------
+ * Remove the I/O clamps from the CPU power partition.
+ * -----------------------------------------------------------------
+ */
+
+ mov r3, #PMC_REMOVE_CLAMPING_CMD_CPU_ENABLE
+ str r3, [r5, #PMC_REMOVE_CLAMPING_CMD_OFFSET]
+
+ ldr r3, =FLOW_CTLR_HALT_COP_EVENTS_ZERO_VAL_20 \
+ | FLOW_CTLR_HALT_COP_EVENTS_MSEC \
+ | FLOW_CTLR_HALT_COP_EVENTS_MODE_STOP
+ str r3, [r6, #FLOW_CTLR_HALT_COP_EVENTS_OFFSET]
+
+ /* ------------------------------------------------------------------
+ * Assert CPU complex reset.
+ * ------------------------------------------------------------------
+ */
+
+ mov r1, #CLK_RST_CTLR_RST_DEV_L_SET_CPU_RST
+ str r1, [r8, #CLK_RST_CTLR_RST_DEV_L_SET_OFFSET]
+
+ /* ------------------------------------------------------------------
+ * Hold both CPUs in reset.
+ * ------------------------------------------------------------------
+ */
+
+ ldr r3, =CLK_RST_CTLR_RST_CPU_CMPLX_SET_CPURESET0 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_SET_CPURESET1 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_SET_DERESET0 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_SET_DERESET1 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_SET_DBGRESET0 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_SET_DBGRESET1
+ str r3, [r8, #CLK_RST_CTLR_RST_CPU_CMPLX_SET_OFFSET]
+
+ /* ------------------------------------------------------------------
+ * Halt CPU1 at the flow controller for uni-processor configurations.
+ * ------------------------------------------------------------------
+ */
+
+ mov r3, #FLOW_CTLR_HALT_CPU1_EVENTS_MODE_FLOW_MODE_STOP
+ str r3, [r6, #FLOW_CTLR_HALT_CPU1_EVENTS_OFFSET]
+
+ /* -----------------------------------------------------------------
+ * Set the CPU reset vector. SCRATCH41 contains the physical
+ * address of the CPU-side restoration code.
+ * -----------------------------------------------------------------
+ */
+
+ ldr r3, [r5, #PMC_SCRATCH41_OFFSET]
+ str r3, [r9, #EVP_CPU_RESET_VECTOR_OFFSET]
+
+ /* ------------------------------------------------------------------
+ * Select CPU complex clock source.
+ * ------------------------------------------------------------------
+ */
+#define CPU_CLK_SRC 4 /* 4 = PLLP_OUT0 */
+ ldr r3, =(CPU_CLK_SRC << CLK_RST_CTLR_CCLK_CWAKE_FIQ_SOURCE_SHIFT) \
+ | (CPU_CLK_SRC << CLK_RST_CTLR_CCLK_CWAKE_IRQ_SOURCE_SHIFT) \
+ | (CPU_CLK_SRC << CLK_RST_CTLR_CCLK_CWAKE_RUN_SOURCE_SHIFT) \
+ | (CPU_CLK_SRC << CLK_RST_CTLR_CCLK_CWAKE_IDLE_SOURCE_SHIFT) \
+ | CLK_RST_CTLR_CCLK_CPU_STATE_RUN
+ str r3, [r8, #CLK_RST_CTLR_CCLK_BURST_POLICY_OFFSET]
+#undef CPU_CLK_SRC
+
+ /* ------------------------------------------------------------------
+ * Start the CPU0 clock and stop the CPU1 clock.
+ * ------------------------------------------------------------------
+ */
+
+ ldr r3, =CLK_RST_CTLR_CPU_CMPLX_CPU_BRIDGE_CLKDIV_BY_4 \
+ | CLK_RST_CTLR_CPU_CMPLX_CPU0_CLK_STP_RUN \
+ | CLK_RST_CTLR_CPU_CMPLX_CPU1_CLK_STP_STOP
+ str r3, [r8, #CLK_RST_CTLR_CPU_CMPLX_OFFSET]
+
+ /* ------------------------------------------------------------------
+ * Enable the CPU complex clock.
+ * ------------------------------------------------------------------
+ */
+
+ mov r3, #CLK_RST_CTLR_CLK_ENB_L_SET_CLK_ENB_CPU
+ str r3, [r8, #CLK_RST_CTLR_CLK_ENB_L_SET_OFFSET]
+
+ /* -----------------------------------------------------------------
+ * Make sure the resets were held for at least 2 microseconds.
+ * -----------------------------------------------------------------
+ */
+
+ add r3, r11, #2
+
+wait:
+ ldr r2, [r7, #TIMERUS_CNTR_1US_OFFSET]
+ cmp r2, r3
+ ble wait
+
+#if !DEBUG_DO_NOT_RESET_CORESIGHT
+
+ /* -----------------------------------------------------------------
+ * De-assert CoreSight reset.
+ * NOTE: We're leaving the CoreSight clock on the oscillator for
+ * now. It will be restored to its original clock source
+ * when the CPU-side restoration code runs.
+ * -----------------------------------------------------------------
+ */
+
+ mov r1, #CLK_RST_CTLR_RST_DEV_U_CLR_CSITE_RST_MASK
+ str r1, [r8, #CLK_RST_CTLR_RST_DEV_U_CLR_OFFSET]
+
+#endif /*!DEBUG_DO_NOT_RESET_CORESIGHT */
+
+ ldr r1, =0xC5ACCE55 /* R0 = CoreSight unlock value*/
+ ldr r2, =CSITE_CPUDBG0_LAR_OFFSET /* R1 = CPU0 lock offset */
+ ldr r3, =CSITE_CPUDBG1_LAR_OFFSET /* R2 = CPU1 lock offset */
+ str r1, [r10, r2] /* Unlock CPU0 */
+ str r1, [r10, r3] /* Unlock CPU1 */
+
+ /* -----------------------------------------------------------------
+ * Sample the microsecond timestamp again. This is the time we must
+ * use when returning from LP0 for PLL stabilization delays.
+ * ----------------------------------------------------------------
+ */
+
+ ldr r11, [r7, #TIMERUS_CNTR_1US_OFFSET]
+ str r11, [r5, #PMC_SCRATCH1_OFFSET]
+
+ /* -----------------------------------------------------------------
+ * Get the oscillator frequency. For 19.2 MHz, just use 19 to
+ * make the calculations easier.
+ * -----------------------------------------------------------------
+ */
+
+ ldr r4, [r7, #TIMERUS_USEC_CFG_OFFSET]
+ and r4, r4, #TIMERUS_USEC_CFG_USEC_DIVISOR_MASK
+ add r4, r4, #1
+ cmp r4, #26
+ MOVGT r4, #19
+
+ /* PLLX_BASE.PLLX_DIVM */
+ ldr r0, [r5, #PMC_SCRATCH3_OFFSET]
+ and r2, r0, #PMC_SCRATCH3_PLLX_BASE_DIVM_MASK
+ cmp r2, r4
+ moveq r4, #0
+ movne r4, #1
+
+ /* PLLX_BASE.PLLX_DIVN */
+ mov r0, r0, ASR #(PMC_SCRATCH3_PLLX_BASE_DIVN_SHIFT - \
+ PMC_SCRATCH3_PLLX_BASE_DIVM_SHIFT)
+ ldr r3, =PMC_SCRATCH3_PLLX_BASE_DIVN_MASK
+ and r1, r0, r3
+ orr r2, r2, r1, LSL #CLK_RST_CTLR_PLLX_BASE_DIVN_SHIFT
+ mov r4, r1, LSL r4
+
+ /* PLLX_BASE.PLLX_DIVP */
+ mov r0, r0, ASR #(PMC_SCRATCH3_PLLX_BASE_DIVP_SHIFT - \
+ PMC_SCRATCH3_PLLX_BASE_DIVN_SHIFT)
+ and r1, r0, #PMC_SCRATCH3_PLLX_BASE_DIVP_MASK
+ orr r2, r2, r1, LSL #CLK_RST_CTLR_PLLX_BASE_DIVP_SHIFT
+ mov r4, r4, ASR r1
+
+ /* PLLX_BASE.PLLX_BYPASS_ENABLE | PLLX_BASE.PLLX_ENABLE_DISABLE |
+ * PLLX_BASE.PLLX_REF_DIS_REF_ENABLE
+ */
+ orr r2, r2, #CLK_RST_CTLR_PLLX_BASE_BYPASS_ENABLE \
+ | CLK_RST_CTLR_PLLX_BASE_ENABLE_DISABLE \
+ | CLK_RST_CTLR_PLLX_BASE_REF_DIS_REF_ENABLE
+
+ /* PLLX_MISC_DCCON must be set for frequencies > 600 MHz. */
+ cmp r4, #600
+ movlt r3, #0
+ movge r3, #CLK_RST_CTLR_PLLX_MISC_DCCON_DEFAULT
+
+ /* PLLX_MISC_LFCON */
+ mov r0, r0, ASR #(PMC_SCRATCH3_PLLX_MISC_LFCON_SHIFT - \
+ PMC_SCRATCH3_PLLX_BASE_DIVP_SHIFT)
+ and r1, r0, #PMC_SCRATCH3_PLLX_MISC_LFCON_MASK
+ orr r3, r3, r1, LSL #CLK_RST_CTLR_PLLX_MISC_LFCON_SHIFT
+
+ /* PLLX_MISC_CPCON */
+ mov r0, r0, ASR #(PMC_SCRATCH3_PLLX_MISC_CPCON_SHIFT - \
+ PMC_SCRATCH3_PLLX_MISC_LFCON_SHIFT)
+ and r1, r0, #PMC_SCRATCH3_PLLX_MISC_LFCON_MASK
+ orr r3, r3, r1, LSL #CLK_RST_CTLR_PLLX_MISC_CPCON_SHIFT
+
+ str r3, [r8, #CLK_RST_CTLR_PLLX_MISC_OFFSET]
+ str r2, [r8, #CLK_RST_CTLR_PLLX_BASE_OFFSET]
+ orr r2, r2, #CLK_RST_CTLR_PLLX_BASE_ENABLE_ENABLE
+ str r2, [r8, #CLK_RST_CTLR_PLLX_BASE_OFFSET]
+ BIC r2, r2, #CLK_RST_CTLR_PLLX_BASE_BYPASS_ENABLE
+ str r2, [r8, #CLK_RST_CTLR_PLLX_BASE_OFFSET]
+
+ mov r3, #0
+ str r3, [r6, #FLOW_CTLR_HALT_CPU_EVENTS_OFFSET]
+
+ ldr r3, =CLK_RST_CTLR_RST_CPU_CMPLX_CLR_CPURESET0 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DBGRESET0 \
+ | CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DERESET0
+ str r3, [r8, #CLK_RST_CTLR_RST_CPU_CMPLX_CLR_OFFSET]
+
+ ldr r1, = CLK_RST_CTLR_PLLM_OUT1_RSTN_RESET_DISABLE \
+ | CLK_RST_CTLR_PLLM_OUT1_CLKEN_ENABLE \
+ | CLK_RST_CTLR_PLLM_OUT1_RATIO_VAL_8
+ str r1, [r8, #CLK_RST_CTLR_PLLM_OUT_OFFSET]
+
+ ldr r2, =CLK_RST_CTLR_SCLK_SWAKE_FIQ_SOURCE_PLLM_OUT1 \
+ | CLK_RST_CTLR_SCLK_SWAKE_IRQ_SOURCE_PLLM_OUT1 \
+ | CLK_RST_CTLR_SCLK_SWAKE_RUN_SOURCE_PLLM_OUT1 \
+ | CLK_RST_CTLR_SCLK_SWAKE_IDLE_SOURCE_PLLM_OUT1 \
+ | CLK_RST_CTLR_SCLK_SYS_STATE_IDLE
+ str r2, [r8, #CLK_RST_CTLR_SCLK_BURST_POLICY_OFFSET]
+ b avp_resume
+
+ .ltorg
+ .align 4
+
+avp_resume:
+
+ mov r1, #CLK_RST_CTLR_RST_DEV_L_CLR_CPU_RST
+ str r1, [r8, #CLK_RST_CTLR_RST_DEV_L_CLR_OFFSET]
+
+avp_halt:
+
+ mov r3, #FLOW_CTLR_HALT_COP_EVENTS_MODE_STOP
+ orr r3, r3, #FLOW_CTLR_HALT_COP_EVENTS_JTAG
+ str r3, [r6, #FLOW_CTLR_HALT_COP_EVENTS_OFFSET]
+ b avp_halt
+
+/* ---------------------------------------------------------------------------
+ * Prototype:
+ * do_reset
+ *
+ * Input:
+ * None
+ *
+ * Output:
+ * None
+ *
+ * Registers Used:
+ * All
+ *
+ * Description:
+ * Execution comes here it something goes wrong. The chip is reset and a
+ * cold boot is performed.
+ * ---------------------------------------------------------------------------
+ */
+
+do_reset:
+
+ mov r0, #CLK_RST_CTLR_RST_DEVICES_L_SWR_TRIG_SYS_RST
+ str r0, [r8, #CLK_RST_CTLR_RST_DEVICES_L_OFFSET]
+ b .
+
+ .ltorg
+
+ .globl wb_end
+wb_end:
+
+ .end
+
+
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h
new file mode 100644
index 00000000000..56cdf7157f9
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2010, 2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _WARMBOOT_AVP_H_
+#define _WARMBOOT_AVP_H_
+
+/* Followings are used by warmboot_avp.S */
+
+#define PMC_SCRATCH1_OFFSET 0x54
+#define PMC_SCRATCH3_OFFSET 0x5c
+#define PMC_SCRATCH41_OFFSET 0x140
+
+#define PG_UP_TAG_OFFSET 0
+#define TIMERUS_CNTR_1US_OFFSET 0
+
+#define CSITE_CPUDBG0_LAR_OFFSET 0x10fb0
+#define CSITE_CPUDBG1_LAR_OFFSET 0x12fb0
+
+#define APB_MISC_PP_CONFIG_CTL_OFFSET 0x24
+#define APB_MISC_PP_CONFIG_CTL_TBE_ENABLE (1 << 7)
+#define APB_MISC_PP_CONFIG_CTL_JTAG_ENABLE (1 << 6)
+
+#define CLK_RST_CTLR_RST_DEV_U_SET_OFFSET 0x310
+#define CLK_RST_DEV_U_SET_SET_CSITE_RST (1 << 9)
+
+#define CLK_RST_CTLR_OSC_CTRL_OFFSET 0x50
+#define CLK_RST_CTLR_OSC_CTRL_XOFS_MASK (0x3f << 4)
+#define CLK_RST_CTLR_OSC_CTRL_XOFS_VAL_4 (0x04 << 4)
+#define CLK_RST_CTLR_OSC_CTRL_XOE_MASK (0x01 << 0)
+#define CLK_RST_CTLR_OSC_CTRL_XOE_ENABLE (0x01 << 0)
+
+#define PMC_PWRGATE_STATUS_OFFSET 0x38
+#define PMC_PWRGATE_STATUS_CPU_MASK (0x01 << 0)
+
+#define PMC_PWRGATE_TOGGLE_OFFSET 0x30
+#define PMC_PWRGATE_TOGGLE_PARTID_CPU (0 << 0)
+#define PMC_PWRGATE_TOGGLE_START_ENABLE (1 << 8)
+
+#define PMC_REMOVE_CLAMPING_CMD_OFFSET 0x34
+#define PMC_REMOVE_CLAMPING_CMD_CPU_ENABLE (1 << 0)
+
+#define FLOW_CTLR_HALT_COP_EVENTS_OFFSET 0x4
+#define FLOW_CTLR_HALT_COP_EVENTS_ZERO_VAL_20 (20 << 0)
+#define FLOW_CTLR_HALT_COP_EVENTS_MSEC (1 << 24)
+#define FLOW_CTLR_HALT_COP_EVENTS_JTAG (1 << 28)
+#define FLOW_CTLR_HALT_COP_EVENTS_MODE_STOP (2 << 29)
+
+#define CLK_RST_CTLR_RST_DEV_L_SET_OFFSET 0x300
+#define CLK_RST_CTLR_RST_DEV_L_SET_CPU_RST (1 << 0)
+
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_OFFSET 0x340
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_CPURESET0 (1 << 0)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_CPURESET1 (1 << 1)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_DERESET0 (1 << 4)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_DERESET1 (1 << 5)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_DBGRESET0 (1 << 12)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_SET_DBGRESET1 (1 << 13)
+
+#define FLOW_CTLR_HALT_CPU1_EVENTS_OFFSET 0x14
+#define FLOW_CTLR_HALT_CPU1_EVENTS_MODE_FLOW_MODE_STOP (2 << 29)
+
+#define EVP_CPU_RESET_VECTOR_OFFSET 0x100
+
+#define CLK_RST_CTLR_CCLK_BURST_POLICY_OFFSET 0x20
+#define CLK_RST_CTLR_CCLK_CWAKE_FIQ_SOURCE_SHIFT 12
+#define CLK_RST_CTLR_CCLK_CWAKE_IRQ_SOURCE_SHIFT 8
+#define CLK_RST_CTLR_CCLK_CWAKE_RUN_SOURCE_SHIFT 4
+#define CLK_RST_CTLR_CCLK_CWAKE_IDLE_SOURCE_SHIFT 0
+#define CLK_RST_CTLR_CCLK_CPU_STATE_RUN (2 << 28)
+
+#define CLK_RST_CTLR_CPU_CMPLX_OFFSET 0x4c
+#define CLK_RST_CTLR_CPU_CMPLX_CPU_BRIDGE_CLKDIV_BY_4 (3 << 0)
+#define CLK_RST_CTLR_CPU_CMPLX_CPU0_CLK_STP_STOP (1 << 8)
+#define CLK_RST_CTLR_CPU_CMPLX_CPU0_CLK_STP_RUN (0 << 8)
+#define CLK_RST_CTLR_CPU_CMPLX_CPU1_CLK_STP_STOP (1 << 9)
+#define CLK_RST_CTLR_CPU_CMPLX_CPU1_CLK_STP_RUN (0 << 9)
+
+#define CLK_RST_CTLR_CLK_ENB_L_SET_OFFSET 0x320
+#define CLK_RST_CTLR_CLK_ENB_L_SET_CLK_ENB_CPU (1 << 0)
+
+#define CLK_RST_CTLR_RST_DEV_U_CLR_OFFSET 0x314
+#define CLK_RST_CTLR_RST_DEV_U_CLR_CSITE_RST_MASK (1 << 9)
+
+#define TIMERUS_USEC_CFG_OFFSET 0x4
+#define TIMERUS_USEC_CFG_USEC_DIVISOR_MASK 0xff
+
+#define CLK_RST_CTLR_PLLX_BASE_OFFSET 0xe0
+#define CLK_RST_CTLR_PLLX_MISC_OFFSET 0xe4
+#define CLK_RST_CTLR_PLLX_BASE_BYPASS_ENABLE (1 << 31)
+#define CLK_RST_CTLR_PLLX_BASE_ENABLE_ENABLE (1 << 30)
+#define CLK_RST_CTLR_PLLX_BASE_ENABLE_DISABLE (0 << 30)
+#define CLK_RST_CTLR_PLLX_BASE_REF_DIS_REF_ENABLE (0 << 29)
+#define CLK_RST_CTLR_PLLX_BASE_DIVP_SHIFT 20
+#define CLK_RST_CTLR_PLLX_BASE_DIVN_SHIFT 8
+
+#define CLK_RST_CTLR_PLLX_MISC_DCCON_DEFAULT (1 << 20)
+#define CLK_RST_CTLR_PLLX_MISC_CPCON_SHIFT 8
+#define CLK_RST_CTLR_PLLX_MISC_LFCON_SHIFT 4
+
+#define PMC_SCRATCH3_PLLX_MISC_CPCON_SHIFT 22
+#define PMC_SCRATCH3_PLLX_MISC_CPCON_MASK 0xf
+#define PMC_SCRATCH3_PLLX_MISC_LFCON_SHIFT 18
+#define PMC_SCRATCH3_PLLX_MISC_LFCON_MASK 0xf
+#define PMC_SCRATCH3_PLLX_BASE_DIVP_SHIFT 15
+#define PMC_SCRATCH3_PLLX_BASE_DIVM_MASK 0x1f
+#define PMC_SCRATCH3_PLLX_BASE_DIVN_SHIFT 5
+#define PMC_SCRATCH3_PLLX_BASE_DIVM_SHIFT 0
+#define PMC_SCRATCH3_PLLX_BASE_DIVN_MASK 0x3ff
+#define PMC_SCRATCH3_PLLX_BASE_DIVN_SHIFT 5
+#define PMC_SCRATCH3_PLLX_BASE_DIVP_MASK 0x07
+
+#define FLOW_CTLR_HALT_CPU_EVENTS_OFFSET 0x0
+
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_OFFSET 0x344
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_CPURESET0 (1 << 0)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_CPURESET1 (1 << 1)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DERESET0 (1 << 4)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DERESET1 (1 << 5)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DBGRESET0 (1 << 12)
+#define CLK_RST_CTLR_RST_CPU_CMPLX_CLR_DBGRESET1 (1 << 13)
+
+#define CLK_RST_CTLR_PLLM_OUT_OFFSET 0x94
+#define CLK_RST_CTLR_PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0)
+#define CLK_RST_CTLR_PLLM_OUT1_CLKEN_ENABLE (1 << 1)
+#define CLK_RST_CTLR_PLLM_OUT1_RATIO_VAL_8 (8 << 8)
+
+#define CLK_RST_CTLR_SCLK_BURST_POLICY_OFFSET 0x28
+#define CLK_RST_CTLR_SCLK_SYS_STATE_IDLE (1 << 28)
+#define CLK_RST_CTLR_SCLK_SWAKE_FIQ_SOURCE_PLLM_OUT1 (7 << 12)
+#define CLK_RST_CTLR_SCLK_SWAKE_IRQ_SOURCE_PLLM_OUT1 (7 << 8)
+#define CLK_RST_CTLR_SCLK_SWAKE_RUN_SOURCE_PLLM_OUT1 (7 << 4)
+#define CLK_RST_CTLR_SCLK_SWAKE_IDLE_SOURCE_PLLM_OUT1 (7 << 0)
+
+#define CLK_RST_CTLR_RST_DEV_L_CLR_OFFSET 0x304
+#define CLK_RST_CTLR_RST_DEV_L_CLR_CPU_RST (1 << 0)
+
+#define CLK_RST_CTLR_RST_DEVICES_L_OFFSET 0x4
+#define CLK_RST_CTLR_RST_DEVICES_L_SWR_TRIG_SYS_RST (1 << 2)
+
+#endif
+
diff --git a/arch/arm/include/asm/arch-tegra2/emc.h b/arch/arm/include/asm/arch-tegra2/emc.h
index 72190f43e26..df16866e06f 100644
--- a/arch/arm/include/asm/arch-tegra2/emc.h
+++ b/arch/arm/include/asm/arch-tegra2/emc.h
@@ -33,4 +33,68 @@ struct tegra_emc_table {
int board_emc_init(void);
-#endif /* _EMC_H_ */
+/* EMC Registers */
+struct emc_ctlr {
+ u32 cfg; /* 0x00: EMC_CFG */
+ u32 reserved0[3]; /* 0x04 ~ 0x0C */
+ u32 adr_cfg; /* 0x10: EMC_ADR_CFG */
+ u32 adr_cfg1; /* 0x14: EMC_ADR_CFG_1 */
+ u32 reserved1[2]; /* 0x18 ~ 0x18 */
+ u32 refresh_ctrl; /* 0x20: EMC_REFCTRL */
+ u32 pin; /* 0x24: EMC_PIN */
+ u32 timing_ctrl; /* 0x28: EMC_TIMING_CONTROL */
+ u32 rc; /* 0x2C: EMC_RC */
+ u32 rfc; /* 0x30: EMC_RFC */
+ u32 ras; /* 0x34: EMC_RAS */
+ u32 rp; /* 0x38: EMC_RP */
+ u32 r2w; /* 0x3C: EMC_R2W */
+ u32 w2r; /* 0x40: EMC_W2R */
+ u32 r2p; /* 0x44: EMC_R2P */
+ u32 w2p; /* 0x48: EMC_W2P */
+ u32 rd_rcd; /* 0x4C: EMC_RD_RCD */
+ u32 wd_rcd; /* 0x50: EMC_WD_RCD */
+ u32 rrd; /* 0x54: EMC_RRD */
+ u32 rext; /* 0x58: EMC_REXT */
+ u32 wdv; /* 0x5C: EMC_WDV */
+ u32 quse; /* 0x60: EMC_QUSE */
+ u32 qrst; /* 0x64: EMC_QRST */
+ u32 qsafe; /* 0x68: EMC_QSAFE */
+ u32 rdv; /* 0x6C: EMC_RDV */
+ u32 refresh; /* 0x70: EMC_REFRESH */
+ u32 burst_refresh_num; /* 0x74: EMC_BURST_REFRESH_NUM */
+ u32 pdex2wr; /* 0x78: EMC_PDEX2WR */
+ u32 pdex2rd; /* 0x7c: EMC_PDEX2RD */
+ u32 pchg2pden; /* 0x80: EMC_PCHG2PDEN */
+ u32 act2pden; /* 0x84: EMC_ACT2PDEN */
+ u32 ar2pden; /* 0x88: EMC_AR2PDEN */
+ u32 rw2pden; /* 0x8C: EMC_RW2PDEN */
+ u32 txsr; /* 0x90: EMC_TXSR */
+ u32 tcke; /* 0x94: EMC_TCKE */
+ u32 tfaw; /* 0x98: EMC_TFAW */
+ u32 trpab; /* 0x9C: EMC_TRPAB */
+ u32 tclkstable; /* 0xA0: EMC_TCLKSTABLE */
+ u32 tclkstop; /* 0xA4: EMC_TCLKSTOP */
+ u32 trefbw; /* 0xA8: EMC_TREFBW */
+ u32 quse_extra; /* 0xAC: EMC_QUSE_EXTRA */
+ u32 odt_write; /* 0xB0: EMC_ODT_WRITE */
+ u32 odt_read; /* 0xB4: EMC_ODT_READ */
+ u32 reserved2[5]; /* 0xB8 ~ 0xC8 */
+ u32 mrs; /* 0xCC: EMC_MRS */
+ u32 emrs; /* 0xD0: EMC_EMRS */
+ u32 ref; /* 0xD4: EMC_REF */
+ u32 pre; /* 0xD8: EMC_PRE */
+ u32 nop; /* 0xDC: EMC_NOP */
+ u32 self_ref; /* 0xE0: EMC_SELF_REF */
+ u32 dpd; /* 0xE4: EMC_DPD */
+ u32 mrw; /* 0xE8: EMC_MRW */
+ u32 mrr; /* 0xEC: EMC_MRR */
+ u32 reserved3; /* 0xF0: */
+ u32 fbio_cfg1; /* 0xF4: EMC_FBIO_CFG1 */
+ u32 fbio_dqsib_dly; /* 0xF8: EMC_FBIO_DQSIB_DLY */
+ u32 fbio_dqsib_dly_msb; /* 0xFC: EMC_FBIO_DQSIB_DLY_MSG */
+ u32 fbio_spare; /* 0x100: SBIO_SPARE */
+ /* There are more registers ... */
+};
+
+#endif
+
diff --git a/arch/arm/include/asm/arch-tegra2/gp_padctrl.h b/arch/arm/include/asm/arch-tegra2/gp_padctrl.h
new file mode 100644
index 00000000000..affb49f3c40
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/gp_padctrl.h
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _GP_PADCTRL_H_
+#define _GP_PADCTRL_H_
+
+/* APB_MISC_GP and padctrl registers */
+struct apb_misc_gp_ctlr {
+ u32 modereg; /* 0x00: APB_MISC_GP_MODEREG */
+ u32 hidrev; /* 0x04: APB_MISC_GP_HIDREV */
+ u32 reserved0[22]; /* 0x08 - 0x5C: */
+ u32 emu_revid; /* 0x60: APB_MISC_GP_EMU_REVID */
+ u32 xactor_scratch; /* 0x64: APB_MISC_GP_XACTOR_SCRATCH */
+ u32 aocfg1; /* 0x68: APB_MISC_GP_AOCFG1PADCTRL */
+ u32 aocfg2; /* 0x6c: APB_MISC_GP_AOCFG2PADCTRL */
+ u32 atcfg1; /* 0x70: APB_MISC_GP_ATCFG1PADCTRL */
+ u32 atcfg2; /* 0x74: APB_MISC_GP_ATCFG2PADCTRL */
+ u32 cdevcfg1; /* 0x78: APB_MISC_GP_CDEV1CFGPADCTRL */
+ u32 cdevcfg2; /* 0x7C: APB_MISC_GP_CDEV2CFGPADCTRL */
+ u32 csuscfg; /* 0x80: APB_MISC_GP_CSUSCFGPADCTRL */
+ u32 dap1cfg; /* 0x84: APB_MISC_GP_DAP1CFGPADCTRL */
+ u32 dap2cfg; /* 0x88: APB_MISC_GP_DAP2CFGPADCTRL */
+ u32 dap3cfg; /* 0x8C: APB_MISC_GP_DAP3CFGPADCTRL */
+ u32 dap4cfg; /* 0x90: APB_MISC_GP_DAP4CFGPADCTRL */
+ u32 dbgcfg; /* 0x94: APB_MISC_GP_DBGCFGPADCTRL */
+ u32 lcdcfg1; /* 0x98: APB_MISC_GP_LCDCFG1PADCTRL */
+ u32 lcdcfg2; /* 0x9C: APB_MISC_GP_LCDCFG2PADCTRL */
+ u32 sdmmc2_cfg; /* 0xA0: APB_MISC_GP_SDMMC2CFGPADCTRL */
+ u32 sdmmc3_cfg; /* 0xA4: APB_MISC_GP_SDMMC3CFGPADCTRL */
+ u32 spicfg; /* 0xA8: APB_MISC_GP_SPICFGPADCTRL */
+ u32 uaacfg; /* 0xAC: APB_MISC_GP_UAACFGPADCTRL */
+ u32 uabcfg; /* 0xB0: APB_MISC_GP_UABCFGPADCTRL */
+ u32 uart2cfg; /* 0xB4: APB_MISC_GP_UART2CFGPADCTRL */
+ u32 uart3cfg; /* 0xB8: APB_MISC_GP_UART3CFGPADCTRL */
+ u32 vicfg1; /* 0xBC: APB_MISC_GP_VICFG1PADCTRL */
+ u32 vicfg2; /* 0xC0: APB_MISC_GP_VICFG2PADCTRL */
+ u32 xm2cfga; /* 0xC4: APB_MISC_GP_XM2CFGAPADCTRL */
+ u32 xm2cfgc; /* 0xC8: APB_MISC_GP_XM2CFGCPADCTRL */
+ u32 xm2cfgd; /* 0xCC: APB_MISC_GP_XM2CFGDPADCTRL */
+ u32 xm2clkcfg; /* 0xD0: APB_MISC_GP_XM2CLKCFGPADCTRL */
+ u32 memcomp; /* 0xD4: APB_MISC_GP_MEMCOMPPADCTRL */
+};
+
+#endif
+
diff --git a/arch/arm/include/asm/arch-tegra2/sdram_param.h b/arch/arm/include/asm/arch-tegra2/sdram_param.h
new file mode 100644
index 00000000000..06faf26b54a
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/sdram_param.h
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2010, 2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _SDRAM_PARAM_H_
+#define _SDRAM_PARAM_H_
+
+/*
+ * Defines the number of 32-bit words provided in each set of SDRAM parameters
+ * for arbitration configuration data.
+ */
+#define BCT_SDRAM_ARB_CONFIG_WORDS 27
+
+enum memory_type {
+ MEMORY_TYPE_NONE = 0,
+ MEMORY_TYPE_DDR,
+ MEMORY_TYPE_LPDDR,
+ MEMORY_TYPE_DDR2,
+ MEMORY_TYPE_LPDDR2,
+ MEMORY_TYPE_NUM,
+ MEMORY_TYPE_FORCE32 = 0x7FFFFFFF
+};
+
+/* Defines the SDRAM parameter structure */
+struct sdram_params {
+ enum memory_type memory_type;
+ u32 pllm_charge_pump_setup_control;
+ u32 pllm_loop_filter_setup_control;
+ u32 pllm_input_divider;
+ u32 pllm_feedback_divider;
+ u32 pllm_post_divider;
+ u32 pllm_stable_time;
+ u32 emc_clock_divider;
+ u32 emc_auto_cal_interval;
+ u32 emc_auto_cal_config;
+ u32 emc_auto_cal_wait;
+ u32 emc_pin_program_wait;
+ u32 emc_rc;
+ u32 emc_rfc;
+ u32 emc_ras;
+ u32 emc_rp;
+ u32 emc_r2w;
+ u32 emc_w2r;
+ u32 emc_r2p;
+ u32 emc_w2p;
+ u32 emc_rd_rcd;
+ u32 emc_wr_rcd;
+ u32 emc_rrd;
+ u32 emc_rext;
+ u32 emc_wdv;
+ u32 emc_quse;
+ u32 emc_qrst;
+ u32 emc_qsafe;
+ u32 emc_rdv;
+ u32 emc_refresh;
+ u32 emc_burst_refresh_num;
+ u32 emc_pdex2wr;
+ u32 emc_pdex2rd;
+ u32 emc_pchg2pden;
+ u32 emc_act2pden;
+ u32 emc_ar2pden;
+ u32 emc_rw2pden;
+ u32 emc_txsr;
+ u32 emc_tcke;
+ u32 emc_tfaw;
+ u32 emc_trpab;
+ u32 emc_tclkstable;
+ u32 emc_tclkstop;
+ u32 emc_trefbw;
+ u32 emc_quseextra;
+ u32 emc_fbioc_fg1;
+ u32 emc_fbio_dqsib_dly;
+ u32 emc_fbio_dqsib_dly_msb;
+ u32 emc_fbio_quse_dly;
+ u32 emc_fbio_quse_dly_msb;
+ u32 emc_fbio_cfg5;
+ u32 emc_fbio_cfg6;
+ u32 emc_fbio_spare;
+ u32 emc_mrs;
+ u32 emc_emrs;
+ u32 emc_mrw1;
+ u32 emc_mrw2;
+ u32 emc_mrw3;
+ u32 emc_mrw_reset_command;
+ u32 emc_mrw_reset_init_wait;
+ u32 emc_adr_cfg;
+ u32 emc_adr_cfg1;
+ u32 mc_emem_cfg;
+ u32 mc_low_latency_config;
+ u32 emc_cfg;
+ u32 emc_cfg2;
+ u32 emc_dbg;
+ u32 ahb_arbitration_xbar_ctrl;
+ u32 emc_cfg_dig_dll;
+ u32 emc_dll_xform_dqs;
+ u32 emc_dll_xform_quse;
+ u32 warm_boot_wait;
+ u32 emc_ctt_term_ctrl;
+ u32 emc_odt_write;
+ u32 emc_odt_read;
+ u32 emc_zcal_ref_cnt;
+ u32 emc_zcal_wait_cnt;
+ u32 emc_zcal_mrw_cmd;
+ u32 emc_mrs_reset_dll;
+ u32 emc_mrw_zq_init_dev0;
+ u32 emc_mrw_zq_init_dev1;
+ u32 emc_mrw_zq_init_wait;
+ u32 emc_mrs_reset_dll_wait;
+ u32 emc_emrs_emr2;
+ u32 emc_emrs_emr3;
+ u32 emc_emrs_ddr2_dll_enable;
+ u32 Emc_mrs_ddr2_dll_reset;
+ u32 emc_emrs_ddr2_ocd_calib;
+ u32 emc_edr2_wait;
+ u32 emc_cfg_clktrim0;
+ u32 emc_cfg_clktrim1;
+ u32 emc_cfg_clktrim2;
+ u32 pmc_ddr_pwr;
+ u32 apb_misc_gp_xm2cfga_padctrl;
+ u32 apb_misc_gp_xm2cfgc_padctrl;
+ u32 apb_misc_gp_xm2cfgc_padctrl2;
+ u32 apb_misc_gp_xm2cfgd_padctrl;
+ u32 apb_misc_gp_xm2cfgd_padctrl2;
+ u32 apb_misc_gp_xm2clkcfg_padctrl;
+ u32 apb_misc_gp_xm2comp_padctrl;
+ u32 apb_misc_gp_xm2vttgen_padctrl;
+ u32 arbitration_config[BCT_SDRAM_ARB_CONFIG_WORDS];
+};
+#endif
+
diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
index af1a21cac83..6af63092217 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -33,6 +33,7 @@
#define NV_PA_GPIO_BASE 0x6000D000
#define NV_PA_EVP_BASE 0x6000F000
#define NV_PA_APB_MISC_BASE 0x70000000
+#define NV_PA_APB_MISC_GP_BASE (NV_PA_APB_MISC_BASE + 0x0800)
#define NV_PA_APB_UARTA_BASE (NV_PA_APB_MISC_BASE + 0x6000)
#define NV_PA_APB_UARTB_BASE (NV_PA_APB_MISC_BASE + 0x6040)
#define NV_PA_APB_UARTC_BASE (NV_PA_APB_MISC_BASE + 0x6200)
@@ -43,8 +44,8 @@
#define TEGRA2_I2C3_BASE 0x7000C500
#define TEGRA2_DVC_BASE 0x7000D000
#define NV_PA_PMC_BASE 0x7000E400
-#define NV_PA_EMC_BASE 0x7000f400
-#define NV_PA_FUSE_BASE 0x7000f800
+#define NV_PA_EMC_BASE 0x7000F400
+#define NV_PA_FUSE_BASE 0x7000F800
#define NV_PA_CSITE_BASE 0x70040000
#define NV_PA_USB1_BASE 0xC5000000
#define NV_PA_USB3_BASE 0xC5008000
@@ -79,4 +80,7 @@ struct timerus {
#define TEGRA_SOC_T25 (1)
#define TEGRA_SOC_COUNT (2)
+/* Address at which WB code runs, it must not overlap Bootrom's IRAM usage */
+#define AP20_WB_RUN_ADDRESS 0x40020000
+
#endif /* TEGRA2_H */
diff --git a/arch/arm/include/asm/arch-tegra2/warmboot.h b/arch/arm/include/asm/arch-tegra2/warmboot.h
new file mode 100644
index 00000000000..249a30dc51e
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/warmboot.h
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2010, 2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _WARM_BOOT_H_
+#define _WARM_BOOT_H_
+
+/* bit fields definitions for APB_MISC_GP_HIDREV register */
+#define HIDREV_MINOPREV_RANGE 19 : 16
+#define HIDREV_CHIPID_RANGE 15 : 8
+#define HIDREV_MAJORPREV_RANGE 7 : 4
+#define HIDREV_HIDFAM_RANGE 3 : 0
+
+/* CHIPID field returned from APB_MISC_GP_HIDREV register */
+#define CHIPID_TEGRA2 0x20
+
+#define STRAP_OPT_A_RAM_CODE_RANGE 7 : 4
+
+/* Defines the supported operating modes */
+enum fuse_operating_mode {
+ MODE_PRODUCTION = 3,
+ MODE_UNDEFINED,
+};
+
+/* Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) */
+enum {
+ HASH_LENGTH = 4
+};
+
+/* Defines the storage for a hash value (128 bits) */
+struct hash {
+ u32 hash[HASH_LENGTH];
+};
+
+/*
+ * Defines the code header information for the boot rom.
+ *
+ * The code immediately follows the code header.
+ *
+ * Note that the code header needs to be 16 bytes aligned to preserve
+ * the alignment of relevant data for hash and decryption computations without
+ * requiring extra copies to temporary memory areas.
+ */
+struct wb_header {
+ u32 length_in_secure; /* length of the code header */
+ u32 reserved[3];
+ struct hash hash; /* hash of header+code, starts next field*/
+ struct hash random_aes_block; /* a data block to aid security. */
+ u32 length_secure; /* length of the code header */
+ u32 destination; /* destination address to put the wb code */
+ u32 entry_point; /* execution address of the wb code */
+ u32 code_length; /* length of the code */
+};
+
+void warmboot_save_sdram_params(void);
+int warmboot_prepare_code(u32 seg_address, u32 seg_length);
+int sign_data_block(u8 *source, u32 length, u8 *signature);
+void wb_start(void); /* Start of WB assembly code */
+void wb_end(void); /* End of WB assembly code */
+
+#endif
+
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 24f4f0ccd09..3bb80fc100a 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -60,6 +60,7 @@
#ifdef CONFIG_DRIVER_LAN91C96
#include "../drivers/net/lan91c96.h"
#endif
+
DECLARE_GLOBAL_DATA_PTR;
ulong monitor_flash_len;
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 93bf4f4d414..9a501a18019 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -46,6 +46,8 @@
#include <mmc.h>
#endif
+#include <asm/arch/warmboot.h>
+
DECLARE_GLOBAL_DATA_PTR;
const struct tegra2_sysinfo sysinfo = {
@@ -220,6 +222,11 @@ int board_init(void)
board_emc_init();
#endif
+#ifdef CONFIG_TEGRA2_LP0
+ /* prepare the WB code to LP0 location */
+ warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE);
+#endif
+
return 0;
}