diff --git a/Makefile b/Makefile index 0169f3f..34f6890 100644 --- a/Makefile +++ b/Makefile @@ -248,7 +248,6 @@ # Common sources and include directories ################################################################################ include lib/compiler-rt/compiler-rt.mk -include lib/libc/libc.mk BL_COMMON_SOURCES += common/bl_common.c \ common/tf_log.c \ @@ -393,6 +392,13 @@ endif ################################################################################ +# Include libc if not overridden +################################################################################ +ifeq (${OVERRIDE_LIBC},0) +include lib/libc/libc.mk +endif + +################################################################################ # Check incompatible options ################################################################################ @@ -595,6 +601,7 @@ $(eval $(call assert_boolean,HW_ASSISTED_COHERENCY)) $(eval $(call assert_boolean,MULTI_CONSOLE_API)) $(eval $(call assert_boolean,NS_TIMER_SWITCH)) +$(eval $(call assert_boolean,OVERRIDE_LIBC)) $(eval $(call assert_boolean,PL011_GENERIC_UART)) $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS)) $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID)) diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst index 90d2ae1..7ed0f2c 100644 --- a/docs/plat/nvidia-tegra.rst +++ b/docs/plat/nvidia-tegra.rst @@ -1,6 +1,23 @@ Tegra SoCs - Overview ===================== +- .. rubric:: T186 + :name: t186 + +The NVIDIA® Parker (T186) series system-on-chip (SoC) delivers a heterogeneous +multi-processing (HMP) solution designed to optimize performance and +efficiency. + +T186 has Dual NVIDIA Denver 2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores, +in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores +support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy ARMv7 applications. The Denver 2 processors each have 128 KB +Instruction and 64 KB Data Level 1 caches; and have a 2MB shared Level 2 +unified cache. The Cortex-A57 processors each have 48 KB Instruction and 32 KB +Data Level 1 caches; and also have a 2 MB shared Level 2 unified cache. A +high speed coherency fabric connects these two processor complexes and allows +heterogeneous multi-processing with all six cores if required. + - .. rubric:: T210 :name: t210 @@ -49,11 +66,21 @@ Trusted OS dispatcher ===================== -Tegra supports multiple Trusted OS', Trusted Little Kernel (TLK) being one of -them. In order to include the 'tlkd' dispatcher in the image, pass 'SPD=tlkd' -on the command line while preparing a bl31 image. This allows other Trusted OS -vendors to use the upstream code and include their dispatchers in the image -without changing any makefiles. +Tegra supports multiple Trusted OS'. + +- Trusted Little Kernel (TLK): In order to include the 'tlkd' dispatcher in + the image, pass 'SPD=tlkd' on the command line while preparing a bl31 image. +- Trusty: In order to include the 'trusty' dispatcher in the image, pass + 'SPD=trusty' on the command line while preparing a bl31 image. + +This allows other Trusted OS vendors to use the upstream code and include +their dispatchers in the image without changing any makefiles. + +These are the supported Trusted OS' by Tegra platforms. + +Tegra132: TLK +Tegra210: TLK and Trusty +Tegra186: Trusty Preparing the BL31 image to run on Tegra SoCs ============================================= @@ -61,7 +88,8 @@ .. code:: shell CROSS_COMPILE=/bin/aarch64-none-elf- make PLAT=tegra \ - TARGET_SOC= SPD= bl31 + TARGET_SOC= SPD= + bl31 Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=`` to the build command line. diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 320bb1d..35d44ca 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -575,6 +575,10 @@ 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it wants the timer registers to be saved and restored. +- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc + for the BL image. It can be either 0 (include) or 1 (remove). The default + value is 0. + - ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that the underlying hardware is not a full PL011 UART but a minimally compliant generic UART, which is a subset of the PL011. The driver will not access diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h index 2c12633..ce8e3e8 100644 --- a/include/bl32/payloads/tlk.h +++ b/include/bl32/payloads/tlk.h @@ -20,7 +20,9 @@ */ #define TLK_REGISTER_LOGBUF TLK_TOS_YIELD_FID(0x1) #define TLK_REGISTER_REQBUF TLK_TOS_YIELD_FID(0x2) -#define TLK_REGISTER_NS_DRAM TLK_TOS_YIELD_FID(0x4) +#define TLK_SS_REGISTER_HANDLER TLK_TOS_YIELD_FID(0x3) +#define TLK_REGISTER_NS_DRAM_RANGES TLK_TOS_YIELD_FID(0x4) +#define TLK_SET_ROOT_OF_TRUST TLK_TOS_YIELD_FID(0x5) #define TLK_RESUME_FID TLK_TOS_YIELD_FID(0x100) #define TLK_SYSTEM_SUSPEND TLK_TOS_YIELD_FID(0xE001) #define TLK_SYSTEM_RESUME TLK_TOS_YIELD_FID(0xE002) diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index c1aa320..76a9fd4 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -122,6 +122,9 @@ # NS timer register save and restore NS_TIMER_SWITCH := 0 +# Include lib/libc in the final image +OVERRIDE_LIBC := 0 + # Build PL011 UART driver in minimal generic UART mode PL011_GENERIC_UART := 0 diff --git a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c index 1c5d2e1..29dc267 100644 --- a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c +++ b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c @@ -16,7 +16,7 @@ #include #include -#define BPMP_TIMEOUT 2 +#define BPMP_TIMEOUT 500 /* 500ms */ static uint32_t channel_base[NR_CHANNELS]; static uint32_t bpmp_init_state = BPMP_INIT_PENDING; @@ -115,58 +115,117 @@ int tegra_bpmp_init(void) { - uint32_t val, base; + uint32_t val, base, timeout = BPMP_TIMEOUT; unsigned int ch; int ret = 0; - if (bpmp_init_state != BPMP_INIT_COMPLETE) { + if (bpmp_init_state == BPMP_INIT_PENDING) { /* check if the bpmp processor is alive. */ - val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); - if (val != SIGN_OF_LIFE) { - ERROR("BPMP precessor not available\n"); - return -ENOTSUP; + do { + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + if (val != SIGN_OF_LIFE) { + mdelay(1); + timeout--; + } + + } while ((val != SIGN_OF_LIFE) && (timeout > 0U)); + + if (val == SIGN_OF_LIFE) { + + /* check if clock for the atomics block is enabled */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V); + if ((val & CAR_ENABLE_ATOMICS) == 0) { + ERROR("Clock to the atomics block is disabled\n"); + } + + /* check if the atomics block is out of reset */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V); + if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) { + ERROR("Reset to the atomics block is asserted\n"); + } + + /* base address to get the result from Atomics */ + base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET; + + /* channel area is setup by BPMP before signaling handshake */ + for (ch = 0; ch < NR_CHANNELS; ch++) { + + /* issue command to get the channel base address */ + mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) | + ATOMIC_CMD_GET); + + /* get the base address for the channel */ + channel_base[ch] = mmio_read_32(base); + + /* increment result register offset */ + base += 4U; + } + + /* mark state as "initialized" */ + bpmp_init_state = BPMP_INIT_COMPLETE; + + /* the channel values have to be visible across all cpus */ + flush_dcache_range((uint64_t)channel_base, + sizeof(channel_base)); + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + + INFO("%s: done\n", __func__); + + } else { + ERROR("BPMP not powered on\n"); + + /* bpmp is not present in the system */ + bpmp_init_state = BPMP_NOT_PRESENT; + + /* communication timed out */ + ret = -ETIMEDOUT; } - - /* check if clock for the atomics block is enabled */ - val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V); - if ((val & CAR_ENABLE_ATOMICS) == 0) { - ERROR("Clock to the atomics block is disabled\n"); - } - - /* check if the atomics block is out of reset */ - val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V); - if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) { - ERROR("Reset to the atomics block is asserted\n"); - } - - /* base address to get the result from Atomics */ - base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET; - - /* channel area is setup by BPMP before signaling handshake */ - for (ch = 0; ch < NR_CHANNELS; ch++) { - - /* issue command to get the channel base address */ - mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) | - ATOMIC_CMD_GET); - - /* get the base address for the channel */ - channel_base[ch] = mmio_read_32(base); - - /* increment result register offset */ - base += 4U; - } - - /* mark state as "initialized" */ - bpmp_init_state = BPMP_INIT_COMPLETE; - - /* the channel values have to be visible across all cpus */ - flush_dcache_range((uint64_t)channel_base, sizeof(channel_base)); - flush_dcache_range((uint64_t)&bpmp_init_state, - sizeof(bpmp_init_state)); - - INFO("%s: done\n", __func__); } return ret; } + +void tegra_bpmp_suspend(void) +{ + /* freeze the interface */ + if (bpmp_init_state == BPMP_INIT_COMPLETE) { + bpmp_init_state = BPMP_SUSPEND_ENTRY; + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + } +} + +void tegra_bpmp_resume(void) +{ + uint32_t val, timeout = 0; + + if (bpmp_init_state == BPMP_SUSPEND_ENTRY) { + + /* check if the bpmp processor is alive. */ + do { + + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + if (val != SIGN_OF_LIFE) { + mdelay(1); + timeout++; + } + + } while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT)); + + if (val == SIGN_OF_LIFE) { + + INFO("%s: BPMP took %d ms to resume\n", __func__, timeout); + + /* mark state as "initialized" */ + bpmp_init_state = BPMP_INIT_COMPLETE; + + /* state has to be visible across all cpus */ + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + } else { + ERROR("BPMP not powered on\n"); + } + } +} diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c index 7faa2f0..2efa1bd 100644 --- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c +++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -302,3 +302,49 @@ return ret; } + +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} + +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h index 689f8bb..7059c37 100644 --- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h +++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,10 +11,10 @@ * Flags used in IPC req */ #define FLAG_DO_ACK (U(1) << 0) -#define FLAG_RING_DOORBELL (U(1) << 1) +#define FLAG_RING_DOORBELL (U(1) << 1) /* Bit 1 is designated for CCPlex in secure world */ -#define HSP_MASTER_CCPLEX_BIT (U(1) << 1) +#define HSP_MASTER_CCPLEX_BIT (U(1) << 1) /* Bit 19 is designated for BPMP in non-secure world */ #define HSP_MASTER_BPMP_BIT (U(1) << 19) /* Timeout to receive response from BPMP is 1 sec */ @@ -49,9 +49,10 @@ */ /** - * MRQ code to issue a module reset command to BPMP + * MRQ command codes */ #define MRQ_RESET U(20) +#define MRQ_CLK U(22) /** * Reset sub-commands @@ -71,4 +72,56 @@ uint32_t reset_id; }; +/** + * MRQ_CLK sub-commands + * + */ +enum { + CMD_CLK_GET_RATE = 1, + CMD_CLK_SET_RATE = 2, + CMD_CLK_ROUND_RATE = 3, + CMD_CLK_GET_PARENT = 4, + CMD_CLK_SET_PARENT = 5, + CMD_CLK_IS_ENABLED = 6, + CMD_CLK_ENABLE = 7, + CMD_CLK_DISABLE = 8, + CMD_CLK_GET_ALL_INFO = 14, + CMD_CLK_GET_MAX_CLK_ID = 15, + CMD_CLK_MAX, +}; + +/** + * Used by the sender of an #MRQ_CLK message to control clocks. The + * clk_request is split into several sub-commands. Some sub-commands + * require no additional data. Others have a sub-command specific + * payload + * + * |sub-command |payload | + * |----------------------------|-----------------------| + * |CMD_CLK_GET_RATE |- | + * |CMD_CLK_SET_RATE |clk_set_rate | + * |CMD_CLK_ROUND_RATE |clk_round_rate | + * |CMD_CLK_GET_PARENT |- | + * |CMD_CLK_SET_PARENT |clk_set_parent | + * |CMD_CLK_IS_ENABLED |- | + * |CMD_CLK_ENABLE |- | + * |CMD_CLK_DISABLE |- | + * |CMD_CLK_GET_ALL_INFO |- | + * |CMD_CLK_GET_MAX_CLK_ID |- | + * + */ +struct mrq_clk_request { + /** + * sub-command and clock id concatenated to 32-bit word. + * - bits[31..24] is the sub-cmd. + * - bits[23..0] is the clock id + */ + uint32_t cmd_and_id; +}; + +/** + * Macro to prepare the MRQ_CLK sub-command + */ +#define make_mrq_clk_cmd(cmd, id) (((cmd) << 24) | (id & 0xFFFFFF)) + #endif /* INTF_H */ diff --git a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c index 775ad30..bdd3ee7 100644 --- a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c +++ b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,6 +15,7 @@ #include #include #include +#include #define CLK_RST_DEV_L_SET 0x300 #define CLK_RST_DEV_L_CLR 0x304 @@ -76,6 +77,47 @@ } /******************************************************************************* + * After this, no core can wake from C7 until the action is reverted. + * If a wake up event is asserted, the FC state machine will stall until + * the action is reverted. + ******************************************************************************/ +void tegra_fc_ccplex_pgexit_lock(void) +{ + unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;; + uint32_t icept_cpu_flags[] = { + INTERCEPT_EXIT_PG_CORE0, + INTERCEPT_EXIT_PG_CORE1, + INTERCEPT_EXIT_PG_CORE2, + INTERCEPT_EXIT_PG_CORE3 + }; + + /* set the intercept flags */ + for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) { + + /* skip current CPU */ + if (i == cpu) + continue; + + /* enable power gate exit intercept locks */ + flags |= icept_cpu_flags[i]; + } + + tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags); + (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT); +} + +/******************************************************************************* + * Revert the ccplex powergate exit locks + ******************************************************************************/ +void tegra_fc_ccplex_pgexit_unlock(void) +{ + /* clear lock bits, clear pending interrupts */ + tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING); + (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT); +} + +/******************************************************************************* * Powerdn the current CPU ******************************************************************************/ void tegra_fc_cpu_powerdn(uint32_t mpidr) @@ -129,6 +171,31 @@ } /******************************************************************************* + * Check if cluster idle or power down state is allowed from this CPU + ******************************************************************************/ +bool tegra_fc_is_ccx_allowed(void) +{ + unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t val; + bool ccx_allowed = true; + + for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) { + + /* skip current CPU */ + if (i == cpu) + continue; + + /* check if all other CPUs are already halted */ + val = mmio_read_32(flowctrl_offset_cpu_csr[i]); + if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) { + ccx_allowed = false; + } + } + + return ccx_allowed; +} + +/******************************************************************************* * Suspend the entire SoC ******************************************************************************/ void tegra_fc_soc_powerdn(uint32_t mpidr) @@ -190,22 +257,19 @@ } /******************************************************************************* - * Reset BPMP processor + * Power ON BPMP processor ******************************************************************************/ -void tegra_fc_reset_bpmp(void) +void tegra_fc_bpmp_on(uint32_t entrypoint) { - uint32_t val; - /* halt BPMP */ tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT); /* Assert BPMP reset */ mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST); - /* Restore reset address (stored in PMC_SCRATCH39) */ - val = tegra_pmc_read_32(PMC_SCRATCH39); - mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val); - while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR)) + /* Set reset address (stored in PMC_SCRATCH39) */ + mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint); + while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR)) ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */ /* Wait for 2us before de-asserting the reset signal. */ @@ -217,3 +281,42 @@ /* Un-halt BPMP */ tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0); } + +/******************************************************************************* + * Power OFF BPMP processor + ******************************************************************************/ +void tegra_fc_bpmp_off(void) +{ + /* halt BPMP */ + tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT); + + /* Assert BPMP reset */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST); + + /* Clear reset address */ + mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0); + while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR)) + ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */ +} + +/******************************************************************************* + * Route legacy FIQ to the GICD + ******************************************************************************/ +void tegra_fc_enable_fiq_to_ccplex_routing(void) +{ + uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL); + + /* set the bit to pass FIQs to the GICD */ + tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE); +} + +/******************************************************************************* + * Disable routing legacy FIQ to the GICD + ******************************************************************************/ +void tegra_fc_disable_fiq_to_ccplex_routing(void) +{ + uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL); + + /* clear the bit to pass FIQs to the GICD */ + tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE); +} diff --git a/plat/nvidia/tegra/common/drivers/pmc/pmc.c b/plat/nvidia/tegra/common/drivers/pmc/pmc.c index b9ff511..6c5a73b 100644 --- a/plat/nvidia/tegra/common/drivers/pmc/pmc.c +++ b/plat/nvidia/tegra/common/drivers/pmc/pmc.c @@ -17,7 +17,7 @@ /* Module IDs used during power ungate procedure */ static const uint32_t pmc_cpu_powergate_id[4] = { - 0, /* CPU 0 */ + 14, /* CPU 0 */ 9, /* CPU 1 */ 10, /* CPU 2 */ 11 /* CPU 3 */ @@ -98,6 +98,45 @@ } /******************************************************************************* + * Find out if this is the last standing CPU + ******************************************************************************/ +bool tegra_pmc_is_last_on_cpu(void) +{ + int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);; + bool status = true; + + /* check if this is the last standing CPU */ + for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { + + /* skip the current CPU */ + if (i == cpu) + continue; + + /* are other CPUs already power gated? */ + if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) { + status = false; + } + } + + return status; +} + +/******************************************************************************* + * Handler to be called on exiting System suspend. Right now only DPD registers + * are cleared. + ******************************************************************************/ +void tegra_pmc_resume(void) +{ + + /* Clear DPD sample */ + mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0); + + /* Clear DPD Enable */ + mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0); +} + +/******************************************************************************* * Restart the system ******************************************************************************/ __dead2 void tegra_pmc_system_reset(void) diff --git a/plat/nvidia/tegra/common/drivers/spe/shared_console.S b/plat/nvidia/tegra/common/drivers/spe/shared_console.S index a9f0334..c1fbc84 100644 --- a/plat/nvidia/tegra/common/drivers/spe/shared_console.S +++ b/plat/nvidia/tegra/common/drivers/spe/shared_console.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -63,12 +63,28 @@ /* Check the input parameter */ cbz x1, putc_error + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* wait until spe is ready */ 1: ldr w2, [x1] and w2, w2, #CONSOLE_IS_BUSY cbnz w2, 1b /* spe is ready */ + mov w2, #0xD /* '\r' */ + and w2, w2, #0xFF + mov w3, #(CONSOLE_WRITE | (1 << CONSOLE_NUM_BYTES_SHIFT)) + orr w2, w2, w3 + str w2, [x1] + + /* wait until spe is ready */ +2: ldr w2, [x1] + and w2, w2, #CONSOLE_IS_BUSY + cbnz w2, 2b + + /* spe is ready */ mov w2, w0 and w2, w2, #0xFF mov w3, #(CONSOLE_WRITE | (1 << CONSOLE_NUM_BYTES_SHIFT)) diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c index 908e4f2..c9beb14 100644 --- a/plat/nvidia/tegra/common/tegra_bl31_setup.c +++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -162,13 +162,15 @@ } /* - * Parse platform specific parameters - TZDRAM aperture base and size + * Parse platform specific parameters */ assert(plat_params != NULL); plat_bl31_params_from_bl2.tzdram_base = plat_params->tzdram_base; plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size; plat_bl31_params_from_bl2.uart_id = plat_params->uart_id; plat_bl31_params_from_bl2.l2_ecc_parity_prot_dis = plat_params->l2_ecc_parity_prot_dis; + plat_bl31_params_from_bl2.sc7entry_fw_size = plat_params->sc7entry_fw_size; + plat_bl31_params_from_bl2.sc7entry_fw_base = plat_params->sc7entry_fw_base; /* * It is very important that we run either from TZDRAM or TZSRAM base. @@ -404,6 +406,14 @@ */ boot_profiler_add_record("[TF] arch setup entry"); + /* add MMIO space */ + plat_mmio_map = plat_get_mmio_map(); + if (plat_mmio_map != NULL) { + mmap_add(plat_mmio_map); + } else { + WARN("MMIO map not available\n"); + } + /* add memory regions */ mmap_add_region(rw_start, rw_start, rw_size, @@ -415,14 +425,6 @@ code_size, MT_CODE | MT_SECURE); - /* map TZDRAM used by BL31 as coherent memory */ - if (TEGRA_TZRAM_BASE == tegra_bl31_phys_base) { - mmap_add_region(params_from_bl2->tzdram_base, - params_from_bl2->tzdram_base, - BL31_SIZE, - MT_DEVICE | MT_RW | MT_SECURE); - } - #if USE_COHERENT_MEM coh_start = total_base + (BL_COHERENT_RAM_BASE - BL31_RO_BASE); coh_size = BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE; @@ -432,18 +434,12 @@ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE); #endif - /* map on-chip free running uS timer */ - mmap_add_region(page_align(TEGRA_TMRUS_BASE, 0), - page_align(TEGRA_TMRUS_BASE, 0), - TEGRA_TMRUS_SIZE, - (uint8_t)MT_DEVICE | (uint8_t)MT_RO | (uint8_t)MT_SECURE); - - /* add MMIO space */ - plat_mmio_map = plat_get_mmio_map(); - if (plat_mmio_map != NULL) { - mmap_add(plat_mmio_map); - } else { - WARN("MMIO map not available\n"); + /* map TZDRAM used by BL31 as coherent memory */ + if (TEGRA_TZRAM_BASE == tegra_bl31_phys_base) { + mmap_add_region(params_from_bl2->tzdram_base, + params_from_bl2->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); } /* set up translation tables */ diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c index cab2e5e..60b5595 100644 --- a/plat/nvidia/tegra/common/tegra_fiq_glue.c +++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,9 +16,15 @@ #include #include +#if ENABLE_WDT_LEGACY_FIQ_HANDLING +#include +#endif #include #include +/* Legacy FIQ used by earlier Tegra platforms */ +#define LEGACY_FIQ_PPI_WDT 28U + static DEFINE_BAKERY_LOCK(tegra_fiq_lock); /******************************************************************************* @@ -46,33 +52,58 @@ (void)handle; (void)cookie; + /* + * Read the pending interrupt ID + */ + irq = plat_ic_get_pending_interrupt_id(); + bakery_lock_get(&tegra_fiq_lock); /* - * The FIQ was generated when the execution was in the non-secure - * world. Save the context registers to start with. + * Jump to NS world only if the NS world's FIQ handler has + * been registered */ - cm_el1_sysregs_context_save(NON_SECURE); + if (ns_fiq_handler_addr != 0U) { - /* - * Save elr_el3 and spsr_el3 from the saved context, and overwrite - * the context with the NS fiq_handler_addr and SPSR value. - */ - fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3)); - fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3)); + /* + * The FIQ was generated when the execution was in the non-secure + * world. Save the context registers to start with. + */ + cm_el1_sysregs_context_save(NON_SECURE); + /* + * Save elr_el3 and spsr_el3 from the saved context, and overwrite + * the context with the NS fiq_handler_addr and SPSR value. + */ + fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3)); + fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3)); + + /* + * Set the new ELR to continue execution in the NS world using the + * FIQ handler registered earlier. + */ + cm_set_elr_el3(NON_SECURE, ns_fiq_handler_addr); + } + +#if ENABLE_WDT_LEGACY_FIQ_HANDLING /* - * Set the new ELR to continue execution in the NS world using the - * FIQ handler registered earlier. + * Tegra platforms that use LEGACY_FIQ as the watchdog timer FIQ + * need to issue an IPI to other CPUs, to allow them to handle + * the "system hung" scenario. This interrupt is passed to the GICD + * via the Flow Controller. So, once we receive this interrupt, + * disable the routing so that we can mark it as "complete" in the + * GIC later. */ - assert(ns_fiq_handler_addr != 0ULL); - write_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3), (ns_fiq_handler_addr)); + if (irq == LEGACY_FIQ_PPI_WDT) { + tegra_fc_disable_fiq_to_ccplex_routing(); + } +#endif /* * Mark this interrupt as complete to avoid a FIQ storm. */ - irq = plat_ic_acknowledge_interrupt(); if (irq < 1022U) { + (void)plat_ic_acknowledge_interrupt(); plat_ic_end_of_interrupt(irq); } diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c index 2805272..e06a116 100644 --- a/plat/nvidia/tegra/common/tegra_pm.c +++ b/plat/nvidia/tegra/common/tegra_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -41,6 +41,7 @@ * provide typical implementations that will be overridden by a SoC. */ #pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early +#pragma weak tegra_soc_cpu_standby #pragma weak tegra_soc_pwr_domain_suspend #pragma weak tegra_soc_pwr_domain_on #pragma weak tegra_soc_pwr_domain_off @@ -55,6 +56,12 @@ return PSCI_E_NOT_SUPPORTED; } +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) +{ + (void)cpu_state; + return PSCI_E_SUCCESS; +} + int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) { (void)target_state; @@ -139,14 +146,37 @@ ******************************************************************************/ void tegra_cpu_standby(plat_local_state_t cpu_state) { + u_register_t saved_scr_el3; + (void)cpu_state; + /* Tegra SoC specific handler */ + if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) + ERROR("%s failed\n", __func__); + + saved_scr_el3 = read_scr_el3(); + + /* + * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the + * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1', + * irrespective of the value of the PSTATE.I bit value. + */ + write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT); + /* * Enter standby state - * dsb is good practice before using wfi to enter low power states + * + * dsb & isb is good practice before using wfi to enter low power states */ dsb(); + isb(); wfi(); + + /* + * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3 + * handling any further interrupts + */ + write_scr_el3(saved_scr_el3); } /******************************************************************************* @@ -244,7 +274,7 @@ /* * Initialize the GIC cpu and distributor interfaces */ - plat_gic_setup(); + tegra_gic_init(); /* * Check if we are exiting from deep sleep. diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c index 4955b2f..957300e 100644 --- a/plat/nvidia/tegra/common/tegra_sip_calls.c +++ b/plat/nvidia/tegra/common/tegra_sip_calls.c @@ -116,6 +116,16 @@ /* new video memory carveout settings */ tegra_memctrl_videomem_setup(x1, local_x2_32); + /* + * Ensure again that GPU is still in reset after VPR resize + */ + regval = mmio_read_32(TEGRA_CAR_RESET_BASE + + TEGRA_GPU_RESET_REG_OFFSET); + if ((regval & GPU_RESET_BIT) == 0U) { + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET, + GPU_SET_BIT); + } + SMC_RET1(handle, 0); /* diff --git a/plat/nvidia/tegra/include/drivers/bpmp.h b/plat/nvidia/tegra/include/drivers/bpmp.h index 03da6f6..dc3fb6b 100644 --- a/plat/nvidia/tegra/include/drivers/bpmp.h +++ b/plat/nvidia/tegra/include/drivers/bpmp.h @@ -27,8 +27,10 @@ #define SIGN_OF_LIFE 0xAAAAAAAAU /* flags to indicate bpmp driver's state */ +#define BPMP_NOT_PRESENT 0xF00DBEEFU #define BPMP_INIT_COMPLETE 0xBEEFF00DU #define BPMP_INIT_PENDING 0xDEADBEEFU +#define BPMP_SUSPEND_ENTRY 0xF00DCAFEU /* requests serviced by the bpmp */ #define MRQ_PING 0 @@ -107,6 +109,16 @@ int tegra_bpmp_init(void); /** + * Function to suspend the interface with the bpmp + */ +void tegra_bpmp_suspend(void); + +/** + * Function to resume the interface with the bpmp + */ +void tegra_bpmp_resume(void); + +/** * Handler to send a MRQ_* command to the bpmp */ int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz, diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h index 9304150..d487956 100644 --- a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h +++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,6 +18,11 @@ #define TEGRA_RESET_ID_GPCDMA U(70) /** + * Clock identifier for the SE device + */ +#define TEGRA_CLK_SE U(124) + +/** * Function to initialise the IPC with the bpmp */ int32_t tegra_bpmp_ipc_init(void); @@ -27,4 +32,16 @@ */ int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id); +/** + * Handler to enable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id); + +/** + * Handler to disable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id); + #endif /* __BPMP_IPC_H__ */ diff --git a/plat/nvidia/tegra/include/drivers/flowctrl.h b/plat/nvidia/tegra/include/drivers/flowctrl.h index 3122181..54336b0 100644 --- a/plat/nvidia/tegra/include/drivers/flowctrl.h +++ b/plat/nvidia/tegra/include/drivers/flowctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,7 +11,7 @@ #include -#define FLOWCTRL_HALT_CPU0_EVENTS 0x0U +#define FLOWCTRL_HALT_CPU0_EVENTS (0x0U) #define FLOWCTRL_WAITEVENT (2U << 29) #define FLOWCTRL_WAIT_FOR_INTERRUPT (4U << 29) #define FLOWCTRL_JTAG_RESUME (1U << 28) @@ -20,19 +20,46 @@ #define FLOWCTRL_HALT_LIC_FIQ (1U << 10) #define FLOWCTRL_HALT_GIC_IRQ (1U << 9) #define FLOWCTRL_HALT_GIC_FIQ (1U << 8) -#define FLOWCTRL_HALT_BPMP_EVENTS 0x4U -#define FLOWCTRL_CPU0_CSR 0x8U -#define FLOW_CTRL_CSR_PWR_OFF_STS (1U << 16) +#define FLOWCTRL_HALT_BPMP_EVENTS (0x4U) +#define FLOWCTRL_CPU0_CSR (0x8U) +#define FLOWCTRL_CSR_HALT_MASK (1U << 22) +#define FLOWCTRL_CSR_PWR_OFF_STS (1U << 16) #define FLOWCTRL_CSR_INTR_FLAG (1U << 15) #define FLOWCTRL_CSR_EVENT_FLAG (1U << 14) #define FLOWCTRL_CSR_IMMEDIATE_WAKE (1U << 3) #define FLOWCTRL_CSR_ENABLE (1U << 0) -#define FLOWCTRL_HALT_CPU1_EVENTS 0x14U -#define FLOWCTRL_CPU1_CSR 0x18U -#define FLOWCTRL_CC4_CORE0_CTRL 0x6cU -#define FLOWCTRL_WAIT_WFI_BITMAP 0x100U -#define FLOWCTRL_L2_FLUSH_CONTROL 0x94U -#define FLOWCTRL_BPMP_CLUSTER_CONTROL 0x98U +#define FLOWCTRL_HALT_CPU1_EVENTS (0x14U) +#define FLOWCTRL_CPU1_CSR (0x18U) +#define FLOW_CTLR_FLOW_DBG_QUAL (0x50U) +#define FLOWCTRL_FIQ2CCPLEX_ENABLE (1U << 28) +#define FLOWCTRL_FC_SEQ_INTERCEPT (0x5cU) +#define INTERCEPT_IRQ_PENDING (0xffU) +#define INTERCEPT_HVC (U(1) << 21) +#define INTERCEPT_ENTRY_CC4 (U(1) << 20) +#define INTERCEPT_ENTRY_PG_NONCPU (U(1) << 19) +#define INTERCEPT_EXIT_PG_NONCPU (U(1) << 18) +#define INTERCEPT_ENTRY_RG_CPU (U(1) << 17) +#define INTERCEPT_EXIT_RG_CPU (U(1) << 16) +#define INTERCEPT_ENTRY_PG_CORE0 (U(1) << 15) +#define INTERCEPT_EXIT_PG_CORE0 (U(1) << 14) +#define INTERCEPT_ENTRY_PG_CORE1 (U(1) << 13) +#define INTERCEPT_EXIT_PG_CORE1 (U(1) << 12) +#define INTERCEPT_ENTRY_PG_CORE2 (U(1) << 11) +#define INTERCEPT_EXIT_PG_CORE2 (U(1) << 10) +#define INTERCEPT_ENTRY_PG_CORE3 (U(1) << 9) +#define INTERCEPT_EXIT_PG_CORE3 (U(1) << 8) +#define INTERRUPT_PENDING_NONCPU (U(1) << 7) +#define INTERRUPT_PENDING_CRAIL (U(1) << 6) +#define INTERRUPT_PENDING_CORE0 (U(1) << 5) +#define INTERRUPT_PENDING_CORE1 (U(1) << 4) +#define INTERRUPT_PENDING_CORE2 (U(1) << 3) +#define INTERRUPT_PENDING_CORE3 (U(1) << 2) +#define CC4_INTERRUPT_PENDING (U(1) << 1) +#define HVC_INTERRUPT_PENDING (U(1) << 0) +#define FLOWCTRL_CC4_CORE0_CTRL (0x6cU) +#define FLOWCTRL_WAIT_WFI_BITMAP (0x100U) +#define FLOWCTRL_L2_FLUSH_CONTROL (0x94U) +#define FLOWCTRL_BPMP_CLUSTER_CONTROL (0x98U) #define FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK (1U << 2) #define FLOWCTRL_ENABLE_EXT 12U @@ -50,13 +77,19 @@ mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val); } +void tegra_fc_bpmp_on(uint32_t entrypoint); +void tegra_fc_bpmp_off(void); +void tegra_fc_ccplex_pgexit_lock(void); +void tegra_fc_ccplex_pgexit_unlock(void); void tegra_fc_cluster_idle(uint32_t midr); void tegra_fc_cpu_powerdn(uint32_t mpidr); void tegra_fc_cluster_powerdn(uint32_t midr); -void tegra_fc_soc_powerdn(uint32_t midr); void tegra_fc_cpu_on(int cpu); void tegra_fc_cpu_off(int cpu); +void tegra_fc_disable_fiq_to_ccplex_routing(void); +void tegra_fc_enable_fiq_to_ccplex_routing(void); +bool tegra_fc_is_ccx_allowed(void); void tegra_fc_lock_active_cluster(void); -void tegra_fc_reset_bpmp(void); +void tegra_fc_soc_powerdn(uint32_t midr); #endif /* FLOWCTRL_H */ diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h index a01a4b6..32252a2 100644 --- a/plat/nvidia/tegra/include/drivers/pmc.h +++ b/plat/nvidia/tegra/include/drivers/pmc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,22 +9,37 @@ #include #include +#include #include #define PMC_CONFIG U(0x0) +#define PMC_IO_DPD_SAMPLE U(0x20) +#define PMC_DPD_ENABLE_0 U(0x24) #define PMC_PWRGATE_STATUS U(0x38) #define PMC_PWRGATE_TOGGLE U(0x30) +#define PMC_SECURE_SCRATCH0 U(0xb0) +#define PMC_SECURE_SCRATCH5 U(0xc4) +#define PMC_CRYPTO_OP_0 U(0xf4) #define PMC_TOGGLE_START U(0x100) #define PMC_SCRATCH39 U(0x138) +#define PMC_SCRATCH41 U(0x140) +#define PMC_SECURE_SCRATCH6 U(0x224) +#define PMC_SECURE_SCRATCH7 U(0x228) #define PMC_SECURE_DISABLE2 U(0x2c4) #define PMC_SECURE_DISABLE2_WRITE22_ON (U(1) << 28) +#define PMC_SECURE_SCRATCH8 U(0x300) +#define PMC_SECURE_SCRATCH79 U(0x41c) +#define PMC_FUSE_CONTROL_0 U(0x450) #define PMC_SECURE_SCRATCH22 U(0x338) #define PMC_SECURE_DISABLE3 U(0x2d8) #define PMC_SECURE_DISABLE3_WRITE34_ON (U(1) << 20) #define PMC_SECURE_DISABLE3_WRITE35_ON (U(1) << 22) #define PMC_SECURE_SCRATCH34 U(0x368) #define PMC_SECURE_SCRATCH35 U(0x36c) +#define PMC_SECURE_SCRATCH80 U(0xa98) +#define PMC_SECURE_SCRATCH119 U(0xb34) +#define PMC_SCRATCH201 U(0x844) static inline uint32_t tegra_pmc_read_32(uint32_t off) { @@ -36,9 +51,11 @@ mmio_write_32(TEGRA_PMC_BASE + off, val); } -void tegra_pmc_cpu_setup(uint64_t reset_addr); -void tegra_pmc_lock_cpu_vectors(void); void tegra_pmc_cpu_on(int32_t cpu); +void tegra_pmc_cpu_setup(uint64_t reset_addr); +bool tegra_pmc_is_last_on_cpu(void); +void tegra_pmc_lock_cpu_vectors(void); +void tegra_pmc_resume(void); __dead2 void tegra_pmc_system_reset(void); #endif /* PMC_H */ diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h index 41b0c51..424a91a 100644 --- a/plat/nvidia/tegra/include/drivers/smmu.h +++ b/plat/nvidia/tegra/include/drivers/smmu.h @@ -618,9 +618,9 @@ .val = 0x00000000U, \ } -#define smmu_make_gnsr0_sec_cfg(name) \ +#define smmu_make_gnsr0_sec_cfg(base_addr, name) \ { \ - .reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_ ## name, \ + .reg = base_addr + SMMU_GNSR0_ ## name, \ .val = 0x00000000U, \ } @@ -628,60 +628,199 @@ * On ARM-SMMU, conditional offset to access secure aliases of non-secure registers * is 0x400. So, add it to register address */ -#define smmu_make_gnsr0_nsec_cfg(name) \ +#define smmu_make_gnsr0_nsec_cfg(base_addr, name) \ { \ - .reg = TEGRA_SMMU0_BASE + 0x400U + SMMU_GNSR0_ ## name, \ + .reg = base_addr + 0x400U + SMMU_GNSR0_ ## name, \ .val = 0x00000000U, \ } -#define smmu_make_gnsr0_smr_cfg(n) \ +#define smmu_make_gnsr0_smr_cfg(base_addr, n) \ { \ - .reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_SMR ## n, \ + .reg = base_addr + SMMU_GNSR0_SMR ## n, \ .val = 0x00000000U, \ } -#define smmu_make_gnsr0_s2cr_cfg(n) \ +#define smmu_make_gnsr0_s2cr_cfg(base_addr, n) \ { \ - .reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_S2CR ## n, \ + .reg = base_addr + SMMU_GNSR0_S2CR ## n, \ .val = 0x00000000U, \ } -#define smmu_make_gnsr1_cbar_cfg(n) \ +#define smmu_make_gnsr1_cbar_cfg(base_addr, n) \ { \ - .reg = TEGRA_SMMU0_BASE + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \ + .reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \ .val = 0x00000000U, \ } -#define smmu_make_gnsr1_cba2r_cfg(n) \ +#define smmu_make_gnsr1_cba2r_cfg(base_addr, n) \ { \ - .reg = TEGRA_SMMU0_BASE + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \ + .reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \ .val = 0x00000000U, \ } -#define make_smmu_cb_cfg(name, n) \ +#define smmu_make_cb_cfg(base_addr, name, n) \ { \ - .reg = TEGRA_SMMU0_BASE + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \ + .reg = base_addr + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \ + SMMU_CBn_ ## name, \ .val = 0x00000000U, \ } -#define smmu_make_smrg_group(n) \ - smmu_make_gnsr0_smr_cfg(n), \ - smmu_make_gnsr0_s2cr_cfg(n), \ - smmu_make_gnsr1_cbar_cfg(n), \ - smmu_make_gnsr1_cba2r_cfg(n) /* don't put "," here. */ +#define smmu_make_smrg_group(base_addr, n) \ + smmu_make_gnsr0_smr_cfg(base_addr, n), \ + smmu_make_gnsr0_s2cr_cfg(base_addr, n), \ + smmu_make_gnsr1_cbar_cfg(base_addr, n), \ + smmu_make_gnsr1_cba2r_cfg(base_addr, n) /* don't put "," here. */ -#define smmu_make_cb_group(n) \ - make_smmu_cb_cfg(SCTLR, n), \ - make_smmu_cb_cfg(TCR2, n), \ - make_smmu_cb_cfg(TTBR0_LO, n), \ - make_smmu_cb_cfg(TTBR0_HI, n), \ - make_smmu_cb_cfg(TCR, n), \ - make_smmu_cb_cfg(PRRR_MAIR0, n),\ - make_smmu_cb_cfg(FSR, n), \ - make_smmu_cb_cfg(FAR_LO, n), \ - make_smmu_cb_cfg(FAR_HI, n), \ - make_smmu_cb_cfg(FSYNR0, n) /* don't put "," here. */ +#define smmu_make_cb_group(base_addr, n) \ + smmu_make_cb_cfg(base_addr, SCTLR, n), \ + smmu_make_cb_cfg(base_addr, TCR2, n), \ + smmu_make_cb_cfg(base_addr, TTBR0_LO, n), \ + smmu_make_cb_cfg(base_addr, TTBR0_HI, n), \ + smmu_make_cb_cfg(base_addr, TCR, n), \ + smmu_make_cb_cfg(base_addr, PRRR_MAIR0, n),\ + smmu_make_cb_cfg(base_addr, FSR, n), \ + smmu_make_cb_cfg(base_addr, FAR_LO, n), \ + smmu_make_cb_cfg(base_addr, FAR_HI, n), \ + smmu_make_cb_cfg(base_addr, FSYNR0, n) /* don't put "," here. */ + +#define smmu_make_cfg(base_addr) \ + smmu_make_gnsr0_nsec_cfg(base_addr, CR0), \ + smmu_make_gnsr0_sec_cfg(base_addr, IDR0), \ + smmu_make_gnsr0_sec_cfg(base_addr, IDR1), \ + smmu_make_gnsr0_sec_cfg(base_addr, IDR2), \ + smmu_make_gnsr0_nsec_cfg(base_addr, GFSR), \ + smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR0), \ + smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR1), \ + smmu_make_gnsr0_nsec_cfg(base_addr, TLBGSTATUS),\ + smmu_make_gnsr0_nsec_cfg(base_addr, PIDR2), \ + smmu_make_smrg_group(base_addr, 0), \ + smmu_make_smrg_group(base_addr, 1), \ + smmu_make_smrg_group(base_addr, 2), \ + smmu_make_smrg_group(base_addr, 3), \ + smmu_make_smrg_group(base_addr, 4), \ + smmu_make_smrg_group(base_addr, 5), \ + smmu_make_smrg_group(base_addr, 6), \ + smmu_make_smrg_group(base_addr, 7), \ + smmu_make_smrg_group(base_addr, 8), \ + smmu_make_smrg_group(base_addr, 9), \ + smmu_make_smrg_group(base_addr, 10), \ + smmu_make_smrg_group(base_addr, 11), \ + smmu_make_smrg_group(base_addr, 12), \ + smmu_make_smrg_group(base_addr, 13), \ + smmu_make_smrg_group(base_addr, 14), \ + smmu_make_smrg_group(base_addr, 15), \ + smmu_make_smrg_group(base_addr, 16), \ + smmu_make_smrg_group(base_addr, 17), \ + smmu_make_smrg_group(base_addr, 18), \ + smmu_make_smrg_group(base_addr, 19), \ + smmu_make_smrg_group(base_addr, 20), \ + smmu_make_smrg_group(base_addr, 21), \ + smmu_make_smrg_group(base_addr, 22), \ + smmu_make_smrg_group(base_addr, 23), \ + smmu_make_smrg_group(base_addr, 24), \ + smmu_make_smrg_group(base_addr, 25), \ + smmu_make_smrg_group(base_addr, 26), \ + smmu_make_smrg_group(base_addr, 27), \ + smmu_make_smrg_group(base_addr, 28), \ + smmu_make_smrg_group(base_addr, 29), \ + smmu_make_smrg_group(base_addr, 30), \ + smmu_make_smrg_group(base_addr, 31), \ + smmu_make_smrg_group(base_addr, 32), \ + smmu_make_smrg_group(base_addr, 33), \ + smmu_make_smrg_group(base_addr, 34), \ + smmu_make_smrg_group(base_addr, 35), \ + smmu_make_smrg_group(base_addr, 36), \ + smmu_make_smrg_group(base_addr, 37), \ + smmu_make_smrg_group(base_addr, 38), \ + smmu_make_smrg_group(base_addr, 39), \ + smmu_make_smrg_group(base_addr, 40), \ + smmu_make_smrg_group(base_addr, 41), \ + smmu_make_smrg_group(base_addr, 42), \ + smmu_make_smrg_group(base_addr, 43), \ + smmu_make_smrg_group(base_addr, 44), \ + smmu_make_smrg_group(base_addr, 45), \ + smmu_make_smrg_group(base_addr, 46), \ + smmu_make_smrg_group(base_addr, 47), \ + smmu_make_smrg_group(base_addr, 48), \ + smmu_make_smrg_group(base_addr, 49), \ + smmu_make_smrg_group(base_addr, 50), \ + smmu_make_smrg_group(base_addr, 51), \ + smmu_make_smrg_group(base_addr, 52), \ + smmu_make_smrg_group(base_addr, 53), \ + smmu_make_smrg_group(base_addr, 54), \ + smmu_make_smrg_group(base_addr, 55), \ + smmu_make_smrg_group(base_addr, 56), \ + smmu_make_smrg_group(base_addr, 57), \ + smmu_make_smrg_group(base_addr, 58), \ + smmu_make_smrg_group(base_addr, 59), \ + smmu_make_smrg_group(base_addr, 60), \ + smmu_make_smrg_group(base_addr, 61), \ + smmu_make_smrg_group(base_addr, 62), \ + smmu_make_smrg_group(base_addr, 63), \ + smmu_make_cb_group(base_addr, 0), \ + smmu_make_cb_group(base_addr, 1), \ + smmu_make_cb_group(base_addr, 2), \ + smmu_make_cb_group(base_addr, 3), \ + smmu_make_cb_group(base_addr, 4), \ + smmu_make_cb_group(base_addr, 5), \ + smmu_make_cb_group(base_addr, 6), \ + smmu_make_cb_group(base_addr, 7), \ + smmu_make_cb_group(base_addr, 8), \ + smmu_make_cb_group(base_addr, 9), \ + smmu_make_cb_group(base_addr, 10), \ + smmu_make_cb_group(base_addr, 11), \ + smmu_make_cb_group(base_addr, 12), \ + smmu_make_cb_group(base_addr, 13), \ + smmu_make_cb_group(base_addr, 14), \ + smmu_make_cb_group(base_addr, 15), \ + smmu_make_cb_group(base_addr, 16), \ + smmu_make_cb_group(base_addr, 17), \ + smmu_make_cb_group(base_addr, 18), \ + smmu_make_cb_group(base_addr, 19), \ + smmu_make_cb_group(base_addr, 20), \ + smmu_make_cb_group(base_addr, 21), \ + smmu_make_cb_group(base_addr, 22), \ + smmu_make_cb_group(base_addr, 23), \ + smmu_make_cb_group(base_addr, 24), \ + smmu_make_cb_group(base_addr, 25), \ + smmu_make_cb_group(base_addr, 26), \ + smmu_make_cb_group(base_addr, 27), \ + smmu_make_cb_group(base_addr, 28), \ + smmu_make_cb_group(base_addr, 29), \ + smmu_make_cb_group(base_addr, 30), \ + smmu_make_cb_group(base_addr, 31), \ + smmu_make_cb_group(base_addr, 32), \ + smmu_make_cb_group(base_addr, 33), \ + smmu_make_cb_group(base_addr, 34), \ + smmu_make_cb_group(base_addr, 35), \ + smmu_make_cb_group(base_addr, 36), \ + smmu_make_cb_group(base_addr, 37), \ + smmu_make_cb_group(base_addr, 38), \ + smmu_make_cb_group(base_addr, 39), \ + smmu_make_cb_group(base_addr, 40), \ + smmu_make_cb_group(base_addr, 41), \ + smmu_make_cb_group(base_addr, 42), \ + smmu_make_cb_group(base_addr, 43), \ + smmu_make_cb_group(base_addr, 44), \ + smmu_make_cb_group(base_addr, 45), \ + smmu_make_cb_group(base_addr, 46), \ + smmu_make_cb_group(base_addr, 47), \ + smmu_make_cb_group(base_addr, 48), \ + smmu_make_cb_group(base_addr, 49), \ + smmu_make_cb_group(base_addr, 50), \ + smmu_make_cb_group(base_addr, 51), \ + smmu_make_cb_group(base_addr, 52), \ + smmu_make_cb_group(base_addr, 53), \ + smmu_make_cb_group(base_addr, 54), \ + smmu_make_cb_group(base_addr, 55), \ + smmu_make_cb_group(base_addr, 56), \ + smmu_make_cb_group(base_addr, 57), \ + smmu_make_cb_group(base_addr, 58), \ + smmu_make_cb_group(base_addr, 59), \ + smmu_make_cb_group(base_addr, 60), \ + smmu_make_cb_group(base_addr, 61), \ + smmu_make_cb_group(base_addr, 62), \ + smmu_make_cb_group(base_addr, 63) /* don't put "," here. */ #define smmu_bypass_cfg \ { \ diff --git a/plat/nvidia/tegra/include/plat_macros.S b/plat/nvidia/tegra/include/plat_macros.S index 01ae821..2796c5d 100644 --- a/plat/nvidia/tegra/include/plat_macros.S +++ b/plat/nvidia/tegra/include/plat_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -50,7 +50,7 @@ bl asm_print_hex adr x4, spacer bl asm_print_str - ldr x4, [x7], #8 + ldr w4, [x7], #4 bl asm_print_hex adr x4, newline bl asm_print_str diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h index 0a0126b..334ad12 100644 --- a/plat/nvidia/tegra/include/platform_def.h +++ b/plat/nvidia/tegra/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -54,12 +54,6 @@ #define BL32_LIMIT TZDRAM_END /******************************************************************************* - * Platform specific page table and MMU setup constants - ******************************************************************************/ -#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) -#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) - -/******************************************************************************* * Some data must be aligned on the biggest cache line size in the platform. * This is known only to the platform as it might have a combination of * integrated and external caches. diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h index fd75fbc..dfed2aa 100644 --- a/plat/nvidia/tegra/include/t132/tegra_def.h +++ b/plat/nvidia/tegra/include/t132/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,6 +25,12 @@ #define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + U(1)) /******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) + +/******************************************************************************* * GIC memory map ******************************************************************************/ #define TEGRA_GICD_BASE U(0x50041000) @@ -41,7 +47,9 @@ ******************************************************************************/ #define TEGRA_CAR_RESET_BASE U(0x60006000) #define TEGRA_GPU_RESET_REG_OFFSET U(0x28C) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x290) #define GPU_RESET_BIT (U(1) << 24) +#define GPU_SET_BIT (U(1) << 24) /******************************************************************************* * Tegra Flow Controller constants diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index 231f93a..da050a8 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -58,6 +58,12 @@ #define PLAT_MAX_OFF_STATE U(8) /******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) + +/******************************************************************************* * Secure IRQ definitions ******************************************************************************/ #define TEGRA186_TOP_WDT_IRQ U(49) @@ -210,7 +216,9 @@ ******************************************************************************/ #define TEGRA_CAR_RESET_BASE U(0x05000000) #define TEGRA_GPU_RESET_REG_OFFSET U(0x30) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x34) #define GPU_RESET_BIT (U(1) << 0) +#define GPU_SET_BIT (U(1) << 0) #define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004) #define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008) diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h index 75919e1..bbcfdc5 100644 --- a/plat/nvidia/tegra/include/t210/tegra_def.h +++ b/plat/nvidia/tegra/include/t210/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,7 +14,6 @@ ******************************************************************************/ #define PSTATE_ID_CORE_POWERDN U(7) #define PSTATE_ID_CLUSTER_IDLE U(16) -#define PSTATE_ID_CLUSTER_POWERDN U(17) #define PSTATE_ID_SOC_POWERDN U(27) /******************************************************************************* @@ -33,9 +32,22 @@ #define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + U(1)) /******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) + +/******************************************************************************* + * SC7 entry firmware's header size + ******************************************************************************/ +#define SC7ENTRY_FW_HEADER_SIZE_BYTES U(0x400) + +/******************************************************************************* * iRAM memory constants ******************************************************************************/ -#define TEGRA_IRAM_BASE 0x40000000 +#define TEGRA_IRAM_BASE U(0x40000000) +#define TEGRA_IRAM_A_SIZE U(0x10000) /* 64KB */ +#define TEGRA_IRAM_SIZE U(40000) /* 256KB */ /******************************************************************************* * GIC memory map @@ -44,6 +56,11 @@ #define TEGRA_GICC_BASE U(0x50042000) /******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA210_WDT_CPU_LEGACY_FIQ U(28) + +/******************************************************************************* * Tegra Memory Select Switch Controller constants ******************************************************************************/ #define TEGRA_MSELECT_BASE U(0x50060000) @@ -84,21 +101,55 @@ * Tegra Clock and Reset Controller constants ******************************************************************************/ #define TEGRA_CAR_RESET_BASE U(0x60006000) +#define TEGRA_BOND_OUT_H U(0x74) +#define APB_DMA_LOCK_BIT (U(1) << 2) +#define AHB_DMA_LOCK_BIT (U(1) << 1) +#define TEGRA_BOND_OUT_U U(0x78) +#define IRAM_D_LOCK_BIT (U(1) << 23) +#define IRAM_C_LOCK_BIT (U(1) << 22) +#define IRAM_B_LOCK_BIT (U(1) << 21) #define TEGRA_GPU_RESET_REG_OFFSET U(0x28C) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x290) #define GPU_RESET_BIT (U(1) << 24) +#define GPU_SET_BIT (U(1) << 24) +#define TEGRA_RST_DEV_SET_Y U(0x2a8) +#define NVENC_RESET_BIT (U(1) << 27) +#define TSECB_RESET_BIT (U(1) << 14) +#define APE_RESET_BIT (U(1) << 6) +#define NVJPG_RESET_BIT (U(1) << 3) +#define NVDEC_RESET_BIT (U(1) << 2) +#define TEGRA_RST_DEV_SET_L U(0x300) +#define HOST1X_RESET_BIT (U(1) << 28) +#define ISP_RESET_BIT (U(1) << 23) +#define USBD_RESET_BIT (U(1) << 22) +#define VI_RESET_BIT (U(1) << 20) +#define SDMMC4_RESET_BIT (U(1) << 15) +#define SDMMC1_RESET_BIT (U(1) << 14) +#define SDMMC2_RESET_BIT (U(1) << 9) +#define TEGRA_RST_DEV_SET_H U(0x308) +#define USB2_RESET_BIT (U(1) << 26) +#define APBDMA_RESET_BIT (U(1) << 2) +#define AHBDMA_RESET_BIT (U(1) << 1) +#define TEGRA_RST_DEV_SET_U U(0x310) +#define XUSB_DEV_RESET_BIT (U(1) << 31) +#define XUSB_HOST_RESET_BIT (U(1) << 25) +#define TSEC_RESET_BIT (U(1) << 19) +#define PCIE_RESET_BIT (U(1) << 6) +#define SDMMC3_RESET_BIT (U(1) << 5) +#define TEGRA_RST_DEVICES_V U(0x358) +#define TEGRA_RST_DEVICES_W U(0x35C) +#define ENTROPY_CLK_ENB_BIT (U(1) << 21) +#define TEGRA_CLK_OUT_ENB_V U(0x360) +#define SE_CLK_ENB_BIT (U(1) << 31) +#define TEGRA_CLK_OUT_ENB_W U(0x364) +#define ENTROPY_RESET_BIT (U(1) << 21) +#define TEGRA_RST_DEV_SET_V U(0x430) +#define SE_RESET_BIT (U(1) << 31) +#define HDA_RESET_BIT (U(1) << 29) +#define SATA_RESET_BIT (U(1) << 28) #define TEGRA_RST_DEV_CLR_V U(0x434) #define TEGRA_CLK_ENB_V U(0x440) -/* SE Clock Offsets */ -#define TEGRA_RST_DEVICES_V 0x358UL -#define SE_RESET_BIT (0x1UL << 31) -#define TEGRA_RST_DEVICES_W 0x35CUL -#define ENTROPY_CLK_ENB_BIT (0x1UL << 21) -#define TEGRA_CLK_OUT_ENB_V 0x360UL -#define SE_CLK_ENB_BIT (0x1UL << 31) -#define TEGRA_CLK_OUT_ENB_W 0x364UL -#define ENTROPY_RESET_BIT (0x1UL << 21) - /******************************************************************************* * Tegra Flow Controller constants ******************************************************************************/ @@ -124,6 +175,10 @@ ******************************************************************************/ #define TEGRA_MISC_BASE U(0x70000000) #define HARDWARE_REVISION_OFFSET U(0x804) +#define APB_SLAVE_SECURITY_ENABLE U(0xC00) +#define PMC_SECURITY_EN_BIT (U(1) << 13) +#define PINMUX_AUX_DVFS_PWM U(0x3184) +#define PINMUX_PWM_TRISTATE (U(1) << 4) /******************************************************************************* * Tegra UART controller base addresses @@ -148,6 +203,7 @@ * Tegra Power Mgmt Controller constants ******************************************************************************/ #define TEGRA_PMC_BASE U(0x7000E400) +#define TEGRA_PMC_SIZE U(0xC00) /* 3k */ /******************************************************************************* * Tegra Atomics constants @@ -181,6 +237,17 @@ #define PPCS_SMMU_ENABLE (0x1U << 31) /******************************************************************************* + * Tegra CLDVFS constants + ******************************************************************************/ +#define TEGRA_CL_DVFS_BASE U(0x70110000) +#define DVFS_DFLL_CTRL U(0x00) +#define ENABLE_OPEN_LOOP U(1) +#define ENABLE_CLOSED_LOOP U(2) +#define DVFS_DFLL_OUTPUT_CFG U(0x20) +#define DFLL_OUTPUT_CFG_I2C_EN_BIT (U(1) << 30) +#define DFLL_OUTPUT_CFG_CLK_EN_BIT (U(1) << 6) + +/******************************************************************************* * Tegra SE constants ******************************************************************************/ #define TEGRA_SE1_BASE U(0x70012000) diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h index 68b4624..cdd9e08 100644 --- a/plat/nvidia/tegra/include/tegra_private.h +++ b/plat/nvidia/tegra/include/tegra_private.h @@ -46,6 +46,10 @@ int32_t l2_ecc_parity_prot_dis; /* SHMEM base address for storing the boot logs */ uint64_t boot_profiler_shmem_base; + /* System Suspend Entry Firmware size */ + uint64_t sc7entry_fw_size; + /* System Suspend Entry Firmware base address */ + uint64_t sc7entry_fw_base; } plat_params_from_bl2_t; /******************************************************************************* @@ -97,6 +101,7 @@ void tegra_pm_system_suspend_entry(void); void tegra_pm_system_suspend_exit(void); int32_t tegra_system_suspended(void); +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state); int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state); int32_t tegra_soc_pwr_domain_on(u_register_t mpidr); int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state); diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk index 614d2a2..6ef1900 100644 --- a/plat/nvidia/tegra/platform.mk +++ b/plat/nvidia/tegra/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -34,6 +34,9 @@ # enable D-cache early during CPU warmboot WARMBOOT_ENABLE_DCACHE_EARLY := 1 +# remove the standard libc +OVERRIDE_LIBC := 1 + include plat/nvidia/tegra/common/tegra_common.mk include ${SOC_DIR}/platform_${TARGET_SOC}.mk @@ -42,3 +45,17 @@ # platform cflags (enable signed comparisons, disable stdlib) TF_CFLAGS += -Wsign-compare -nostdlib + +# override with necessary libc files for the Tegra platform +override LIBC_SRCS := $(addprefix lib/libc/, \ + assert.c \ + memcpy.c \ + memmove.c \ + memset.c \ + printf.c \ + putchar.c \ + strlen.c \ + snprintf.c) + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c index 3f9cda9..fef5e0a 100644 --- a/plat/nvidia/tegra/soc/t132/plat_setup.c +++ b/plat/nvidia/tegra/soc/t132/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -101,4 +101,5 @@ void plat_gic_setup(void) { tegra_gic_setup(NULL, 0); + tegra_gic_init(); } diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c index 376ee86..df94396 100644 --- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c +++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -94,7 +94,7 @@ * Array to hold the security configs for stream IDs ******************************************************************************/ const static mc_streamid_security_cfg_t tegra186_streamid_sec_cfgs[] = { - mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, ENABLE), @@ -109,17 +109,17 @@ mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, ENABLE), @@ -129,20 +129,20 @@ mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), @@ -151,7 +151,7 @@ mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, ENABLE), @@ -162,10 +162,10 @@ mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE), - mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), }; /******************************************************************************* @@ -219,9 +219,7 @@ assert(val == MC_CLIENT_HOTRESET_CTRL0_RESET_VAL); wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB | -#if ENABLE_AFI_DEVICE MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB | -#endif MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB | MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB | MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB; @@ -271,9 +269,7 @@ * MC clients with default SO_DEV override still enabled at TSA: * AONW, BPMPW, SCEW, APEW */ -#if ENABLE_AFI_DEVICE mc_set_tsa_passthrough(AFIW); -#endif mc_set_tsa_passthrough(HDAW); mc_set_tsa_passthrough(SATAW); mc_set_tsa_passthrough(XUSB_HOSTW); @@ -413,9 +409,7 @@ * boot and strongly ordered MSS clients */ val = MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL & -#if ENABLE_AFI_DEVICE mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) & -#endif mc_set_pcfifo_unordered_boot_so_mss(1, HDAW) & mc_set_pcfifo_unordered_boot_so_mss(1, SATAW); tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG1, val); diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index fd109e5..ef0ba4e 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -91,6 +91,8 @@ MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */ MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_TMRUS_BASE, 0x1000U, /* 4KB */ + MT_DEVICE | MT_RO | MT_SECURE), MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000U, /* 64KB */ MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000U, /* 384KB */ @@ -194,14 +196,13 @@ void plat_gic_setup(void) { tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props)); + tegra_gic_init(); /* * Initialize the FIQ handler only if the platform supports any * FIQ interrupt sources. */ - if (sizeof(tegra186_interrupt_props) > 0U) { - tegra_fiq_handler_setup(); - } + tegra_fiq_handler_setup(); } /******************************************************************************* diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c index 95f6def..b4a7fe5 100644 --- a/plat/nvidia/tegra/soc/t186/plat_smmu.c +++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c @@ -161,143 +161,7 @@ mc_make_sid_override_cfg(UFSHCR), mc_make_sid_override_cfg(NVENCSWR), mc_make_sid_override_cfg(AFIW), - smmu_make_gnsr0_nsec_cfg(CR0), - smmu_make_gnsr0_sec_cfg(IDR0), - smmu_make_gnsr0_sec_cfg(IDR1), - smmu_make_gnsr0_sec_cfg(IDR2), - smmu_make_gnsr0_nsec_cfg(GFSR), - smmu_make_gnsr0_nsec_cfg(GFSYNR0), - smmu_make_gnsr0_nsec_cfg(GFSYNR1), - smmu_make_gnsr0_nsec_cfg(TLBGSTATUS), - smmu_make_gnsr0_nsec_cfg(PIDR2), - smmu_make_smrg_group(0), - smmu_make_smrg_group(1), - smmu_make_smrg_group(2), - smmu_make_smrg_group(3), - smmu_make_smrg_group(4), - smmu_make_smrg_group(5), - smmu_make_smrg_group(6), - smmu_make_smrg_group(7), - smmu_make_smrg_group(8), - smmu_make_smrg_group(9), - smmu_make_smrg_group(10), - smmu_make_smrg_group(11), - smmu_make_smrg_group(12), - smmu_make_smrg_group(13), - smmu_make_smrg_group(14), - smmu_make_smrg_group(15), - smmu_make_smrg_group(16), - smmu_make_smrg_group(17), - smmu_make_smrg_group(18), - smmu_make_smrg_group(19), - smmu_make_smrg_group(20), - smmu_make_smrg_group(21), - smmu_make_smrg_group(22), - smmu_make_smrg_group(23), - smmu_make_smrg_group(24), - smmu_make_smrg_group(25), - smmu_make_smrg_group(26), - smmu_make_smrg_group(27), - smmu_make_smrg_group(28), - smmu_make_smrg_group(29), - smmu_make_smrg_group(30), - smmu_make_smrg_group(31), - smmu_make_smrg_group(32), - smmu_make_smrg_group(33), - smmu_make_smrg_group(34), - smmu_make_smrg_group(35), - smmu_make_smrg_group(36), - smmu_make_smrg_group(37), - smmu_make_smrg_group(38), - smmu_make_smrg_group(39), - smmu_make_smrg_group(40), - smmu_make_smrg_group(41), - smmu_make_smrg_group(42), - smmu_make_smrg_group(43), - smmu_make_smrg_group(44), - smmu_make_smrg_group(45), - smmu_make_smrg_group(46), - smmu_make_smrg_group(47), - smmu_make_smrg_group(48), - smmu_make_smrg_group(49), - smmu_make_smrg_group(50), - smmu_make_smrg_group(51), - smmu_make_smrg_group(52), - smmu_make_smrg_group(53), - smmu_make_smrg_group(54), - smmu_make_smrg_group(55), - smmu_make_smrg_group(56), - smmu_make_smrg_group(57), - smmu_make_smrg_group(58), - smmu_make_smrg_group(59), - smmu_make_smrg_group(60), - smmu_make_smrg_group(61), - smmu_make_smrg_group(62), - smmu_make_smrg_group(63), - smmu_make_cb_group(0), - smmu_make_cb_group(1), - smmu_make_cb_group(2), - smmu_make_cb_group(3), - smmu_make_cb_group(4), - smmu_make_cb_group(5), - smmu_make_cb_group(6), - smmu_make_cb_group(7), - smmu_make_cb_group(8), - smmu_make_cb_group(9), - smmu_make_cb_group(10), - smmu_make_cb_group(11), - smmu_make_cb_group(12), - smmu_make_cb_group(13), - smmu_make_cb_group(14), - smmu_make_cb_group(15), - smmu_make_cb_group(16), - smmu_make_cb_group(17), - smmu_make_cb_group(18), - smmu_make_cb_group(19), - smmu_make_cb_group(20), - smmu_make_cb_group(21), - smmu_make_cb_group(22), - smmu_make_cb_group(23), - smmu_make_cb_group(24), - smmu_make_cb_group(25), - smmu_make_cb_group(26), - smmu_make_cb_group(27), - smmu_make_cb_group(28), - smmu_make_cb_group(29), - smmu_make_cb_group(30), - smmu_make_cb_group(31), - smmu_make_cb_group(32), - smmu_make_cb_group(33), - smmu_make_cb_group(34), - smmu_make_cb_group(35), - smmu_make_cb_group(36), - smmu_make_cb_group(37), - smmu_make_cb_group(38), - smmu_make_cb_group(39), - smmu_make_cb_group(40), - smmu_make_cb_group(41), - smmu_make_cb_group(42), - smmu_make_cb_group(43), - smmu_make_cb_group(44), - smmu_make_cb_group(45), - smmu_make_cb_group(46), - smmu_make_cb_group(47), - smmu_make_cb_group(48), - smmu_make_cb_group(49), - smmu_make_cb_group(50), - smmu_make_cb_group(51), - smmu_make_cb_group(52), - smmu_make_cb_group(53), - smmu_make_cb_group(54), - smmu_make_cb_group(55), - smmu_make_cb_group(56), - smmu_make_cb_group(57), - smmu_make_cb_group(58), - smmu_make_cb_group(59), - smmu_make_cb_group(60), - smmu_make_cb_group(61), - smmu_make_cb_group(62), - smmu_make_cb_group(63), + smmu_make_cfg(TEGRA_SMMU0_BASE), smmu_bypass_cfg, /* TBU settings */ _END_OF_TABLE_, }; diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index fdeb886..fe15853 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -1,13 +1,10 @@ # -# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # # platform configs -ENABLE_AFI_DEVICE := 1 -$(eval $(call add_define,ENABLE_AFI_DEVICE)) - ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1 $(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS)) @@ -33,7 +30,7 @@ MAX_XLAT_TABLES := 24 $(eval $(call add_define,MAX_XLAT_TABLES)) -MAX_MMAP_REGIONS := 24 +MAX_MMAP_REGIONS := 25 $(eval $(call add_define,MAX_MMAP_REGIONS)) # platform files diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c index f52d975..b7d10af 100644 --- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,12 +15,14 @@ #include #include +#include #include #include #include #include #include #include +#include /* * Register used to clear CPU reset signals. Each CPU has two reset @@ -35,11 +37,13 @@ #define SCLK_BURST_POLICY_DEFAULT 0x10000000 static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER]; +static bool tegra_bpmp_available = true; int32_t tegra_soc_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { int state_id = psci_get_pstate_id(power_state); + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); /* Sanity check the requested state id */ switch (state_id) { @@ -52,16 +56,24 @@ break; case PSTATE_ID_CLUSTER_IDLE: - case PSTATE_ID_CLUSTER_POWERDN: - /* - * Cluster powerdown/idle request only for afflvl 1 - */ - req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; - req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN; + /* + * Cluster idle request for afflvl 0 + */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN; + req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; break; case PSTATE_ID_SOC_POWERDN: + + /* + * sc7entry-fw must be present in the system when the bpmp + * firmware is not present, for a successful System Suspend + * entry. + */ + if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base) + return PSCI_E_NOT_SUPPORTED; + /* * System powerdown request only for afflvl 2 */ @@ -83,7 +95,7 @@ /******************************************************************************* * Platform handler to calculate the proper target power level at the - * specified affinity level + * specified affinity level. ******************************************************************************/ plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, const plat_local_state_t *states, @@ -92,7 +104,7 @@ plat_local_state_t target = PSCI_LOCAL_STATE_RUN; int cpu = plat_my_core_pos(); int core_pos = read_mpidr() & MPIDR_CPU_MASK; - uint32_t bpmp_reply, data[3]; + uint32_t bpmp_reply, data[3], val; int ret; /* get the power state at this level */ @@ -107,40 +119,44 @@ ret = tegra_bpmp_init(); if (ret != 0U) { + /* + * flag to indicate that BPMP firmware is not + * available and the CPU has to handle entry/exit + * for all power states + */ + tegra_bpmp_available = false; + /* Cluster idle not allowed */ target = PSCI_LOCAL_STATE_RUN; - } else { - /* Cluster idle */ - data[0] = (uint32_t)cpu; - data[1] = TEGRA_PM_CC6; - data[2] = TEGRA_PM_SC1; - ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE, - (void *)&data, (int)sizeof(data), - (void *)&bpmp_reply, - (int)sizeof(bpmp_reply)); + /******************************************* + * BPMP is not present, so handle CC6 entry + * from the CPU + ******************************************/ - /* check if cluster idle entry is allowed */ - if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) { + /* check if cluster idle state has been enabled */ + val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL); + if (val == ENABLE_CLOSED_LOOP) { + /* + * Acquire the cluster idle lock to stop + * other CPUs from powering up. + */ + tegra_fc_ccplex_pgexit_lock(); - /* Cluster idle not allowed */ - target = PSCI_LOCAL_STATE_RUN; + /* Cluster idle only from the last standing CPU */ + if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) { + /* Cluster idle allowed */ + target = PSTATE_ID_CLUSTER_IDLE; + } else { + /* release cluster idle lock */ + tegra_fc_ccplex_pgexit_unlock(); + } } - } - - } else if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_POWERDN)) { - - /* initialize the bpmp interface */ - ret = tegra_bpmp_init(); - if (ret != 0U) { - - /* Cluster power down not allowed */ - target = PSCI_LOCAL_STATE_RUN; } else { /* Cluster power-down */ data[0] = (uint32_t)cpu; - data[1] = TEGRA_PM_CC7; + data[1] = TEGRA_PM_CC6; data[2] = TEGRA_PM_SC1; ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE, (void *)&data, (int)sizeof(data), @@ -176,7 +192,9 @@ unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2]; unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1]; unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0]; + uint32_t cfg; int ret = PSCI_E_SUCCESS; + uint32_t val; if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { @@ -197,16 +215,43 @@ assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN); + if (!tegra_bpmp_available) { + + /* + * When disabled, DFLL loses its state. Enable + * open loop state for the DFLL as we dont want + * garbage values being written to the pmic + * when we enter cluster idle state. + */ + mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, + ENABLE_OPEN_LOOP); + + /* Find if the platform uses OVR2/MAX77621 PMIC */ + cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); + if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { + /* OVR2 */ + + /* PWM tristate */ + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + val |= PINMUX_PWM_TRISTATE; + mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); + + /* + * SCRATCH201[1] is being used to identify CPU + * PMIC in warmboot code. + * 0 : OVR2 + * 1 : MAX77621 + */ + tegra_pmc_write_32(PMC_SCRATCH201, 0x0); + } else { + /* MAX77621 */ + tegra_pmc_write_32(PMC_SCRATCH201, 0x2); + } + } + /* Prepare for cluster idle */ tegra_fc_cluster_idle(mpidr); - } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) { - - assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN); - - /* Prepare for cluster powerdn */ - tegra_fc_cluster_powerdn(mpidr); - } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { /* Prepare for cpu powerdn */ @@ -221,12 +266,82 @@ return ret; } +static void tegra_reset_all_dma_masters(void) +{ + uint32_t val, mask; + + /* + * Reset all possible DMA masters in the system. + */ + val = GPU_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val); + + val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | + NVJPG_RESET_BIT | NVDEC_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val); + + val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | + VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | + SDMMC2_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val); + + val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val); + + val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | + PCIE_RESET_BIT | SDMMC3_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val); + + val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val); + + /* + * If any of the DMA masters are still alive, assume + * that the system has been compromised and reboot. + */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); + mask = GPU_RESET_BIT; + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | + NVJPG_RESET_BIT | NVDEC_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | + VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | + SDMMC2_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | + PCIE_RESET_BIT | SDMMC3_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V); + mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; + if ((val & mask) != mask) + tegra_pmc_system_reset(); +} + int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) { u_register_t mpidr = read_mpidr(); const plat_local_state_t *pwr_domain_state = target_state->pwr_domain_state; unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL]; + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint32_t val; if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { @@ -235,6 +350,61 @@ tegra_se_save_tzram(); } + /* de-init the interface */ + tegra_bpmp_suspend(); + + /* + * The CPU needs to load the System suspend entry firmware + * if nothing is running on the BPMP. + */ + if (!tegra_bpmp_available) { + + /* + * BPMP firmware is not running on the co-processor, so + * we need to explicitly load the firmware to enable + * entry/exit to/from System Suspend and set the BPMP + * on its way. + */ + + /* Power off BPMP before we proceed */ + tegra_fc_bpmp_off(); + + /* bond out IRAM banks B, C and D */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U, + IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT | + IRAM_D_LOCK_BIT); + + /* bond out APB/AHB DMAs */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H, + APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT); + + /* Power off BPMP before we proceed */ + tegra_fc_bpmp_off(); + + /* + * Reset all the hardware blocks that can act as DMA + * masters on the bus. + */ + tegra_reset_all_dma_masters(); + + /* clean up IRAM of any cruft */ + zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE, + TEGRA_IRAM_A_SIZE); + + /* Copy the firmware to BPMP's internal RAM */ + (void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE, + (const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES), + plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES); + + /* Power on the BPMP and execute from IRAM base */ + tegra_fc_bpmp_on(TEGRA_IRAM_BASE); + + /* Wait until BPMP powers up */ + do { + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + } while (val != SIGN_OF_LIFE); + } + /* enter system suspend */ tegra_fc_soc_powerdn(mpidr); } @@ -245,7 +415,9 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) { const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); - uint32_t val; + uint32_t cfg; + uint32_t val, entrypoint = 0; + uint64_t offset; /* platform parameter passed by the previous bootloader */ if (plat_params->l2_ecc_parity_prot_dis != 1) { @@ -284,9 +456,61 @@ /* * Restore Boot and Power Management Processor (BPMP) reset - * address and reset it. + * address and reset it, if it is supported by the platform. */ - tegra_fc_reset_bpmp(); + if (!tegra_bpmp_available) { + tegra_fc_bpmp_off(); + } else { + entrypoint = tegra_pmc_read_32(PMC_SCRATCH39); + tegra_fc_bpmp_on(entrypoint); + + /* initialise the interface */ + tegra_bpmp_resume(); + } + + /* sc7entry-fw is part of TZDRAM area */ + if (plat_params->sc7entry_fw_base != 0U) { + offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base; + tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base, + plat_params->tzdram_size + offset); + + /* restrict PMC access to secure world */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val |= PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + } + } + + /* + * Check if we are exiting cluster idle state + */ + if (target_state->pwr_domain_state[MPIDR_AFFLVL1] == + PSTATE_ID_CLUSTER_IDLE) { + + if (!tegra_bpmp_available) { + + /* PWM un-tristate */ + cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); + if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + val &= ~PINMUX_PWM_TRISTATE; + mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); + + /* make sure the setting took effect */ + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + assert((val & PINMUX_PWM_TRISTATE) == 0U); + } + + /* + * Restore operation mode for the DFLL ring + * oscillator + */ + mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, + ENABLE_CLOSED_LOOP); + + /* release cluster idle lock */ + tegra_fc_ccplex_pgexit_unlock(); + } } /* @@ -296,6 +520,12 @@ */ tegra_fc_lock_active_cluster(); + /* + * Resume PMC hardware block for Tegra210 platforms supporting sc7entry-fw + */ + if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U)) + tegra_pmc_resume(); + return PSCI_E_SUCCESS; } diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c index 6246dde..4a42644 100644 --- a/plat/nvidia/tegra/soc/t210/plat_setup.c +++ b/plat/nvidia/tegra/soc/t210/plat_setup.c @@ -1,15 +1,24 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include -#include +#include #include #include +#include +#include #include #include +#include +#include +#include + +#include +#include +#include #include #include #include @@ -137,10 +146,76 @@ } } +/* Secure IRQs for Tegra186 */ +static const interrupt_prop_t tegra210_interrupt_props[] = { + INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), +}; + +void plat_late_platform_setup(void) +{ + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint64_t sc7entry_end, offset; + int ret; + uint32_t val; + + /* memmap TZDRAM area containing the SC7 Entry Firmware */ + if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) { + + assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_A_SIZE); + + /* + * Verify that the SC7 entry firmware resides inside the TZDRAM + * aperture, _before_ the BL31 code and the start address is + * exactly 1MB from BL31 base. + */ + + /* sc7entry-fw must be _before_ BL31 base */ + assert(plat_params->tzdram_base > plat_params->sc7entry_fw_base); + + sc7entry_end = plat_params->sc7entry_fw_base + + plat_params->sc7entry_fw_size; + assert(sc7entry_end < plat_params->tzdram_base); + + /* sc7entry-fw start must be exactly 1MB behind BL31 base */ + offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base; + assert(offset == 0x100000); + + /* secure TZDRAM area */ + tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base, + plat_params->tzdram_size + offset); + + /* power off BPMP processor until SC7 entry */ + tegra_fc_bpmp_off(); + + /* memmap SC7 entry firmware code */ + ret = mmap_add_dynamic_region(plat_params->sc7entry_fw_base, + plat_params->sc7entry_fw_base, + plat_params->sc7entry_fw_size, + MT_SECURE | MT_RO_DATA); + assert(ret == 0); + + /* restrict PMC access to secure world */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val |= PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + } +} + /******************************************************************************* * Initialize the GIC and SGIs ******************************************************************************/ void plat_gic_setup(void) { - tegra_gic_setup(NULL, 0); + tegra_gic_setup(tegra210_interrupt_props, ARRAY_SIZE(tegra210_interrupt_props)); + tegra_gic_init(); + + /* Enable handling for FIQs */ + tegra_fiq_handler_setup(); + + /* + * Enable routing watchdog FIQs from the flow controller to + * the GICD. + */ + tegra_fc_enable_fiq_to_ccplex_routing(); } diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c new file mode 100644 index 0000000..0e8900e --- /dev/null +++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * PMC parameters + ******************************************************************************/ +#define PMC_READ U(0xaa) +#define PMC_WRITE U(0xbb) + +/******************************************************************************* + * Tegra210 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_PMC_COMMANDS U(0xC2FFFE00) + +/******************************************************************************* + * This function is responsible for handling all T210 SiP calls + ******************************************************************************/ +int plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags) +{ + uint32_t val, ns; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (!ns) + SMC_RET1(handle, SMC_UNK); + + switch (smc_fid) { + case TEGRA_SIP_PMC_COMMANDS: + + /* check the address is within PMC range and is 4byte aligned */ + if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3)) + return -EINVAL; + + /* pmc_secure_scratch registers are not accessible */ + if (((x2 >= PMC_SECURE_SCRATCH0) && (x2 <= PMC_SECURE_SCRATCH5)) || + ((x2 >= PMC_SECURE_SCRATCH6) && (x2 <= PMC_SECURE_SCRATCH7)) || + ((x2 >= PMC_SECURE_SCRATCH8) && (x2 <= PMC_SECURE_SCRATCH79)) || + ((x2 >= PMC_SECURE_SCRATCH80) && (x2 <= PMC_SECURE_SCRATCH119))) + return -EFAULT; + + /* PMC secure-only registers are not accessible */ + if ((x2 == PMC_DPD_ENABLE_0) || (x2 == PMC_FUSE_CONTROL_0) || + (x2 == PMC_CRYPTO_OP_0)) + return -EFAULT; + + /* Perform PMC read/write */ + if (x1 == PMC_READ) { + val = mmio_read_32((uint32_t)(TEGRA_PMC_BASE + x2)); + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, val); + } else if (x1 == PMC_WRITE) { + mmio_write_32((uint32_t)(TEGRA_PMC_BASE + x2), (uint32_t)x3); + } else { + return -EINVAL; + } + + break; + + default: + ERROR("%s: unsupported function ID\n", __func__); + return -ENOTSUP; + } + + return 0; +} diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk index e23d7e3..a11aef4 100644 --- a/plat/nvidia/tegra/soc/t210/platform_t210.mk +++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -19,9 +19,12 @@ MAX_XLAT_TABLES := 10 $(eval $(call add_define,MAX_XLAT_TABLES)) -MAX_MMAP_REGIONS := 15 +MAX_MMAP_REGIONS := 16 $(eval $(call add_define,MAX_MMAP_REGIONS)) +ENABLE_WDT_LEGACY_FIQ_HANDLING := 1 +$(eval $(call add_define,ENABLE_WDT_LEGACY_FIQ_HANDLING)) + PLAT_INCLUDES += -I${SOC_DIR}/drivers/se BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S \ @@ -33,7 +36,8 @@ ${SOC_DIR}/plat_psci_handlers.c \ ${SOC_DIR}/plat_setup.c \ ${SOC_DIR}/drivers/se/security_engine.c \ - ${SOC_DIR}/plat_secondary.c + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c # Enable workarounds for selected Cortex-A57 erratas. A57_DISABLE_NON_TEMPORAL_HINT := 1 @@ -48,3 +52,6 @@ ERRATA_A53_826319 := 1 ERRATA_A53_836870 := 1 ERRATA_A53_855873 := 1 + +# Skip L1 $ flush when powering down Cortex-A57 CPUs +SKIP_A57_L1_FLUSH_PWR_DWN := 1 diff --git a/services/spd/tlkd/tlkd_common.c b/services/spd/tlkd/tlkd_common.c index 2f0194e..dbe6c2e 100644 --- a/services/spd/tlkd/tlkd_common.c +++ b/services/spd/tlkd/tlkd_common.c @@ -126,7 +126,6 @@ /* Passing a NULL context is a critical programming error */ assert(tlk_ctx); - assert(tlk_ctx->c_rt_ctx == 0); /* Apply the Secure EL1 system register context and switch to it */ assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c index b1a0477..f6f2af5 100644 --- a/services/spd/tlkd/tlkd_main.c +++ b/services/spd/tlkd/tlkd_main.c @@ -195,14 +195,18 @@ * b. register shared memory with the SP for passing args * required for maintaining sessions with the Trusted * Applications. - * c. register non-secure world's memory map with the OS - * d. open/close sessions - * e. issue commands to the Trusted Apps - * f. resume the preempted yielding SMC call. + * c. register shared persistent buffers for secure storage + * d. register NS DRAM ranges passed by Cboot + * e. register Root of Trust parameters from Cboot for Verified Boot + * f. open/close sessions + * g. issue commands to the Trusted Apps + * h. resume the preempted yielding SMC call. */ case TLK_REGISTER_LOGBUF: case TLK_REGISTER_REQBUF: - case TLK_REGISTER_NS_DRAM: + case TLK_SS_REGISTER_HANDLER: + case TLK_REGISTER_NS_DRAM_RANGES: + case TLK_SET_ROOT_OF_TRUST: case TLK_OPEN_TA_SESSION: case TLK_CLOSE_TA_SESSION: case TLK_TA_LAUNCH_OP: @@ -400,6 +404,7 @@ SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); default: + WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid); break; } diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c index 83c14b4..b059a43 100644 --- a/services/spd/trusty/trusty.c +++ b/services/spd/trusty/trusty.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -352,32 +353,32 @@ } } -static int32_t trusty_cpu_off_handler(u_register_t unused) +static int32_t trusty_cpu_off_handler(u_register_t max_off_lvl) { - trusty_cpu_suspend(1); + trusty_cpu_suspend(max_off_lvl); return 0; } -static void trusty_cpu_on_finish_handler(u_register_t unused) +static void trusty_cpu_on_finish_handler(u_register_t max_off_lvl) { struct trusty_cpu_ctx *ctx = get_trusty_ctx(); if (ctx->saved_sp == NULL) { (void)trusty_init(); } else { - trusty_cpu_resume(1); + trusty_cpu_resume(max_off_lvl); } } -static void trusty_cpu_suspend_handler(u_register_t unused) +static void trusty_cpu_suspend_handler(u_register_t max_off_lvl) { - trusty_cpu_suspend(0); + trusty_cpu_suspend(max_off_lvl); } -static void trusty_cpu_suspend_finish_handler(u_register_t unused) +static void trusty_cpu_suspend_finish_handler(u_register_t max_off_lvl) { - trusty_cpu_resume(0); + trusty_cpu_resume(max_off_lvl); } static const spd_pm_ops_t trusty_pm = { @@ -412,6 +413,14 @@ return -1; } + /* memmap first page of trusty's code memory before peeking */ + ret = mmap_add_dynamic_region(ep_info->pc, /* PA */ + ep_info->pc, /* VA */ + PAGE_SIZE, /* size */ + MT_SECURE | MT_RW_DATA); /* attrs */ + assert(ret == 0); + + /* peek into trusty's code to see if we have a 32-bit or 64-bit image */ instr = *(uint32_t *)ep_info->pc; if (instr >> 24 == 0xeaU) { @@ -424,6 +433,9 @@ return -1; } + /* unmap trusty's memory page */ + (void)mmap_remove_dynamic_region(ep_info->pc, PAGE_SIZE); + SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); if (!aarch32) ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,