aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/nvidia/tegra132/addressmap.c55
-rw-r--r--src/soc/nvidia/tegra132/include/soc/addressmap.h9
-rw-r--r--src/soc/nvidia/tegra132/ramstage.c23
-rw-r--r--src/soc/nvidia/tegra132/romstage.c11
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();