Patchwork [U-Boot,v3,07/14] ARM: add tegra20 support to arm720t

login
register
mail settings
Submitter Allen Martin
Date June 8, 2012, 9:16 p.m.
Message ID <1339190167-20320-8-git-send-email-amartin@nvidia.com>
Download mbox | patch
Permalink /patch/163861/
State Superseded
Headers show

Comments

Allen Martin - June 8, 2012, 9:16 p.m.
Add support for tegra20 arm7 boot processor.  This processor is used
to power on the Cortex A9 and transfer control to it.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/cpu/arm720t/cpu.c                         |    2 +
 arch/arm/cpu/arm720t/interrupts.c                  |    4 +
 arch/arm/cpu/arm720t/start.S                       |    6 +-
 .../{tegra20-common => arm720t/tegra20}/Makefile   |   22 +-
 arch/arm/cpu/arm720t/tegra20/board.h               |   25 ++
 arch/arm/cpu/arm720t/tegra20/cpu.c                 |  259 ++++++++++++++++++++
 arch/arm/cpu/arm720t/tegra20/cpu.h                 |   99 ++++++++
 arch/arm/cpu/arm720t/tegra20/spl.c                 |  133 ++++++++++
 arch/arm/cpu/tegra20-common/Makefile               |    2 +-
 arch/arm/include/asm/arch-tegra20/hardware.h       |   29 +++
 10 files changed, 562 insertions(+), 19 deletions(-)
 copy arch/arm/cpu/{tegra20-common => arm720t/tegra20}/Makefile (64%)
 create mode 100644 arch/arm/cpu/arm720t/tegra20/board.h
 create mode 100644 arch/arm/cpu/arm720t/tegra20/cpu.c
 create mode 100644 arch/arm/cpu/arm720t/tegra20/cpu.h
 create mode 100644 arch/arm/cpu/arm720t/tegra20/spl.c
 create mode 100644 arch/arm/include/asm/arch-tegra20/hardware.h
Stephen Warren - June 9, 2012, 5:15 a.m.
On 06/08/2012 03:16 PM, Allen Martin wrote:
> Add support for tegra20 arm7 boot processor.  This processor is used
> to power on the Cortex A9 and transfer control to it.

> diff --git a/arch/arm/cpu/tegra20-common/Makefile b/arch/arm/cpu/tegra20-common/Makefile

> -COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o crypto.o warmboot_avp.o
> +COBJS-$(CONFIG_TEGRA20_LP0) += warmboot.o crypto.o warmboot_avp.o

That should be part of an earlier patch.
Simon Glass - June 9, 2012, 6:32 p.m.
Hi Allen,

On Fri, Jun 8, 2012 at 2:16 PM, Allen Martin <amartin@nvidia.com> wrote:

> Add support for tegra20 arm7 boot processor.  This processor is used
> to power on the Cortex A9 and transfer control to it.
>
> Signed-off-by: Allen Martin <amartin@nvidia.com>

---
>  arch/arm/cpu/arm720t/cpu.c                         |    2 +
>  arch/arm/cpu/arm720t/interrupts.c                  |    4 +
>  arch/arm/cpu/arm720t/start.S                       |    6 +-
>  .../{tegra20-common => arm720t/tegra20}/Makefile   |   22 +-
>  arch/arm/cpu/arm720t/tegra20/board.h               |   25 ++
>  arch/arm/cpu/arm720t/tegra20/cpu.c                 |  259
> ++++++++++++++++++++
>  arch/arm/cpu/arm720t/tegra20/cpu.h                 |   99 ++++++++
>  arch/arm/cpu/arm720t/tegra20/spl.c                 |  133 ++++++++++
>  arch/arm/cpu/tegra20-common/Makefile               |    2 +-
>  arch/arm/include/asm/arch-tegra20/hardware.h       |   29 +++
>

I think this (empty) file is required by arm720t/cpu.c, right?

You are using arm720t here, but your chip is actually an ARM7TDMI. I
suppose that doesn't matter since there is no cache and they share the same
core. But perhaps a comment would be useful explaining this difference and
how it was convenient to use the same code.



