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