summaryrefslogtreecommitdiff
path: root/plat/nvidia/tegra/common/drivers/memctrl/memctrl.c
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2015-06-18 14:58:33 +0100
committerdanh-arm <dan.handley@arm.com>2015-06-18 14:58:33 +0100
commit09aa0392b3a632ccf0dcbaaa5918a8aea4288551 (patch)
treec7ae5f4e62b72c3ef0bccfd9d5f658c1f471fd4e /plat/nvidia/tegra/common/drivers/memctrl/memctrl.c
parent79b1ebdaae021c0a9c4880849d181a5b91ecac8a (diff)
parent9a9645105b7aece52f4fdefc7fdeec7d73ceaed5 (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.c79
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;
+}