>  10 files changed, 562 insertions(+), 19 deletions(-)
>  copy arch/arm/cpu/{tegra20-common => arm720t/tegra20}/Makefile (64%)
>  create mode 100644 arch/arm/cpu/arm720t/tegra20/board.h
>  create mode 100644 arch/arm/cpu/arm720t/tegra20/cpu.c
>  create mode 100644 arch/arm/cpu/arm720t/tegra20/cpu.h
>  create mode 100644 arch/arm/cpu/arm720t/tegra20/spl.c
>  create mode 100644 arch/arm/include/asm/arch-tegra20/hardware.h
>
> diff --git a/arch/arm/cpu/arm720t/cpu.c b/arch/arm/cpu/arm720t/cpu.c
> index 974f288..b6eee7e 100644
> --- a/arch/arm/cpu/arm720t/cpu.c
> +++ b/arch/arm/cpu/arm720t/cpu.c
> @@ -51,6 +51,8 @@ int cleanup_before_linux (void)
>        /* Nothing more needed */
>  #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
>        /* No cleanup before linux for IntegratorAP/CM720T as yet */
> +#elif defined (CONFIG_TEGRA)
> +       /* No cleanup before linux for tegra as yet */
>  #else
>  #error No cleanup_before_linux() defined for this CPU type
>  #endif
> diff --git a/arch/arm/cpu/arm720t/interrupts.c
> b/arch/arm/cpu/arm720t/interrupts.c
> index 464dd30..e64e6f2 100644
> --- a/arch/arm/cpu/arm720t/interrupts.c
> +++ b/arch/arm/cpu/arm720t/interrupts.c
> @@ -180,6 +180,8 @@ int timer_init (void)
>        PUT32(T0TC, 0);
>        PUT32(T0TCR, 1);        /* enable timer0 */
>
> +#elif defined(CONFIG_TEGRA)
> +       /* No timer routines for tegra as yet */
>  #else
>  #error No timer_init() defined for this CPU type
>  #endif
> @@ -282,6 +284,8 @@ void __udelay (unsigned long usec)
>
>  #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
>        /* No timer routines for IntegratorAP/CM720T as yet */
> +#elif defined(CONFIG_TEGRA)
> +       /* No timer routines for tegra as yet */
>  #else
>  #error Timer routines not defined for this CPU type
>  #endif
> diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S
> index df66946..3371d3d 100644
> --- a/arch/arm/cpu/arm720t/start.S
> +++ b/arch/arm/cpu/arm720t/start.S
> @@ -407,6 +407,8 @@ lock_loop:
>        ldr     r0, VPBDIV_ADR
>        mov     r1, #0x01       /* VPB clock is same as process clock */
>        str     r1, [r0]
> +#elif defined(CONFIG_TEGRA)
> +       /* No cpu_init_crit for tegra as yet */
>  #else
>  #error No cpu_init_crit() defined for current CPU type
>  #endif
> @@ -422,7 +424,7 @@ lock_loop:
>        str     r1, [r0]
>  #endif
>
> -#ifndef CONFIG_LPC2292
> +#if !defined(CONFIG_LPC2292) && !defined(CONFIG_TEGRA)
>        mov     ip, lr
>        /*
>         * before relocating, we have to setup RAM timing
> @@ -631,6 +633,8 @@ reset_cpu:
>  .globl reset_cpu
>  reset_cpu:
>        mov     pc, r0
> +#elif defined(CONFIG_TEGRA)
> +       /* No specific reset actions for tegra as yet */
>  #else
>  #error No reset_cpu() defined for current CPU type
>  #endif
> diff --git a/arch/arm/cpu/tegra20-common/Makefile
> b/arch/arm/cpu/arm720t/tegra20/Makefile
> similarity index 64%
> copy from arch/arm/cpu/tegra20-common/Makefile
> copy to arch/arm/cpu/arm720t/tegra20/Makefile
> index 28a4c81..6e48475 100644
> --- a/arch/arm/cpu/tegra20-common/Makefile
> +++ b/arch/arm/cpu/arm720t/tegra20/Makefile
> @@ -25,31 +25,19 @@
>
>  include $(TOPDIR)/config.mk
>
> -# The AVP is ARMv4T architecture so we must use special compiler
> -# flags for any startup files it might use.
> -CFLAGS_arch/arm/cpu/tegra20-common/ap20.o += -march=armv4t
> -CFLAGS_arch/arm/cpu/tegra20-common/clock.o += -march=armv4t
> -CFLAGS_arch/arm/cpu/tegra20-common/warmboot_avp.o += -march=armv4t
> +LIB    = $(obj)lib$(SOC).o
>
> -LIB    = $(obj)lib$(SOC)-common.o
> +COBJS-y        += cpu.o
> +COBJS-$(CONFIG_SPL_BUILD) += spl.o
>
> -SOBJS += lowlevel_init.o
> -COBJS-y        += ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o
> timer.o
> -COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o crypto.o warmboot_avp.o
> -COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
> -COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
> -
> -SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
> -OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
> +SRCS   := $(COBJS-y:.o=.c)
> +OBJS   := $(addprefix $(obj),$(COBJS-y))
>
>  all:   $(obj).depend $(LIB)
>
>  $(LIB):        $(OBJS)
>        $(call cmd_link_o_target, $(OBJS))
>
> -$(obj).depend:
> -       echo wtf
> -
>  #########################################################################
>
>  # defines $(obj).depend target
> diff --git a/arch/arm/cpu/arm720t/tegra20/board.h
> b/arch/arm/cpu/arm720t/tegra20/board.h
> new file mode 100644
> index 0000000..61b91c0
> --- /dev/null
> +++ b/arch/arm/cpu/arm720t/tegra20/board.h
> @@ -0,0 +1,25 @@
> +/*
> + * (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
> + */
> +
> +void board_init_uart_f(void);
> +void gpio_config_uart(void);
> diff --git a/arch/arm/cpu/arm720t/tegra20/cpu.c
> b/arch/arm/cpu/arm720t/tegra20/cpu.c
> new file mode 100644
> index 0000000..cdf417d
> --- /dev/null
> +++ b/arch/arm/cpu/arm720t/tegra20/cpu.c
> @@ -0,0 +1,259 @@
> +/*
> +* (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/io.h>
> +#include <asm/arch/tegra20.h>
> +#include <asm/arch/clk_rst.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/pmc.h>
> +#include <asm/arch/pinmux.h>
> +#include <asm/arch/scu.h>
> +#include <common.h>
> +#include "cpu.h"
> +
> +/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
> +int ap20_cpu_is_cortexa9(void)
> +{
> +       u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
> +       return id == (PG_UP_TAG_0_PID_CPU & 0xff);
> +}
> +
> +void init_pllx(void)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr
> *)NV_PA_CLK_RST_BASE;
> +       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
> +       u32 reg;
> +
> +       /* If PLLX is already enabled, just return */
> +       if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
> +               return;
> +
> +       /* Set PLLX_MISC */
> +       writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
> +
> +       /* Use 12MHz clock here */
> +       reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
> +       reg |= 1000 << PLL_DIVN_SHIFT;
> +       writel(reg, &pll->pll_base);
> +
> +       reg |= PLL_ENABLE_MASK;
> +       writel(reg, &pll->pll_base);
> +
> +       reg &= ~PLL_BYPASS_MASK;
> +       writel(reg, &pll->pll_base);
> +}
> +
> +static void enable_cpu_clock(int enable)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr
> *)NV_PA_CLK_RST_BASE;
> +       u32 clk;
> +
> +       /*
> +        * NOTE:
> +        * Regardless of whether the request is to enable or disable the
> CPU
> +        * clock, every processor in the CPU complex except the master
> (CPU 0)
> +        * will have it's clock stopped because the AVP only talks to the
> +        * master. The AVP does not know (nor does it need to know) that
> there
> +        * are multiple processors in the CPU complex.
> +        */
> +
> +       if (enable) {
> +               /* Initialize PLLX */
> +               init_pllx();
> +
> +               /* Wait until all clocks are stable */
> +               udelay(PLL_STABILIZATION_DELAY);
> +
> +               writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
> +               writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
> +       }
> +
> +       /*
> +        * Read the register containing the individual CPU clock enables
> and
> +        * always stop the clock to CPU 1.
> +        */
> +       clk = readl(&clkrst->crc_clk_cpu_cmplx);
> +       clk |= 1 << CPU1_CLK_STP_SHIFT;
> +
> +       /* Stop/Unstop the CPU clock */
> +       clk &= ~CPU0_CLK_STP_MASK;
> +       clk |= !enable << CPU0_CLK_STP_SHIFT;
> +       writel(clk, &clkrst->crc_clk_cpu_cmplx);
> +
> +       clock_enable(PERIPH_ID_CPU);
> +}
> +
> +static int is_cpu_powered(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
> +
> +       return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
> +}
> +
> +static void remove_cpu_io_clamps(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
> +       u32 reg;
> +
> +       /* Remove the clamps on the CPU I/O signals */
> +       reg = readl(&pmc->pmc_remove_clamping);
> +       reg |= CPU_CLMP;
> +       writel(reg, &pmc->pmc_remove_clamping);
> +
> +       /* Give I/O signals time to stabilize */
> +       udelay(IO_STABILIZATION_DELAY);
> +}
> +
> +static void powerup_cpu(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
> +       u32 reg;
> +       int timeout = IO_STABILIZATION_DELAY;
> +
> +       if (!is_cpu_powered()) {
> +               /* Toggle the CPU power state (OFF -> ON) */
> +               reg = readl(&pmc->pmc_pwrgate_toggle);
> +               reg &= PARTID_CP;
> +               reg |= START_CP;
> +               writel(reg, &pmc->pmc_pwrgate_toggle);
> +
> +               /* Wait for the power to come up */
> +               while (!is_cpu_powered()) {
> +                       if (timeout-- == 0)
> +                               printf("CPU failed to power up!\n");
> +                       else
> +                               udelay(10);
> +               }
> +
> +               /*
> +                * Remove the I/O clamps from CPU power partition.
> +                * Recommended only on a Warm boot, if the CPU partition
> gets
> +                * power gated. Shouldn't cause any harm when called after
> a
> +                * cold boot according to HW, probably just redundant.
> +                */
> +               remove_cpu_io_clamps();
> +       }
> +}
> +
> +static void enable_cpu_power_rail(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
> +       u32 reg;
> +
> +       reg = readl(&pmc->pmc_cntrl);
> +       reg |= CPUPWRREQ_OE;
> +       writel(reg, &pmc->pmc_cntrl);
> +
> +       /*
> +        * The TI PMU65861C needs a 3.75ms delay between enabling
> +        * the power rail and enabling the CPU clock.  This delay
> +        * between SM1EN and SM1 is for switching time + the ramp
> +        * up of the voltage to the CPU (VDD_CPU from PMU).
> +        */
> +       udelay(3750);
> +}
> +
> +static void reset_A9_cpu(int reset)
> +{
> +       /*
> +       * NOTE:  Regardless of whether the request is to hold the CPU in
> reset
> +       *        or take it out of reset, every processor in the CPU
> complex
> +       *        except the master (CPU 0) will be held in reset because
> the
> +       *        AVP only talks to the master. The AVP does not know that
> there
> +       *        are multiple processors in the CPU complex.
> +       */
> +
> +       /* Hold CPU 1 in reset, and CPU 0 if asked */
> +       reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de |
> crc_rst_debug, 1);
> +       reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
> +                              reset);
> +
> +       /* Enable/Disable master CPU reset */
> +       reset_set_enable(PERIPH_ID_CPU, reset);
> +}
> +
> +static void clock_enable_coresight(int enable)
> +{
> +       u32 rst, src;
> +
> +       clock_set_enable(PERIPH_ID_CORESIGHT, enable);
> +       reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
> +
> +       if (enable) {
> +               /*
> +                * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down
> by
> +                *  1.5, giving an effective frequency of 144MHz.
> +                * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
> +                *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
> +                */
> +               src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
> +               clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
> +
> +               /* Unlock the CPU CoreSight interfaces */
> +               rst = 0xC5ACCE55;
> +               writel(rst, CSITE_CPU_DBG0_LAR);
> +               writel(rst, CSITE_CPU_DBG1_LAR);
> +       }
> +}
> +
> +void start_cpu(u32 reset_vector)
> +{
> +       /* Enable VDD_CPU */
> +       enable_cpu_power_rail();
> +
> +       /* Hold the CPUs in reset */
> +       reset_A9_cpu(1);
> +
> +       /* Disable the CPU clock */
> +       enable_cpu_clock(0);
> +
> +       /* Enable CoreSight */
> +       clock_enable_coresight(1);
> +
> +       /*
> +        * Set the entry point for CPU execution from reset,
> +        *  if it's a non-zero value.
> +        */
> +       if (reset_vector)
> +               writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
> +
> +       /* Enable the CPU clock */
> +       enable_cpu_clock(1);
> +
> +       /* If the CPU doesn't already have power, power it up */
> +       powerup_cpu();
> +
> +       /* Take the CPU out of reset */
> +       reset_A9_cpu(0);
> +}
> +
> +
> +void halt_avp(void)
> +{
> +       for (;;) {
> +               writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
> +                       | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
> +                       FLOW_CTLR_HALT_COP_EVENTS);
> +       }
> +}
> +
> diff --git a/arch/arm/cpu/arm720t/tegra20/cpu.h
> b/arch/arm/cpu/arm720t/tegra20/cpu.h
> new file mode 100644
> index 0000000..90857a8
> --- /dev/null
> +++ b/arch/arm/cpu/arm720t/tegra20/cpu.h
> @@ -0,0 +1,99 @@
> +/*
> + * (C) Copyright 2010-2011
> + * NVIDIA Corporation <www.nvidia.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +#include <asm/types.h>
> +
> +/* Stabilization delays, in usec */
> +#define PLL_STABILIZATION_DELAY (300)
> +#define IO_STABILIZATION_DELAY (1000)
> +
> +#define NVBL_PLLP_KHZ  (216000)
> +
> +#define PLLX_ENABLED           (1 << 30)
> +#define CCLK_BURST_POLICY      0x20008888
> +#define SUPER_CCLK_DIVIDER     0x80000000
> +
> +/* Calculate clock fractional divider value from ref and target
> frequencies */
> +#define CLK_DIVIDER(REF, FREQ)  ((((REF) * 2) / FREQ) - 2)
> +
> +/* Calculate clock frequency value from reference and clock divider value
> */
> +#define CLK_FREQUENCY(REF, REG)  (((REF) * 2) / (REG + 2))
> +
> +/* AVP/CPU ID */
> +#define PG_UP_TAG_0_PID_CPU    0x55555555      /* CPU aka "a9" aka
> "mpcore" */
> +#define PG_UP_TAG_0             0x0
> +
> +#define CORESIGHT_UNLOCK       0xC5ACCE55;
> +
> +/* AP20-Specific Base Addresses */
> +
> +/* AP20 Base physical address of SDRAM. */
> +#define AP20_BASE_PA_SDRAM      0x00000000
> +/* AP20 Base physical address of internal SRAM. */
> +#define AP20_BASE_PA_SRAM       0x40000000
> +/* AP20 Size of internal SRAM (256KB). */
> +#define AP20_BASE_PA_SRAM_SIZE  0x00040000
> +/* AP20 Base physical address of flash. */
> +#define AP20_BASE_PA_NOR_FLASH  0xD0000000
> +/* AP20 Base physical address of boot information table. */
> +#define AP20_BASE_PA_BOOT_INFO  AP20_BASE_PA_SRAM
> +
> +/*
> + * Super-temporary stacks for EXTREMELY early startup. The values chosen
> for
> + * these addresses must be valid on ALL SOCs because this value is used
> before
> + * we are able to differentiate between the SOC types.
> + *
> + * NOTE: The since CPU's stack will eventually be moved from IRAM to
> SDRAM, its
> + *       stack is placed below the AVP stack. Once the CPU stack has been
> moved,
> + *       the AVP is free to use the IRAM the CPU stack previously
> occupied if
> + *       it should need to do so.
> + *
> + * NOTE: In multi-processor CPU complex configurations, each processor
> will have
> + *       its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have
> a
> + *       limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will
> have a
> + *       stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the
> previous
> + *       CPU.
> + */
> +
> +/* Common AVP early boot stack limit */
> +#define AVP_EARLY_BOOT_STACK_LIMIT     \
> +       (AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
> +/* Common AVP early boot stack size */
> +#define AVP_EARLY_BOOT_STACK_SIZE      0x1000
> +/* Common CPU early boot stack limit */
> +#define CPU_EARLY_BOOT_STACK_LIMIT     \
> +       (AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
> +/* Common CPU early boot stack size */
> +#define CPU_EARLY_BOOT_STACK_SIZE      0x1000
> +
> +#define EXCEP_VECTOR_CPU_RESET_VECTOR  (NV_PA_EVP_BASE + 0x100)
> +#define CSITE_CPU_DBG0_LAR             (NV_PA_CSITE_BASE + 0x10FB0)
> +#define CSITE_CPU_DBG1_LAR             (NV_PA_CSITE_BASE + 0x12FB0)
> +
> +#define FLOW_CTLR_HALT_COP_EVENTS      (NV_PA_FLOW_BASE + 4)
> +#define FLOW_MODE_STOP                 2
> +#define HALT_COP_EVENT_JTAG            (1 << 28)
> +#define HALT_COP_EVENT_IRQ_1           (1 << 11)
> +#define HALT_COP_EVENT_FIQ_1           (1 << 9)
> +
> +void start_cpu(u32 reset_vector);
> +int ap20_cpu_is_cortexa9(void);
> diff --git a/arch/arm/cpu/arm720t/tegra20/spl.c
> b/arch/arm/cpu/arm720t/tegra20/spl.c
> new file mode 100644
> index 0000000..e3d4dcc
> --- /dev/null
> +++ b/arch/arm/cpu/arm720t/tegra20/spl.c
> @@ -0,0 +1,133 @@
> +/*
> + * (C) Copyright 2012
> + * NVIDIA Inc, <www.nvidia.com>
> + *
> + * Allen Martin <amartin@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/u-boot.h>
> +#include <asm/utils.h>
> +#include <asm/arch/sys_proto.h>
> +#include <asm/arch/clock.h>
> +#include <nand.h>
> +#include <mmc.h>
> +#include <fat.h>
> +#include <version.h>
> +#include <i2c.h>
> +#include <image.h>
> +#include <malloc.h>
> +#include <linux/compiler.h>
> +#include "board.h"
> +#include "cpu.h"
> +
> +#include <asm/io.h>
> +#include <asm/arch/tegra20.h>
> +#include <asm/arch/clk_rst.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/pmc.h>
> +#include <asm/arch/pinmux.h>
> +#include <asm/arch/scu.h>
> +#include <common.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Define global data structure pointer to it*/
> +static gd_t gdata __attribute__ ((section(".data")));
> +static bd_t bdata __attribute__ ((section(".data")));
> +
> +inline void hang(void)
> +{
> +       puts("### ERROR ### Please RESET the board ###\n");
> +       for (;;)
> +               ;
> +}
> +
> +void board_init_f(ulong dummy)
> +{
> +       board_init_uart_f();
> +
> +       /* Initialize periph GPIOs */
> +#ifdef CONFIG_SPI_UART_SWITCH
> +       gpio_early_init_uart();
> +#else
> +       gpio_config_uart();
> +#endif
> +
> +       /*
> +        * We call relocate_code() with relocation target same as the
> +        * CONFIG_SYS_SPL_TEXT_BASE. This will result in relocation getting
> +        * skipped. Instead, only .bss initialization will happen. That's
> +        * all we need
> +        */
> +       debug(">>board_init_f()\n");
> +       relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
> +}
> +
> +/* This requires UART clocks to be enabled */
> +static void preloader_console_init(void)
> +{
> +       const char *u_boot_rev = U_BOOT_VERSION;
> +
> +       gd = &gdata;
> +       gd->bd = &bdata;
> +       gd->flags |= GD_FLG_RELOC;
> +       gd->baudrate = CONFIG_BAUDRATE;
> +
> +       serial_init();          /* serial communications setup */
> +
> +       gd->have_console = 1;
> +
> +       /* Avoid a second "U-Boot" coming from this string */
> +       u_boot_rev = &u_boot_rev[7];
> +
> +       printf("\nU-Boot SPL %s (%s - %s)\n", u_boot_rev, U_BOOT_DATE,
> +               U_BOOT_TIME);
> +}
> +
> +void board_init_r(gd_t *id, ulong dummy)
> +{
> +       u32 boot_device;
> +       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr
> *)NV_PA_APB_MISC_BASE;
> +       debug(">>spl:board_init_r()\n");
> +
> +       mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
> +                       CONFIG_SYS_SPL_MALLOC_SIZE);
> +
> +#ifdef CONFIG_SPL_BOARD_INIT
> +       spl_board_init();
> +#endif
> +
> +       clock_early_init();
> +       serial_init();
> +       preloader_console_init();
> +
> +       /* enable JTAG */
> +       writel(0xC0, &pmt->pmt_cfg_ctl);
> +
> +       start_cpu((u32)CONFIG_SYS_TEXT_BASE);
> +       halt_avp();
> +       /* not reached */
> +}
> +
> +int board_usb_init(const void *blob)
> +{
> +       return 0;
> +}
> diff --git a/arch/arm/cpu/tegra20-common/Makefile
> b/arch/arm/cpu/tegra20-common/Makefile
> index 28a4c81..572538b 100644
> --- a/arch/arm/cpu/tegra20-common/Makefile
> +++ b/arch/arm/cpu/tegra20-common/Makefile
> @@ -35,7 +35,7 @@ LIB   = $(obj)lib$(SOC)-common.o
>
>  SOBJS += lowlevel_init.o
>  COBJS-y        += ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o
> timer.o
> -COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o crypto.o warmboot_avp.o
> +COBJS-$(CONFIG_TEGRA20_LP0) += warmboot.o crypto.o warmboot_avp.o
>  COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
>  COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
>
> diff --git a/arch/arm/include/asm/arch-tegra20/hardware.h
> b/arch/arm/include/asm/arch-tegra20/hardware.h
> new file mode 100644
> index 0000000..8c47578
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-tegra20/hardware.h
> @@ -0,0 +1,29 @@
> +/*
> +* (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 __TEGRA2_HW_H
> +#define __TEGRA2_HW_H
> +
> +/* include tegra specific hardware definitions */
> +
> +#endif /* __TEGRA2_HW_H */
> --
> 1.7.9.5
>
> Regards,
Simon
Allen Martin - June 11, 2012, 7:01 p.m.
On Sat, Jun 09, 2012 at 11:32:08AM -0700, Simon Glass wrote:
> Hi Allen,
> 
> On Fri, Jun 8, 2012 at 2:16 PM, Allen Martin <amartin@nvidia.com<mailto:amartin@nvidia.com>> wrote:
> Add support for tegra20 arm7 boot processor.  This processor is used
> to power on the Cortex A9 and transfer control to it.
> 
> Signed-off-by: Allen Martin <amartin@nvidia.com<mailto:amartin@nvidia.com>>
> ---
>  arch/arm/cpu/arm720t/cpu.c                         |    2 +
>  arch/arm/cpu/arm720t/interrupts.c                  |    4 +
>  arch/arm/cpu/arm720t/start.S                       |    6 +-
>  .../{tegra20-common => arm720t/tegra20}/Makefile   |   22 +-
>  arch/arm/cpu/arm720t/tegra20/board.h               |   25 ++
>  arch/arm/cpu/arm720t/tegra20/cpu.c                 |  259 ++++++++++++++++++++
>  arch/arm/cpu/arm720t/tegra20/cpu.h                 |   99 ++++++++
>  arch/arm/cpu/arm720t/tegra20/spl.c                 |  133 ++++++++++
>  arch/arm/cpu/tegra20-common/Makefile               |    2 +-
>  arch/arm/include/asm/arch-tegra20/hardware.h       |   29 +++
> 
> I think this (empty) file is required by arm720t/cpu.c, right?

