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