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