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