Tegra: Support for Tegra's T132 platforms
This patch implements support for T132 (Denver CPU) based Tegra
platforms.
The following features have been added:
* SiP calls to switch T132 CPU's AARCH mode
* Complete PSCI support, including 'System Suspend'
* Platform specific MMIO settings
* Locking of CPU vector registers
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index 1d79c80..de36a3c 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -28,6 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
@@ -38,7 +39,21 @@
#include <runtime_svc.h>
#include <tegra_private.h>
+#define NS_SWITCH_AARCH32 1
+#define SCR_RW_BITPOS __builtin_ctz(SCR_RW_BIT)
+
+/*******************************************************************************
+ * Tegra SiP SMCs
+ ******************************************************************************/
#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
+#define TEGRA_SIP_AARCH_SWITCH 0x82000004
+
+/*******************************************************************************
+ * SPSR settings for AARCH32/AARCH64 modes
+ ******************************************************************************/
+#define SPSR32 SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, \
+ DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)
+#define SPSR64 SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)
/*******************************************************************************
* This function is responsible for handling all SiP calls from the NS world
@@ -64,6 +79,10 @@
case TEGRA_SIP_NEW_VIDEOMEM_REGION:
+ /* clean up the high bits */
+ x1 = (uint32_t)x1;
+ x2 = (uint32_t)x2;
+
/*
* Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
* or falls outside of the valid DRAM range
@@ -84,6 +103,30 @@
tegra_memctrl_videomem_setup(x1, x2);
SMC_RET1(handle, 0);
+ break;
+
+ case TEGRA_SIP_AARCH_SWITCH:
+
+ /* clean up the high bits */
+ x1 = (uint32_t)x1;
+ x2 = (uint32_t)x2;
+
+ if (!x1 || x2 > NS_SWITCH_AARCH32) {
+ ERROR("%s: invalid parameters\n", __func__);
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /* x1 = ns entry point */
+ cm_set_elr_spsr_el3(NON_SECURE, x1,
+ (x2 == NS_SWITCH_AARCH32) ? SPSR32 : SPSR64);
+
+ /* switch NS world mode */
+ cm_write_scr_el3_bit(NON_SECURE, SCR_RW_BITPOS, !x2);
+
+ INFO("CPU switched to AARCH%s mode\n",
+ (x2 == NS_SWITCH_AARCH32) ? "32" : "64");
+ SMC_RET1(handle, 0);
+ break;
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);