[U-Boot] [PATCH] arm: Tegra2: add support for A9 CPU init
Peter Tyser
ptyser at xes-inc.com
Mon Mar 14 16:33:40 CET 2011
Hi Tom,
I'm not too familiar with the architecture, so many comments are
aesthetic. It would be a good idea to run the patch through
checkpatch.pl too.
> 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
> +
It'd be good to add a comment about what's going on above, and why its
tegra2-specific. Eg why is it needed?
<snip>
> +static void init_pll_x(void)
> +{
> + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
> + u32 reg;
The spaces in front of "reg" can be removed. Ditto for all
functions/variables.
> + /* 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 */
> +}
The above function looks incorrect.
> +static void set_cpu_reset_vector(u32 vector)
> +{
> + writel(vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
> +}
Is it worth breaking this out into its own function? The define names
make it pretty clear what is being done, and its only called from 1
location.
> +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);
It'd look cleaner to not set "reg" for each access, just use the define
directly. I'd personally use less temporary variables in general and
only use them when it made the code cleaner and easier to understand.
> + 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);
Is this read necessary? You overwrite reg unconditionally below.
> + /*
> + * 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;
> + }
For if/elses that share common code, the common code should be broken
out. eg above only the one-line |=/&= operations should be conditional.
> + 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;
I'd remove the reg variable. eg something like:
return readl(&pmc->pmc_pwrgate_status & CPU_PWRED ? 1 : 0);
> + 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);
For magic delays it'd be good to reference why you're waiting a specific
amount of time. Does a manual state 1 ms? Did testing show 1ms was
required?
> +}
> +
> +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;
Why ()'s on one operation, but not the other?
> + 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);
Ditto for description.
> +}
> +
> +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);
The cpu variable can be removed.
> + 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;
> +
Extra newline.
> + } 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;
What's this number? Is there a define that could be used instead?
> + 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.
> + */
Spaces should be added above.
> + 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 (;;)
> + ;
I'd remove the use of reg, and a secondary infinite loop seems
necessary.
> +}
> +
> +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"
> + );
The assembly code should be indented. Actually, is there a reason not
to move all these assembly functions into a seperate assembly file?
> +}
> +
> +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"
> + );
Ditto on indentation/move.
> +}
> +
> +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;
> + }
I'd not use reg above, and not use brackets, eg:
/* If the SCU is already enabled, we have nothing to do */
if (readl(&scu_ctrl) & SCU_ENABLE)
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;
Remove 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"
> + );
Ditto on indentation/move.
> +}
> +
> +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);
Is it safe to memset on IO regions here? A for loop of writel's would
be safer, and more consistent.
> + writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
> +}
> +
> +u32 s_first_boot = 1;
I'd move all global variables to the top of the file.
> +
> +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;
Remove 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
These shouldn't be added here. They should be somewhere common, or
shouldn't be used (my preference).
> +
> +#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
Should this be here? Seems like its not the proper location to enable
things...
> +
> +#endif /* SCU_H */
Best,
Peter
More information about the U-Boot
mailing list