2015-05-19 12:18:04 +01:00
|
|
|
/*
|
Tegra: memctrl: map video memory as uncached
Memmap video memory as uncached normal memory by adding flag
'MT_NON_CACHEABLE' in mmap_add_dynamic_region().
This improves the time taken for clearing the non-overlapping video
memory:
test conditions: 32MB memory size, EMC running at 1866MHz, t186
1) without MT_NON_CACHEABLE: 30ms ~ 40ms
<3>[ 133.852885] vpr-heap: update vpr base to 0x00000000c6000000, size=e000000
<3>[ 133.860471] _tegra_set_vpr_params[120]: begin
<3>[ 133.896481] _tegra_set_vpr_params[123]: end
<3>[ 133.908944] vpr-heap: update vpr base to 0x00000000c6000000, size=c000000
<3>[ 133.916397] _tegra_set_vpr_params[120]: begin
<3>[ 133.956369] _tegra_set_vpr_params[123]: end
<3>[ 133.970394] vpr-heap: update vpr base to 0x00000000c6000000, size=a000000
<3>[ 133.977934] _tegra_set_vpr_params[120]: begin
<3>[ 134.013874] _tegra_set_vpr_params[123]: end
<3>[ 134.025666] vpr-heap: update vpr base to 0x00000000c6000000, size=8000000
<3>[ 134.033512] _tegra_set_vpr_params[120]: begin
<3>[ 134.065996] _tegra_set_vpr_params[123]: end
<3>[ 134.075465] vpr-heap: update vpr base to 0x00000000c6000000, size=6000000
<3>[ 134.082923] _tegra_set_vpr_params[120]: begin
<3>[ 134.113119] _tegra_set_vpr_params[123]: end
<3>[ 134.123448] vpr-heap: update vpr base to 0x00000000c6000000, size=4000000
<3>[ 134.130790] _tegra_set_vpr_params[120]: begin
<3>[ 134.162523] _tegra_set_vpr_params[123]: end
<3>[ 134.172413] vpr-heap: update vpr base to 0x00000000c6000000, size=2000000
<3>[ 134.179772] _tegra_set_vpr_params[120]: begin
<3>[ 134.209142] _tegra_set_vpr_params[123]: end
2) with MT_NON_CACHEABLE: 10ms ~ 18ms
<3>[ 102.108702] vpr-heap: update vpr base to 0x00000000c6000000, size=e000000
<3>[ 102.116296] _tegra_set_vpr_params[120]: begin
<3>[ 102.134272] _tegra_set_vpr_params[123]: end
<3>[ 102.145839] vpr-heap: update vpr base to 0x00000000c6000000, size=c000000
<3>[ 102.153226] _tegra_set_vpr_params[120]: begin
<3>[ 102.164201] _tegra_set_vpr_params[123]: end
<3>[ 102.172275] vpr-heap: update vpr base to 0x00000000c6000000, size=a000000
<3>[ 102.179638] _tegra_set_vpr_params[120]: begin
<3>[ 102.190342] _tegra_set_vpr_params[123]: end
<3>[ 102.197524] vpr-heap: update vpr base to 0x00000000c6000000, size=8000000
<3>[ 102.205085] _tegra_set_vpr_params[120]: begin
<3>[ 102.216112] _tegra_set_vpr_params[123]: end
<3>[ 102.224080] vpr-heap: update vpr base to 0x00000000c6000000, size=6000000
<3>[ 102.231387] _tegra_set_vpr_params[120]: begin
<3>[ 102.241775] _tegra_set_vpr_params[123]: end
<3>[ 102.248825] vpr-heap: update vpr base to 0x00000000c6000000, size=4000000
<3>[ 102.256069] _tegra_set_vpr_params[120]: begin
<3>[ 102.266368] _tegra_set_vpr_params[123]: end
<3>[ 102.273400] vpr-heap: update vpr base to 0x00000000c6000000, size=2000000
<3>[ 102.280672] _tegra_set_vpr_params[120]: begin
<3>[ 102.290929] _tegra_set_vpr_params[123]: end
Change-Id: I5f604064ce7b8b73ea9ad5860156ae5e2c6cc42a
Signed-off-by: Ken Chang <kenc@nvidia.com>
2018-12-28 00:44:12 +00:00
|
|
|
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
2019-06-17 19:45:11 +01:00
|
|
|
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
2015-05-19 12:18:04 +01:00
|
|
|
*
|
2017-05-03 09:38:09 +01:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2015-05-19 12:18:04 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <arch_helpers.h>
|
|
|
|
#include <common/debug.h>
|
|
|
|
#include <lib/mmio.h>
|
|
|
|
#include <lib/utils.h>
|
|
|
|
#include <lib/xlat_tables/xlat_tables_v2.h>
|
|
|
|
|
2015-05-19 12:18:04 +01:00
|
|
|
#include <memctrl.h>
|
2015-09-18 06:51:22 +01:00
|
|
|
#include <memctrl_v1.h>
|
2015-05-19 12:18:04 +01:00
|
|
|
#include <tegra_def.h>
|
2015-06-10 09:34:32 +01:00
|
|
|
|
|
|
|
/* Video Memory base and size (live values) */
|
2016-12-13 00:14:57 +00:00
|
|
|
static uint64_t video_mem_base;
|
2015-06-10 09:34:32 +01:00
|
|
|
static uint64_t video_mem_size;
|
2015-05-19 12:18:04 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Init SMMU.
|
|
|
|
*/
|
|
|
|
void tegra_memctrl_setup(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Setup the Memory controller to allow only secure accesses to
|
|
|
|
* the TZDRAM carveout
|
|
|
|
*/
|
2015-09-18 06:51:22 +01:00
|
|
|
INFO("Tegra Memory Controller (v1)\n");
|
2015-05-19 12:18:04 +01:00
|
|
|
|
|
|
|
/* allow translations for all MC engines */
|
|
|
|
tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0,
|
|
|
|
(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
|
|
|
|
tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0,
|
|
|
|
(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
|
|
|
|
tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0,
|
|
|
|
(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
|
|
|
|
tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0,
|
|
|
|
(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
|
|
|
|
tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0,
|
|
|
|
(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
|
|
|
|
|
|
|
|
tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY);
|
|
|
|
|
|
|
|
tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL);
|
|
|
|
tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL);
|
|
|
|
|
|
|
|
/* flush PTC and TLB */
|
|
|
|
tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL);
|
|
|
|
(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
|
|
|
|
tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL);
|
|
|
|
|
|
|
|
/* enable SMMU */
|
|
|
|
tegra_mc_write_32(MC_SMMU_CONFIG_0,
|
|
|
|
MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
|
|
|
|
(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
|
2015-06-10 09:34:32 +01:00
|
|
|
|
|
|
|
/* video memory carveout */
|
2016-12-13 00:14:57 +00:00
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
|
|
|
|
(uint32_t)(video_mem_base >> 32));
|
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base);
|
2015-06-10 09:34:32 +01:00
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
|
2015-05-19 12:18:04 +01:00
|
|
|
}
|
|
|
|
|
2016-03-03 21:28:10 +00:00
|
|
|
/*
|
|
|
|
* Restore Memory Controller settings after "System Suspend"
|
|
|
|
*/
|
|
|
|
void tegra_memctrl_restore_settings(void)
|
|
|
|
{
|
|
|
|
tegra_memctrl_setup();
|
|
|
|
}
|
|
|
|
|
2015-05-19 12:18:04 +01:00
|
|
|
/*
|
|
|
|
* Secure the BL31 DRAM aperture.
|
|
|
|
*
|
|
|
|
* phys_base = physical base of TZDRAM aperture
|
|
|
|
* size_in_bytes = size of aperture in bytes
|
|
|
|
*/
|
|
|
|
void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Setup the Memory controller to allow only secure accesses to
|
|
|
|
* the TZDRAM carveout
|
|
|
|
*/
|
|
|
|
INFO("Configuring TrustZone DRAM Memory Carveout\n");
|
|
|
|
|
|
|
|
tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
|
|
|
|
tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
|
|
|
|
}
|
2015-06-10 09:34:32 +01:00
|
|
|
|
2015-09-10 14:12:36 +01:00
|
|
|
static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
|
|
|
|
unsigned long long non_overlap_area_size)
|
|
|
|
{
|
2017-08-03 19:40:34 +01:00
|
|
|
int ret;
|
|
|
|
|
2015-09-10 14:12:36 +01:00
|
|
|
/*
|
2017-04-10 23:30:17 +01:00
|
|
|
* Map the NS memory first, clean it and then unmap it.
|
2015-09-10 14:12:36 +01:00
|
|
|
*/
|
2017-08-03 19:40:34 +01:00
|
|
|
ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
|
2017-04-10 23:30:17 +01:00
|
|
|
non_overlap_area_start, /* VA */
|
|
|
|
non_overlap_area_size, /* size */
|
Tegra: memctrl: map video memory as uncached
Memmap video memory as uncached normal memory by adding flag
'MT_NON_CACHEABLE' in mmap_add_dynamic_region().
This improves the time taken for clearing the non-overlapping video
memory:
test conditions: 32MB memory size, EMC running at 1866MHz, t186
1) without MT_NON_CACHEABLE: 30ms ~ 40ms
<3>[ 133.852885] vpr-heap: update vpr base to 0x00000000c6000000, size=e000000
<3>[ 133.860471] _tegra_set_vpr_params[120]: begin
<3>[ 133.896481] _tegra_set_vpr_params[123]: end
<3>[ 133.908944] vpr-heap: update vpr base to 0x00000000c6000000, size=c000000
<3>[ 133.916397] _tegra_set_vpr_params[120]: begin
<3>[ 133.956369] _tegra_set_vpr_params[123]: end
<3>[ 133.970394] vpr-heap: update vpr base to 0x00000000c6000000, size=a000000
<3>[ 133.977934] _tegra_set_vpr_params[120]: begin
<3>[ 134.013874] _tegra_set_vpr_params[123]: end
<3>[ 134.025666] vpr-heap: update vpr base to 0x00000000c6000000, size=8000000
<3>[ 134.033512] _tegra_set_vpr_params[120]: begin
<3>[ 134.065996] _tegra_set_vpr_params[123]: end
<3>[ 134.075465] vpr-heap: update vpr base to 0x00000000c6000000, size=6000000
<3>[ 134.082923] _tegra_set_vpr_params[120]: begin
<3>[ 134.113119] _tegra_set_vpr_params[123]: end
<3>[ 134.123448] vpr-heap: update vpr base to 0x00000000c6000000, size=4000000
<3>[ 134.130790] _tegra_set_vpr_params[120]: begin
<3>[ 134.162523] _tegra_set_vpr_params[123]: end
<3>[ 134.172413] vpr-heap: update vpr base to 0x00000000c6000000, size=2000000
<3>[ 134.179772] _tegra_set_vpr_params[120]: begin
<3>[ 134.209142] _tegra_set_vpr_params[123]: end
2) with MT_NON_CACHEABLE: 10ms ~ 18ms
<3>[ 102.108702] vpr-heap: update vpr base to 0x00000000c6000000, size=e000000
<3>[ 102.116296] _tegra_set_vpr_params[120]: begin
<3>[ 102.134272] _tegra_set_vpr_params[123]: end
<3>[ 102.145839] vpr-heap: update vpr base to 0x00000000c6000000, size=c000000
<3>[ 102.153226] _tegra_set_vpr_params[120]: begin
<3>[ 102.164201] _tegra_set_vpr_params[123]: end
<3>[ 102.172275] vpr-heap: update vpr base to 0x00000000c6000000, size=a000000
<3>[ 102.179638] _tegra_set_vpr_params[120]: begin
<3>[ 102.190342] _tegra_set_vpr_params[123]: end
<3>[ 102.197524] vpr-heap: update vpr base to 0x00000000c6000000, size=8000000
<3>[ 102.205085] _tegra_set_vpr_params[120]: begin
<3>[ 102.216112] _tegra_set_vpr_params[123]: end
<3>[ 102.224080] vpr-heap: update vpr base to 0x00000000c6000000, size=6000000
<3>[ 102.231387] _tegra_set_vpr_params[120]: begin
<3>[ 102.241775] _tegra_set_vpr_params[123]: end
<3>[ 102.248825] vpr-heap: update vpr base to 0x00000000c6000000, size=4000000
<3>[ 102.256069] _tegra_set_vpr_params[120]: begin
<3>[ 102.266368] _tegra_set_vpr_params[123]: end
<3>[ 102.273400] vpr-heap: update vpr base to 0x00000000c6000000, size=2000000
<3>[ 102.280672] _tegra_set_vpr_params[120]: begin
<3>[ 102.290929] _tegra_set_vpr_params[123]: end
Change-Id: I5f604064ce7b8b73ea9ad5860156ae5e2c6cc42a
Signed-off-by: Ken Chang <kenc@nvidia.com>
2018-12-28 00:44:12 +00:00
|
|
|
MT_NS | MT_RW | MT_EXECUTE_NEVER |
|
|
|
|
MT_NON_CACHEABLE); /* attrs */
|
2017-08-03 19:40:34 +01:00
|
|
|
assert(ret == 0);
|
2017-04-10 23:30:17 +01:00
|
|
|
|
2016-12-02 13:51:54 +00:00
|
|
|
zeromem((void *)non_overlap_area_start, non_overlap_area_size);
|
2017-04-10 23:30:17 +01:00
|
|
|
flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
|
|
|
|
|
|
|
|
mmap_remove_dynamic_region(non_overlap_area_start,
|
|
|
|
non_overlap_area_size);
|
2015-09-10 14:12:36 +01:00
|
|
|
}
|
|
|
|
|
2015-06-10 09:34:32 +01:00
|
|
|
/*
|
|
|
|
* Program the Video Memory carveout region
|
|
|
|
*
|
|
|
|
* phys_base = physical base of aperture
|
|
|
|
* size_in_bytes = size of aperture in bytes
|
|
|
|
*/
|
|
|
|
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
|
|
|
|
{
|
|
|
|
uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
|
|
|
|
uintptr_t vmem_end_new = phys_base + size_in_bytes;
|
2015-09-10 14:12:36 +01:00
|
|
|
unsigned long long non_overlap_area_size;
|
2015-06-10 09:34:32 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup the Memory controller to restrict CPU accesses to the Video
|
|
|
|
* Memory region
|
|
|
|
*/
|
|
|
|
INFO("Configuring Video Memory Carveout\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Configure Memory Controller directly for the first time.
|
|
|
|
*/
|
|
|
|
if (video_mem_base == 0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the old regions now being exposed. The following cases
|
|
|
|
* can occur -
|
|
|
|
*
|
|
|
|
* 1. clear whole old region (no overlap with new region)
|
|
|
|
* 2. clear old sub-region below new base
|
|
|
|
* 3. clear old sub-region above new end
|
|
|
|
*/
|
|
|
|
INFO("Cleaning previous Video Memory Carveout\n");
|
|
|
|
|
2015-08-26 10:36:14 +01:00
|
|
|
if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
|
2015-09-10 14:12:36 +01:00
|
|
|
tegra_clear_videomem(video_mem_base, video_mem_size << 20);
|
2015-08-26 10:36:14 +01:00
|
|
|
} else {
|
|
|
|
if (video_mem_base < phys_base) {
|
2015-09-10 14:12:36 +01:00
|
|
|
non_overlap_area_size = phys_base - video_mem_base;
|
|
|
|
tegra_clear_videomem(video_mem_base, non_overlap_area_size);
|
2015-08-26 10:36:14 +01:00
|
|
|
}
|
|
|
|
if (vmem_end_old > vmem_end_new) {
|
2015-09-10 14:12:36 +01:00
|
|
|
non_overlap_area_size = vmem_end_old - vmem_end_new;
|
|
|
|
tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
|
2015-08-26 10:36:14 +01:00
|
|
|
}
|
|
|
|
}
|
2015-06-10 09:34:32 +01:00
|
|
|
|
|
|
|
done:
|
2016-12-13 00:14:57 +00:00
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32));
|
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
|
2015-06-10 09:34:32 +01:00
|
|
|
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
|
|
|
|
|
|
|
|
/* store new values */
|
|
|
|
video_mem_base = phys_base;
|
|
|
|
video_mem_size = size_in_bytes >> 20;
|
|
|
|
}
|
2017-03-29 22:57:29 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* During boot, USB3 and flash media (SDMMC/SATA) devices need access to
|
|
|
|
* IRAM. Because these clients connect to the MC and do not have a direct
|
|
|
|
* path to the IRAM, the MC implements AHB redirection during boot to allow
|
|
|
|
* path to IRAM. In this mode, accesses to a programmed memory address aperture
|
|
|
|
* are directed to the AHB bus, allowing access to the IRAM. The AHB aperture
|
|
|
|
* is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are
|
|
|
|
* initialized to disable this aperture.
|
|
|
|
*
|
|
|
|
* Once bootup is complete, we must program IRAM base to 0xffffffff and
|
|
|
|
* IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then
|
|
|
|
* potentially accessible in this address range. These aperture registers
|
|
|
|
* also have an access_control/lock bit. After disabling the aperture, the
|
|
|
|
* access_control register should be programmed to lock the registers.
|
|
|
|
*/
|
|
|
|
void tegra_memctrl_disable_ahb_redirection(void)
|
|
|
|
{
|
|
|
|
/* program the aperture registers */
|
|
|
|
tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF);
|
|
|
|
tegra_mc_write_32(MC_IRAM_TOP_LO, 0);
|
|
|
|
tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0);
|
|
|
|
|
|
|
|
/* lock the aperture registers */
|
|
|
|
tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES);
|
|
|
|
}
|
2017-08-21 08:01:53 +01:00
|
|
|
|
|
|
|
void tegra_memctrl_clear_pending_interrupts(void)
|
|
|
|
{
|
|
|
|
uint32_t mcerr;
|
|
|
|
|
|
|
|
/* check if there are any pending interrupts */
|
|
|
|
mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS);
|
|
|
|
|
|
|
|
if (mcerr != (uint32_t)0U) { /* should not see error here */
|
|
|
|
WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr);
|
|
|
|
mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS), mcerr);
|
|
|
|
}
|
|
|
|
}
|