[U-Boot] [PATCH] arm: Tegra2: add support for A9 CPU init

Tom Warren twarren.nvidia at gmail.com
Wed Feb 23 00:41:38 CET 2011


Anyone willing to review this? I'd like to get it pulled in to
Albert's arm repo ASAP.

Thanks,

Tom

On Wed, Feb 16, 2011 at 1:26 PM, Tom Warren <twarren.nvidia at gmail.com> wrote:
> Signed-off-by: Tom Warren <twarren at nvidia.com>
> ---
>  arch/arm/cpu/armv7/start.S                 |    6 +
>  arch/arm/cpu/armv7/tegra2/Makefile         |    2 +-
>  arch/arm/cpu/armv7/tegra2/ap20.c           |  490 ++++++++++++++++++++++++++++
>  arch/arm/cpu/armv7/tegra2/ap20.h           |  105 ++++++
>  arch/arm/include/asm/arch-tegra2/clk_rst.h |   27 ++
>  arch/arm/include/asm/arch-tegra2/pmc.h     |    8 +
>  arch/arm/include/asm/arch-tegra2/scu.h     |   43 +++
>  arch/arm/include/asm/arch-tegra2/tegra2.h  |    5 +
>  board/nvidia/common/board.c                |   10 +
>  board/nvidia/common/board.h                |   29 ++
>  include/configs/harmony.h                  |    1 +
>  include/configs/seaboard.h                 |    1 +
>  include/configs/tegra2-common.h            |    2 +
>  13 files changed, 728 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/tegra2/ap20.c
>  create mode 100644 arch/arm/cpu/armv7/tegra2/ap20.h
>  create mode 100644 arch/arm/include/asm/arch-tegra2/scu.h
>  create mode 100644 board/nvidia/common/board.h
>
> diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
> index 684f2d2..50a1725 100644
> --- a/arch/arm/cpu/armv7/start.S
> +++ b/arch/arm/cpu/armv7/start.S
> @@ -70,6 +70,12 @@ _end_vect:
>  _TEXT_BASE:
>        .word   CONFIG_SYS_TEXT_BASE
>
> +#ifdef CONFIG_TEGRA2
> +.globl _armboot_start
> +_armboot_start:
> +        .word _start
> +#endif
> +
>  /*
>  * These are defined in the board-specific linker script.
>  */
> diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
> index 687c887..f1ea915 100644
> --- a/arch/arm/cpu/armv7/tegra2/Makefile
> +++ b/arch/arm/cpu/armv7/tegra2/Makefile
> @@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
>  LIB    =  $(obj)lib$(SOC).o
>
>  SOBJS  := lowlevel_init.o
> -COBJS  := board.o sys_info.o timer.o
> +COBJS  := ap20.o board.o sys_info.o timer.o
>
>  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
> new file mode 100644
> index 0000000..89d0d5e
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/tegra2/ap20.c
> @@ -0,0 +1,490 @@
> +/*
> +* (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 "ap20.h"
> +#include <asm/io.h>
> +#include <asm/arch/tegra2.h>
> +#include <asm/arch/clk_rst.h>
> +#include <asm/arch/pmc.h>
> +#include <asm/arch/pinmux.h>
> +#include <asm/arch/scu.h>
> +#include <common.h>
> +
> +static void init_pll_x(void)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
> +       u32     reg;
> +
> +       /* Is PLL-X already running? */
> +       reg = readl(&clkrst->crc_pllx_base);
> +       if (reg & PLL_ENABLE)
> +               return;
> +
> +       /* Do PLLX init if it isn't running, but BootROM sets it, so TBD */
> +}
> +
> +static void set_cpu_reset_vector(u32 vector)
> +{
> +       writel(vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
> +}
> +
> +static void enable_cpu_clock(int enable)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
> +       u32   reg, 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.
> +        */
> +
> +       /* Need to initialize PLLX? */
> +       if (enable) {
> +               /* Initialize PLL */
> +               init_pll_x();
> +
> +               /* Wait until stable */
> +               udelay(NVBOOT_CLOCKS_PLL_STABILIZATION_DELAY);
> +
> +               reg = CCLK_BURST_POLICY;
> +               writel(reg, &clkrst->crc_cclk_brst_pol);
> +
> +               reg = SUPER_CCLK_DIVIDER;
> +               writel(reg, &clkrst->crc_super_cclk_div);
> +       }
> +
> +       /* Fetch the register containing the main CPU complex clock enable */
> +       reg = readl(&clkrst->crc_clk_out_enb_l);
> +
> +       /*
> +        * 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 |= CPU1_CLK_STP;
> +
> +       if (enable) {
> +               /* Enable the CPU clock */
> +               reg = readl(&clkrst->crc_clk_out_enb_l);
> +               reg |= CLK_ENB_CPU;
> +               clk = readl(&clkrst->crc_clk_cpu_cmplx);
> +               clk &= ~CPU0_CLK_STP;
> +       } else {
> +               /* Disable the CPU clock */
> +               reg = readl(&clkrst->crc_clk_out_enb_l);
> +               reg |= CLK_ENB_CPU;
> +               clk = readl(&clkrst->crc_clk_cpu_cmplx);
> +               clk |= CPU0_CLK_STP;
> +       }
> +
> +       writel(clk, &clkrst->crc_clk_cpu_cmplx);
> +       writel(reg, &clkrst->crc_clk_out_enb_l);
> +}
> +
> +static int is_cpu_powered(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
> +       u32   reg;
> +
> +       reg = readl(&pmc->pmc_pwrgate_status);
> +
> +       if (reg & CPU_PWRED)
> +               return TRUE;
> +
> +       return FALSE;
> +}
> +
> +static void remove_cpu_io_clamps(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_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(1000);
> +}
> +
> +static void powerup_cpu(void)
> +{
> +       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
> +       u32   reg;
> +
> +       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())
> +                       ;                       /* Do nothing */
> +
> +               /*
> +                * 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 *)NV_PA_PMC_BASE;
> +       u32   reg;
> +
> +       reg = readl(&pmc->pmc_cntrl);
> +       reg |= CPUPWRREQ_OE;
> +       writel(reg, &pmc->pmc_cntrl);
> +
> +       /* Delay to allow for stable power (CPU_PWR_REQ -> VDD_CPU from PMU) */
> +       udelay(3750);
> +}
> +
> +static void reset_A9_cpu(int reset)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
> +       u32   reg, cpu;
> +
> +       /*
> +       * 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 */
> +       cpu = SET_DBGRESET1 | SET_DERESET1 | SET_CPURESET1;
> +       writel(cpu, &clkrst->crc_cpu_cmplx_set);
> +
> +       reg = readl(&clkrst->crc_rst_dev_l);
> +       if (reset) {
> +               /* Place CPU0 into reset */
> +               cpu = SET_DBGRESET0 | SET_DERESET0 | SET_CPURESET0;
> +               writel(cpu, &clkrst->crc_cpu_cmplx_set);
> +
> +               /* Enable master CPU reset */
> +               reg |= SWR_CPU_RST;
> +
> +       } else {
> +               /* Take CPU0 out of reset */
> +               cpu = CLR_DBGRESET0 | CLR_DERESET0 | CLR_CPURESET0;
> +               writel(cpu, &clkrst->crc_cpu_cmplx_clr);
> +
> +               /* Disable master CPU reset */
> +               reg &= ~SWR_CPU_RST;
> +       }
> +
> +       writel(reg, &clkrst->crc_rst_dev_l);
> +}
> +
> +static void clock_enable_coresight(int enable)
> +{
> +       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
> +       u32   rst, clk, src;
> +
> +       rst = readl(&clkrst->crc_rst_dev_u);
> +       clk = readl(&clkrst->crc_clk_out_enb_u);
> +
> +       if (enable) {
> +               rst &= ~SWR_CSITE_RST;
> +               clk |= CLK_ENB_CSITE;
> +       } else {
> +               rst |= SWR_CSITE_RST;
> +               clk &= ~CLK_ENB_CSITE;
> +       }
> +
> +       writel(clk, &clkrst->crc_clk_out_enb_u);
> +       writel(rst, &clkrst->crc_rst_dev_u);
> +
> +       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);
> +               writel(src, &clkrst->crc_clk_src_csite);
> +
> +               /* 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(TRUE);
> +
> +       /* Disable the CPU clock */
> +       enable_cpu_clock(FALSE);
> +
> +       /* Enable CoreSight */
> +       clock_enable_coresight(TRUE);
> +
> +       /*
> +       * Set the entry point for CPU execution from reset,
> +       *  if it's a non-zero value.
> +       */
> +       if (reset_vector)
> +               set_cpu_reset_vector(reset_vector);
> +
> +       /* Enable the CPU clock */
> +       enable_cpu_clock(TRUE);
> +
> +       /* If the CPU doesn't already have power, power it up */
> +       if (!is_cpu_powered())
> +               powerup_cpu();
> +
> +       /* Take the CPU out of reset */
> +       reset_A9_cpu(FALSE);
> +}
> +
> +
> +void halt_avp(void)
> +{
> +       u32   reg;
> +
> +       for (;;) {
> +               reg = HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
> +                       | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29);
> +               writel(reg, FLOW_CTLR_HALT_COP_EVENTS);
> +       }
> +       /* Should never get here */
> +       for (;;)
> +               ;
> +}
> +
> +void startup_cpu(void)
> +{
> +       /* Initialize the AVP, clocks, and memory controller */
> +       /* SDRAM is guaranteed to be on at this point */
> +
> +       asm volatile(
> +
> +       /* Start the CPU */
> +       /* R0 = reset vector for CPU */
> +       "ldr     r0, =cold_boot      \n"
> +       "bl      start_cpu           \n"
> +
> +       /* Transfer control to the AVP code */
> +       "bl      halt_avp            \n"
> +
> +       /* Should never get here */
> +       "b       .                   \n"
> +       );
> +}
> +
> +extern ulong _armboot_start;
> +u32 cpu_boot_stack = CPU_EARLY_BOOT_STACK_LIMIT;
> +u32 avp_boot_stack = AVP_EARLY_BOOT_STACK_LIMIT;
> +u32 proc_tag = PG_UP_TAG_0_PID_CPU & 0xFF;
> +u32 deadbeef = 0xdeadbeef;
> +
> +void cold_boot(void)
> +{
> +       asm volatile(
> +
> +       "msr     cpsr_c, #0xd3            \n"
> +       /*
> +       * Check current processor: CPU or AVP?
> +       * If AVP, go to AVP boot code, else continue on.
> +       */
> +       "mov     r0, %0                   \n"
> +       "ldrb    r2, [r0, %1]             \n"
> +       /* are we the CPU? */
> +       "cmp     r2, %2                   \n"
> +       "mov     sp, %3                   \n"
> +       /* leave in some symbols for release debugging */
> +       "mov     r3, %6                   \n"
> +       "str     r3, [sp, #-4]!           \n"
> +       "str     r3, [sp, #-4]!           \n"
> +       /*  yep, we are the CPU */
> +       "bxeq     %4                      \n"
> +       /* AVP Initialization follows this path */
> +       "mov     sp, %5                   \n"
> +       /* leave in some symbols for release debugging */
> +       "mov     r3, %6                   \n"
> +       "str     r3, [sp, #-4]!           \n"
> +       "str     r3, [sp, #-4]!           \n"
> +
> +       /* Init and Start CPU */
> +       "b       startup_cpu              \n"
> +       :
> +       : "i"(NV_PA_PG_UP_BASE),
> +       "i"(PG_UP_TAG_0),
> +       "r"(proc_tag),
> +       "r"(cpu_boot_stack),
> +       "r"(_armboot_start),
> +       "r"(avp_boot_stack),
> +       "r"(deadbeef)
> +       : "r0", "r2", "r3", "cc", "lr"
> +       );
> +}
> +
> +void enable_scu(void)
> +{
> +       struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
> +       u32 reg;
> +
> +       reg = readl(&scu->scu_ctrl);
> +       if (reg & SCU_ENABLE) {
> +               /* SCU already enabled, return */
> +               return;
> +       }
> +
> +       /* Invalidate all ways for all processors */
> +       writel(0xFFFF, &scu->scu_inv_all);
> +
> +       /* Enable SCU - bit 0 */
> +       reg = readl(&scu->scu_ctrl);
> +       reg |= SCU_ENABLE;
> +       writel(reg, &scu->scu_ctrl);
> +
> +       return;
> +}
> +
> +void cache_configure(void)
> +{
> +       asm volatile(
> +
> +       "stmdb r13!,{r14}                 \n"
> +       /* invalidate instruction cache */
> +       "mov r1, #0                       \n"
> +       "mcr p15, 0, r1, c7, c5, 0        \n"
> +
> +       /* invalidate the i&d tlb entries */
> +       "mcr p15, 0, r1, c8, c5, 0        \n"
> +       "mcr p15, 0, r1, c8, c6, 0        \n"
> +
> +       /* enable instruction cache */
> +       "mrc  p15, 0, r1, c1, c0, 0       \n"
> +       "orr  r1, r1, #(1<<12)            \n"
> +       "mcr  p15, 0, r1, c1, c0, 0       \n"
> +
> +       "bl enable_scu                    \n"
> +
> +       /* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
> +       "mrc p15, 0, r0, c1, c0, 1        \n"
> +       "orr r0, r0, #0x41                \n"
> +       "mcr p15, 0, r0, c1, c0, 1        \n"
> +
> +       /* Now flush the Dcache */
> +       "mov r0, #0                       \n"
> +       /* 256 cache lines */
> +       "mov r1, #256                     \n"
> +
> +       "invalidate_loop:                 \n"
> +
> +       "add r1, r1, #-1                  \n"
> +       "mov r0, r1, lsl #5               \n"
> +       /* invalidate d-cache using line (way0) */
> +       "mcr p15, 0, r0, c7, c6, 2        \n"
> +
> +       "orr r2, r0, #(1<<30)             \n"
> +       /* invalidate d-cache using line (way1) */
> +       "mcr p15, 0, r2, c7, c6, 2        \n"
> +
> +       "orr r2, r0, #(2<<30)             \n"
> +       /* invalidate d-cache using line (way2) */
> +       "mcr p15, 0, r2, c7, c6, 2        \n"
> +
> +       "orr r2, r0, #(3<<30)             \n"
> +       /* invalidate d-cache using line (way3) */
> +       "mcr p15, 0, r2, c7, c6, 2        \n"
> +       "cmp r1, #0                       \n"
> +       "bne invalidate_loop              \n"
> +
> +       /* FIXME: should have ap20's L2 disabled too */
> +       "invalidate_done:                 \n"
> +       "ldmia r13!,{pc}                  \n"
> +       ".ltorg                           \n"
> +       );
> +}
> +
> +void init_pmc_scratch(void)
> +{
> +       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
> +
> +       /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
> +       memset(&pmc->pmc_scratch1, 0, 23*4);
> +       writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
> +}
> +
> +u32 s_first_boot = 1;
> +
> +void cpu_start(void)
> +{
> +       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
> +
> +       /* enable JTAG */
> +       writel(0xC0, &pmt->pmt_cfg_ctl);
> +
> +       if (s_first_boot) {
> +               /*
> +                * Need to set this before cold-booting,
> +                *  otherwise we'll end up in an infinite loop.
> +                */
> +               s_first_boot = 0;
> +               cold_boot();
> +       }
> +
> +       return;
> +}
> +
> +void tegra2_start()
> +{
> +       if (s_first_boot) {
> +               /* Init Debug UART Port (115200 8n1) */
> +               uart_init();
> +
> +               /* Init PMC scratch memory */
> +               init_pmc_scratch();
> +       }
> +
> +#ifdef CONFIG_ENABLE_CORTEXA9
> +       /* take the mpcore out of reset */
> +       cpu_start();
> +
> +       /* configure cache */
> +       cache_configure();
> +#endif
> +}
> +
> diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/cpu/armv7/tegra2/ap20.h
> new file mode 100644
> index 0000000..de7622d
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/tegra2/ap20.h
> @@ -0,0 +1,105 @@
> +/*
> + * (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>
> +
> +#ifndef        FALSE
> +#define FALSE  0
> +#endif
> +#ifndef TRUE
> +#define TRUE   1
> +#endif
> +
> +#define NVBL_PLLP_KHZ  (432000/2)
> +/* The stabilization delay in usec */
> +#define NVBOOT_CLOCKS_PLL_STABILIZATION_DELAY (300)
> +
> +#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
> +
> +/* 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)
> +
> +/* Prototypes */
> +
> +void tegra2_start(void);
> +void uart_init(void);
> +void udelay(unsigned long);
> diff --git a/arch/arm/include/asm/arch-tegra2/clk_rst.h b/arch/arm/include/asm/arch-tegra2/clk_rst.h
> index 6d573bf..d67a5d7 100644
> --- a/arch/arm/include/asm/arch-tegra2/clk_rst.h
> +++ b/arch/arm/include/asm/arch-tegra2/clk_rst.h
> @@ -149,6 +149,9 @@ struct clk_rst_ctlr {
>        uint crc_clk_src_csite;         /*_CSITE_0,             0x1D4 */
>        uint crc_reserved19[9];         /*                      0x1D8-1F8 */
>        uint crc_clk_src_osc;           /*_OSC_0,               0x1FC */
> +       uint crc_reserved20[80];        /*                      0x200-33C */
> +       uint crc_cpu_cmplx_set;         /* _CPU_CMPLX_SET_0,    0x340 */
> +       uint crc_cpu_cmplx_clr;         /* _CPU_CMPLX_CLR_0,    0x344 */
>  };
>
>  #define PLL_BYPASS             (1 << 31)
> @@ -162,4 +165,28 @@ struct clk_rst_ctlr {
>  #define SWR_UARTA_RST          (1 << 6)
>  #define CLK_ENB_UARTA          (1 << 6)
>
> +#define SWR_CPU_RST            (1 << 0)
> +#define CLK_ENB_CPU            (1 << 0)
> +#define SWR_CSITE_RST          (1 << 9)
> +#define CLK_ENB_CSITE          (1 << 9)
> +
> +#define SET_CPURESET0          (1 << 0)
> +#define SET_DERESET0           (1 << 4)
> +#define SET_DBGRESET0          (1 << 12)
> +
> +#define SET_CPURESET1          (1 << 1)
> +#define SET_DERESET1           (1 << 5)
> +#define SET_DBGRESET1          (1 << 13)
> +
> +#define CLR_CPURESET0          (1 << 0)
> +#define CLR_DERESET0           (1 << 4)
> +#define CLR_DBGRESET0          (1 << 12)
> +
> +#define CLR_CPURESET1          (1 << 1)
> +#define CLR_DERESET1           (1 << 5)
> +#define CLR_DBGRESET1          (1 << 13)
> +
> +#define CPU0_CLK_STP           (1 << 8)
> +#define CPU1_CLK_STP           (1 << 9)
> +
>  #endif /* CLK_RST_H */
> diff --git a/arch/arm/include/asm/arch-tegra2/pmc.h b/arch/arm/include/asm/arch-tegra2/pmc.h
> index 7ec9eeb..b1d47cd 100644
> --- a/arch/arm/include/asm/arch-tegra2/pmc.h
> +++ b/arch/arm/include/asm/arch-tegra2/pmc.h
> @@ -121,4 +121,12 @@ struct pmc_ctlr {
>        uint pmc_gate;                  /* _GATE_0, offset 15C */
>  };
>
> +#define CPU_PWRED      1
> +#define CPU_CLMP       1
> +
> +#define PARTID_CP      0xFFFFFFF8
> +#define START_CP       (1 << 8)
> +
> +#define CPUPWRREQ_OE   (1 << 16)
> +
>  #endif /* PMC_H */
> diff --git a/arch/arm/include/asm/arch-tegra2/scu.h b/arch/arm/include/asm/arch-tegra2/scu.h
> new file mode 100644
> index 0000000..d2faa6f
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-tegra2/scu.h
> @@ -0,0 +1,43 @@
> +/*
> + *  (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 _SCU_H_
> +#define _SCU_H_
> +
> +/* ARM Snoop Control Unit (SCU) registers */
> +struct scu_ctlr {
> +       uint scu_ctrl;          /* SCU Control Register, offset 00 */
> +       uint scu_cfg;           /* SCU Config Register, offset 04 */
> +       uint scu_cpu_pwr_stat;  /* SCU CPU Power Status Register, offset 08 */
> +       uint scu_inv_all;       /* SCU Invalidate All Register, offset 0C */
> +       uint scu_reserved0[12]; /* reserved, offset 10-3C */
> +       uint scu_filt_start;    /* SCU Filtering Start Address Reg, offset 40 */
> +       uint scu_filt_end;      /* SCU Filtering End Address Reg, offset 44 */
> +       uint scu_reserved1[2];  /* reserved, offset 48-4C */
> +       uint scu_acc_ctl;       /* SCU Access Control Register, offset 50 */
> +       uint scu_ns_acc_ctl;    /* SCU Non-secure Access Cntrl Reg, offset 54 */
> +};
> +
> +#define SCU_ENABLE     1
> +
> +#endif /* SCU_H */
> diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
> index 9001b68..5813cd9 100644
> --- a/arch/arm/include/asm/arch-tegra2/tegra2.h
> +++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
> @@ -25,8 +25,12 @@
>  #define _TEGRA2_H_
>
>  #define NV_PA_SDRAM_BASE       0x00000000
> +#define NV_PA_ARM_PERIPHBASE   0x50040000
> +#define NV_PA_PG_UP_BASE       0x60000000
>  #define NV_PA_TMRUS_BASE       0x60005010
>  #define NV_PA_CLK_RST_BASE     0x60006000
> +#define NV_PA_FLOW_BASE                0x60007000
> +#define NV_PA_EVP_BASE         0x6000F000
>  #define NV_PA_APB_MISC_BASE    0x70000000
>  #define NV_PA_APB_UARTA_BASE   (NV_PA_APB_MISC_BASE + 0x6000)
>  #define NV_PA_APB_UARTB_BASE   (NV_PA_APB_MISC_BASE + 0x6040)
> @@ -34,6 +38,7 @@
>  #define NV_PA_APB_UARTD_BASE   (NV_PA_APB_MISC_BASE + 0x6300)
>  #define NV_PA_APB_UARTE_BASE   (NV_PA_APB_MISC_BASE + 0x6400)
>  #define NV_PA_PMC_BASE         0x7000E400
> +#define NV_PA_CSITE_BASE       0x70040000
>
>  #define TEGRA2_SDRC_CS0                NV_PA_SDRAM_BASE
>  #define LOW_LEVEL_SRAM_STACK   0x4000FFFC
> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
> index b2c412c..078547b 100644
> --- a/board/nvidia/common/board.c
> +++ b/board/nvidia/common/board.c
> @@ -30,6 +30,7 @@
>  #include <asm/arch/clk_rst.h>
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/uart.h>
> +#include "board.h"
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> @@ -37,6 +38,15 @@ const struct tegra2_sysinfo sysinfo = {
>        CONFIG_TEGRA2_BOARD_STRING
>  };
>
> +#ifdef CONFIG_BOARD_EARLY_INIT_F
> +int board_early_init_f(void)
> +{
> +       debug("Board Early Init\n");
> +       tegra2_start();
> +       return 0;
> +}
> +#endif /* EARLY_INIT */
> +
>  /*
>  * Routine: timer_init
>  * Description: init the timestamp and lastinc value
> diff --git a/board/nvidia/common/board.h b/board/nvidia/common/board.h
> new file mode 100644
> index 0000000..47c7885
> --- /dev/null
> +++ b/board/nvidia/common/board.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 _BOARD_H_
> +#define _BOARD_H_
> +
> +void tegra2_start(void);
> +
> +#endif /* BOARD_H */
> diff --git a/include/configs/harmony.h b/include/configs/harmony.h
> index d004f31..34bd899 100644
> --- a/include/configs/harmony.h
> +++ b/include/configs/harmony.h
> @@ -46,4 +46,5 @@
>  #define CONFIG_MACH_TYPE               MACH_TYPE_HARMONY
>  #define CONFIG_SYS_BOARD_ODMDATA       0x300d8011 /* lp1, 1GB */
>
> +#define CONFIG_BOARD_EARLY_INIT_F
>  #endif /* __CONFIG_H */
> diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h
> index fd87560..b7b72bb 100644
> --- a/include/configs/seaboard.h
> +++ b/include/configs/seaboard.h
> @@ -40,4 +40,5 @@
>  #define CONFIG_MACH_TYPE               MACH_TYPE_TEGRA_SEABOARD
>  #define CONFIG_SYS_BOARD_ODMDATA       0x300d8011 /* lp1, 1GB */
>
> +#define CONFIG_BOARD_EARLY_INIT_F
>  #endif /* __CONFIG_H */
> diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h
> index 4f4374a..2924325 100644
> --- a/include/configs/tegra2-common.h
> +++ b/include/configs/tegra2-common.h
> @@ -33,6 +33,8 @@
>  #define CONFIG_MACH_TEGRA_GENERIC      /* which is a Tegra generic machine */
>  #define CONFIG_L2_OFF                  /* No L2 cache */
>
> +#define CONFIG_ENABLE_CORTEXA9         /* enable CPU (A9 complex) */
> +
>  #include <asm/arch/tegra2.h>           /* get chip and board defs */
>
>  /*
> --
> 1.7.4.1
>
>


More information about the U-Boot mailing list