diff options
author | danh-arm <dan.handley@arm.com> | 2015-06-18 14:58:33 +0100 |
---|---|---|
committer | danh-arm <dan.handley@arm.com> | 2015-06-18 14:58:33 +0100 |
commit | 09aa0392b3a632ccf0dcbaaa5918a8aea4288551 (patch) | |
tree | c7ae5f4e62b72c3ef0bccfd9d5f658c1f471fd4e /plat/nvidia/tegra/common/drivers/memctrl/memctrl.c | |
parent | 79b1ebdaae021c0a9c4880849d181a5b91ecac8a (diff) | |
parent | 9a9645105b7aece52f4fdefc7fdeec7d73ceaed5 (diff) |
Merge pull request #319 from vwadekar/tegra-video-mem-aperture-v3
Reserve a Video Memory aperture in DRAM memory
Diffstat (limited to 'plat/nvidia/tegra/common/drivers/memctrl/memctrl.c')
-rw-r--r-- | plat/nvidia/tegra/common/drivers/memctrl/memctrl.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c index 9a8ba66f..fff89519 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c @@ -28,11 +28,23 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <arch_helpers.h> #include <assert.h> #include <debug.h> #include <mmio.h> #include <memctrl.h> +#include <string.h> #include <tegra_def.h> +#include <xlat_tables.h> + +extern void zeromem16(void *mem, unsigned int length); + +#define TEGRA_GPU_RESET_REG_OFFSET 0x28c +#define GPU_RESET_BIT (1 << 24) + +/* Video Memory base and size (live values) */ +static uintptr_t video_mem_base; +static uint64_t video_mem_size; /* * Init SMMU. @@ -71,6 +83,10 @@ void tegra_memctrl_setup(void) 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 */ + + /* video memory carveout */ + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, video_mem_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size); } /* @@ -90,3 +106,66 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base); tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20); } + +/* + * 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; + uint32_t regval; + + /* + * The GPU is the user of the Video Memory region. In order to + * transition to the new memory region smoothly, we program the + * new base/size ONLY if the GPU is in reset mode. + */ + regval = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); + if ((regval & GPU_RESET_BIT) == 0) { + ERROR("GPU not in reset! Video Memory setup failed\n"); + return; + } + + /* + * 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"); + + disable_mmu_el3(); + if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) + zeromem16((void *)video_mem_base, video_mem_size << 20); + else if (video_mem_base < phys_base) + zeromem16((void *)video_mem_base, phys_base - video_mem_base); + else if (vmem_end_old > vmem_end_new) + zeromem16((void *)vmem_end_new, vmem_end_old - vmem_end_new); + enable_mmu_el3(0); + +done: + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, phys_base); + 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; +} |