BUG=None BRANCH=None TEST=Verified by reading back the value of SMMU_CONFIG register that enable bit is set to 1 Original-Change-Id: Iccc870141f9b9729971bf12119f9f3dae8181a43 Original-Signed-off-by: Furquan Shaikh <furquan@google.com> Original-Reviewed-on: https://chromium-review.googlesource.com/222770 Original-Reviewed-by: Olof Johansson <olofj@chromium.org> Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org> Original-Tested-by: Furquan Shaikh <furquan@chromium.org> Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org> (cherry picked from commit a06b36f9003d801709d83a8faed6fc04bb91df1b) Signed-off-by: Aaron Durbin <adurbin@chromium.org> Change-Id: Iae3949940a5a0efa2761542974d5c209178ce397 Reviewed-on: http://review.coreboot.org/9258 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com> Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
195 lines
4.8 KiB
C
195 lines
4.8 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
#include <arch/io.h>
|
|
#include <stdlib.h>
|
|
#include <console/console.h>
|
|
#include <soc/addressmap.h>
|
|
#include <soc/id.h>
|
|
#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)
|
|
{
|
|
struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
|
|
static int total_size = 0;
|
|
|
|
if (total_size)
|
|
return total_size;
|
|
|
|
/*
|
|
* This obtains memory size from the External Memory Aperture
|
|
* Configuration register. Nvidia confirmed that it is safe to assume
|
|
* this value represents the total physical DRAM size.
|
|
*/
|
|
total_size = (read32(&mc->emem_cfg) >> MC_EMEM_CFG_SIZE_MB_SHIFT) &
|
|
MC_EMEM_CFG_SIZE_MB_MASK;
|
|
|
|
return total_size;
|
|
}
|
|
|
|
static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib,
|
|
uint32_t bom, uint32_t bom_hi, uint32_t size)
|
|
{
|
|
|
|
/* All size regs of carveouts are in MiB. */
|
|
if (size == 0)
|
|
return;
|
|
|
|
*size_mib = size;
|
|
bom >>= 20;
|
|
bom |= bom_hi << (32 - 20);
|
|
|
|
*base_mib = bom;
|
|
}
|
|
|
|
void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib)
|
|
{
|
|
*base_mib = 0;
|
|
*size_mib = 0;
|
|
struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
|
|
|
|
switch (id) {
|
|
case CARVEOUT_TZ:
|
|
*base_mib = tz_base_mib;
|
|
*size_mib = tz_size_mib;
|
|
break;
|
|
case CARVEOUT_SEC:
|
|
carveout_from_regs(base_mib, size_mib,
|
|
read32(&mc->sec_carveout_bom),
|
|
read32(&mc->sec_carveout_adr_hi),
|
|
read32(&mc->sec_carveout_size_mb));
|
|
break;
|
|
case CARVEOUT_MTS:
|
|
carveout_from_regs(base_mib, size_mib,
|
|
read32(&mc->mts_carveout_bom),
|
|
read32(&mc->mts_carveout_adr_hi),
|
|
read32(&mc->mts_carveout_size_mb));
|
|
break;
|
|
case CARVEOUT_VPR:
|
|
carveout_from_regs(base_mib, size_mib,
|
|
read32(&mc->video_protect_bom),
|
|
read32(&mc->video_protect_bom_adr_hi),
|
|
read32(&mc->video_protect_size_mb));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
|
|
int ignore_tz)
|
|
{
|
|
uintptr_t base;
|
|
uintptr_t end;
|
|
int i;
|
|
|
|
base = CONFIG_SYS_SDRAM_BASE / MiB;
|
|
end = base + sdram_size_mb();
|
|
|
|
/* Requested limits out of range. */
|
|
if (*end_mib <= base || *base_mib >= end) {
|
|
*end_mib = *base_mib = 0;
|
|
return;
|
|
}
|
|
|
|
/* Clip region to passed in limits. */
|
|
if (*end_mib < end)
|
|
end = *end_mib;
|
|
if (*base_mib > base)
|
|
base = *base_mib;
|
|
|
|
for (i = 0; i < CARVEOUT_NUM; i++) {
|
|
uintptr_t carveout_base;
|
|
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)
|
|
continue;
|
|
|
|
carveout_end = carveout_base + carveout_size;
|
|
|
|
/* Bypass carveouts out of requested range. */
|
|
if (carveout_base >= end || carveout_end <= base)
|
|
continue;
|
|
|
|
/*
|
|
* This is crude, but the assumption is that carveouts live
|
|
* at the upper range of physical memory. Therefore, update
|
|
* the end address to be equal to the base of the carveout.
|
|
*/
|
|
end = carveout_base;
|
|
}
|
|
|
|
*base_mib = base;
|
|
*end_mib = end;
|
|
}
|
|
|
|
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, 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, 0);
|
|
}
|
|
|
|
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);
|
|
|
|
/* Enable SMMU translations */
|
|
write32(MC_SMMU_CONFIG_ENABLE, &mc->smmu_config);
|
|
}
|