summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2015-01-19 16:25:52 -0700
committerTom Warren <twarren@nvidia.com>2015-03-04 10:08:57 -0700
commit73c38934daa10b518b20f2d21298fc8a8226843b (patch)
tree68d0f8837373d2fce809f7e38bb4ff89f14558b9 /arch/arm/mach-tegra
parent026baff755cbab0c8bfc12d78e6966718f5325a5 (diff)
downloadu-boot-imx-73c38934daa10b518b20f2d21298fc8a8226843b.zip
u-boot-imx-73c38934daa10b518b20f2d21298fc8a8226843b.tar.gz
u-boot-imx-73c38934daa10b518b20f2d21298fc8a8226843b.tar.bz2
ARM: tegra: support running in non-secure mode
When the CPU is in non-secure (NS) mode (when running U-Boot under a secure monitor), certain actions cannot be taken, since they would need to write to secure-only registers. One example is configuring the ARM architectural timer's CNTFRQ register. We could support this in one of two ways: 1) Compile twice, once for secure mode (in which case anything goes) and once for non-secure mode (in which case certain actions are disabled). This complicates things, since everyone needs to keep track of different U-Boot binaries for different situations. 2) Detect NS mode at run-time, and optionally skip any impossible actions. This has the advantage of a single U-Boot binary working in all cases. (2) is not possible on ARM in general, since there's no architectural way to detect secure-vs-non-secure. However, there is a Tegra-specific way to detect this. This patches uses that feature to detect secure vs. NS mode on Tegra, and uses that to: * Skip the ARM arch timer initialization. * Set/clear an environment variable so that boot scripts can take different action depending on which mode the CPU is in. This might be something like: if CPU is secure: load secure monitor code into RAM. boot secure monitor. secure monitor will restart (a new copy of) U-Boot in NS mode. else: execute normal boot process Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/board.c19
-rw-r--r--arch/arm/mach-tegra/clock.c6
2 files changed, 24 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c
index 87511a3..0ebaf19 100644
--- a/arch/arm/mach-tegra/board.c
+++ b/arch/arm/mach-tegra/board.c
@@ -11,6 +11,7 @@
#include <asm/arch/funcmux.h>
#include <asm/arch/mc.h>
#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/board.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/sys_proto.h>
@@ -28,6 +29,24 @@ enum {
UART_COUNT = 5,
};
+#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
+#if !defined(CONFIG_TEGRA124)
+#error tegra_cpu_is_non_secure has only been validated on Tegra124
+#endif
+bool tegra_cpu_is_non_secure(void)
+{
+ /*
+ * This register reads 0xffffffff in non-secure mode. This register
+ * only implements bits 31:20, so the lower bits will always read 0 in
+ * secure mode. Thus, the lower bits are an indicator for secure vs.
+ * non-secure mode.
+ */
+ struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE;
+ uint32_t mc_s_cfg0 = readl(&mc->mc_security_cfg0);
+ return (mc_s_cfg0 & 1) == 1;
+}
+#endif
+
/* Read the RAM size directly from the memory controller */
unsigned int query_sdram_size(void)
{
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 11c7435..7c274b5 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/timer.h>
#include <div64.h>
@@ -573,7 +574,10 @@ void clock_init(void)
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
/* Do any special system timer/TSC setup */
- arch_timer_init();
+#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
+ if (!tegra_cpu_is_non_secure())
+#endif
+ arch_timer_init();
}
static void set_avp_clock_source(u32 src)