Merge pull request #1785 from vwadekar/tf2.0-tegra-downstream-rebase-1.25.19
Tf2.0 tegra downstream rebase 1.25.19
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 \
@@ -390,6 +389,13 @@
include ${AARCH32_SP_MAKE}
endif
+endif
+
+################################################################################
+# Include libc if not overridden
+################################################################################
+ifeq (${OVERRIDE_LIBC},0)
+include lib/libc/libc.mk
endif
################################################################################
@@ -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'.
+
-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.
+- 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=<path-to-aarch64-gcc>/bin/aarch64-none-elf- make PLAT=tegra \
- TARGET_SOC=<target-soc e.g. t210|t132> SPD=<dispatcher e.g. tlkd> bl31
+ TARGET_SOC=<target-soc e.g. t186|t210|t132> SPD=<dispatcher e.g. trusty|tlkd>
+ bl31
Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=<value>``
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 <string.h>
#include <tegra_def.h>
-#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--;
+ }
- /* 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");
- }
+ } while ((val != SIGN_OF_LIFE) && (timeout > 0U));
- /* 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");
- }
+ if (val == SIGN_OF_LIFE) {
- /* base address to get the result from Atomics */
- base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
+ /* 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");
+ }
- /* channel area is setup by BPMP before signaling handshake */
- for (ch = 0; ch < NR_CHANNELS; ch++) {
+ /* base address to get the result from Atomics */
+ base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
- /* issue command to get the channel base address */
- mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
- ATOMIC_CMD_GET);
+ /* channel area is setup by BPMP before signaling handshake */
+ for (ch = 0; ch < NR_CHANNELS; ch++) {
- /* get the base address for the channel */
- channel_base[ch] = mmio_read_32(base);
+ /* issue command to get the channel base address */
+ mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
+ ATOMIC_CMD_GET);
- /* increment result register offset */
- base += 4U;
+ /* 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;
}
+ }
- /* mark state as "initialized" */
- bpmp_init_state = BPMP_INIT_COMPLETE;
+ return ret;
+}
- /* the channel values have to be visible across all cpus */
- flush_dcache_range((uint64_t)channel_base, sizeof(channel_base));
+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));
-
- INFO("%s: done\n", __func__);
}
+}
- return ret;
+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 <flowctrl.h>
#include <pmc.h>
#include <tegra_def.h>
+#include <utils_def.h>
#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 <lib/el3_runtime/context_mgmt.h>
#include <plat/common/platform.h>
+#if ENABLE_WDT_LEGACY_FIQ_HANDLING
+#include <flowctrl.h>
+#endif
#include <tegra_def.h>
#include <tegra_private.h>
+/* 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;
- 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.
+ * Read the pending interrupt ID
*/
- cm_el1_sysregs_context_save(NON_SECURE);
+ irq = plat_ic_get_pending_interrupt_id();
+
+ bakery_lock_get(&tegra_fiq_lock);
/*
- * Save elr_el3 and spsr_el3 from the saved context, and overwrite
- * the context with the NS fiq_handler_addr and SPSR value.
+ * Jump to NS world only if the NS world's FIQ handler has
+ * been registered
*/
- 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));
+ if (ns_fiq_handler_addr != 0U) {
+
+ /*
+ * 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 <tegra_def.h>
-#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 <lib/mmio.h>
#include <lib/utils_def.h>
+#include <stdbool.h>
#include <tegra_def.h>
#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_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_cpu_on(int32_t cpu);
+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(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_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_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 <bpmp.h>
#include <flowctrl.h>
+#include <memctrl.h>
#include <pmc.h>
#include <platform_def.h>
#include <security_engine.h>
#include <tegra_def.h>
#include <tegra_private.h>
#include <tegra_platform.h>
+#include <utils.h>
/*
* 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
+ * Cluster idle request for afflvl 0
*/
- req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
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,15 +215,42 @@
assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
- /* Prepare for cluster idle */
- tegra_fc_cluster_idle(mpidr);
+ if (!tegra_bpmp_available) {
- } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) {
+ /*
+ * 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);
- assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
+ /* 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 powerdn */
- tegra_fc_cluster_powerdn(mpidr);
+ /* Prepare for cluster idle */
+ tegra_fc_cluster_idle(mpidr);
} else if (stateid_afflvl0 == PSTATE_ID_CORE_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,18 +456,76 @@
/*
* 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();
+ }
+ }
+
+ /*
* T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's
* used for power management and boot purposes. Inform the BPMP that
* we have completed the cluster power up.
*/
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 <arch_helpers.h>
-#include <bpmp.h>
+#include <assert.h>
#include <cortex_a57.h>
#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
#include <drivers/console.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <bl31/interrupt_mgmt.h>
+
+#include <bpmp.h>
+#include <flowctrl.h>
+#include <memctrl.h>
#include <platform.h>
#include <security_engine.h>
#include <tegra_def.h>
@@ -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 <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <errno.h>
+#include <mmio.h>
+#include <utils_def.h>
+
+#include <memctrl.h>
+#include <pmc.h>
+#include <tegra_private.h>
+#include <tegra_platform.h>
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * 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 <assert.h>
#include <stdbool.h>
#include <string.h>
+#include <xlat_tables_v2.h>
#include <arch_helpers.h>
#include <bl31/bl31.h>
@@ -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,