Yes.

> 
> You are using arm720t here, but your chip is actually an ARM7TDMI. I
> suppose that doesn't matter since there is no cache and they share
> the same core. But perhaps a comment would be useful explaining this
> difference and how it was convenient to use the same code.

Good point, will do.

-Allen

Patch

diff --git a/arch/arm/cpu/arm720t/cpu.c b/arch/arm/cpu/arm720t/cpu.c
index 974f288..b6eee7e 100644
--- a/arch/arm/cpu/arm720t/cpu.c
+++ b/arch/arm/cpu/arm720t/cpu.c
@@ -51,6 +51,8 @@  int cleanup_before_linux (void)
 	/* Nothing more needed */
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
 	/* No cleanup before linux for IntegratorAP/CM720T as yet */
+#elif defined (CONFIG_TEGRA)
+	/* No cleanup before linux for tegra as yet */
 #else
 #error No cleanup_before_linux() defined for this CPU type
 #endif
diff --git a/arch/arm/cpu/arm720t/interrupts.c b/arch/arm/cpu/arm720t/interrupts.c
index 464dd30..e64e6f2 100644
--- a/arch/arm/cpu/arm720t/interrupts.c
+++ b/arch/arm/cpu/arm720t/interrupts.c
@@ -180,6 +180,8 @@  int timer_init (void)
 	PUT32(T0TC, 0);
 	PUT32(T0TCR, 1);	/* enable timer0 */
 
