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