xref: /aosp_15_r20/external/coreboot/src/soc/nvidia/tegra210/addressmap.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <device/mmio.h>
5 #include <commonlib/helpers.h>
6 #include <console/console.h>
7 #include <soc/addressmap.h>
8 #include <soc/id.h>
9 #include <soc/mc.h>
10 #include <soc/sdram.h>
11 #include <symbols.h>
12 #include <soc/nvidia/tegra/types.h>
13 #include <types.h>
14 
15 static uintptr_t tz_base_mib;
16 static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB;
17 
18 /* returns total amount of DRAM (in MB) from memory controller registers */
sdram_size_mb(void)19 int sdram_size_mb(void)
20 {
21 	struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
22 	static int total_size = 0;
23 
24 	if (total_size)
25 		return total_size;
26 
27 	/*
28 	 * This obtains memory size from the External Memory Aperture
29 	 * Configuration register. Nvidia confirmed that it is safe to assume
30 	 * this value represents the total physical DRAM size.
31 	 */
32 	total_size = (read32(&mc->emem_cfg) >>
33 			MC_EMEM_CFG_SIZE_MB_SHIFT) & MC_EMEM_CFG_SIZE_MB_MASK;
34 
35 	return total_size;
36 }
37 
carveout_from_regs(uintptr_t * base_mib,size_t * size_mib,uint32_t bom,uint32_t bom_hi,uint32_t size)38 static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib,
39 				uint32_t bom, uint32_t bom_hi, uint32_t size)
40 {
41 	/* All size regs of carveouts are in MiB. */
42 	if (size == 0)
43 		return;
44 
45 	*size_mib = size;
46 	bom >>= 20;
47 	bom |= bom_hi << (32 - 20);
48 
49 	*base_mib = bom;
50 }
51 
carveout_range(int id,uintptr_t * base_mib,size_t * size_mib)52 void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib)
53 {
54 	*base_mib = 0;
55 	*size_mib = 0;
56 	struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
57 	size_t region_size_mb;
58 
59 	switch (id) {
60 	case CARVEOUT_TZ:
61 		*base_mib = tz_base_mib;
62 		*size_mib = tz_size_mib;
63 		break;
64 	case CARVEOUT_SEC:
65 		carveout_from_regs(base_mib, size_mib,
66 					read32(&mc->sec_carveout_bom),
67 					read32(&mc->sec_carveout_adr_hi),
68 					read32(&mc->sec_carveout_size_mb));
69 		break;
70 	case CARVEOUT_MTS:
71 		carveout_from_regs(base_mib, size_mib,
72 					read32(&mc->mts_carveout_bom),
73 					read32(&mc->mts_carveout_adr_hi),
74 					read32(&mc->mts_carveout_size_mb));
75 		break;
76 	case CARVEOUT_VPR:
77 		/*
78 		 * A 128MB VPR carveout is felt to be sufficient as per syseng.
79 		 * Set it up in vpr_region_init, below.
80 		 */
81 		carveout_from_regs(base_mib, size_mib,
82 					read32(&mc->video_protect_bom),
83 					read32(&mc->video_protect_bom_adr_hi),
84 					read32(&mc->video_protect_size_mb));
85 		break;
86 	case CARVEOUT_GPU:
87 		/* These carveout regs use 128KB granularity - convert to MB */
88 		region_size_mb = DIV_ROUND_UP(read32(&mc->security_carveout2_size_128kb), 8);
89 
90 		/* BOM address set in gpu_region_init, below */
91 		carveout_from_regs(base_mib, size_mib,
92 					read32(&mc->security_carveout2_bom),
93 					read32(&mc->security_carveout2_bom_hi),
94 					region_size_mb);
95 		break;
96 	case CARVEOUT_NVDEC:
97 		/* These carveout regs use 128KB granularity - convert to MB */
98 		region_size_mb = DIV_ROUND_UP(read32(&mc->security_carveout1_size_128kb), 8);
99 
100 		/* BOM address set in nvdec_region_init, below */
101 		carveout_from_regs(base_mib, size_mib,
102 					read32(&mc->security_carveout1_bom),
103 					read32(&mc->security_carveout1_bom_hi),
104 					region_size_mb);
105 		break;
106 	case CARVEOUT_TSEC:
107 		/* These carveout regs use 128KB granularity - convert to MB */
108 		region_size_mb = DIV_ROUND_UP(read32(&mc->security_carveout4_size_128kb), 8);
109 
110 		/* BOM address set in tsec_region_init, below.
111 		 * Since the TSEC region consumes 2 carveouts, and is
112 		 * expected to be split evenly between the two, size_mib
113 		 * is doubled here.
114 		 */
115 		region_size_mb *= 2;
116 		carveout_from_regs(base_mib, size_mib,
117 					read32(&mc->security_carveout4_bom),
118 					read32(&mc->security_carveout4_bom_hi),
119 					region_size_mb);
120 		break;
121 	default:
122 		break;
123 	}
124 }
125 
print_carveouts(void)126 void print_carveouts(void)
127 {
128 	int i;
129 	printk(BIOS_INFO, "Carveout ranges:\n");
130 	for (i = 0; i < CARVEOUT_NUM; i++) {
131 		uintptr_t base, end;
132 		size_t size;
133 		carveout_range(i, &base, &size);
134 		end = base + size;
135 		if (end && base)
136 			printk(BIOS_INFO, "ID:%d [%lx - %lx)\n", i,
137 			       (unsigned long)base * MiB,
138 			       (unsigned long)end * MiB);
139 	}
140 }
141 
142 /*
143  *    Memory Map is as follows
144  *
145  * ------------------------------   <-- Start of DRAM
146  * |                            |
147  * |      Available DRAM        |
148  * |____________________________|
149  * |                            |
150  * |          CBMEM             |
151  * |____________________________|
152  * |                            |
153  * |      Other carveouts       |
154  * | (with dynamic allocation)  |
155  * |____________________________|
156  * |                            |
157  * |    TZ carveout of size     |
158  * | TRUSTZONE_CARVEOUT_SIZE_MB |
159  * |____________________________|   <-- 0x100000000
160  * |                            |
161  * |      Available DRAM        |
162  * |                            |
163  * ------------------------------   <-- End of DRAM
164  *
165  */
memory_in_range(uintptr_t * base_mib,uintptr_t * end_mib,int ignore_carveout_id)166 static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
167 				int ignore_carveout_id)
168 {
169 	uintptr_t base;
170 	uintptr_t end;
171 	int i;
172 
173 	base = (uintptr_t)_dram / MiB;
174 	end = base + sdram_size_mb();
175 
176 	/* Requested limits out of range. */
177 	if (*end_mib <= base || *base_mib >= end) {
178 		*end_mib = *base_mib = 0;
179 		return;
180 	}
181 
182 	/* Clip region to passed in limits. */
183 	if (*end_mib < end)
184 		end = *end_mib;
185 	if (*base_mib > base)
186 		base = *base_mib;
187 
188 	for (i = 0; i < CARVEOUT_NUM; i++) {
189 		uintptr_t carveout_base;
190 		uintptr_t carveout_end;
191 		size_t carveout_size;
192 
193 		if (i == ignore_carveout_id)
194 			continue;
195 
196 		carveout_range(i, &carveout_base, &carveout_size);
197 		if (carveout_size == 0)
198 			continue;
199 
200 		carveout_end = carveout_base + carveout_size;
201 
202 		/* Bypass carveouts out of requested range. */
203 		if (carveout_base >= end || carveout_end <= base)
204 			continue;
205 
206 		/*
207 		 * This is crude, but the assumption is that carveouts live
208 		 * at the upper range of physical memory. Therefore, update
209 		 * the end address to be equal to the base of the carveout.
210 		 */
211 		end = carveout_base;
212 	}
213 
214 	*base_mib = base;
215 	*end_mib = end;
216 }
217 
memory_in_range_below_4gb(uintptr_t * base_mib,uintptr_t * end_mib)218 void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
219 {
220 	*base_mib = 0;
221 	*end_mib = 4096;
222 	memory_in_range(base_mib, end_mib, CARVEOUT_NUM);
223 }
224 
memory_in_range_above_4gb(uintptr_t * base_mib,uintptr_t * end_mib)225 void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
226 {
227 	*base_mib = 4096;
228 	*end_mib = ~0UL;
229 	memory_in_range(base_mib, end_mib, CARVEOUT_NUM);
230 }
231 
trustzone_region_init(void)232 void trustzone_region_init(void)
233 {
234 	struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
235 	uintptr_t end = 4096;
236 
237 	/* Already has been initialized. */
238 	if (tz_size_mib != 0 && tz_base_mib != 0)
239 		return;
240 
241 	/*
242 	 * Get memory layout below 4GiB ignoring the TZ carveout because
243 	 * that's the one to initialize.
244 	 */
245 	tz_base_mib = end - tz_size_mib;
246 	memory_in_range(&tz_base_mib, &end, CARVEOUT_TZ);
247 
248 	/*
249 	 * IMPORTANT!!!!!
250 	 * We need to ensure that trustzone region is located at the end of
251 	 * 32-bit address space. If any carveout is allocated space before
252 	 * trustzone_region_init is called, then this assert will ensure that
253 	 * the boot flow fails. If you are here because of this assert, please
254 	 * move your call to initialize carveout after trustzone_region_init in
255 	 * romstage and ramstage.
256 	 */
257 	assert(end == 4096);
258 
259 	/* AVP cannot set the TZ registers proper as it is always non-secure. */
260 	if (context_avp())
261 		return;
262 
263 	/* Set the carveout region. */
264 	write32(&mc->security_cfg0, tz_base_mib << 20);
265 	write32(&mc->security_cfg1, tz_size_mib);
266 
267 	/* Enable SMMU translations */
268 	write32(&mc->smmu_config, MC_SMMU_CONFIG_ENABLE);
269 }
270 
gpu_region_init(void)271 void gpu_region_init(void)
272 {
273 	struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
274 	uintptr_t gpu_base_mib = 0, end = 4096;
275 	size_t gpu_size_mib = GPU_CARVEOUT_SIZE_MB;
276 
277 	/* Get memory layout below 4GiB */
278 	memory_in_range(&gpu_base_mib, &end, CARVEOUT_GPU);
279 	gpu_base_mib = end - gpu_size_mib;
280 
281 	/* Set the carveout2 base address. Everything else has been set in the BCT cfg/inc */
282 	write32(&mc->security_carveout2_bom, gpu_base_mib << 20);
283 	write32(&mc->security_carveout2_bom_hi, 0);
284 
285 	/* Set the locked bit. This will lock out any other writes! */
286 	setbits32(&mc->security_carveout2_cfg0, MC_SECURITY_CARVEOUT_LOCKED);
287 
288 	/* Set the carveout3 base to 0, unused */
289 	write32(&mc->security_carveout3_bom, 0);
290 	write32(&mc->security_carveout3_bom_hi, 0);
291 
292 	/* Set the locked bit. This will lock out any other writes! */
293 	setbits32(&mc->security_carveout3_cfg0, MC_SECURITY_CARVEOUT_LOCKED);
294 }
295 
nvdec_region_init(void)296 void nvdec_region_init(void)
297 {
298 	struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
299 	uintptr_t nvdec_base_mib = 0, end = 4096;
300 	size_t nvdec_size_mib = NVDEC_CARVEOUT_SIZE_MB;
301 
302 	/* Get memory layout below 4GiB */
303 	memory_in_range(&nvdec_base_mib, &end, CARVEOUT_NVDEC);
304 	nvdec_base_mib = end - nvdec_size_mib;
305 
306 	/* Set the carveout1 base address. Everything else has been set in the BCT cfg/inc */
307 	write32(&mc->security_carveout1_bom, nvdec_base_mib << 20);
308 	write32(&mc->security_carveout1_bom_hi, 0);
309 
310 	/* Set the locked bit. This will lock out any other writes! */
311 	setbits32(&mc->security_carveout1_cfg0, MC_SECURITY_CARVEOUT_LOCKED);
312 }
313 
tsec_region_init(void)314 void tsec_region_init(void)
315 {
316 	struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
317 	uintptr_t tsec_base_mib = 0, end = 4096;
318 	size_t tsec_size_mib = TSEC_CARVEOUT_SIZE_MB;
319 
320 	/* Get memory layout below 4GiB */
321 	memory_in_range(&tsec_base_mib, &end, CARVEOUT_TSEC);
322 	tsec_base_mib = end - tsec_size_mib;
323 
324 	/*
325 	 * Set the carveout4/5 base address. Everything else has been set in the BCT cfg/inc
326 	 * Note that the TSEC range is split evenly between the 2 carveouts (i.e. 1MB each)
327 	 */
328 	write32(&mc->security_carveout4_bom, tsec_base_mib << 20);
329 	write32(&mc->security_carveout4_bom_hi, 0);
330 	write32(&mc->security_carveout5_bom, (tsec_base_mib + (TSEC_CARVEOUT_SIZE_MB / 2)) << 20);
331 	write32(&mc->security_carveout5_bom_hi, 0);
332 
333 	/* Set the locked bit. This will lock out any other writes! */
334 	setbits32(&mc->security_carveout4_cfg0, MC_SECURITY_CARVEOUT_LOCKED);
335 	setbits32(&mc->security_carveout5_cfg0, MC_SECURITY_CARVEOUT_LOCKED);
336 }
337 
vpr_region_init(void)338 void vpr_region_init(void)
339 {
340 	struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
341 	uintptr_t vpr_base_mib = 0, end = 4096;
342 	size_t vpr_size_mib = VPR_CARVEOUT_SIZE_MB;
343 
344 	/* Get memory layout below 4GiB */
345 	memory_in_range(&vpr_base_mib, &end, CARVEOUT_VPR);
346 	vpr_base_mib = end - vpr_size_mib;
347 
348 	/* Set the carveout base address and size */
349 	write32(&mc->video_protect_bom, vpr_base_mib << 20);
350 	write32(&mc->video_protect_bom_adr_hi, 0);
351 	write32(&mc->video_protect_size_mb, vpr_size_mib);
352 
353 	/* Set the locked bit. This will lock out any other writes! */
354 	write32(&mc->video_protect_reg_ctrl, MC_VPR_WR_ACCESS_DISABLE);
355 }
356