Add A9 CPU complex support
Subsystems (2)
PATCH 1/1 Add A9 CPU complex support
This patch adds code to initialize the A9 dual CPU complex in the Tegra2 SoC. The code is run on the AVP first to set up the A9 and Coresight clocks, then the AVP is halted, the A9 CPU is brought out of reset, and the code executes again on the CPU, but down a slightly different path. Normal POST then proceeds using the A9 CPU.
Tom Warren (1):
arm: Tegra2: add support for A9 CPU init
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
Signature · 1 line
1.7.4.1
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
--- 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
arch/arm/cpu/armv7/start.S +6 -0
@@ -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. */
arch/arm/cpu/armv7/tegra2/Makefile +1 -1
@@ -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))
arch/arm/cpu/armv7/tegra2/ap20.c new file +490 -0
490 lines not on this page · raw message
arch/arm/cpu/armv7/tegra2/ap20.h new file +105 -0
105 lines not on this page · raw message
arch/arm/include/asm/arch-tegra2/clk_rst.h +27 -0
@@ -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 */
arch/arm/include/asm/arch-tegra2/pmc.h +8 -0
@@ -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 */
arch/arm/include/asm/arch-tegra2/scu.h new file +43 -0
43 lines not on this page · raw message
arch/arm/include/asm/arch-tegra2/tegra2.h +5 -0
@@ -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
board/nvidia/common/board.c +10 -0
@@ -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
board/nvidia/common/board.h new file +29 -0
@@ -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 */
include/configs/harmony.h +1 -0
@@ -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 */
include/configs/seaboard.h +1 -0
@@ -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 */
include/configs/tegra2-common.h +2 -0
@@ -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 */ /*
Signature · 1 line
1.7.4.1
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Anyone willing to review this? I'd like to get it pulled in to Albert's arm repo ASAP.
Thanks,
Tom
Quoted 892 lines · Tom Warren
Signed-off-by Tom Warren <[email protected]>---
?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 100644arch/arm/cpu/armv7/tegra2/ap20.h?create mode 100644arch/arm/include/asm/arch-tegra2/scu.h?create mode 100644board/nvidia/common/board.harch/arm/cpu/armv7/start.S +0
-0@@ -70,6 +70,12 @@ _end_vect:?_TEXT_BASE:
? ? ? ?.word ?CONFIG_SYS_TEXT_BASEarch/arm/cpu/armv7/start.S +6
-0+#ifdef CONFIG_TEGRA2 +.globl _armboot_start +_armboot_start: + ? ? ? ?.word _start +#endif +?/*
?* These are defined in the board-specific linker script. ?*/arch/arm/cpu/armv7/tegra2/Makefile +0
-0@@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk?LIB ? ?= ?$(obj)lib$(SOC).o
?SOBJS ?:= lowlevel_init.o
arch/arm/cpu/armv7/tegra2/Makefile +1
-1-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))arch/arm/cpu/armv7/tegra2/ap20.c new file +490
-0@@ -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 +} +arch/arm/cpu/armv7/tegra2/ap20.h new file +105
-0@@ -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 );arch/arm/include/asm/arch-tegra2/clk_rst.h +0
-0@@ -149,6 +149,9 @@ struct clk_rst_ctlr {? ? ? ?uint
crc_clk_src_csite; ? ? ? ? /*_CSITE_0, ? ? ? ? ? ?0x1D4*/ ? ? ? ?uint crc_reserved19[9]; ? ? ? ? /* ? ? ? ? ? ? ? ? ? ? ?0x1D8-1F8 */ ? ? ? ?uintcrc_clk_src_osc; ? ? ? ? ? /*_OSC_0, ? ? ? ? ? ? ?0x1FC*/
+ ? ? ? uint crc_reserved20[80]; ? ? ? ?/* ? ? ? ? ? ? ? ? ? ? ?0x200-33C */
+ ? ? ? uintcrc_cpu_cmplx_set; ? ? ? ? /*_CPU_CMPLX_SET_0, ? ?0x340 */
+ ? ? ? uintcrc_cpu_cmplx_clr; ? ? ? ? /*_CPU_CMPLX_CLR_0, ? ?0x344 */ ?};?#define
PLL_BYPASS? ? ? ? ? ? (1 << 31)arch/arm/include/asm/arch-tegra2/clk_rst.h +24
-0@@ -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*/arch/arm/include/asm/arch-tegra2/pmc.h +0
-0@@ -121,4 +121,12 @@ struct pmc_ctlr {? ? ? ?uint
pmc_gate; ? ? ? ? ? ? ? ? ?/*_GATE_0, offset 15C */ ?};arch/arm/include/asm/arch-tegra2/pmc.h +8
-0+#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*/arch/arm/include/asm/arch-tegra2/scu.h new file +43
-0@@ -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 */ arch/arm/include/asm/arch-tegra2/tegra2.h +0
-0@@ -25,8 +25,12 @@?#define _TEGRA2_H_
?#define
NV_PA_SDRAM_BASE? ? ?0x00000000arch/arm/include/asm/arch-tegra2/tegra2.h +2
-0+#define NV_PA_ARM_PERIPHBASE ? 0x50040000 +#define NV_PA_PG_UP_BASE ? ? ? 0x60000000?#define
NV_PA_TMRUS_BASE? ? ?0x60005010
?#defineNV_PA_CLK_RST_BASE? ?0x60006000arch/arm/include/asm/arch-tegra2/tegra2.h +2
-0+#define NV_PA_FLOW_BASE ? ? ? ? ? ? ? ?0x60007000 +#define NV_PA_EVP_BASE ? ? ? ? 0x6000F000?#define
NV_PA_APB_MISC_BASE? ?0x70000000
?#defineNV_PA_APB_UARTA_BASE? (NV_PA_APB_MISC_BASE+0x6000) ?#defineNV_PA_APB_UARTB_BASE? (NV_PA_APB_MISC_BASE+0x6040)arch/arm/include/asm/arch-tegra2/tegra2.h +0
-0@@ -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
+#defineNV_PA_CSITE_BASE? ? ?0x70040000?#define
TEGRA2_SDRC_CS0? ? ? ? ? ? ? ?NV_PA_SDRAM_BASE ?#defineLOW_LEVEL_SRAM_STACK?0x4000FFFCboard/nvidia/common/board.c +0
-0@@ -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;
board/nvidia/common/board.c +0
-0@@ -37,6 +38,15 @@ const struct tegra2_sysinfo sysinfo = {? ? ? ?CONFIG_TEGRA2_BOARD_STRING
?};board/nvidia/common/board.c +9
-0+#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 valueboard/nvidia/common/board.h new file +29
-0@@ -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 */ include/configs/harmony.h +0
-0@@ -46,4 +46,5 @@?#define
CONFIG_MACH_TYPE? ? ? ? ? ? ?MACH_TYPE_HARMONY?#defineCONFIG_SYS_BOARD_ODMDATA? ? ?0x300d8011/* lp1, 1GB */+#define
CONFIG_BOARD_EARLY_INIT_F
?#endif /*__CONFIG_H*/include/configs/seaboard.h +0
-0@@ -40,4 +40,5 @@?#define
CONFIG_MACH_TYPE? ? ? ? ? ? ?MACH_TYPE_TEGRA_SEABOARD?#defineCONFIG_SYS_BOARD_ODMDATA? ? ?0x300d8011/* lp1, 1GB */+#define
CONFIG_BOARD_EARLY_INIT_F
?#endif /*__CONFIG_H*/include/configs/tegra2-common.h +0
-0@@ -33,6 +33,8 @@?#define
CONFIG_MACH_TEGRA_GENERIC? ? ?/* which is a Tegra generic machine */ ?#defineCONFIG_L2_OFF? ? ? ? ? ? ? ? ?/* No L2 cache */include/configs/tegra2-common.h +2
-0+#define CONFIG_ENABLE_CORTEXA9 ? ? ? ?/* enable CPU (A9 complex) */ +?#include <
asm/arch/tegra2.h> ? ? ? ? ? /* get chip and board defs */?/*
--
1.7.4.1
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Hi Tom,
Le 23/02/2011 00:41, Tom Warren a ?crit :
Quoted 2 lines
Anyone willing to review this? I'd like to get it pulled in to Albert's arm repo ASAP.
I should be able to review it during the week-end--not before, sorry.
Note however that since this is not a bugfix and it came after the merge window closed, it would go to u-boot-arm/next, not /master; it will go to u-boot-arm/master after the the upcoming release (and then to u-boot/master when the next merge window closes).
Quoted 3 lines
Thanks,
Tom
Amicalement,
Signature · 1 line
Albert.
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Albert,
Quoted 9 lines · Albert ARIBAUD
Hi Tom,
Le 23/02/2011 00:41, Tom Warren a ?crit :
Quoted 3 lines
Anyone willing to review this? I'd like to get it pulled in to Albert's arm repo ASAP.
I should be able to review it during the week-end--not before, sorry.
Thank you. That would be fine - no rush.
Quoted 4 lines
Note however that since this is not a bugfix and it came after the merge window closed, it would go to u-boot-arm/next, not /master; it will go to u-boot-arm/master after the the upcoming release (and then to u-boot/master when the next merge window closes).
Understood. Just wanted an ACK, etc. so I can sign off on the CPU work and move on to the drivers.
Quoted 9 lines
Quoted 4 lines
Thanks,
Tom
Amicalement,
--
Albert.
Thanks for your help,
Tom
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
In reply to Albert ARIBAUDAlbert,
Quoted 9 lines · Albert ARIBAUD
Hi Tom,
Le 23/02/2011 00:41, Tom Warren a ?crit :
Quoted 3 lines
Anyone willing to review this? I'd like to get it pulled in to Albert's arm repo ASAP.
I should be able to review it during the week-end--not before, sorry.
Any chance you can give this some bandwidth? I'd like to get it into the arm tree.
As far as I know, it should still apply, but let me know if I need to rebase it against next (or master).
Thanks,
Tom
Quoted 13 lines
Note however that since this is not a bugfix and it came after the merge window closed, it would go to u-boot-arm/next, not /master; it will go to u-boot-arm/master after the the upcoming release (and then to u-boot/master when the next merge window closes).
Quoted 3 lines
Thanks,
Tom
Amicalement,
--
Albert.
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
In reply to Tom WarrenLe 16/02/2011 21:26, Tom Warren a ?crit :
Quoted 6 lines
Signed-off-by Tom Warren<[email protected]>--- arch/arm/cpu/armv7/start.S | 6 + arch/arm/cpu/armv7/tegra2/Makefile | 2 +-arch/arm/cpu/armv7/tegra2/ap20.c | 490 ++++++++++++++++++++++++++++
This one has an extra empty line at end of file.
Quoted 21 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +21
-0+void cold_boot (void ) +{ + asmvolatile ( + +"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 */
arch/arm/cpu/armv7/tegra2/ap20.c line 351
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +10
-0+ "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),
If I'm not mistaken, NV_PA_PG_UP_BASE could be used just as well directly in the asm statement instead of via %0 and i(), as anyway the asm will be preprocessed and the macro will turn to a number. That would simplify the asm instruction as a whole and make the asm statement more understandable (also applies to other macros used similarly).
Apart from that, I must admit I don't know the Tegra2/A9 well enough to comment further.
amicalement,
Amicalement,
Signature · 1 line
Albert.
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Albert,
Quoted 7 lines · Albert ARIBAUD
Le 16/02/2011 21:26, Tom Warren a ?crit :
Quoted 5 lines
Signed-off-by Tom Warren<[email protected]>---
?arch/arm/cpu/armv7/start.S ? ? ? ? ? ? ? ? | ? ?6 + ?arch/arm/cpu/armv7/tegra2/Makefile ? ? ? ? | ? ?2 +-
Quoted 5 lines
Quoted 2 lines
?arch/arm/cpu/armv7/tegra2/ap20.c ? ? ? ? ? | ?490
++++++++++++++++++++++++++++This one has an extra empty line at end of file.
Thanks - I'll remove it.
Quoted 29 lines
Quoted 29 lines
(quoted diff) +29
-0+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"
Quoted 9 lines
Quoted 2 lines
+ ? ? ? :
+ ? ? ? : "i"(NV_PA_PG_UP_BASE),If I'm not mistaken,
NV_PA_PG_UP_BASEcould be used just as well directly in the asm statement instead of via %0 andi(), as anyway the asm will be preprocessed and the macro will turn to a number. That would simplify the asm instruction as a whole and make the asm statement more understandable (also applies to other macros used similarly).
Yeah, this code came this way from our bringup group for out in-house bootloader, and it's always been confusing.
I'll try to simplify it when I incorporate Peter's critiques. Thanks.
Quoted 7 lines
Apart from that, I must admit I don't know the Tegra2/A9 well enough to comment further.
amicalement,
Amicalement,
--
Albert.
Thanks for the input,
Tom
Quoted 1 line
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
In reply to Tom WarrenHi 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.
Quoted 5 lines
arch/arm/cpu/armv7/start.S +0
-0
arch/arm/cpu/armv7/start.S _end_vect: · line 78
Quoted 9 lines
arch/arm/cpu/armv7/start.S +6
-0@@ -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>
arch/arm/cpu/armv7/start.S _end_vect:
Quoted 4 lines
arch/arm/cpu/armv7/start.S +4
-0+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.
arch/arm/cpu/armv7/start.S
Quoted 7 lines
arch/arm/cpu/armv7/start.S +7
-0+ /* 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.
arch/arm/cpu/armv7/start.S
Quoted 4 lines
arch/arm/cpu/armv7/start.S +4
-0+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.
Quoted 14 lines
arch/arm/cpu/armv7/start.S +14
-0+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. + */ +
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ /* 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.
arch/arm/cpu/armv7/start.S
Quoted 6 lines
arch/arm/cpu/armv7/start.S +6
-0+ 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.
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ /* + * 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);
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ 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.
arch/arm/cpu/armv7/start.S
Quoted 13 lines
arch/arm/cpu/armv7/start.S +13
-0+ 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);
Quoted 5 lines
arch/arm/cpu/armv7/start.S +5
-0+ return FALSE; +} + +static void remove_cpu_io_clamps(void) +{
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ 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?
arch/arm/cpu/armv7/start.S
Quoted 12 lines
arch/arm/cpu/armv7/start.S +12
-0+} + +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?
Quoted 17 lines
arch/arm/cpu/armv7/start.S +17
-0+ 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)
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+{ + 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.
Quoted 8 lines
arch/arm/cpu/armv7/start.S +8
-0+} + +static void reset_A9_cpu(int reset) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg, cpu; + + /*
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ * 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.
arch/arm/cpu/armv7/start.S
Quoted 9 lines
arch/arm/cpu/armv7/start.S +9
-0+ 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.
Quoted 33 lines
arch/arm/cpu/armv7/start.S +33
-0+ } 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) { + /*
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ * 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?
Quoted 13 lines
arch/arm/cpu/armv7/start.S +13
-0+ 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); +
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ /* 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.
Quoted 17 lines
arch/arm/cpu/armv7/start.S +17
-0+ 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) +{
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ 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.
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+} + +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 */
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ /* 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?
Quoted 37 lines
arch/arm/cpu/armv7/start.S +37
-0+} + +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"
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ : + : "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.
arch/arm/cpu/armv7/start.S
Quoted 12 lines
arch/arm/cpu/armv7/start.S +12
-0+} + +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;
arch/arm/cpu/armv7/start.S
Quoted 9 lines
arch/arm/cpu/armv7/start.S +9
-0+ /* 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.
Quoted 48 lines
arch/arm/cpu/armv7/start.S +48
-0+} + +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"
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ /* 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.
arch/arm/cpu/armv7/start.S
Quoted 8 lines
arch/arm/cpu/armv7/start.S +8
-0+} + +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.
arch/arm/cpu/armv7/start.S
Quoted 4 lines
arch/arm/cpu/armv7/start.S +4
-0+ 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.
Quoted 8 lines
arch/arm/cpu/armv7/start.S +8
-0+ +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); +
arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ 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.
Quoted 47 lines
arch/arm/cpu/armv7/start.S +21
-0+} + +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 +} +arch/arm/cpu/armv7/tegra2/ap20.h new file +20
-0@@ -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,
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +10
-0+* 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).
Quoted 172 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +75
-0+ +#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 );arch/arm/include/asm/arch-tegra2/clk_rst.h +27
-0@@ -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 */ arch/arm/include/asm/arch-tegra2/pmc.h +8
-0@@ -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 */ arch/arm/include/asm/arch-tegra2/scu.h new file +31
-0@@ -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 */
arch/arm/include/asm/arch-tegra2/scu.h line 41
Quoted 10 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +10
-0+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...
arch/arm/include/asm/arch-tegra2/scu.h line 43
Quoted 2 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +2
-0+ +#endif /* SCU_H */
Best,
Peter
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Peter,
Quoted 4 lines · Peter Tyser
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.
I run checkpatch on every submission. Only 1 warning was generated (about an extern), and no errors.
Quoted 9 lines
Quoted 9 lines
arch/arm/cpu/armv7/start.S +0
-0@@ -70,6 +70,12 @@ _end_vect:?_TEXT_BASE:
? ? ? .word ?CONFIG_SYS_TEXT_BASE
Quoted 9 lines
arch/arm/cpu/armv7/start.S _end_vect: · line 78
Quoted 6 lines
arch/arm/cpu/armv7/start.S +6
-0+#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?
Tegra uses 2 separate CPUs - the AVP (ARM7TDI) and the dual-core A9. A bootloader first runs on the AVP and sets things up for the CPU complex to take over.
The CPU complex jumps here during it's init phase/boot (from it's reset vector). It needs a dereferenced jump to the _start code in start.S (which in turn chains to the reset code).
I'll add a comment about this in the next patch.
Quoted 9 lines
<snip>
arch/arm/cpu/armv7/start.S
Quoted 4 lines
arch/arm/cpu/armv7/start.S +4
-0+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.
Not sure what you mean, here, Peter. There are no spaces here in my ap20.c file, just tabs.
Please clarify.
Quoted 10 lines
arch/arm/cpu/armv7/start.S
Quoted 8 lines
+ ? ? /* Is PLL-X already running? */
+ ? ? reg =readl(&clkrst->crc_pllx_base);
+ ? ? if (reg &PLL_ENABLE)
+ ? ? ? ? ? ? return;arch/arm/cpu/armv7/start.S +3
-0+ + ? ? /* Do PLLX init if it isn't running, but BootROM sets it, so TBD */ +}The above function looks incorrect.
What looks incorrect? It checks to see if the PLL is already running/enabled, and returns if it is.
Tegra2 mask ROM (BootROM) currently always sets PLLX, so this will always return, but the comment is there for future chips that may not set up PLLX.
Quoted 9 lines
arch/arm/cpu/armv7/start.S
Quoted 5 lines
arch/arm/cpu/armv7/start.S +4
-0+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.
I can move the writel() to the called location and remove this func.
Quoted 21 lines
Quoted 21 lines
arch/arm/cpu/armv7/start.S +20
-0+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 */
Quoted 8 lines
Quoted 4 lines
+ ? ? ? ? ? ?
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.
Will do. This code was ported from our orignal, in-house bootloader, so it's going to be a bit hairy.
Quoted 9 lines
Quoted 7 lines
+ ? ? ? ? ? ? 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.
Yeah, I saw that and did a rewrite a week or two ago, but was waiting to incorporate into the next patch to get everything in one place.
Quoted 22 lines
Quoted 13 lines
+ ? ? /*
+ ? ? ?* 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);Quoted 8 lines
+ ? ? ? ? ? ? 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;
+ ? ? }
Quoted 2 lines
For if/elses that share common code, the common code should be broken out. ?eg above only the one-line |=/&= operations should be conditional.
Yep, already done as part of the previous cleanup. Just need to put it into the full patchset #2.
Quoted 17 lines
Quoted 4 lines
+ ? ?
writel(clk, &clkrst->crc_clk_cpu_cmplx);
+ ? ?writel(reg, &clkrst->crc_clk_out_enb_l);arch/arm/cpu/armv7/start.S +1
-0+}arch/arm/cpu/armv7/start.S
Quoted 10 lines
arch/arm/cpu/armv7/start.S +10
-0+ +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:
returnreadl(&pmc->pmc_pwrgate_status & CPU_PWRED ? 1 : 0);
Good. Will do.
Quoted 12 lines
Quoted 12 lines
+ ? ? return FALSE;
arch/arm/cpu/armv7/start.S +10
-0+} + +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;
Quoted 8 lines
Quoted 4 lines
+ ? ?
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?
Not sure, since this code came from the dark ages of Tegra bringup, and was ported from our in-house bootloader.
The Tegra TRM doesn't call out a specific delay, and no one seems to be able to point to any reference for this.
I think the 'give I/O signals time to stabilize' will have to suffice here. I can make it a #define such as 'IO_STAB_TIME', if that'd help.
Quoted 15 lines
arch/arm/cpu/armv7/start.S
Quoted 13 lines
arch/arm/cpu/armv7/start.S +12
-0+} + +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?
Don't know - part of the porting process. I'll remove 'em.
Quoted 22 lines
Quoted 22 lines
+ ? ? ? ? ? ?
writel(reg, &pmc->pmc_pwrgate_toggle);arch/arm/cpu/armv7/start.S +20
-0+ + ? ? ? ? ? ? /* 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; +
Quoted 8 lines
Quoted 6 lines
+ ? ? reg =
readl(&pmc->pmc_cntrl);
+ ? ? reg |=CPUPWRREQ_OE;
+ ? ?writel(reg, &pmc->pmc_cntrl);
+
+ ? ? /* Delay to allow for stable power (CPU_PWR_REQ->VDD_CPUfrom PMU) */
+ ? ? udelay(3750);Ditto for description.
Ditto on why the delay? In this case, I did find a reference to the time needed between the request from the chipset to the PMU, hence the comment.
Quoted 13 lines
Quoted 13 lines
arch/arm/cpu/armv7/start.S +12
-0+} + +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
Quoted 8 lines
Quoted 6 lines
+ ? ? * ? ? ? ?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.
It could be, sure. But it makes the line longer, >80 chars, and hence it would have to be broken into two lines.
Actually, now that I look at the code again, it appears that 'cpu' later should be OR'd with the SET_/CLR_DBGRESET0, etc. bits, depending on the state of 'reset'.
I'll give it a rewrite for the next patch.
Quoted 12 lines
arch/arm/cpu/armv7/start.S
Quoted 10 lines
+ ? ? 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);arch/arm/cpu/armv7/start.S +4
-0+ + ? ? ? ? ? ? /* Enable master CPU reset */ + ? ? ? ? ? ? reg |= SWR_CPU_RST; +Extra newline.
OK.
Quoted 38 lines
Quoted 38 lines
+ ? ? } else {
+ ? ? ? ? ? ? /* Take CPU0 out of reset */
+ ? ? ? ? ? ? cpu =CLR_DBGRESET0|CLR_DERESET0|CLR_CPURESET0;
+ ? ? ? ? ? ?writel(cpu, &clkrst->crc_cpu_cmplx_clr);arch/arm/cpu/armv7/start.S +33
-0+ + ? ? ? ? ? ? /* 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)
Quoted 8 lines
Quoted 6 lines
+ ? ? ? ? ? ? ?*/
+ ? ? ? ? ? ? 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?
Sure, I can add a #define. Some magic ARM access sequence to unlock the CoreSight I/F, as the comment says
Quoted 18 lines
Quoted 18 lines
+ ? ? ? ? ? ?
writel(rst, CSITE_CPU_DBG0_LAR);
+ ? ? ? ? ? ?writel(rst, CSITE_CPU_DBG1_LAR);
+ ? ? }arch/arm/cpu/armv7/start.S +14
-0+} + +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 */
Quoted 8 lines
Quoted 6 lines
+ ? ?
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.
Spaces where? Please be more specific. Again, checkpatch had no problem with this section.
Quoted 23 lines
Quoted 23 lines
+ ? ? if (
reset_vector)
+ ? ? ? ? ? ?set_cpu_reset_vector(reset_vector);arch/arm/cpu/armv7/start.S +20
-0+ + ? ? /* 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);
Quoted 8 lines
Quoted 5 lines
+ ? ? ? ? ? ?
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.
OK, I'll rewrite it.
Quoted 16 lines
Quoted 16 lines
arch/arm/cpu/armv7/start.S +15
-0+} + +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 */
Quoted 8 lines
Quoted 5 lines
+ ? ? "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?
I can indent the asm code, no problem.
I don't see the need to move it to a .S file, though. Lots of examples of embedded assembly code in the U-Boot tree.
Unless I see some strong objections, I'm just going to indent it (and other asm statements).
Quoted 42 lines
Quoted 42 lines
arch/arm/cpu/armv7/start.S +41
-0+} + +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),
Quoted 8 lines
Quoted 6 lines
+ ? ? "r"(cpu_boot_stack),
+ ? ? "r"(_armboot_start),
+ ? ? "r"(avp_boot_stack),
+ ? ? "r"(deadbeef)
+ ? ? : "r0", "r2", "r3", "cc", "lr"
+ ? ? );Ditto on indentation/move.
Albert pointed out that this code is kinda dense, and I agree. I'm going to rewrite without the %0 stuff, plus add indents.
Quoted 10 lines
Quoted 10 lines
arch/arm/cpu/armv7/start.S +9
-0+} + +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) {
Quoted 8 lines
Quoted 3 lines
+ ? ? ? ? ? ? /* 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;
Sure, I can do that.
Quoted 12 lines
arch/arm/cpu/armv7/start.S
Quoted 10 lines
+ ? ? /* Invalidate all ways for all processors */
+ ? ?writel(0xFFFF, &scu->scu_inv_all);arch/arm/cpu/armv7/start.S +7
-0+ + ? ? /* Enable SCU - bit 0 */ + ? ? reg = readl(&scu->scu_ctrl); + ? ? reg |= SCU_ENABLE; + ? ? writel(reg, &scu->scu_ctrl); + + ? ? return;Remove return.
OK.
Quoted 53 lines
Quoted 53 lines
arch/arm/cpu/armv7/start.S +52
-0+} + +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"
Quoted 8 lines
Quoted 6 lines
+
+ ? ? /* FIXME: should have ap20's L2 disabled too */
+ ? ? "invalidate_done: ? ? ? ? ? ? ? ? \n"
+ ? ? "ldmia r13!,{pc} ? ? ? ? ? ? ? ? ?\n"
+ ? ? ".ltorg ? ? ? ? ? ? ? ? ? ? ? ? ? \n"
+ ? ? );Ditto on indentation/move.
I'll indent it.
Quoted 12 lines
arch/arm/cpu/armv7/start.S
Quoted 9 lines
arch/arm/cpu/armv7/start.S +8
-0+} + +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.
The generated assembly looks OK. These are mem-mapped scratch registers, so there're no side-effects here.
I can convert to a loop if you insist.
Quoted 7 lines
arch/arm/cpu/armv7/start.S
Quoted 5 lines
+ ? ?
writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);arch/arm/cpu/armv7/start.S +3
-0+} + +u32 s_first_boot = 1;I'd move all global variables to the top of the file.
OK, will do.
Quoted 13 lines
Quoted 13 lines
arch/arm/cpu/armv7/start.S +12
-0+ +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.
Quoted 8 lines
Quoted 6 lines
+ ? ? ? ? ? ? ?*/
+ ? ? ? ? ? ?s_first_boot= 0;
+ ? ? ? ? ? ?cold_boot();
+ ? ? }
+
+ ? ? return;Remove return.
OK.
Quoted 53 lines
Quoted 53 lines
arch/arm/cpu/armv7/start.S +21
-0+} + +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 +} +arch/arm/cpu/armv7/tegra2/ap20.h new file +25
-0@@ -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
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 5 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +5
-0+#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).
I would think they'd be in the ARM tree somewhere, but I couldn't find them so I added 'em here.
My preference is to use TRUE/FALSE - it carries more context than 1/0 to me.
Quoted 178 lines
Quoted 178 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +75
-0+ +#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 );arch/arm/include/asm/arch-tegra2/clk_rst.h +0
-0@@ -149,6 +149,9 @@ struct clk_rst_ctlr {? ? ? uint
crc_clk_src_csite; ? ? ? ? /*_CSITE_0, ? ? ? ? ? ?0x1D4*/ ? ? ? uint crc_reserved19[9]; ? ? ? ? /* ? ? ? ? ? ? ? ? ? ? ?0x1D8-1F8 */ ? ? ? uintcrc_clk_src_osc; ? ? ? ? ? /*_OSC_0, ? ? ? ? ? ? ?0x1FC*/
+ ? ? uint crc_reserved20[80]; ? ? ? ?/* ? ? ? ? ? ? ? ? ? ? ?0x200-33C */
+ ? ? uintcrc_cpu_cmplx_set; ? ? ? ? /*_CPU_CMPLX_SET_0, ? ?0x340 */
+ ? ? uintcrc_cpu_cmplx_clr; ? ? ? ? /*_CPU_CMPLX_CLR_0, ? ?0x344 */ ?};?#define
PLL_BYPASS? ? ? ? ? (1 << 31)arch/arm/include/asm/arch-tegra2/clk_rst.h +24
-0@@ -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*/arch/arm/include/asm/arch-tegra2/pmc.h +0
-0@@ -121,4 +121,12 @@ struct pmc_ctlr {? ? ? uint
pmc_gate; ? ? ? ? ? ? ? ? ?/*_GATE_0, offset 15C */ ?};arch/arm/include/asm/arch-tegra2/pmc.h +8
-0+#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*/arch/arm/include/asm/arch-tegra2/scu.h new file +36
-0@@ -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 */
Quoted 8 lines
arch/arm/include/asm/arch-tegra2/scu.h line 41
Quoted 5 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +5
-0+ ? ? 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 ? 1Should this be here? ?Seems like its not the proper location to enable things...
It's a bit setting, for the scu_ctrl register. I could change it to (1 << 0), if you'd prefer.
There are other bits in the SCU, but since they aren't used in this code, I didn't declare 'em.
Quoted 6 lines
arch/arm/include/asm/arch-tegra2/scu.h line 43
Quoted 3 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +2
-0+ +#endif ? ? ? /* SCU_H */Best,
Peter
Thanks for the review. I'll have a new patch in a couple of days, once I have your feedback on my questions, above.
Tom
Quoted 3 lines
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Hi Tom,
<snip>
Quoted 10 lines
Quoted 7 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 36
Quoted 4 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +4
-0+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.
Not sure what you mean, here, Peter. There are no spaces here in my
ap20.cfile, just tabs.
Please clarify.
My email client converted to spaces I was referring to the "u32 reg;"
above. I think it should be "u32<space>reg" instead of "u32<tab>reg". Other places in this patch spaces are used (eg in enable_cpu_clock, and in the struct declaration above), so at a minimum the tabs/spaces should be changed to be consistent, and <type><space><name> seems cleanest to me.
Quoted 10 lines
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 44
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +7
-0+/* 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.
Quoted 5 lines
What looks incorrect? It checks to see if the PLL is already running/enabled, and returns if it is.
Tegra2 mask ROM (BootROM) currently always sets PLLX, so this will always return, but the comment is there for future chips that may not set up PLLX.
It looks like a function that does a read of a value it doesn't care about, does an unnecessary comparison, and then returns either way, without doing anything:) If/when you want to do future stuff with the PLL-X, code should be added then - as is it doesn't do anything and is confusing. The general policy of U-Boot is not to add dead code.
<snip>
Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +5
-0+static void enable_cpu_power_rail (void ) +{ +struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE ; +u32 reg; +Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 171
Quoted 6 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +6
-0+ 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.
Quoted 3 lines
Ditto on why the delay? In this case, I did find a reference to the time needed between the request from the chipset to the PMU, hence the comment.
It'd be nice mention that reference in the comment. For those designing boards around your chips, during debug they will look through the initialization code and wonder "I wonder if we need to delay longer", or "I'm not using the same power supply sequencer, I wonder if this might be a problem". If you more explicitly state where the delay came from, or what the delay specifically accomplishes, it saves others from having to guess and investigate.
Quoted 20 lines
Quoted 12 lines
Quoted 12 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +12
-0+} + +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 Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 189
Quoted 6 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +6
-0+* 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.
Quoted 6 lines
It could be, sure. But it makes the line longer, >80 chars, and hence it would have to be broken into two lines.
Actually, now that I look at the code again, it appears that 'cpu' later should be OR'd with the SET_/CLR_DBGRESET0, etc. bits, depending on the state of 'reset'.
I'll give it a rewrite for the next patch.
Its a matter of preference, but is acceptable either way. I think:
+ writel(SET_DBGRESET1 | SET_DERESET1 | SET_CPURESET1,
+ &clkrst->crc_cpu_cmplx_set);
makes it clearer what is going on. Setting 'cpu', then writing would imply to me that 'cpu' has some additional purpose, or is being used later. If you restructure the code, this comment will likely be moot.
<snip>
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +12
-0+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 ;
Quoted 3 lines
Quoted 1 line
What's this number? Is there a define that could be used instead?
Sure, I can add a #define. Some magic ARM access sequence to unlock the CoreSight I/F, as the comment says
Its not clear what the number is from the comment. Is it a bitmask where each bit has some significance? Or is it just a "magic number" of some sort? If its a magic number with no other significance, a more verbose comment is fine stating so without adding a define.
Quoted 26 lines
Quoted 18 lines
Quoted 18 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +17
-0+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 */ Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 265
Quoted 6 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +6
-0+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.
Quoted 2 lines
Spaces where? Please be more specific. Again, checkpatch had no problem with this section.
The multiline comment is not aligned:
/*
*
*
*/
should be
/*
*
*/
<snip>
Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +7
-0+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 );Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 292
Quoted 5 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +5
-0+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.
Quoted 1 line
OK, I'll rewrite it.
Sorry, should have said "unnecessary" instead of "necessary" in the original comment.
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +13
-0+void startup_cpu (void ) +{ +/* Initialize the AVP, clocks, and memory controller */ +/* SDRAM is guaranteed to be on at this point */ + + asmvolatile ( + +/* Start the CPU */ +/* R0 = reset vector for CPU */ +"ldr r0, =cold_boot \n" +"bl start_cpu \n" + + /* Transfer control to the AVP code */Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 312
Quoted 5 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +5
-0+"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?
Quoted 5 lines
I can indent the asm code, no problem.
I don't see the need to move it to a .S file, though. Lots of examples of embedded assembly code in the U-Boot tree.
Unless I see some strong objections, I'm just going to indent it (and other asm statements).
Agreed are lots of embedded assembly in C files, but they are generally small snippets that interact with surrounding C-code, or simple one-liners.
Eg look in arch/powerpc:
find grep -r asm arch/powerpc | grep vola | grep -v ";"
There are only a handful of multi-line inline assembly references, lots are in headers, and the remaining generally interact with surrounding code.
It looks like most of your uses are standalone functions that would function just fine on their own. Is there a reason you prefer to have them in a C-file instead of in an assembly file?
<snip>
Quoted 61 lines
Quoted 53 lines
Quoted 53 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +52
-0+} + +void cache_configure (void ) +{ + asmvolatile ( + +"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"Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 439
Quoted 6 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +6
-0+ +/* FIXME: should have ap20's L2 disabled too */ +"invalidate_done: \n" +"ldmia r13!,{pc} \n" +".ltorg \n" + );Ditto on indentation/move.
Quoted 1 line
I'll indent it.
That's a pretty big and ugly inline assembly function... I'd push to have it in an assembly file along with the few other assembly-only functions, but its not my say ultimately.
Quoted 12 lines
Quoted 12 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 447
Quoted 9 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +8
-0+} + +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.
Quoted 3 lines
The generated assembly looks OK. These are mem-mapped scratch registers, so there're no side-effects here.
I can convert to a loop if you insist.
The policy is if you are accessing registers, you should use proper IO access functions. The generated assembly and/or CPU may behave differently down the road, as others have ran into.
<snip>
Quoted 11 lines
Quoted 11 lines
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +8
-0+#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).
Quoted 3 lines
I would think they'd be in the ARM tree somewhere, but I couldn't find them so I added 'em here.
My preference is to use TRUE/FALSE - it carries more context than 1/0 to me.
If you prefer to use TRUE/FALSE, they should be moved into a common location so everywhere uses the same, once-defined definition. Their definitions are already littered over a few files, which would ideally be cleaned up. Perhaps moving all definitions into include/common.h, or somewhere similar would work. Others may have opinions about TRUE/FALSE vs 1/0 - it seems like TRUE/FALSE aren't generally used.
< snip>
Quoted 18 lines
Quoted 10 lines
Quoted 10 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +10
-0+/* 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 */ Quoted 8 lines
arch/arm/include/asm/arch-tegra2/scu.h line 41
Quoted 5 lines
arch/arm/include/asm/arch-tegra2/scu.h new file +5
-0+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 1Should this be here? Seems like its not the proper location to enable things...
Quoted 4 lines
It's a bit setting, for the
scu_ctrlregister. I could change it to (1 << 0), if you'd prefer.
There are other bits in the SCU, but since they aren't used in this code, I didn't declare 'em.
Ahh, I get it - wasn't thinking of a bit definition. I think (1 << 0) would be clearer, or a comment, or the inclusion of the other SCU registers. If its for a specific register, naming it similarly would help too, eg "SCU_CTRL_ENABLE".
Best,
Peter
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Peter,
Quoted 15 lines · Peter Tyser
Hi Tom,
<snip>
Quoted 10 lines
Quoted 7 lines
arch/arm/cpu/armv7/tegra2/ap20.c
Quoted 4 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +4
-0+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.
Not sure what you mean, here, Peter. There are no spaces here in my
ap20.cfile, just tabs.
Please clarify.
Quoted 6 lines
My email client converted to spaces I was referring to the "u32 ? ?reg;" above. ?I think it should be "u32<space>reg" instead of "u32<tab>reg". Other places in this patch spaces are used (eg in
enable_cpu_clock, and in the struct declaration above), so at a minimum the tabs/spaces should be changed to be consistent, and <type><space><name> seems cleanest to me.
I see. I can change to <type><space><name> globally, no problem.
Quoted 17 lines
Quoted 11 lines
Quoted 11 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 44
Quoted 9 lines
+ ? ? /* Is PLL-X already running? */
+ ? ? reg =readl(&clkrst->crc_pllx_base);
+ ? ? if (reg &PLL_ENABLE)
+ ? ? ? ? ? ? return;arch/arm/cpu/armv7/tegra2/ap20.c new file +3
-0+ + ? ? /* Do PLLX init if it isn't running, but BootROM sets it, so TBD */ +}The above function looks incorrect.
Quoted 5 lines
What looks incorrect? It checks to see if the PLL is already running/enabled, and returns if it is.
Tegra2 mask ROM (BootROM) currently always sets PLLX, so this will always return, but the comment is there for future chips that may not set up PLLX.
Quoted 5 lines
It looks like a function that does a read of a value it doesn't care about, does an unnecessary comparison, and then returns either way, without doing anything:) ?If/when you want to do future stuff with the PLL-X, code should be added then - as is it doesn't do anything and is confusing. ?The general policy of U-Boot is not to add dead code.
OK, so not really incorrect, just unnecessary. Agreed - again a vestigial leftover from our in-house code. I'll remove it.
Quoted 20 lines
<snip>
Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +5
-0+static void enable_cpu_power_rail (void ) +{ + ? ? struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + ? ? u32 ? reg; +Quoted 8 lines
Quoted 6 lines
+ ? ? reg =
readl(&pmc->pmc_cntrl);
+ ? ? reg |=CPUPWRREQ_OE;
+ ? ?writel(reg, &pmc->pmc_cntrl);
+
+ ? ? /* Delay to allow for stable power (CPU_PWR_REQ->VDD_CPUfrom PMU) */
+ ? ? udelay(3750);Ditto for description.
Quoted 3 lines
Ditto on why the delay? In this case, I did find a reference to the time needed between the request from the chipset to the PMU, hence the comment.
Quoted 7 lines
It'd be nice mention that reference in the comment. ?For those designing boards around your chips, during debug they will look through the initialization code and wonder "I wonder if we need to delay longer", or "I'm not using the same power supply sequencer, I wonder if this might be a problem". ?If you more explicitly state where the delay came from, or what the delay specifically accomplishes, it saves others from having to guess and investigate.
OK, I'll expand the comment.
Quoted 51 lines
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
(quoted diff) +12
-0+} + +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 thereQuoted 8 lines
Quoted 6 lines
+ ? ? * ? ? ? ?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.
Quoted 6 lines
It could be, sure. But it makes the line longer, >80 chars, and hence it would have to be broken into two lines.
Actually, now that I look at the code again, it appears that 'cpu' later should be OR'd with the SET_/CLR_DBGRESET0, etc. bits, depending on the state of 'reset'.
I'll give it a rewrite for the next patch.Its a matter of preference, but is acceptable either way. ?I think:
+ ? ? ? writel(SET_DBGRESET1 |SET_DERESET1|SET_CPURESET1,
+ ? ? ? ? ? ? ?&clkrst->crc_cpu_cmplx_set);makes it clearer what is going on. ?Setting 'cpu', then writing would imply to me that 'cpu' has some additional purpose, or is being used later. ?If you restructure the code, this comment will likely be moot.
<snip>
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
+ ? ? if (enable) {
+ ? ? ? ? ? ? /*
+ ? ? ? ? ? ? ?* Put CoreSight onPLLP_OUT0(216 MHz) and divide it down by
+ ? ? ? ? ? ? ?* ?1.5, giving an effective frequency of 144MHz.
+ ? ? ? ? ? ? ?* SetPLLP_OUT0[bits31:30 = 00], and use a 7.1 divisor
+ ? ? ? ? ? ? ?* ?(bits 7:0), so00000001b== 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;
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
What's this number? ?Is there a define that could be used instead?
Sure, I can add a #define. Some magic ARM access sequence to unlock the CoreSight I/F, as the comment says
Its not clear what the number is from the comment. ?Is it a bitmask where each bit has some significance? ?Or is it just a "magic number" of some sort? ?If its a magic number with no other significance, a more verbose comment is fine stating so without adding a define.
OK, I'll expand the comment.
Quoted 30 lines
Quoted 27 lines
Quoted 19 lines
Quoted 19 lines
+ ? ? ? ? ? ?
writel(rst, CSITE_CPU_DBG0_LAR);
+ ? ? ? ? ? ?writel(rst, CSITE_CPU_DBG1_LAR);
+ ? ? }arch/arm/cpu/armv7/tegra2/ap20.c new file +14
-0+} + +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 */Quoted 8 lines
Quoted 6 lines
+ ? ?
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.
Quoted 2 lines
Spaces where? Please be more specific. ?Again, checkpatch had no problem with this section.
Quoted 10 lines
The multiline comment is not aligned:
/*
*
*
*/
should be
/*
?*
?*/
OK, now I see it. Will fix, thanks.
Quoted 56 lines
<snip>
Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
(quoted diff) +7
-0+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);Quoted 8 lines
Quoted 5 lines
+ ? ? ? ? ? ?
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.
Quoted 1 line
OK, I'll rewrite it.
Sorry, should have said "unnecessary" instead of "necessary" in the original comment.
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
(quoted diff) +13
-0+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 */Quoted 8 lines
Quoted 5 lines
+ ? ? "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?
Quoted 5 lines
I can indent the asm code, no problem.
I don't see the need to move it to a .S file, though. Lots of examples of embedded assembly code in the U-Boot tree.
Unless I see some strong objections, I'm just going to indent it (and other asm statements).Agreed are lots of embedded assembly in C files, but they are generally small snippets that interact with surrounding C-code, or simple one-liners.
Eg look in
arch/powerpc:
find grep -r asmarch/powerpc| grep vola | grep -v ";"
Quoted 7 lines
There are only a handful of multi-line inline assembly references, lots are in headers, and the remaining generally interact with surrounding code.
It looks like most of your uses are standalone functions that would function just fine on their own. ?Is there a reason you prefer to have them in a C-file instead of in an assembly file?
Just laziness ;)
I'll move these to a new .S file in the next patchset.
Quoted 64 lines
<snip>
Quoted 61 lines
Quoted 61 lines
Quoted 49 lines
(quoted diff) +48
-0+} + +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"Review
Quoted 10 lines
(quoted diff) +10
-0+ ? ? /* 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.
Quoted 5 lines
Quoted 1 line
I'll indent it.
That's a pretty big and ugly inline assembly function... ?I'd push to have it in an assembly file along with the few other assembly-only functions, but its not my say ultimately.
No problem - I'll move to .S.
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
arch/arm/cpu/armv7/tegra2/ap20.c
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +8
-0+} + +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.
Quoted 7 lines
Quoted 3 lines
The generated assembly looks OK. These are mem-mapped scratch registers, so there're no side-effects here.
I can convert to a loop if you insist.The policy is if you are accessing registers, you should use proper IO access functions. ?The generated assembly and/or CPU may behave differently down the road, as others have ran into.
All right. I'll put in a loop of writel()'s.
Quoted 18 lines
<snip>
Quoted 11 lines
Quoted 11 lines
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +8
-0+#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).
Quoted 3 lines
I would think they'd be in the ARM tree somewhere, but I couldn't find them so I added 'em here.
My preference is to use TRUE/FALSE - it carries more context than 1/0 to me.
Quoted 6 lines
If you prefer to use TRUE/FALSE, they should be moved into a common location so everywhere uses the same, once-defined definition. ?Their definitions are already littered over a few files, which would ideally be cleaned up. ?Perhaps moving all definitions into
include/common.h, or somewhere similar would work. ?Others may have opinions about TRUE/FALSE vs 1/0 - it seems like TRUE/FALSE aren't generally used.
I don't want to pollute all builds by adding to include/common.h. I'll try to find a more central header in my own tree.
Quoted 26 lines
< snip>
Quoted 18 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +10
-0+/* 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 */Quoted 8 lines
arch/arm/include/asm/arch-tegra2/scu.h
Quoted 5 lines
+ ? ? uint
scu_acc_ctl; ? ? ? /* SCU Access Control Register, offset 50 */
+ ? ? uintscu_ns_acc_ctl; ? ?/* SCU Non-secure Access Cntrl Reg, offset 54 */arch/arm/include/asm/arch-tegra2/scu.h new file +3
-0+}; + +#define SCU_ENABLE ? 1Should this be here? ?Seems like its not the proper location to enable things...
Quoted 4 lines
It's a bit setting, for the
scu_ctrlregister. I could change it to (1 << 0), if you'd prefer.
There are other bits in the SCU, but since they aren't used in this code, I didn't declare 'em.
Quoted 4 lines
Ahh, I get it - wasn't thinking of a bit definition. ?I think (1 << 0) would be clearer, or a comment, or the inclusion of the other SCU registers. ?If its for a specific register, naming it similarly would help too, eg "
SCU_CTRL_ENABLE".
Good idea. I'll make it SCU_CTRL_ENABLE. Thanks.
Quoted 3 lines
Best,
Peter
Thanks,
Tom
Quoted 1 line
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Hi Tom,
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 44
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c new file +7
-0+/* 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.
What looks incorrect? It checks to see if the PLL is already running/enabled, and returns if it is.
Tegra2 mask ROM (BootROM) currently always sets PLLX, so this will always return, but the comment is there for future chips that may not set up PLLX.
Quoted 7 lines
Quoted 5 lines
It looks like a function that does a read of a value it doesn't care about, does an unnecessary comparison, and then returns either way, without doing anything:) If/when you want to do future stuff with the PLL-X, code should be added then - as is it doesn't do anything and is confusing. The general policy of U-Boot is not to add dead code.
OK, so not really incorrect, just unnecessary. Agreed - again a vestigial leftover from our in-house code. I'll remove it.
Unnecessary/misleading/dead code is inherently not correct:)
<snip>
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 11 lines
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +8
-0+#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).
I would think they'd be in the ARM tree somewhere, but I couldn't find them so I added 'em here.
My preference is to use TRUE/FALSE - it carries more context than 1/0 to me.
Quoted 8 lines
Quoted 6 lines
If you prefer to use TRUE/FALSE, they should be moved into a common location so everywhere uses the same, once-defined definition. Their definitions are already littered over a few files, which would ideally be cleaned up. Perhaps moving all definitions into
include/common.h, or somewhere similar would work. Others may have opinions about TRUE/FALSE vs 1/0 - it seems like TRUE/FALSE aren't generally used.I don't want to pollute all builds by adding to
include/common.h. I'll try to find a more central header in my own tree.
My point is that there are already 32 definitions of TRUE/FALSE - adding a 33rd doesn't seem like a good thing to do. I view a 33rd identical definition as polluting the code more than 1 common definition that most people won't generally use.
Its not my decision, but I assume the powers that be would recommend one of:
- Not using TRUE/FALSE since using non-zero values and 0 are widely accepted as TRUE/FALSE. I think using TRUE/FALSE makes the code harder to understand and more open to bugs. Eg for other code that interacts with your code, or someone reviewing your code, they either have to either assume you defined TRUE as 1, FALSE as 0, or import your definitions. Anyway, I view their use as another layer of unnecessary abstraction with very little benefit.
- Consolidating the definition of TRUE/FALSE.
Wolfgang, do you have a preference about how TRUE/FALSE are generally used/defined?
Best,
Peter
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Peter,
Quoted 59 lines · Peter Tyser
Hi Tom,
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 10 lines
arch/arm/cpu/armv7/tegra2/ap20.c line 44
Quoted 8 lines
+ ? ? /* Is PLL-X already running? */
+ ? ? reg =readl(&clkrst->crc_pllx_base);
+ ? ? if (reg &PLL_ENABLE)
+ ? ? ? ? ? ? return;arch/arm/cpu/armv7/tegra2/ap20.c new file +3
-0+ + ? ? /* Do PLLX init if it isn't running, but BootROM sets it, so TBD */ +}The above function looks incorrect.
What looks incorrect? It checks to see if the PLL is already running/enabled, and returns if it is.
Tegra2 mask ROM (BootROM) currently always sets PLLX, so this will always return, but the comment is there for future chips that may not set up PLLX.Quoted 7 lines
Quoted 5 lines
It looks like a function that does a read of a value it doesn't care about, does an unnecessary comparison, and then returns either way, without doing anything:) ?If/when you want to do future stuff with the PLL-X, code should be added then - as is it doesn't do anything and is confusing. ?The general policy of U-Boot is not to add dead code.
OK, so not really incorrect, just unnecessary. Agreed - again a vestigial leftover from our in-house code. I'll remove it.
Unnecessary/misleading/dead code is inherently not correct:)
<snip>
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 11 lines
arch/arm/cpu/armv7/tegra2/ap20.h line 30
Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.h new file +8
-0+#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).
I would think they'd be in the ARM tree somewhere, but I couldn't find them so I added 'em here.
My preference is to use TRUE/FALSE - it carries more context than 1/0 to me.Quoted 8 lines
Quoted 6 lines
If you prefer to use TRUE/FALSE, they should be moved into a common location so everywhere uses the same, once-defined definition. ?Their definitions are already littered over a few files, which would ideally be cleaned up. ?Perhaps moving all definitions into
include/common.h, or somewhere similar would work. ?Others may have opinions about TRUE/FALSE vs 1/0 - it seems like TRUE/FALSE aren't generally used.I don't want to pollute all builds by adding to
include/common.h. I'll try to find a more central header in my own tree.My point is that there are already 32 definitions of TRUE/FALSE - adding a 33rd doesn't seem like a good thing to do. ?I view a 33rd identical definition as polluting the code more than 1 common definition that most people won't generally use.
Quoted 9 lines
Its not my decision, but I assume the powers that be would recommend one of:
- Not using TRUE/FALSE since using non-zero values and 0 are widely accepted as TRUE/FALSE. ?I think using TRUE/FALSE makes the code harder to understand and more open to bugs. ?Eg for other code that interacts with your code, or someone reviewing your code, they either have to either assume you defined TRUE as 1, FALSE as 0, or import your definitions. ?Anyway, I view their use as another layer of unnecessary abstraction with very little benefit.
I've removed both the defines and the use of TRUE/FALSE in ap20.* - there were only a few instances.
Quoted 8 lines
- Consolidating the definition of TRUE/FALSE.
Wolfgang, do you have a preference about how TRUE/FALSE are generally used/defined?
Best,
Peter
Thanks,
Tom
Quoted 4 lines
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
In reply to Tom WarrenQuoted 7 lines
Quoted 4 lines
It looks like most of your uses are standalone functions that would function just fine on their own. Is there a reason you prefer to have them in a C-file instead of in an assembly file?
Just laziness ;)
I'll move these to a new .S file in the next patchset.
Actually, writing assembly-only C functions is difficul and error-pronet. I've seen you use "r0" and other registers esplicitly, but this is not allowed in general.
I once wasted some hours in tracking why a non-submitted port of u-boot was not working with a newer compiler. The problem was just
that: the new compiler was inlining a void(void) function; the asm used "r0" and "r1" explicitly, which worked over a function call but was corrupting data when inlined by the newer and more optimizing compiler.
While your functions are currently not inlined (or, like cold_boot, they may be inlined in a place where no register needs to be preserved), another user may move them to a context where the semantics are different, for another board or another boot loader. If they are in a .S files, they will only be called by "bl" and you know the rules for register allocation appy. Besides, a _real_ lazy programmer avoids the extra quotes and \n in the code :)
/alessandro
PATCH 1/1 arm: Tegra2: add support for A9 CPU init
Allesandro,
Quoted 12 lines · Alessandro Rubini
Quoted 7 lines
Quoted 4 lines
It looks like most of your uses are standalone functions that would function just fine on their own. ?Is there a reason you prefer to have them in a C-file instead of in an assembly file?
Just laziness ;)
I'll move these to a new .S file in the next patchset.Actually, writing assembly-only C functions is difficul and error-pronet. I've seen you use "r0" and other registers esplicitly, but this is not allowed in general.
Quoted 6 lines
I once wasted some hours in tracking why a non-submitted port of u-boot was not working with a newer compiler. The problem was just
that: the new compiler was inlining a void(void) function; the asm used "r0" and "r1" explicitly, which worked over a function call but was corrupting data when inlined by the newer and more optimizing compiler.
I've moved most of the in-line assembly to lowlevel_init.S. However, the cold_boot() code proved difficult - I got fixup errors, undefined constants, etc.
I've cleaned it up a bit, but left it in ap20.c, using the %vars - again, replacing them with the actual values caused errors that I couldn't resolve.
Maybe someone else on the list can help to port this code to the assembly file - I'm not expert enough in gcc/as and ARM to do it. New patch to follow RSN.
Quoted 10 lines
While your functions are currently not inlined (or, like
cold_boot, they may be inlined in a place where no register needs to be preserved), another user may move them to a context where the semantics are different, for another board or another boot loader. ?If they are in a .S files, they will only be called by "bl" and you know the rules for register allocation appy. Besides, a _real_ lazy programmer avoids the extra quotes and \n in the code :)/alessandro
Thanks for your insight,
Tom