diff options
Diffstat (limited to 'src/soc/nvidia')
-rw-r--r-- | src/soc/nvidia/tegra132/addressmap.c | 55 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/include/soc/addressmap.h | 9 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/ramstage.c | 23 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/romstage.c | 11 |
4 files changed, 58 insertions, 40 deletions
diff --git a/src/soc/nvidia/tegra132/addressmap.c b/src/soc/nvidia/tegra132/addressmap.c index 7dbab556ea..65371872fe 100644 --- a/src/soc/nvidia/tegra132/addressmap.c +++ b/src/soc/nvidia/tegra132/addressmap.c @@ -27,6 +27,9 @@ #include "mc.h" #include "sdram.h" +static uintptr_t tz_base_mib; +static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB; + /* returns total amount of DRAM (in MB) from memory controller registers */ int sdram_size_mb(void) { @@ -71,13 +74,8 @@ void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib) switch (id) { case CARVEOUT_TZ: - /* AVP does not have access to the TZ carveout registers. */ - if (context_avp()) - return; - carveout_from_regs(base_mib, size_mib, - read32(&mc->security_cfg0), - 0, - read32(&mc->security_cfg1)); + *base_mib = tz_base_mib; + *size_mib = tz_size_mib; break; case CARVEOUT_SEC: carveout_from_regs(base_mib, size_mib, @@ -102,7 +100,8 @@ void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib) } } -static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib) +static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib, + int ignore_tz) { uintptr_t base; uintptr_t end; @@ -128,6 +127,9 @@ static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib) uintptr_t carveout_end; size_t carveout_size; + if (i == CARVEOUT_TZ && ignore_tz) + continue; + carveout_range(i, &carveout_base, &carveout_size); if (carveout_size == 0) @@ -155,14 +157,14 @@ void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib) { *base_mib = 0; *end_mib = 4096; - memory_in_range(base_mib, end_mib); + memory_in_range(base_mib, end_mib, 0); } void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib) { *base_mib = 4096; *end_mib = ~0UL; - memory_in_range(base_mib, end_mib); + memory_in_range(base_mib, end_mib, 0); } uintptr_t framebuffer_attributes(size_t *size_mib) @@ -173,16 +175,33 @@ uintptr_t framebuffer_attributes(size_t *size_mib) /* Place the framebuffer just below the 32-bit addressable limit. */ memory_in_range_below_4gb(&begin, &end); - /* - * Need to take into account that the Trust Zone region is not able to - * be read by the AVP. The Trust Zone region will live just below the - * rest of the carveout regions. - */ - if (context_avp()) - end -= CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB; - *size_mib = FB_SIZE_MB; end -= *size_mib; return end; } + +void trustzone_region_init(void) +{ + struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE; + uintptr_t end = 4096; + + /* Already has been initialized. */ + if (tz_size_mib != 0 && tz_base_mib != 0) + return; + + /* + * Get memory layout below 4GiB ignoring the TZ carveout because + * that's the one to initialize. + */ + memory_in_range(&tz_base_mib, &end, 1); + tz_base_mib = end - tz_size_mib; + + /* AVP cannot set the TZ registers proper as it is always non-secure. */ + if (context_avp()) + return; + + /* Set the carveout region. */ + write32(tz_base_mib << 20, &mc->security_cfg0); + write32(tz_size_mib, &mc->security_cfg1); +} diff --git a/src/soc/nvidia/tegra132/include/soc/addressmap.h b/src/soc/nvidia/tegra132/include/soc/addressmap.h index 3d0fc59900..52e4d54356 100644 --- a/src/soc/nvidia/tegra132/include/soc/addressmap.h +++ b/src/soc/nvidia/tegra132/include/soc/addressmap.h @@ -99,6 +99,15 @@ enum { /* Provided the careout id, obtain the base and size in 1MiB units. */ void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib); +/* + * There are complications accessing the Trust Zone carveout region. The + * AVP cannot access these registers and the CPU can't access this register + * as a non-secure access. When the page tables live in non-secure memory + * these registers cannot be accessed either. Thus, this function handles + * both the AVP case and non-secured access case by keeping global state. + */ +void trustzone_region_init(void); + /* Return pointer and size in 1MiB units. */ uintptr_t framebuffer_attributes(size_t *size_mib); diff --git a/src/soc/nvidia/tegra132/ramstage.c b/src/soc/nvidia/tegra132/ramstage.c index ad553d43cc..b3b4db2c86 100644 --- a/src/soc/nvidia/tegra132/ramstage.c +++ b/src/soc/nvidia/tegra132/ramstage.c @@ -17,34 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <arch/io.h> #include <arch/stages.h> #include <soc/addressmap.h> -#include "mc.h" #include "mmu_operations.h" void arm64_soc_init(void) { - struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE; - const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB; - uintptr_t base; - uintptr_t end; - - if (!tz_size_mib) - return; - - /* - * Ramstage is when the arm64 first gets running. It also is the - * only entity that the capabilities to program the Trust Zone region. - * Therefore configure the region early. Also, the TZ region can only - * live in 32-bit space. - */ - memory_in_range_below_4gb(&base, &end); - - /* Place the TZ area just below current carveout regions. */ - end -= tz_size_mib; - write32(end << 20, &mc->security_cfg0); - write32(tz_size_mib, &mc->security_cfg1); + trustzone_region_init(); tegra132_mmu_init(); } diff --git a/src/soc/nvidia/tegra132/romstage.c b/src/soc/nvidia/tegra132/romstage.c index 2a1bd46d07..4b1c8431eb 100644 --- a/src/soc/nvidia/tegra132/romstage.c +++ b/src/soc/nvidia/tegra132/romstage.c @@ -24,6 +24,7 @@ #include <console/console.h> #include <arch/exception.h> +#include <soc/addressmap.h> #include <soc/sdram_configs.h> #include "sdram.h" #include "ccplex.h" @@ -45,6 +46,16 @@ void romstage(void) sdram_init(get_sdram_config()); printk(BIOS_INFO, "T132 romstage: sdram_init done\n"); #endif + + /* + * Trust Zone needs to be initialized after the DRAM initialization + * because carveout registers are programmed during DRAM init. + * cbmem_initialize() is dependent on the Trust Zone region + * initalization because CBMEM lives right below the Trust Zone which + * needs to be properly identified. + */ + trustzone_region_init(); + cbmem_initialize(); ccplex_cpu_prepare(); |