From 68e2a64181df8c6bfe1c474ea968f1e82e61ccfc Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 8 Jul 2015 12:57:50 +0530 Subject: [PATCH 1/8] Tegra: Exclude coherent memory region from memory map This patch sets the 'USE_COHERENT_MEM' flag to '0', so that the coherent memory region will not be included in the memory map. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/tegra_bl31_setup.c | 10 +++++----- plat/nvidia/tegra/common/tegra_common.mk | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c index dea8457bd..87e4ae145 100644 --- a/plat/nvidia/tegra/common/tegra_bl31_setup.c +++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -196,13 +196,9 @@ void bl31_plat_arch_setup(void) unsigned long total_size = TZDRAM_END - BL31_RO_BASE; unsigned long ro_start = bl31_base_pa; unsigned long ro_size = BL31_RO_LIMIT - BL31_RO_BASE; - unsigned long coh_start = 0; - unsigned long coh_size = 0; const mmap_region_t *plat_mmio_map = NULL; - #if USE_COHERENT_MEM - coh_start = total_base + (BL31_COHERENT_RAM_BASE - BL31_RO_BASE); - coh_size = BL31_COHERENT_RAM_LIMIT - BL31_COHERENT_RAM_BASE; + unsigned long coh_start, coh_size; #endif /* add memory regions */ @@ -212,7 +208,11 @@ void bl31_plat_arch_setup(void) mmap_add_region(ro_start, ro_start, ro_size, MT_MEMORY | MT_RO | MT_SECURE); + #if USE_COHERENT_MEM + coh_start = total_base + (BL31_COHERENT_RAM_BASE - BL31_RO_BASE); + coh_size = BL31_COHERENT_RAM_LIMIT - BL31_COHERENT_RAM_BASE; + mmap_add_region(coh_start, coh_start, coh_size, MT_DEVICE | MT_RW | MT_SECURE); diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk index 73e128111..5ec52fb2f 100644 --- a/plat/nvidia/tegra/common/tegra_common.mk +++ b/plat/nvidia/tegra/common/tegra_common.mk @@ -34,6 +34,8 @@ $(eval $(call add_define,CRASH_REPORTING)) ASM_ASSERTION := 1 $(eval $(call add_define,ASM_ASSERTION)) +USE_COHERENT_MEM := 0 + PLAT_INCLUDES := -Iplat/nvidia/tegra/include/drivers \ -Iplat/nvidia/tegra/include \ -Iplat/nvidia/tegra/include/${TARGET_SOC} From c896132679440481cfca0324255dbdfb689ed203 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 16 Jul 2015 15:47:03 +0530 Subject: [PATCH 2/8] Tegra: introduce delay timer support This patch introduces the backend required for implementing the delay timer API. Tegra has an on-chip free flowing us timer which can be used as the delay timer. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/tegra_bl31_setup.c | 5 ++ plat/nvidia/tegra/common/tegra_common.mk | 2 + plat/nvidia/tegra/common/tegra_delay_timer.c | 53 ++++++++++++++++++++ plat/nvidia/tegra/include/tegra_private.h | 3 ++ 4 files changed, 63 insertions(+) create mode 100644 plat/nvidia/tegra/common/tegra_delay_timer.c diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c index 87e4ae145..ce7f31757 100644 --- a/plat/nvidia/tegra/common/tegra_bl31_setup.c +++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -161,6 +161,11 @@ void bl31_platform_setup(void) { uint32_t tmp_reg; + /* + * Initialize delay timer + */ + tegra_delay_timer_init(); + /* * Setup secondary CPU POR infrastructure. */ diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk index 5ec52fb2f..b88742a8d 100644 --- a/plat/nvidia/tegra/common/tegra_common.mk +++ b/plat/nvidia/tegra/common/tegra_common.mk @@ -48,6 +48,7 @@ COMMON_DIR := plat/nvidia/tegra/common BL31_SOURCES += drivers/arm/gic/gic_v2.c \ drivers/arm/gic/gic_v3.c \ drivers/console/console.S \ + drivers/delay_timer/delay_timer.c \ drivers/ti/uart/16550_console.S \ lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ @@ -57,6 +58,7 @@ BL31_SOURCES += drivers/arm/gic/gic_v2.c \ ${COMMON_DIR}/drivers/pmc/pmc.c \ ${COMMON_DIR}/drivers/flowctrl/flowctrl.c \ ${COMMON_DIR}/tegra_bl31_setup.c \ + ${COMMON_DIR}/tegra_delay_timer.c \ ${COMMON_DIR}/tegra_gic.c \ ${COMMON_DIR}/tegra_pm.c \ ${COMMON_DIR}/tegra_sip_calls.c \ diff --git a/plat/nvidia/tegra/common/tegra_delay_timer.c b/plat/nvidia/tegra/common/tegra_delay_timer.c new file mode 100644 index 000000000..e1f6eded0 --- /dev/null +++ b/plat/nvidia/tegra/common/tegra_delay_timer.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static uint32_t tegra_timerus_get_value(void) +{ + return mmio_read_32(TEGRA_TMRUS_BASE); +} + +static const timer_ops_t tegra_timer_ops = { + .get_timer_value = tegra_timerus_get_value, + .clk_mult = 1, + .clk_div = 1, +}; + +/* + * Initialise the on-chip free rolling us counter as the delay + * timer. + */ +void tegra_delay_timer_init(void) +{ + timer_init(&tegra_timer_ops); +} diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h index fa29fbb42..d0cde2afd 100644 --- a/plat/nvidia/tegra/include/tegra_private.h +++ b/plat/nvidia/tegra/include/tegra_private.h @@ -74,4 +74,7 @@ int tegra_prepare_cpu_on_finish(unsigned long mpidr); plat_params_from_bl2_t *bl31_get_plat_params(void); int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes); +/* Declarations for tegra_delay_timer.c */ +void tegra_delay_timer_init(void); + #endif /* __TEGRA_PRIVATE_H__ */ From 6a367fd1efb37a02df22b5f8b61a7b3d5c5a12a6 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 8 Jul 2015 13:46:42 +0530 Subject: [PATCH 3/8] Tegra: Fix the delay loop used during SC7 exit This patch fixes the delay loop used to wake up the BPMP during SC7 exit. The earlier loop would fail just when the timer was about to wrap-around (e.g. when TEGRA_TMRUS_BASE is 0xfffffffe, the target value becomes 0, which would cause the loop to exit before it's expiry). Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c index a36cf2d73..b473dd656 100644 --- a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c +++ b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -230,10 +231,7 @@ void tegra_fc_reset_bpmp(void) ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */ /* Wait for 2us before de-asserting the reset signal. */ - val = mmio_read_32(TEGRA_TMRUS_BASE); - val += 2; - while (val > mmio_read_32(TEGRA_TMRUS_BASE)) - ; /* wait for 2us */ + udelay(2); /* De-assert BPMP reset */ mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST); From 03cd23a10aac675773a90ef238c33dba73cdae7c Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 8 Jul 2015 17:42:02 +0530 Subject: [PATCH 4/8] Tegra210: deassert CPU reset signals during power on This patch de-asserts the CPU reset signals for each CPU as part of it's power on sequence. This is needed to get rid of the wait in BPMP firmware during SC7 exit. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t210/plat_psci_handlers.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c index f594d2097..010899ac3 100644 --- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c @@ -40,6 +40,13 @@ #include #include +/* + * Register used to clear CPU reset signals. Each CPU has two reset + * signals: CPU reset (3:0) and Core reset (19:16). + */ +#define CPU_CMPLX_RESET_CLR 0x454 +#define CPU_CORE_RESET_MASK 0x10001 + static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER]; int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl) @@ -116,6 +123,10 @@ int tegra_prepare_cpu_on_finish(unsigned long mpidr) int tegra_prepare_cpu_on(unsigned long mpidr) { int cpu = mpidr & MPIDR_CPU_MASK; + uint32_t mask = CPU_CORE_RESET_MASK << cpu; + + /* Deassert CPU reset signals */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask); /* Turn on CPU using flow controller or PMC */ if (cpu_powergate_mask[cpu] == 0) { From 2e7aea3d485821b8c78dbf092489f8a20a4e5e1d Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 16 Jul 2015 10:35:12 +0530 Subject: [PATCH 5/8] Tegra: PMC: check if a CPU is already online This patch checks if the target CPU is already online before proceeding with it's power ON sequence. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/drivers/pmc/pmc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plat/nvidia/tegra/common/drivers/pmc/pmc.c b/plat/nvidia/tegra/common/drivers/pmc/pmc.c index 5796ac79e..6e7f23c6c 100644 --- a/plat/nvidia/tegra/common/drivers/pmc/pmc.c +++ b/plat/nvidia/tegra/common/drivers/pmc/pmc.c @@ -51,6 +51,13 @@ void tegra_pmc_cpu_on(int cpu) { uint32_t val; + /* + * Check if CPU is already power ungated + */ + val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); + if (val & (1 << pmc_cpu_powergate_id[cpu])) + return; + /* * The PMC deasserts the START bit when it starts the power * ungate process. Loop till no power toggle is in progress. From 764c57f6f501cc08734283415aff1366dcd4d41e Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 16 Jul 2015 10:38:11 +0530 Subject: [PATCH 6/8] Tegra: PMC: lock SCRATCH22 register The PMC Scratch22 register contains the CPU reset vector to be used by the warmboot code to power up the CPU while resuming from system suspend. This patch locks this PMC register to avoid any further writes. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/drivers/pmc/pmc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plat/nvidia/tegra/common/drivers/pmc/pmc.c b/plat/nvidia/tegra/common/drivers/pmc/pmc.c index 6e7f23c6c..d48b57549 100644 --- a/plat/nvidia/tegra/common/drivers/pmc/pmc.c +++ b/plat/nvidia/tegra/common/drivers/pmc/pmc.c @@ -105,6 +105,11 @@ void tegra_pmc_lock_cpu_vectors(void) { uint32_t val; + /* lock PMC_SECURE_SCRATCH22 */ + val = tegra_pmc_read_32(PMC_SECURE_DISABLE2); + val |= PMC_SECURE_DISABLE2_WRITE22_ON; + tegra_pmc_write_32(PMC_SECURE_DISABLE2, val); + /* lock PMC_SECURE_SCRATCH34/35 */ val = tegra_pmc_read_32(PMC_SECURE_DISABLE3); val |= (PMC_SECURE_DISABLE3_WRITE34_ON | From e5b0664ce75850e1a291d4f282fd6735b821fec4 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 16 Jul 2015 11:58:19 +0530 Subject: [PATCH 7/8] Tegra210: lock PMC registers holding CPU vector addresses This patch locks access to the PMC registers which hold the CPU reset vector addresses. The PMC registers are used by the warmboot code and must be locked during boot/resume to avoid booting into custom firmware installed by unknown parties e.g. hackers. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t210/plat_secondary.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/nvidia/tegra/soc/t210/plat_secondary.c b/plat/nvidia/tegra/soc/t210/plat_secondary.c index fb3cf7143..b07f446d0 100644 --- a/plat/nvidia/tegra/soc/t210/plat_secondary.c +++ b/plat/nvidia/tegra/soc/t210/plat_secondary.c @@ -60,4 +60,5 @@ void plat_secondary_setup(void) /* configure PMC */ tegra_pmc_cpu_setup(reset_addr); + tegra_pmc_lock_cpu_vectors(); } From 8061a973ec122b49e2fb79a51a67695f2b888e59 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 16 Jul 2015 09:46:28 +0530 Subject: [PATCH 8/8] Tegra: Introduce config for enabling NS access to L2/CPUECTRL regs A new config, ENABLE_NS_L2_CPUECTRL_RW_ACCESS, allows Tegra platforms to enable read/write access to the L2 and CPUECTRL registers. T210 is the only platform that needs to enable this config for now. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/aarch64/tegra_helpers.S | 2 ++ plat/nvidia/tegra/soc/t210/platform_t210.mk | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S index 264749b68..2979b32dc 100644 --- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S +++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S @@ -57,6 +57,7 @@ */ .macro cpu_init_common +#if ENABLE_NS_L2_CPUECTRL_RW_ACCESS /* ------------------------------------------------------- * Enable L2 and CPU ECTLR RW access from non-secure world * ------------------------------------------------------- @@ -65,6 +66,7 @@ msr actlr_el3, x0 msr actlr_el2, x0 isb +#endif /* -------------------------------- * Enable the cycle count register diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk index 41651d35e..003b48960 100644 --- a/plat/nvidia/tegra/soc/t210/platform_t210.mk +++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -28,19 +28,22 @@ # POSSIBILITY OF SUCH DAMAGE. # -TEGRA_BOOT_UART_BASE := 0x70006000 +TEGRA_BOOT_UART_BASE := 0x70006000 $(eval $(call add_define,TEGRA_BOOT_UART_BASE)) -TZDRAM_BASE := 0xFDC00000 +TZDRAM_BASE := 0xFDC00000 $(eval $(call add_define,TZDRAM_BASE)) ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT := 1 $(eval $(call add_define,ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT)) -PLATFORM_CLUSTER_COUNT := 2 +ENABLE_NS_L2_CPUECTRL_RW_ACCESS := 1 +$(eval $(call add_define,ENABLE_NS_L2_CPUECTRL_RW_ACCESS)) + +PLATFORM_CLUSTER_COUNT := 2 $(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) -PLATFORM_MAX_CPUS_PER_CLUSTER := 4 +PLATFORM_MAX_CPUS_PER_CLUSTER := 4 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) BL31_SOURCES += ${SOC_DIR}/plat_psci_handlers.c \ @@ -49,3 +52,4 @@ BL31_SOURCES += ${SOC_DIR}/plat_psci_handlers.c \ # Enable workarounds for selected Cortex-A53 erratas. ERRATA_A53_826319 := 1 +