+#elif defined(CONFIG_TEGRA)
+	/* No timer routines for tegra as yet */
 #else
 #error No timer_init() defined for this CPU type
 #endif
@@ -282,6 +284,8 @@  void __udelay (unsigned long usec)
 
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
 	/* No timer routines for IntegratorAP/CM720T as yet */
+#elif defined(CONFIG_TEGRA)
+	/* No timer routines for tegra as yet */
 #else
 #error Timer routines not defined for this CPU type
 #endif
diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S
index df66946..3371d3d 100644
--- a/arch/arm/cpu/arm720t/start.S
+++ b/arch/arm/cpu/arm720t/start.S
@@ -407,6 +407,8 @@  lock_loop:
 	ldr	r0, VPBDIV_ADR
 	mov	r1, #0x01	/* VPB clock is same as process clock */
 	str	r1, [r0]
+#elif defined(CONFIG_TEGRA)
+	/* No cpu_init_crit for tegra as yet */
 #else
 #error No cpu_init_crit() defined for current CPU type
 #endif
@@ -422,7 +424,7 @@  lock_loop:
 	str	r1, [r0]
 #endif
 
-#ifndef CONFIG_LPC2292
+#if !defined(CONFIG_LPC2292) && !defined(CONFIG_TEGRA)
 	mov	ip, lr
 	/*
 	 * before relocating, we have to setup RAM timing
@@ -631,6 +633,8 @@  reset_cpu:
 .globl reset_cpu
 reset_cpu:
 	mov	pc, r0
+#elif defined(CONFIG_TEGRA)
+	/* No specific reset actions for tegra as yet */
 #else
 #error No reset_cpu() defined for current CPU type
 #endif
