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