xref: /rk3399_ARM-atf/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c (revision 01096cac3a052487f5efc1a68b2a4b989e4d9797)
1e2469d82SVarun Wadekar /*
2e2469d82SVarun Wadekar  * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
3*66e0b947SVarun Wadekar  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4e2469d82SVarun Wadekar  *
5e2469d82SVarun Wadekar  * SPDX-License-Identifier: BSD-3-Clause
6e2469d82SVarun Wadekar  */
7e2469d82SVarun Wadekar 
8e2469d82SVarun Wadekar #include <assert.h>
9e2469d82SVarun Wadekar #include <string.h>
10e2469d82SVarun Wadekar 
11e2469d82SVarun Wadekar #include <arch_helpers.h>
12e2469d82SVarun Wadekar #include <common/debug.h>
13e2469d82SVarun Wadekar #include <lib/mmio.h>
14e2469d82SVarun Wadekar #include <lib/utils.h>
15e2469d82SVarun Wadekar #include <lib/xlat_tables/xlat_tables_v2.h>
16e2469d82SVarun Wadekar 
17e2469d82SVarun Wadekar #include <memctrl.h>
18e2469d82SVarun Wadekar #include <memctrl_v1.h>
19e2469d82SVarun Wadekar #include <tegra_def.h>
20e2469d82SVarun Wadekar 
21e2469d82SVarun Wadekar /* Video Memory base and size (live values) */
22e2469d82SVarun Wadekar static uint64_t video_mem_base;
23e2469d82SVarun Wadekar static uint64_t video_mem_size;
24e2469d82SVarun Wadekar 
25e2469d82SVarun Wadekar /*
26e2469d82SVarun Wadekar  * Init SMMU.
27e2469d82SVarun Wadekar  */
tegra_memctrl_setup(void)28e2469d82SVarun Wadekar void tegra_memctrl_setup(void)
29e2469d82SVarun Wadekar {
30e2469d82SVarun Wadekar 	/*
31e2469d82SVarun Wadekar 	 * Setup the Memory controller to allow only secure accesses to
32e2469d82SVarun Wadekar 	 * the TZDRAM carveout
33e2469d82SVarun Wadekar 	 */
34e2469d82SVarun Wadekar 	INFO("Tegra Memory Controller (v1)\n");
35e2469d82SVarun Wadekar 
36e2469d82SVarun Wadekar 	/* allow translations for all MC engines */
37e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0,
38e2469d82SVarun Wadekar 			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
39e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0,
40e2469d82SVarun Wadekar 			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
41e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0,
42e2469d82SVarun Wadekar 			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
43e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0,
44e2469d82SVarun Wadekar 			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
45e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0,
46e2469d82SVarun Wadekar 			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
47e2469d82SVarun Wadekar 
48e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY);
49e2469d82SVarun Wadekar 
50e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL);
51e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL);
52e2469d82SVarun Wadekar 
53e2469d82SVarun Wadekar 	/* flush PTC and TLB */
54e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL);
55e2469d82SVarun Wadekar 	(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
56e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL);
57e2469d82SVarun Wadekar 
58e2469d82SVarun Wadekar 	/* enable SMMU */
59e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SMMU_CONFIG_0,
60e2469d82SVarun Wadekar 			  MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
61e2469d82SVarun Wadekar 	(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
62e2469d82SVarun Wadekar 
63e2469d82SVarun Wadekar 	/* video memory carveout */
64e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
65e2469d82SVarun Wadekar 			  (uint32_t)(video_mem_base >> 32));
66e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base);
67e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
68e2469d82SVarun Wadekar }
69e2469d82SVarun Wadekar 
70e2469d82SVarun Wadekar /*
71e2469d82SVarun Wadekar  * Restore Memory Controller settings after "System Suspend"
72e2469d82SVarun Wadekar  */
tegra_memctrl_restore_settings(void)73e2469d82SVarun Wadekar void tegra_memctrl_restore_settings(void)
74e2469d82SVarun Wadekar {
75e2469d82SVarun Wadekar 	tegra_memctrl_setup();
76e2469d82SVarun Wadekar }
77e2469d82SVarun Wadekar 
78e2469d82SVarun Wadekar /*
79e2469d82SVarun Wadekar  * Secure the BL31 DRAM aperture.
80e2469d82SVarun Wadekar  *
81e2469d82SVarun Wadekar  * phys_base = physical base of TZDRAM aperture
82e2469d82SVarun Wadekar  * size_in_bytes = size of aperture in bytes
83e2469d82SVarun Wadekar  */
tegra_memctrl_tzdram_setup(uint64_t phys_base,uint32_t size_in_bytes)84e2469d82SVarun Wadekar void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
85e2469d82SVarun Wadekar {
86e2469d82SVarun Wadekar 	/*
87e2469d82SVarun Wadekar 	 * Setup the Memory controller to allow only secure accesses to
88e2469d82SVarun Wadekar 	 * the TZDRAM carveout
89e2469d82SVarun Wadekar 	 */
90e2469d82SVarun Wadekar 	INFO("Configuring TrustZone DRAM Memory Carveout\n");
91e2469d82SVarun Wadekar 
92e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
93e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
94e2469d82SVarun Wadekar }
95e2469d82SVarun Wadekar 
tegra_clear_videomem(uintptr_t non_overlap_area_start,unsigned long long non_overlap_area_size)96e2469d82SVarun Wadekar static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
97e2469d82SVarun Wadekar 				 unsigned long long non_overlap_area_size)
98e2469d82SVarun Wadekar {
99e2469d82SVarun Wadekar 	int ret;
100e2469d82SVarun Wadekar 
101e2469d82SVarun Wadekar 	/*
102e2469d82SVarun Wadekar 	 * Map the NS memory first, clean it and then unmap it.
103e2469d82SVarun Wadekar 	 */
104e2469d82SVarun Wadekar 	ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
105e2469d82SVarun Wadekar 				non_overlap_area_start, /* VA */
106e2469d82SVarun Wadekar 				non_overlap_area_size, /* size */
107e2469d82SVarun Wadekar 				MT_NS | MT_RW | MT_EXECUTE_NEVER |
108e2469d82SVarun Wadekar 				MT_NON_CACHEABLE); /* attrs */
109e2469d82SVarun Wadekar 	assert(ret == 0);
110e2469d82SVarun Wadekar 
111e2469d82SVarun Wadekar 	zeromem((void *)non_overlap_area_start, non_overlap_area_size);
112e2469d82SVarun Wadekar 	flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
113e2469d82SVarun Wadekar 
114e2469d82SVarun Wadekar 	mmap_remove_dynamic_region(non_overlap_area_start,
115e2469d82SVarun Wadekar 		non_overlap_area_size);
116e2469d82SVarun Wadekar }
117e2469d82SVarun Wadekar 
118e2469d82SVarun Wadekar /*
119e2469d82SVarun Wadekar  * Program the Video Memory carveout region
120e2469d82SVarun Wadekar  *
121e2469d82SVarun Wadekar  * phys_base = physical base of aperture
122e2469d82SVarun Wadekar  * size_in_bytes = size of aperture in bytes
123e2469d82SVarun Wadekar  */
tegra_memctrl_videomem_setup(uint64_t phys_base,uint32_t size_in_bytes)124e2469d82SVarun Wadekar void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
125e2469d82SVarun Wadekar {
126e2469d82SVarun Wadekar 	uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
127e2469d82SVarun Wadekar 	uintptr_t vmem_end_new = phys_base + size_in_bytes;
128e2469d82SVarun Wadekar 	unsigned long long non_overlap_area_size;
129e2469d82SVarun Wadekar 
130e2469d82SVarun Wadekar 	/*
131e2469d82SVarun Wadekar 	 * Setup the Memory controller to restrict CPU accesses to the Video
132e2469d82SVarun Wadekar 	 * Memory region
133e2469d82SVarun Wadekar 	 */
134e2469d82SVarun Wadekar 	INFO("Configuring Video Memory Carveout\n");
135e2469d82SVarun Wadekar 
136e2469d82SVarun Wadekar 	/*
137e2469d82SVarun Wadekar 	 * Configure Memory Controller directly for the first time.
138e2469d82SVarun Wadekar 	 */
139e2469d82SVarun Wadekar 	if (video_mem_base == 0)
140e2469d82SVarun Wadekar 		goto done;
141e2469d82SVarun Wadekar 
142e2469d82SVarun Wadekar 	/*
143e2469d82SVarun Wadekar 	 * Clear the old regions now being exposed. The following cases
144e2469d82SVarun Wadekar 	 * can occur -
145e2469d82SVarun Wadekar 	 *
146e2469d82SVarun Wadekar 	 * 1. clear whole old region (no overlap with new region)
147e2469d82SVarun Wadekar 	 * 2. clear old sub-region below new base
148e2469d82SVarun Wadekar 	 * 3. clear old sub-region above new end
149e2469d82SVarun Wadekar 	 */
150e2469d82SVarun Wadekar 	INFO("Cleaning previous Video Memory Carveout\n");
151e2469d82SVarun Wadekar 
152e2469d82SVarun Wadekar 	if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
153e2469d82SVarun Wadekar 		tegra_clear_videomem(video_mem_base, video_mem_size << 20);
154e2469d82SVarun Wadekar 	} else {
155e2469d82SVarun Wadekar 		if (video_mem_base < phys_base) {
156e2469d82SVarun Wadekar 			non_overlap_area_size = phys_base - video_mem_base;
157e2469d82SVarun Wadekar 			tegra_clear_videomem(video_mem_base, non_overlap_area_size);
158e2469d82SVarun Wadekar 		}
159e2469d82SVarun Wadekar 		if (vmem_end_old > vmem_end_new) {
160e2469d82SVarun Wadekar 			non_overlap_area_size = vmem_end_old - vmem_end_new;
161e2469d82SVarun Wadekar 			tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
162e2469d82SVarun Wadekar 		}
163e2469d82SVarun Wadekar 	}
164e2469d82SVarun Wadekar 
165e2469d82SVarun Wadekar done:
166e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32));
167e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
168e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
169e2469d82SVarun Wadekar 
170e2469d82SVarun Wadekar 	/* store new values */
171e2469d82SVarun Wadekar 	video_mem_base = phys_base;
172e2469d82SVarun Wadekar 	video_mem_size = size_in_bytes >> 20;
173e2469d82SVarun Wadekar }
174e2469d82SVarun Wadekar 
175e2469d82SVarun Wadekar /*
176e2469d82SVarun Wadekar  * During boot, USB3 and flash media (SDMMC/SATA) devices need access to
177e2469d82SVarun Wadekar  * IRAM. Because these clients connect to the MC and do not have a direct
178e2469d82SVarun Wadekar  * path to the IRAM, the MC implements AHB redirection during boot to allow
179e2469d82SVarun Wadekar  * path to IRAM. In this mode, accesses to a programmed memory address aperture
180e2469d82SVarun Wadekar  * are directed to the AHB bus, allowing access to the IRAM. The AHB aperture
181e2469d82SVarun Wadekar  * is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are
182e2469d82SVarun Wadekar  * initialized to disable this aperture.
183e2469d82SVarun Wadekar  *
184e2469d82SVarun Wadekar  * Once bootup is complete, we must program IRAM base to 0xffffffff and
185e2469d82SVarun Wadekar  * IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then
186e2469d82SVarun Wadekar  * potentially accessible in this address range. These aperture registers
187e2469d82SVarun Wadekar  * also have an access_control/lock bit. After disabling the aperture, the
188e2469d82SVarun Wadekar  * access_control register should be programmed to lock the registers.
189e2469d82SVarun Wadekar  */
tegra_memctrl_disable_ahb_redirection(void)190e2469d82SVarun Wadekar void tegra_memctrl_disable_ahb_redirection(void)
191e2469d82SVarun Wadekar {
192e2469d82SVarun Wadekar 	/* program the aperture registers */
193e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF);
194e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_IRAM_TOP_LO, 0);
195e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0);
196e2469d82SVarun Wadekar 
197e2469d82SVarun Wadekar 	/* lock the aperture registers */
198e2469d82SVarun Wadekar 	tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES);
199e2469d82SVarun Wadekar }
200e2469d82SVarun Wadekar 
tegra_memctrl_clear_pending_interrupts(void)201e2469d82SVarun Wadekar void tegra_memctrl_clear_pending_interrupts(void)
202e2469d82SVarun Wadekar {
203e2469d82SVarun Wadekar 	uint32_t mcerr;
204e2469d82SVarun Wadekar 
205e2469d82SVarun Wadekar 	/* check if there are any pending interrupts */
206e2469d82SVarun Wadekar 	mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS);
207e2469d82SVarun Wadekar 
208e2469d82SVarun Wadekar 	if (mcerr != (uint32_t)0U) { /* should not see error here */
209e2469d82SVarun Wadekar 		WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr);
210e2469d82SVarun Wadekar 		mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS),  mcerr);
211e2469d82SVarun Wadekar 	}
212e2469d82SVarun Wadekar }
213