diff --git a/arch/arm/cpu/tegra20-common/Makefile b/arch/arm/cpu/arm720t/tegra20/Makefile
similarity index 64%
copy from arch/arm/cpu/tegra20-common/Makefile
copy to arch/arm/cpu/arm720t/tegra20/Makefile
index 28a4c81..6e48475 100644
--- a/arch/arm/cpu/tegra20-common/Makefile
+++ b/arch/arm/cpu/arm720t/tegra20/Makefile
@@ -25,31 +25,19 @@ 
 
 include $(TOPDIR)/config.mk
 
-# The AVP is ARMv4T architecture so we must use special compiler
-# flags for any startup files it might use.
-CFLAGS_arch/arm/cpu/tegra20-common/ap20.o += -march=armv4t
-CFLAGS_arch/arm/cpu/tegra20-common/clock.o += -march=armv4t
-CFLAGS_arch/arm/cpu/tegra20-common/warmboot_avp.o += -march=armv4t
+LIB	= $(obj)lib$(SOC).o
 
-LIB	= $(obj)lib$(SOC)-common.o
+COBJS-y	+= cpu.o
+COBJS-$(CONFIG_SPL_BUILD) += spl.o
 
-SOBJS += lowlevel_init.o
-COBJS-y	+= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
-COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o crypto.o warmboot_avp.o
-COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
-COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
-OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+SRCS	:= $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
 
 all:	$(obj).depend $(LIB)
 
 $(LIB):	$(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
-$(obj).depend:
-	echo wtf
-
 #########################################################################
 
 # defines $(obj).depend target
diff --git a/arch/arm/cpu/arm720t/tegra20/board.h b/arch/arm/cpu/arm720t/tegra20/board.h
new file mode 100644
index 0000000..61b91c0
--- /dev/null
+++ b/arch/arm/cpu/arm720t/tegra20/board.h
@@ -0,0 +1,25 @@ 
+/*
+ * (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
+ */
+
+void board_init_uart_f(void);
+void gpio_config_uart(void);
diff --git a/arch/arm/cpu/arm720t/tegra20/cpu.c b/arch/arm/cpu/arm720t/tegra20/cpu.c
new file mode 100644
index 0000000..cdf417d
--- /dev/null
+++ b/arch/arm/cpu/arm720t/tegra20/cpu.c
@@ -0,0 +1,259 @@ 
+/*
+* (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/io.h>
+#include <asm/arch/tegra20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/scu.h>
+#include <common.h>
+#include "cpu.h"
+
+/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
+int ap20_cpu_is_cortexa9(void)
+{
+	u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
+	return id == (PG_UP_TAG_0_PID_CPU & 0xff);
+}
+
+void init_pllx(void)
+{
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
+	u32 reg;
+
+	/* If PLLX is already enabled, just return */
+	if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
+		return;
+
+	/* Set PLLX_MISC */
+	writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
+
+	/* Use 12MHz clock here */
+	reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
+	reg |= 1000 << PLL_DIVN_SHIFT;
+	writel(reg, &pll->pll_base);
+
+	reg |= PLL_ENABLE_MASK;
+	writel(reg, &pll->pll_base);
+
+	reg &= ~PLL_BYPASS_MASK;
+	writel(reg, &pll->pll_base);
+}
+
+static void enable_cpu_clock(int enable)
+{
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 clk;
+
+	/*
+	 * NOTE:
+	 * Regardless of whether the request is to enable or disable the CPU
+	 * clock, every processor in the CPU complex except the master (CPU 0)
+	 * will have it's clock stopped because the AVP only talks to the
+	 * master. The AVP does not know (nor does it need to know) that there
+	 * are multiple processors in the CPU complex.
+	 */
+
+	if (enable) {
+		/* Initialize PLLX */
+		init_pllx();
+
+		/* Wait until all clocks are stable */
+		udelay(PLL_STABILIZATION_DELAY);
+
+		writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+		writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
+	}
+
+	/*
+	 * Read the register containing the individual CPU clock enables and
+	 * always stop the clock to CPU 1.
+	 */
+	clk = readl(&clkrst->crc_clk_cpu_cmplx);
+	clk |= 1 << CPU1_CLK_STP_SHIFT;
+
+	/* Stop/Unstop the CPU clock */
+	clk &= ~CPU0_CLK_STP_MASK;
+	clk |= !enable << CPU0_CLK_STP_SHIFT;
+	writel(clk, &clkrst->crc_clk_cpu_cmplx);
+
+	clock_enable(PERIPH_ID_CPU);
+}
+
+static int is_cpu_powered(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+
+	return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+}
+
+static void remove_cpu_io_clamps(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+	u32 reg;
+
+	/* Remove the clamps on the CPU I/O signals */
+	reg = readl(&pmc->pmc_remove_clamping);
+	reg |= CPU_CLMP;
+	writel(reg, &pmc->pmc_remove_clamping);
+
+	/* Give I/O signals time to stabilize */
+	udelay(IO_STABILIZATION_DELAY);
+}
+
+static void powerup_cpu(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+	u32 reg;
+	int timeout = IO_STABILIZATION_DELAY;
+
+	if (!is_cpu_powered()) {
+		/* Toggle the CPU power state (OFF -> ON) */
+		reg = readl(&pmc->pmc_pwrgate_toggle);
+		reg &= PARTID_CP;
+		reg |= START_CP;
+		writel(reg, &pmc->pmc_pwrgate_toggle);
+
+		/* Wait for the power to come up */
+		while (!is_cpu_powered()) {
+			if (timeout-- == 0)
+				printf("CPU failed to power up!\n");
+			else
+				udelay(10);
+		}
+
+		/*
+		 * Remove the I/O clamps from CPU power partition.
+		 * Recommended only on a Warm boot, if the CPU partition gets
+		 * power gated. Shouldn't cause any harm when called after a
+		 * cold boot according to HW, probably just redundant.
+		 */
+		remove_cpu_io_clamps();
+	}
+}
+
+static void enable_cpu_power_rail(void)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+	u32 reg;
+
+	reg = readl(&pmc->pmc_cntrl);
+	reg |= CPUPWRREQ_OE;
+	writel(reg, &pmc->pmc_cntrl);
+
+	/*
+	 * The TI PMU65861C needs a 3.75ms delay between enabling
+	 * the power rail and enabling the CPU clock.  This delay
+	 * between SM1EN and SM1 is for switching time + the ramp
+	 * up of the voltage to the CPU (VDD_CPU from PMU).
+	 */
+	udelay(3750);
+}
+
+static void reset_A9_cpu(int reset)
+{
+	/*
+	* NOTE:  Regardless of whether the request is to hold the CPU in reset
+	*        or take it out of reset, every processor in the CPU complex
+	*        except the master (CPU 0) will be held in reset because the
+	*        AVP only talks to the master. The AVP does not know that there
+	*        are multiple processors in the CPU complex.
+	*/
+
+	/* Hold CPU 1 in reset, and CPU 0 if asked */
+	reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
+	reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
+			       reset);
+
+	/* Enable/Disable master CPU reset */
+	reset_set_enable(PERIPH_ID_CPU, reset);
+}
+
+static void clock_enable_coresight(int enable)
+{
+	u32 rst, src;
+
+	clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+	reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
+
+	if (enable) {
+		/*
+		 * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
+		 *  1.5, giving an effective frequency of 144MHz.
+		 * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
+		 *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
+		 */
+		src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
+		clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
+
+		/* Unlock the CPU CoreSight interfaces */
+		rst = 0xC5ACCE55;
+		writel(rst, CSITE_CPU_DBG0_LAR);
+		writel(rst, CSITE_CPU_DBG1_LAR);
+	}
+}
+
+void start_cpu(u32 reset_vector)
+{
+	/* Enable VDD_CPU */
+	enable_cpu_power_rail();
+
+	/* Hold the CPUs in reset */
+	reset_A9_cpu(1);
+
+	/* Disable the CPU clock */
+	enable_cpu_clock(0);
+
+	/* Enable CoreSight */
+	clock_enable_coresight(1);
+
+	/*
+	 * Set the entry point for CPU execution from reset,
+	 *  if it's a non-zero value.
+	 */
+	if (reset_vector)
+		writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+	/* Enable the CPU clock */
+	enable_cpu_clock(1);
+
+	/* If the CPU doesn't already have power, power it up */
+	powerup_cpu();
+
+	/* Take the CPU out of reset */
+	reset_A9_cpu(0);
+}
+
+
+void halt_avp(void)
+{
+	for (;;) {
+		writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
+			| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
+			FLOW_CTLR_HALT_COP_EVENTS);
+	}
+}
+
diff --git a/arch/arm/cpu/arm720t/tegra20/cpu.h b/arch/arm/cpu/arm720t/tegra20/cpu.h
new file mode 100644
index 0000000..90857a8
--- /dev/null
+++ b/arch/arm/cpu/arm720t/tegra20/cpu.h
@@ -0,0 +1,99 @@ 
+/*
+ * (C) Copyright 2010-2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <asm/types.h>
+
+/* Stabilization delays, in usec */
+#define PLL_STABILIZATION_DELAY (300)
+#define IO_STABILIZATION_DELAY	(1000)
+
+#define NVBL_PLLP_KHZ	(216000)
+
+#define PLLX_ENABLED		(1 << 30)
+#define CCLK_BURST_POLICY	0x20008888
+#define SUPER_CCLK_DIVIDER	0x80000000
+
+/* Calculate clock fractional divider value from ref and target frequencies */
+#define CLK_DIVIDER(REF, FREQ)  ((((REF) * 2) / FREQ) - 2)
+
+/* Calculate clock frequency value from reference and clock divider value */
+#define CLK_FREQUENCY(REF, REG)  (((REF) * 2) / (REG + 2))
+
+/* AVP/CPU ID */
+#define PG_UP_TAG_0_PID_CPU	0x55555555	/* CPU aka "a9" aka "mpcore" */
+#define PG_UP_TAG_0             0x0
+
+#define CORESIGHT_UNLOCK	0xC5ACCE55;
+
+/* AP20-Specific Base Addresses */
+
+/* AP20 Base physical address of SDRAM. */
+#define AP20_BASE_PA_SDRAM      0x00000000
+/* AP20 Base physical address of internal SRAM. */
+#define AP20_BASE_PA_SRAM       0x40000000
+/* AP20 Size of internal SRAM (256KB). */
+#define AP20_BASE_PA_SRAM_SIZE  0x00040000
+/* AP20 Base physical address of flash. */
+#define AP20_BASE_PA_NOR_FLASH  0xD0000000
+/* AP20 Base physical address of boot information table. */
+#define AP20_BASE_PA_BOOT_INFO  AP20_BASE_PA_SRAM
+
+/*
+ * Super-temporary stacks for EXTREMELY early startup. The values chosen for
+ * these addresses must be valid on ALL SOCs because this value is used before
+ * we are able to differentiate between the SOC types.
+ *
+ * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
+ *       stack is placed below the AVP stack. Once the CPU stack has been moved,
+ *       the AVP is free to use the IRAM the CPU stack previously occupied if
+ *       it should need to do so.
+ *
+ * NOTE: In multi-processor CPU complex configurations, each processor will have
+ *       its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
+ *       limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
+ *       stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
+ *       CPU.
+ */
+
+/* Common AVP early boot stack limit */
+#define AVP_EARLY_BOOT_STACK_LIMIT	\
+	(AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
+/* Common AVP early boot stack size */
+#define AVP_EARLY_BOOT_STACK_SIZE	0x1000
+/* Common CPU early boot stack limit */
+#define CPU_EARLY_BOOT_STACK_LIMIT	\
+	(AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
+/* Common CPU early boot stack size */
+#define CPU_EARLY_BOOT_STACK_SIZE	0x1000
+
+#define EXCEP_VECTOR_CPU_RESET_VECTOR	(NV_PA_EVP_BASE + 0x100)
+#define CSITE_CPU_DBG0_LAR		(NV_PA_CSITE_BASE + 0x10FB0)
+#define CSITE_CPU_DBG1_LAR		(NV_PA_CSITE_BASE + 0x12FB0)
+
+#define FLOW_CTLR_HALT_COP_EVENTS	(NV_PA_FLOW_BASE + 4)
+#define FLOW_MODE_STOP			2
+#define HALT_COP_EVENT_JTAG		(1 << 28)
+#define HALT_COP_EVENT_IRQ_1		(1 << 11)
+#define HALT_COP_EVENT_FIQ_1		(1 << 9)
+
+void start_cpu(u32 reset_vector);
+int ap20_cpu_is_cortexa9(void);
diff --git a/arch/arm/cpu/arm720t/tegra20/spl.c b/arch/arm/cpu/arm720t/tegra20/spl.c
new file mode 100644
index 0000000..e3d4dcc
--- /dev/null
+++ b/arch/arm/cpu/arm720t/tegra20/spl.c
@@ -0,0 +1,133 @@ 
+/*
+ * (C) Copyright 2012
+ * NVIDIA Inc, <www.nvidia.com>
+ *
+ * Allen Martin <amartin@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/u-boot.h>
+#include <asm/utils.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clock.h>
+#include <nand.h>
+#include <mmc.h>
+#include <fat.h>
+#include <version.h>
+#include <i2c.h>
+#include <image.h>
+#include <malloc.h>
+#include <linux/compiler.h>
+#include "board.h"
+#include "cpu.h"
+
+#include <asm/io.h>
+#include <asm/arch/tegra20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/scu.h>
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Define global data structure pointer to it*/
+static gd_t gdata __attribute__ ((section(".data")));
+static bd_t bdata __attribute__ ((section(".data")));
+
+inline void hang(void)
+{
+	puts("### ERROR ### Please RESET the board ###\n");
+	for (;;)
+		;
+}
+
+void board_init_f(ulong dummy)
+{
+	board_init_uart_f();
+
+	/* Initialize periph GPIOs */
+#ifdef CONFIG_SPI_UART_SWITCH
+	gpio_early_init_uart();
+#else
+	gpio_config_uart();
+#endif
+
+	/*
+	 * We call relocate_code() with relocation target same as the
+	 * CONFIG_SYS_SPL_TEXT_BASE. This will result in relocation getting
+	 * skipped. Instead, only .bss initialization will happen. That's
+	 * all we need
+	 */
+	debug(">>board_init_f()\n");
+	relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
+}
+
+/* This requires UART clocks to be enabled */
+static void preloader_console_init(void)
+{
+	const char *u_boot_rev = U_BOOT_VERSION;
+
+	gd = &gdata;
+	gd->bd = &bdata;
+	gd->flags |= GD_FLG_RELOC;
+	gd->baudrate = CONFIG_BAUDRATE;
+
+	serial_init();		/* serial communications setup */
+
+	gd->have_console = 1;
+
+	/* Avoid a second "U-Boot" coming from this string */
+	u_boot_rev = &u_boot_rev[7];
+
+	printf("\nU-Boot SPL %s (%s - %s)\n", u_boot_rev, U_BOOT_DATE,
+		U_BOOT_TIME);
+}
+
+void board_init_r(gd_t *id, ulong dummy)
+{
+	u32 boot_device;
+	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	debug(">>spl:board_init_r()\n");
+
+	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
+			CONFIG_SYS_SPL_MALLOC_SIZE);
+
+#ifdef CONFIG_SPL_BOARD_INIT
+	spl_board_init();
+#endif
+
+	clock_early_init();
+	serial_init();
+	preloader_console_init();
+
+	/* enable JTAG */
+	writel(0xC0, &pmt->pmt_cfg_ctl);
+
+	start_cpu((u32)CONFIG_SYS_TEXT_BASE);
+	halt_avp();
+	/* not reached */
+}
+
+int board_usb_init(const void *blob)
+{
+	return 0;
+}
diff --git a/arch/arm/cpu/tegra20-common/Makefile b/arch/arm/cpu/tegra20-common/Makefile
index 28a4c81..572538b 100644
--- a/arch/arm/cpu/tegra20-common/Makefile
+++ b/arch/arm/cpu/tegra20-common/Makefile
@@ -35,7 +35,7 @@  LIB	= $(obj)lib$(SOC)-common.o
 
 SOBJS += lowlevel_init.o
 COBJS-y	+= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
-COBJS-$(CONFIG_TEGRA2_LP0) += warmboot.o crypto.o warmboot_avp.o
+COBJS-$(CONFIG_TEGRA20_LP0) += warmboot.o crypto.o warmboot_avp.o
 COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
 
diff --git a/arch/arm/include/asm/arch-tegra20/hardware.h b/arch/arm/include/asm/arch-tegra20/hardware.h
new file mode 100644
index 0000000..8c47578
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra20/hardware.h
@@ -0,0 +1,29 @@ 
+/*
+* (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 __TEGRA2_HW_H
+#define __TEGRA2_HW_H
+
+/* include tegra specific hardware definitions */
+
+#endif /* __TEGRA2_HW_H */