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>utp
parent
026baff755
commit
73c38934da
7
README
7
README
|
@ -621,6 +621,13 @@ The following options need to be configured:
|
||||||
exists, unlike the similar options in the Linux kernel. Do not
|
exists, unlike the similar options in the Linux kernel. Do not
|
||||||
set these options unless they apply!
|
set these options unless they apply!
|
||||||
|
|
||||||
|
- Tegra SoC options:
|
||||||
|
CONFIG_TEGRA_SUPPORT_NON_SECURE
|
||||||
|
|
||||||
|
Support executing U-Boot in non-secure (NS) mode. Certain
|
||||||
|
impossible actions will be skipped if the CPU is in NS mode,
|
||||||
|
such as ARM architectural timer initialization.
|
||||||
|
|
||||||
- Driver Model
|
- Driver Model
|
||||||
Driver model is a new framework for devices in U-Boot
|
Driver model is a new framework for devices in U-Boot
|
||||||
introduced in early 2014. U-Boot is being progressively
|
introduced in early 2014. U-Boot is being progressively
|
||||||
|
|
|
@ -74,3 +74,7 @@ static inline void config_vpr(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||||
|
bool tegra_cpu_is_non_secure(void);
|
||||||
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <asm/arch/funcmux.h>
|
#include <asm/arch/funcmux.h>
|
||||||
#include <asm/arch/mc.h>
|
#include <asm/arch/mc.h>
|
||||||
#include <asm/arch/tegra.h>
|
#include <asm/arch/tegra.h>
|
||||||
|
#include <asm/arch-tegra/ap.h>
|
||||||
#include <asm/arch-tegra/board.h>
|
#include <asm/arch-tegra/board.h>
|
||||||
#include <asm/arch-tegra/pmc.h>
|
#include <asm/arch-tegra/pmc.h>
|
||||||
#include <asm/arch-tegra/sys_proto.h>
|
#include <asm/arch-tegra/sys_proto.h>
|
||||||
|
@ -28,6 +29,24 @@ enum {
|
||||||
UART_COUNT = 5,
|
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 */
|
/* Read the RAM size directly from the memory controller */
|
||||||
unsigned int query_sdram_size(void)
|
unsigned int query_sdram_size(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/arch/clock.h>
|
#include <asm/arch/clock.h>
|
||||||
#include <asm/arch/tegra.h>
|
#include <asm/arch/tegra.h>
|
||||||
|
#include <asm/arch-tegra/ap.h>
|
||||||
#include <asm/arch-tegra/clk_rst.h>
|
#include <asm/arch-tegra/clk_rst.h>
|
||||||
#include <asm/arch-tegra/timer.h>
|
#include <asm/arch-tegra/timer.h>
|
||||||
#include <div64.h>
|
#include <div64.h>
|
||||||
|
@ -573,7 +574,10 @@ void clock_init(void)
|
||||||
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
|
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
|
||||||
|
|
||||||
/* Do any special system timer/TSC setup */
|
/* 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)
|
static void set_avp_clock_source(u32 src)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <asm/arch/pwm.h>
|
#include <asm/arch/pwm.h>
|
||||||
#endif
|
#endif
|
||||||
#include <asm/arch/tegra.h>
|
#include <asm/arch/tegra.h>
|
||||||
|
#include <asm/arch-tegra/ap.h>
|
||||||
#include <asm/arch-tegra/board.h>
|
#include <asm/arch-tegra/board.h>
|
||||||
#include <asm/arch-tegra/clk_rst.h>
|
#include <asm/arch-tegra/clk_rst.h>
|
||||||
#include <asm/arch-tegra/pmc.h>
|
#include <asm/arch-tegra/pmc.h>
|
||||||
|
@ -179,6 +180,14 @@ int board_late_init(void)
|
||||||
#ifdef CONFIG_LCD
|
#ifdef CONFIG_LCD
|
||||||
/* Make sure we finish initing the LCD */
|
/* Make sure we finish initing the LCD */
|
||||||
tegra_lcd_check_next_stage(gd->fdt_blob, 1);
|
tegra_lcd_check_next_stage(gd->fdt_blob, 1);
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
|
||||||
|
if (tegra_cpu_is_non_secure()) {
|
||||||
|
printf("CPU is in NS mode\n");
|
||||||
|
setenv("cpu_ns_mode", "1");
|
||||||
|
} else {
|
||||||
|
setenv("cpu_ns_mode", "");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue