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