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