Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bootloader/l4t/l4t.c
3694 views
1
/*
2
* L4T Loader for Tegra X1
3
*
4
* Copyright (c) 2020-2026 CTCaer
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms and conditions of the GNU General Public License,
8
* version 2, as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <string.h>
20
21
#include <bdk.h>
22
23
#include "../hos/hos.h"
24
#include "../hos/pkg1.h"
25
#include "l4t.h"
26
#include "l4t_config.inl"
27
28
/*
29
* API Revision info
30
*
31
* 0: Base.
32
* 1: SDMMC1 LA programming for SDMMC1 UHS DDR200.
33
* 2: Arachne Register Cell v1.
34
* 3: Arachne Register Cell v2. PTSA Rework support.
35
* 4: Arachne Register Cell v3. DRAM OPT and DDR200 changes.
36
* 5: Arachne Register Cell v4. DRAM FREQ and DDR200 changes.
37
* 6: Arachne Register Cell v5. Signal quality and performance changes. TZ param changes.
38
* 7: Arachne Register Cell v6. Decouple of rd/wr latencies.
39
*/
40
41
#define L4T_LOADER_API_REV 7
42
#define L4T_FIRMWARE_REV 0x37524556 // REV7.
43
44
#ifdef DEBUG_UART_PORT
45
#include <soc/uart.h>
46
#define UPRINTF(...) uart_printf(__VA_ARGS__)
47
#else
48
#define UPRINTF(...)
49
#endif
50
51
#if CARVEOUT_NVDEC_TSEC_ENABLE && CARVEOUT_SECFW_ENABLE
52
#error "NVDEC and SECFW carveouts can't be used together!"
53
#endif
54
55
#if CARVEOUT_NVDEC_TSEC_ENABLE
56
#define TZDRAM_SIZE_CFG SZ_8M
57
#else
58
#define TZDRAM_SIZE_CFG SZ_1M
59
#endif
60
61
// TZDRAM addresses and sizes.
62
#define TZDRAM_SIZE TZDRAM_SIZE_CFG // Secure Element.
63
#define TZDRAM_BASE (0xFFFFFFFF - TZDRAM_SIZE + 1) // 0xFFF00000 or 0xFF800000.
64
#define TZDRAM_COLD_ENTRY (TZDRAM_BASE)
65
#define TZDRAM_WARM_ENTRY (TZDRAM_BASE + 0x200)
66
#define TZ_PARAM_SIZE SZ_4K
67
#define TZ_PARAM_BASE (0xFFFFFFFF - TZ_PARAM_SIZE + 1) // 0xFFFFF000.
68
69
// Carveout sizes.
70
#define CARVEOUT_NVDEC_SIZE SZ_1M
71
#define CARVEOUT_TSEC_SIZE SZ_1M
72
#define CARVEOUT_SECFW_SIZE SZ_1M
73
#define CARVEOUT_GPUFW_SIZE SZ_256K
74
#if CARVEOUT_NVDEC_TSEC_ENABLE
75
#define CARVEOUT_GPUWPR_SIZE CARVEOUT_GPUWPR_SIZE_CFG
76
#else
77
#define CARVEOUT_GPUWPR_SIZE (SZ_512K + SZ_256K)
78
#endif
79
80
#define SC7ENTRY_HDR_SIZE 0x400
81
82
// Always start 1MB below TZDRAM for Secure Firmware or NVDEC.
83
#define GEN_CARVEOUT_TOP (TZDRAM_BASE - SZ_1M)
84
85
// NVDEC and SECFW bases.
86
#define NVDFW_BASE GEN_CARVEOUT_TOP // 0xFF700000.
87
#define SECFW_BASE GEN_CARVEOUT_TOP // 0xFFE00000.
88
89
// Secure Elements addresses for T210.
90
#define SC7ENTRY_HDR_BASE (SECFW_BASE + 0)
91
#define SC7ENTRY_BASE (SECFW_BASE + SC7ENTRY_HDR_SIZE) // After header.
92
#define SC7EXIT_BASE (SECFW_BASE + SZ_64K) // 64KB after SECFW_BASE.
93
#define R2P_PAYLOAD_BASE (SECFW_BASE + SZ_256K) // 256KB after SECFW_BASE.
94
#define MTCTABLE_BASE (SECFW_BASE + SZ_512K) // 512KB after SECFW_BASE.
95
#define BPMPFW_BASE (SECFW_BASE + SZ_512K + SZ_256K) // 768KB after SECFW_BASE.
96
#define BPMPFW_ENTRYPOINT (BPMPFW_BASE + 0x100) // Used internally also.
97
98
// Secure Elements addresses for T210B01.
99
#define BPMPFW_B01_BASE (SECFW_BASE) // !! DTS carveout-start must match !!
100
#define BPMPFW_B01_ENTRYPOINT (BPMPFW_B01_BASE + 0x40) // Used internally also.
101
#define BPMPFW_B01_HEAP_BASE (BPMPFW_B01_BASE + SZ_256K - SZ_1K) // 255KB after BPMPFW_B01_BASE.
102
#define BPMPFW_B01_EDTB_BASE (BPMPFW_B01_BASE + SZ_1M - 0) // Top BPMPFW carveout minus EMC DTB size.
103
#define BPMPFW_B01_ADTB_BASE (BPMPFW_B01_BASE + 0x26008) // Attached BPMP-FW DTB address.
104
#define SC7EXIT_B01_BASE (BPMPFW_B01_HEAP_BASE - SZ_4K) // 4KB before BPMP heap.
105
106
// BPMP-FW defines. Offsets are 0xD8 below real main binary.
107
#define BPMPFW_B01_DTB_ADDR (BPMPFW_B01_BASE + 0x14) // u32. DTB address if not attached.
108
#define BPMPFW_B01_CC_INIT_OP (BPMPFW_B01_BASE + 0x17324) // u8. Initial table training OP. 0: OP_SWITCH, 1: OP_TRAIN, 2: OP_TRAIN_SWITCH. Default: OP_TRAIN.
109
#define BPMPFW_B01_LOGLEVEL (BPMPFW_B01_BASE + 0x2547C) // u32. Log level. Default 3.
110
#define BPMPFW_B01_LOGLEVEL (BPMPFW_B01_BASE + 0x2547C) // u32. Log level. Default 3.
111
#define BPMPFW_B01_CC_PT_TIME (BPMPFW_B01_BASE + 0x25644) // u32. Periodic training period (in ms). Default 100 ms.
112
#define BPMPFW_B01_CC_DEBUG (BPMPFW_B01_BASE + 0x257F8) // u32. EMC Clock Change debug mask. Default: 0x50000101.
113
114
// BPMP-FW attached DTB defines. Can be generalized.
115
#define BPMPFW_B01_DTB_EMC_ENTRIES 4
116
#define BPMPFW_B01_DTB_SERIAL_PORT_VAL (BPMPFW_B01_ADTB_BASE + 0x5B) // u8. DTB UART port offset. 0: Disabled.
117
#define BPMPFW_B01_DTB_SET_SERIAL_PORT(port) (*(u8 *)BPMPFW_B01_DTB_SERIAL_PORT_VAL = port)
118
#define BPMPFW_B01_DTB_EMC_TBL_OFF (BPMPFW_B01_ADTB_BASE + 0xA0)
119
#define BPMPFW_B01_DTB_EMC_TBL_SZ 0x1120
120
#define BPMPFW_B01_DTB_EMC_NAME_VAL 0xA
121
#define BPMPFW_B01_DTB_EMC_ENABLE_OFF 0x20
122
#define BPMPFW_B01_DTB_EMC_VALUES_OFF 0x4C
123
#define BPMPFW_B01_DTB_EMC_FREQ_VAL 0x8C
124
#define BPMPFW_B01_DTB_EMC_OPT_VAL 0xEDC
125
#define BPMPFW_B01_DTB_EMC_TBL_START(idx) (BPMPFW_B01_DTB_EMC_TBL_OFF + BPMPFW_B01_DTB_EMC_TBL_SZ * (idx))
126
#define BPMPFW_B01_DTB_EMC_TBL_SET_VAL(idx, off, val) (*(u32 *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + (off)) = (val))
127
#define BPMPFW_B01_DTB_EMC_TBL_SET_FREQ(idx, freq) (*(u32 *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + BPMPFW_B01_DTB_EMC_FREQ_VAL) = (freq))
128
#define BPMPFW_B01_DTB_EMC_TBL_SET_OPTC(idx, opt) (*(u32 *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + BPMPFW_B01_DTB_EMC_OPT_VAL) = (opt))
129
#define BPMPFW_B01_DTB_EMC_TBL_SET_NAME(idx, name) (strcpy((char *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + BPMPFW_B01_DTB_EMC_NAME_VAL), (name)))
130
#define BPMPFW_B01_DTB_EMC_TBL_ENABLE(idx) (*(char *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + BPMPFW_B01_DTB_EMC_ENABLE_OFF) = 'n')
131
#define BPMPFW_B01_DTB_EMC_TBL_OFFSET(idx) ((void *)(BPMPFW_B01_DTB_EMC_TBL_START(idx) + BPMPFW_B01_DTB_EMC_VALUES_OFF))
132
133
// MTC table defines for T210B01.
134
#define BPMPFW_B01_MTC_TABLE_BASE 0xA0000000
135
#define BPMPFW_B01_MTC_FREQ_TABLE_SIZE 4300
136
#define BPMPFW_B01_MTC_TABLE_SIZE (BPMPFW_B01_MTC_FREQ_TABLE_SIZE * 3)
137
#define BPMPFW_B01_MTC_TABLE(idx) (BPMPFW_B01_MTC_TABLE_BASE + BPMPFW_B01_MTC_TABLE_SIZE * (idx))
138
#define BPMPFW_B01_MTC_TABLE_OFFSET(idx, fidx) ((void *)(BPMPFW_B01_MTC_TABLE(idx) + BPMPFW_B01_MTC_FREQ_TABLE_SIZE * (fidx)))
139
140
// BL31 Enable IRAM based config.
141
#define BL31_IRAM_PARAMS 0x4D415249 // "IRAM".
142
#define BL31_EXTRA_FEATURES_ENABLE 0x52545845 // "EXTR".
143
144
// BL31 Flags.
145
#define FLAGS_PMC_NON_SECURE BIT(0)
146
#define FLAGS_SC7_NO_BASE_RESTRICTION BIT(1)
147
148
// BL31 config.
149
#define PARAM_EP 1
150
#define PARAM_BL31 3
151
#define PARAM_EP_SECURE 0
152
#define PARAM_EP_NON_SECURE 1
153
#define VERSION_1 1
154
#define SPSR_EL2T BIT(3)
155
156
// BL33 config.
157
#define BL33_LOAD_BASE 0xAA000000 // DTB is loaded at 0xA8000000, so 32MB above.
158
#define BL33_ENV_BASE (BL33_LOAD_BASE - SZ_256K) // Before BL33_LOAD_BASE.
159
#define BL33_ENV_MAGIC_OFFSET (BL33_ENV_BASE - 4)
160
#define BL33_ENV_MAGIC 0x33334C42
161
#define BL33_DTB_OFFSET (BL33_LOAD_BASE + 0x10) // After code end.
162
#define BL33_DTB_BASE (BL33_LOAD_BASE + *(u32 *)BL33_DTB_OFFSET)
163
#define BL33_DTB_UART_STATUS 0x1C94
164
#define BL33_DTB_UART_STS_OF 0x12C
165
#define BL33_DTB_STDOUT_PATH 0x3F34
166
#define BL33_DTB_STDERR_PATH 0x3F54
167
#define BL33_DTB_SET_UART_STATUS(port) (strcpy((char *)(BL33_DTB_BASE + BL33_DTB_UART_STATUS + (port - 1) * BL33_DTB_UART_STS_OF), "okay"))
168
#define BL33_DTB_SET_STDOUT_PATH(path) (strcpy((char *)(BL33_DTB_BASE + BL33_DTB_STDOUT_PATH), (path)))
169
#define BL33_DTB_SET_STDERR_PATH(path) (strcpy((char *)(BL33_DTB_BASE + BL33_DTB_STDERR_PATH), (path)))
170
171
// Misc.
172
#define DTB_MAGIC 0xEDFE0DD0 // D00DFEED.
173
#define FALCON_DMA_PAGE_SIZE 0x100
174
#define SOC_ID_T210 0x210
175
#define SOC_ID_T210B01 0x214
176
#define SKU_NX 0x83
177
#define HDCP22 2
178
179
typedef struct _tsec_init_t {
180
u32 sku;
181
u32 hdcp;
182
u32 soc;
183
} tsec_init_t;
184
185
typedef struct _param_header {
186
u8 type; // type of the structure.
187
u8 version; // version of this structure.
188
u16 size; // size of this structure in bytes.
189
u32 attr; // attributes: unused bits SBZ.
190
} param_header_t;
191
192
typedef struct _aapcs64_params {
193
u64 x0;
194
u64 x1;
195
u64 x2;
196
u64 x3;
197
u64 x4;
198
u64 x5;
199
u64 x6;
200
u64 x7;
201
} aapcs64_params_t;
202
203
typedef struct _entry_point_info {
204
param_header_t hdr;
205
u64 pc;
206
u32 spsr;
207
u32 align0; // Alignment to u64 for the above member.
208
aapcs64_params_t args;
209
} entry_point_info_t;
210
211
typedef struct _image_info {
212
param_header_t hdr;
213
u64 image_base; // physical address of base of image.
214
u32 image_size; // bytes read from image file.
215
u32 image_max_size;
216
} image_info_t;
217
218
typedef struct _bl_v1_params {
219
param_header_t hdr;
220
u64 bl31_image_info;
221
u64 bl32_ep_info;
222
u64 bl32_image_info;
223
u64 bl33_ep_info;
224
u64 bl33_image_info;
225
} bl31_v1_params_t;
226
227
typedef struct _plat_params_from_bl2 {
228
// TZDRAM.
229
u64 tzdram_size;
230
u64 tzdram_base;
231
232
s32 uart_id; // UART port ID.
233
s32 l2_ecc_parity_prot_dis; // L2 ECC parity protection disable flag.
234
u64 boot_profiler_shmem_base; // SHMEM base address for storing the boot logs.
235
236
// SC7-Entry firmware.
237
u64 sc7entry_fw_size;
238
u64 sc7entry_fw_base;
239
240
s32 enable_ccplex_lock_step; // Enable dual execution.
241
242
// Enable below features.
243
s32 enable_extra_features;
244
245
// MTC table.
246
u64 emc_table_size;
247
u64 emc_table_base;
248
249
// Initial R2P payload.
250
u64 r2p_payload_size;
251
u64 r2p_payload_base;
252
253
u64 flags; // Platform flags.
254
} bl31_plat_params_from_bl2_t;
255
256
typedef struct _l4t_fw_t
257
{
258
u32 addr;
259
char *name;
260
} l4t_fw_t;
261
262
typedef struct _l4t_ctxt_t
263
{
264
char *path;
265
266
char *ram_oc_txt;
267
int ram_oc_freq;
268
int ram_oc_vdd2;
269
int ram_oc_vddq;
270
int ram_oc_opt;
271
272
u32 serial_port;
273
bool sld_type;
274
275
u32 sc7entry_size;
276
277
emc_table_t *mtc_table;
278
279
bl31_v1_params_t bl31_v1_params;
280
bl31_plat_params_from_bl2_t bl31_plat_params;
281
entry_point_info_t bl33_ep_info;
282
} l4t_ctxt_t;
283
284
#define DRAM_VDD2_OC_MIN_VOLTAGE 1050
285
#define DRAM_VDD2_OC_MAX_VOLTAGE 1175
286
#define DRAM_VDD2Q_OC_MAX_VOLTAGE 1237
287
#define DRAM_VDDQ_OC_MIN_VOLTAGE 550
288
#define DRAM_VDDQ_OC_MAX_VOLTAGE 650
289
#define DRAM_T210B01_TBL_MAX_FREQ 1600000
290
291
#define NA 0 // Default to 0 for incorrect dram ids.
292
293
//!TODO: Update on dram config changes.
294
static const u8 mtc_table_idx_t210b01[] = {
295
/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 */
296
NA, NA, NA, 7, NA, 7, 7, NA, 0, 1, 2, 3, 0, 1, 2, 3, NA, 4, 5, 4, 8, 8, 8, 5, 4, 6, 6, 6, 5, 9, 9, 9, 10, 10, 10
297
};
298
299
#undef NA
300
301
static const l4t_fw_t l4t_fw[] = {
302
{ TZDRAM_BASE, "bl31.bin" },
303
{ BL33_LOAD_BASE, "bl33.bin" },
304
{ SC7ENTRY_BASE, "sc7entry.bin" },
305
{ SC7EXIT_BASE, "sc7exit.bin" },
306
{ BPMPFW_BASE, "bpmpfw.bin" },
307
{ BPMPFW_B01_BASE, "bpmpfw_b01.bin" },
308
{ BPMPFW_B01_MTC_TABLE_BASE, "mtc_tbl_b01.bin" },
309
};
310
311
enum {
312
BL31_FW = 0,
313
BL33_FW = 1,
314
SC7ENTRY_FW = 2,
315
SC7EXIT_FW = 3,
316
BPMPFW_FW = 4,
317
BPMPFW_B01_FW = 5,
318
BPMPFW_B01_MTC_TBL = 6
319
};
320
321
static void _l4t_crit_error(const char *text, bool needs_update)
322
{
323
gfx_con.mute = false;
324
gfx_printf("%kL4T Error: %s!%sFailed to launch L4T!\n%k",
325
TXT_CLR_ERROR, text, needs_update ? "\nUpdate bootloader folder!\n\n" : "\n\n", TXT_CLR_DEFAULT);
326
}
327
328
char *sd_path;
329
u32 sd_path_len;
330
static int _l4t_sd_load(u32 idx)
331
{
332
FIL fp;
333
void *load_address = (void *)l4t_fw[idx].addr;
334
335
strcpy(sd_path + sd_path_len, l4t_fw[idx].name);
336
337
if (f_open(&fp, sd_path, FA_READ) != FR_OK)
338
return 0;
339
340
u32 size = f_size(&fp);
341
if (f_read(&fp, load_address, size, NULL) != FR_OK)
342
size = 0;
343
344
f_close(&fp);
345
346
u32 rev = *(u32 *)(load_address + size - sizeof(u32));
347
if (idx >= SC7ENTRY_FW && rev != L4T_FIRMWARE_REV)
348
return 0;
349
350
return size;
351
}
352
353
static void _l4t_sdram_lp0_save_params(bool t210b01)
354
{
355
pmc_regs_t210_t *pmc = (pmc_regs_t210_t *)PMC_BASE;
356
357
#define _REG_S(base, off) *(u32 *)((base) + (off))
358
#define MC_S(off) _REG_S(MC_BASE, off)
359
360
#define pack(src, src_bits, dst, dst_bits) { \
361
u32 mask = 0xFFFFFFFF >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \
362
dst &= ~(mask << (0 ? dst_bits)); \
363
dst |= ((src >> (0 ? src_bits)) & mask) << (0 ? dst_bits); }
364
365
#define s(param, src_bits, pmcreg, dst_bits) \
366
pack(MC_S(param), src_bits, pmc->pmc_ ## pmcreg, dst_bits)
367
368
// 32 bits version of s macro.
369
#define s32(param, pmcreg) pmc->pmc_ ## pmcreg = MC_S(param)
370
371
// Only save changed carveout registers into PMC for SC7 Exit.
372
373
// VPR.
374
#if CARVEOUT_NVDEC_TSEC_ENABLE
375
s32(MC_VIDEO_PROTECT_GPU_OVERRIDE_0, secure_scratch12);
376
s(MC_VIDEO_PROTECT_GPU_OVERRIDE_1, 15:0, secure_scratch49, 15:0);
377
#endif
378
s(MC_VIDEO_PROTECT_BOM, 31:20, secure_scratch52, 26:15);
379
s(MC_VIDEO_PROTECT_SIZE_MB, 11:0, secure_scratch53, 11:0);
380
if (!t210b01) {
381
s(MC_VIDEO_PROTECT_REG_CTRL, 1:0, secure_scratch13, 31:30);
382
} else {
383
s(MC_VIDEO_PROTECT_REG_CTRL, 1:0, secure_scratch14, 31:30);
384
}
385
386
// TZDRAM.
387
s(MC_SEC_CARVEOUT_BOM, 31:20, secure_scratch53, 23:12);
388
s(MC_SEC_CARVEOUT_SIZE_MB, 11:0, secure_scratch54, 11:0);
389
if (!t210b01) {
390
s(MC_SEC_CARVEOUT_REG_CTRL, 0:0, secure_scratch18, 30:30);
391
} else {
392
s(MC_SEC_CARVEOUT_REG_CTRL, 0:0, secure_scratch19, 29:29);
393
}
394
395
// NVDEC or SECFW.
396
s(MC_SECURITY_CARVEOUT1_BOM, 31:17, secure_scratch50, 29:15);
397
s(MC_SECURITY_CARVEOUT1_SIZE_128KB, 11:0, secure_scratch57, 11:0);
398
s32(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0, secure_scratch59);
399
s32(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1, secure_scratch60);
400
s32(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2, secure_scratch61);
401
s32(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3, secure_scratch62);
402
if (!t210b01)
403
{
404
s(MC_SECURITY_CARVEOUT1_CFG0, 2:0, secure_scratch56, 27:25);
405
s(MC_SECURITY_CARVEOUT1_CFG0, 6:3, secure_scratch41, 28:25);
406
s(MC_SECURITY_CARVEOUT1_CFG0, 13:7, secure_scratch42, 31:25);
407
s(MC_SECURITY_CARVEOUT1_CFG0, 17:14, secure_scratch43, 28:25);
408
s(MC_SECURITY_CARVEOUT1_CFG0, 21:18, secure_scratch44, 28:25);
409
s(MC_SECURITY_CARVEOUT1_CFG0, 25:22, secure_scratch56, 31:28);
410
s(MC_SECURITY_CARVEOUT1_CFG0, 26:26, secure_scratch57, 24:24);
411
}
412
else
413
{
414
s(MC_SECURITY_CARVEOUT1_CFG0, 1:0, secure_scratch56, 31:30);
415
s(MC_SECURITY_CARVEOUT1_CFG0, 2:2, secure_scratch57, 24:24);
416
s(MC_SECURITY_CARVEOUT1_CFG0, 6:3, secure_scratch42, 28:25);
417
s(MC_SECURITY_CARVEOUT1_CFG0, 10:7, secure_scratch43, 28:25);
418
s(MC_SECURITY_CARVEOUT1_CFG0, 13:11, secure_scratch42, 31:29);
419
s(MC_SECURITY_CARVEOUT1_CFG0, 17:14, secure_scratch44, 28:25);
420
s(MC_SECURITY_CARVEOUT1_CFG0, 21:18, secure_scratch47, 25:22);
421
s(MC_SECURITY_CARVEOUT1_CFG0, 26:22, secure_scratch57, 29:25);
422
}
423
424
// GPU FW.
425
s(MC_SECURITY_CARVEOUT2_BOM, 31:17, secure_scratch51, 29:15);
426
s(MC_SECURITY_CARVEOUT2_SIZE_128KB, 11:0, secure_scratch56, 23:12);
427
if (!t210b01)
428
{
429
s(MC_SECURITY_CARVEOUT2_CFG0, 2:0, secure_scratch55, 27:25);
430
s(MC_SECURITY_CARVEOUT2_CFG0, 6:3, secure_scratch19, 31:28);
431
s(MC_SECURITY_CARVEOUT2_CFG0, 10:7, secure_scratch20, 31:28);
432
s(MC_SECURITY_CARVEOUT2_CFG0, 13:11, secure_scratch41, 31:29);
433
s(MC_SECURITY_CARVEOUT2_CFG0, 17:14, secure_scratch39, 30:27);
434
s(MC_SECURITY_CARVEOUT2_CFG0, 21:18, secure_scratch40, 30:27);
435
s(MC_SECURITY_CARVEOUT2_CFG0, 25:22, secure_scratch55, 31:28);
436
s(MC_SECURITY_CARVEOUT2_CFG0, 26:26, secure_scratch56, 24:24);
437
}
438
else
439
{
440
s(MC_SECURITY_CARVEOUT2_CFG0, 1:0, secure_scratch55, 31:30);
441
s(MC_SECURITY_CARVEOUT2_CFG0, 2:2, secure_scratch56, 24:24);
442
s(MC_SECURITY_CARVEOUT2_CFG0, 6:3, secure_scratch20, 31:28);
443
s(MC_SECURITY_CARVEOUT2_CFG0, 10:7, secure_scratch39, 30:27);
444
s(MC_SECURITY_CARVEOUT2_CFG0, 13:11, secure_scratch41, 31:29);
445
s(MC_SECURITY_CARVEOUT2_CFG0, 17:14, secure_scratch40, 30:27);
446
s(MC_SECURITY_CARVEOUT2_CFG0, 21:18, secure_scratch41, 28:25);
447
s(MC_SECURITY_CARVEOUT2_CFG0, 26:22, secure_scratch56, 29:25);
448
}
449
450
// GPU WPR.
451
s(MC_SECURITY_CARVEOUT3_BOM, 31:17, secure_scratch50, 14:0);
452
s(MC_SECURITY_CARVEOUT3_SIZE_128KB, 11:0, secure_scratch56, 11:0);
453
s32(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2, secure_scratch71);
454
s32(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4, secure_scratch73);
455
if (!t210b01)
456
{
457
s(MC_SECURITY_CARVEOUT3_CFG0, 2:0, secure_scratch57, 27:25);
458
s(MC_SECURITY_CARVEOUT3_CFG0, 10:3, secure_scratch47, 29:22);
459
s(MC_SECURITY_CARVEOUT3_CFG0, 13:11, secure_scratch43, 31:29);
460
s(MC_SECURITY_CARVEOUT3_CFG0, 21:14, secure_scratch48, 29:22);
461
s(MC_SECURITY_CARVEOUT3_CFG0, 25:22, secure_scratch57, 31:28);
462
s(MC_SECURITY_CARVEOUT3_CFG0, 26:26, secure_scratch58, 0:0);
463
}
464
else
465
{
466
s(MC_SECURITY_CARVEOUT3_CFG0, 1:0, secure_scratch57, 31:30);
467
s(MC_SECURITY_CARVEOUT3_CFG0, 2:2, secure_scratch58, 0:0);
468
s(MC_SECURITY_CARVEOUT3_CFG0, 6:3, secure_scratch47, 29:26);
469
s(MC_SECURITY_CARVEOUT3_CFG0, 10:7, secure_scratch48, 25:22);
470
s(MC_SECURITY_CARVEOUT3_CFG0, 13:11, secure_scratch43, 31:29);
471
s(MC_SECURITY_CARVEOUT3_CFG0, 17:14, secure_scratch48, 29:26);
472
s(MC_SECURITY_CARVEOUT3_CFG0, 21:18, secure_scratch52, 30:27);
473
s(MC_SECURITY_CARVEOUT3_CFG0, 26:22, secure_scratch58, 5:1);
474
}
475
476
// TSECA.
477
s(MC_SECURITY_CARVEOUT4_BOM, 31:17, secure_scratch51, 14:0);
478
s(MC_SECURITY_CARVEOUT4_SIZE_128KB, 11:0, secure_scratch55, 23:12);
479
s(MC_SECURITY_CARVEOUT4_CFG0, 26:0, secure_scratch39, 26:0);
480
481
// TSECB.
482
s(MC_SECURITY_CARVEOUT5_BOM, 31:17, secure_scratch52, 14:0);
483
s(MC_SECURITY_CARVEOUT5_SIZE_128KB, 11:0, secure_scratch57, 23:12);
484
s(MC_SECURITY_CARVEOUT5_CFG0, 26:0, secure_scratch40, 26:0);
485
}
486
487
static void _l4t_mc_config_carveout(bool t210b01)
488
{
489
#if CARVEOUT_NVDEC_TSEC_ENABLE
490
// Re-enable access for TSEC clients.
491
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) &= ~BIT(22);
492
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) &= ~(BIT(15) | BIT(14) | BIT(13));
493
#endif
494
495
// Disabled VPR carveout. DT decides if enabled or not.
496
MC(MC_VIDEO_PROTECT_BOM) = 0;
497
MC(MC_VIDEO_PROTECT_SIZE_MB) = 0;
498
MC(MC_VIDEO_PROTECT_REG_CTRL) = VPR_CTRL_TZ_SECURE | VPR_CTRL_LOCKED;
499
500
// Temporarily disable TZDRAM carveout. For launching coldboot TZ.
501
MC(MC_SEC_CARVEOUT_BOM) = 0;
502
MC(MC_SEC_CARVEOUT_SIZE_MB) = 0;
503
MC(MC_SEC_CARVEOUT_REG_CTRL) = 0;
504
505
// Print real one, not temp disabled.
506
UPRINTF("TZD: TZDRAM Carveout: %08X - %08X\n", TZDRAM_BASE, TZDRAM_BASE - 1 + TZDRAM_SIZE);
507
508
// Configure generalized security carveouts.
509
u32 carveout_base = GEN_CARVEOUT_TOP;
510
511
#if CARVEOUT_NVDEC_TSEC_ENABLE
512
513
// Set NVDEC keyslot sticky bits.
514
clock_enable_nvdec();
515
clock_enable_nvjpg();
516
NVDEC(NVDEC_SA_KEYSLOT_GLOBAL_RW) = 0xFFFF; // Read disable.
517
NVDEC(NVDEC_SA_KEYSLOT_TZ) = 0xFFFFFFFF; // TZ enable.
518
NVDEC(NVDEC_SA_KEYSLOT_FALCON) = 0; // Falcon disable.
519
NVDEC(NVDEC_SA_KEYSLOT_OTF) = 0; // OTF disable.
520
NVDEC(NVDEC_VPR_ALL_OTF_GOTO_VPR) = 1; // Enable.
521
clock_disable_nvjpg();
522
clock_disable_nvdec();
523
524
// Set NVDEC carveout. Only for NVDEC bl/prod.
525
carveout_base -= ALIGN(CARVEOUT_NVDEC_SIZE, SZ_1M);
526
MC(MC_SECURITY_CARVEOUT1_BOM) = carveout_base;
527
MC(MC_SECURITY_CARVEOUT1_BOM_HI) = 0;
528
MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = CARVEOUT_NVDEC_SIZE / SZ_128K;
529
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0;
530
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0;
531
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_TSEC | SEC_CARVEOUT_CA2_W_TSEC;
532
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = SEC_CARVEOUT_CA3_R_NVDEC | SEC_CARVEOUT_CA3_W_NVDEC;
533
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
534
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
535
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
536
SEC_CARVEOUT_CFG_RD_SEC |
537
SEC_CARVEOUT_CFG_RD_FALCON_LS |
538
SEC_CARVEOUT_CFG_RD_FALCON_HS |
539
SEC_CARVEOUT_CFG_WR_FALCON_HS |
540
SEC_CARVEOUT_CFG_APERTURE_ID(1) |
541
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
542
UPRINTF("GSC1: NVDEC Carveout: %08X - %08X\n",
543
MC(MC_SECURITY_CARVEOUT1_BOM), MC(MC_SECURITY_CARVEOUT1_BOM) + MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) * SZ_128K);
544
545
#elif CARVEOUT_SECFW_ENABLE
546
547
// Flush data to ram.
548
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
549
550
// Set SC7-Entry/SC7-Exit/R2P/MTC Table or SC7-Exit/BPMP-FW carveout. Only BPMP, CCPLEX and AHB have R/W access.
551
MC(MC_SECURITY_CARVEOUT1_BOM) = carveout_base;
552
MC(MC_SECURITY_CARVEOUT1_BOM_HI) = 0;
553
MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = CARVEOUT_SECFW_SIZE / SZ_128K;
554
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = SEC_CARVEOUT_CA0_R_BPMP_C |
555
SEC_CARVEOUT_CA0_R_PPCSAHBSLV;
556
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = SEC_CARVEOUT_CA1_W_BPMP_C |
557
SEC_CARVEOUT_CA1_R_CCPLEX_C |
558
SEC_CARVEOUT_CA1_R_CCPLEXLP_C |
559
SEC_CARVEOUT_CA1_W_CCPLEX_C |
560
SEC_CARVEOUT_CA1_W_CCPLEXLP_C |
561
SEC_CARVEOUT_CA1_W_PPCSAHBSLV;
562
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
563
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
564
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
565
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_RD_NS |
566
SEC_CARVEOUT_CFG_RD_SEC |
567
SEC_CARVEOUT_CFG_WR_NS |
568
SEC_CARVEOUT_CFG_WR_SEC |
569
SEC_CARVEOUT_CFG_LOCKED;
570
UPRINTF("GSC1: SECFW Carveout: %08X - %08X\n",
571
MC(MC_SECURITY_CARVEOUT1_BOM), MC(MC_SECURITY_CARVEOUT1_BOM) + MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) * SZ_128K);
572
573
#endif
574
575
// Set GPU FW WPR carveout. Same value is used for GPU WPR carveout calculation if not full TOS.
576
carveout_base -= ALIGN(CARVEOUT_GPUFW_SIZE, SZ_1M);
577
578
// Sanitize it and enable GSC3 for ACR.
579
memset((void *)carveout_base, 0, CARVEOUT_GPUFW_SIZE);
580
*(u32 *)(carveout_base + CARVEOUT_GPUFW_SIZE - sizeof(u32)) = ACR_GSC3_ENABLE_MAGIC;
581
582
tsec_init_t *tsec_init = (tsec_init_t *)(carveout_base + CARVEOUT_GPUFW_SIZE - FALCON_DMA_PAGE_SIZE);
583
584
// Set TSEC init info.
585
tsec_init->sku = SKU_NX;
586
tsec_init->hdcp = HDCP22;
587
tsec_init->soc = t210b01 ? SOC_ID_T210B01 : SOC_ID_T210;
588
589
// Flush data to ram.
590
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
591
592
// Set carveout config.
593
MC(MC_SECURITY_CARVEOUT2_BOM) = carveout_base;
594
MC(MC_SECURITY_CARVEOUT2_BOM_HI) = 0;
595
MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = CARVEOUT_GPUFW_SIZE / SZ_128K;
596
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0;
597
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0;
598
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC;
599
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
600
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2;
601
MC(MC_SECURITY_CARVEOUT2_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
602
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
603
SEC_CARVEOUT_CFG_RD_NS |
604
SEC_CARVEOUT_CFG_RD_SEC |
605
SEC_CARVEOUT_CFG_RD_FALCON_LS |
606
SEC_CARVEOUT_CFG_RD_FALCON_HS |
607
SEC_CARVEOUT_CFG_WR_FALCON_LS |
608
SEC_CARVEOUT_CFG_WR_FALCON_HS |
609
SEC_CARVEOUT_CFG_APERTURE_ID(2) |
610
SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU |
611
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH; // SEC_CARVEOUT_CFG_IS_WPR is set from GPU.
612
UPRINTF("GSC2: GPUFW Carveout: %08X - %08X\n",
613
MC(MC_SECURITY_CARVEOUT2_BOM), MC(MC_SECURITY_CARVEOUT2_BOM) + MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) * SZ_128K);
614
615
// Set GPU WPR carveout.
616
#if CARVEOUT_NVDEC_TSEC_ENABLE
617
carveout_base -= ALIGN(CARVEOUT_GPUWPR_SIZE, SZ_1M);
618
MC(MC_SECURITY_CARVEOUT3_BOM) = carveout_base;
619
#else
620
MC(MC_SECURITY_CARVEOUT3_BOM) = carveout_base + CARVEOUT_GPUFW_SIZE;
621
#endif
622
MC(MC_SECURITY_CARVEOUT3_BOM_HI) = 0x0;
623
MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) = CARVEOUT_GPUWPR_SIZE / SZ_128K;
624
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0;
625
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0;
626
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0; // HOS: SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU
627
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0;
628
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0; // HOS: SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2
629
MC(MC_SECURITY_CARVEOUT3_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
630
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
631
SEC_CARVEOUT_CFG_RD_NS |
632
SEC_CARVEOUT_CFG_RD_SEC |
633
SEC_CARVEOUT_CFG_RD_FALCON_LS |
634
SEC_CARVEOUT_CFG_RD_FALCON_HS |
635
SEC_CARVEOUT_CFG_WR_FALCON_LS |
636
SEC_CARVEOUT_CFG_WR_FALCON_HS |
637
SEC_CARVEOUT_CFG_APERTURE_ID(3) |
638
SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU |
639
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH; // SEC_CARVEOUT_CFG_IS_WPR is set from GPU.
640
UPRINTF("GSC3: GPUW2 Carveout: %08X - %08X\n",
641
MC(MC_SECURITY_CARVEOUT3_BOM), MC(MC_SECURITY_CARVEOUT3_BOM) + MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) * SZ_128K);
642
643
/*
644
* Set TSECA/B carveout. Only for NVDEC bl/prod and TSEC.
645
*
646
* Otherwise disabled.
647
*
648
* With HOS SC7-Exit fw, it gets set to disallow RAM access for BPMP. But TZ can change it.
649
* We lock the carveout and save it in restore scratch registers so SC7-Exit can't touch it.
650
*/
651
carveout_base -= CARVEOUT_NVDEC_TSEC_ENABLE ? ALIGN(CARVEOUT_TSEC_SIZE, SZ_1M) : 0;
652
MC(MC_SECURITY_CARVEOUT4_BOM) = CARVEOUT_NVDEC_TSEC_ENABLE ? carveout_base : 0;
653
MC(MC_SECURITY_CARVEOUT4_BOM_HI) = 0x0;
654
MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = CARVEOUT_NVDEC_TSEC_ENABLE ? CARVEOUT_TSEC_SIZE / SZ_128K : 0;
655
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_TSEC | SEC_CARVEOUT_CA2_W_TSEC;
656
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_TSECB | SEC_CARVEOUT_CA4_W_TSECB;
657
MC(MC_SECURITY_CARVEOUT4_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
658
SEC_CARVEOUT_CFG_RD_FALCON_HS |
659
SEC_CARVEOUT_CFG_WR_FALCON_HS |
660
SEC_CARVEOUT_CFG_APERTURE_ID(4) |
661
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
662
UPRINTF("GSC4: TSEC1 Carveout: %08X - %08X\n",
663
MC(MC_SECURITY_CARVEOUT4_BOM), MC(MC_SECURITY_CARVEOUT4_BOM) + MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) * SZ_128K);
664
665
// Set TSECA carveout. Only for NVDEC bl/prod and TSEC. Otherwise disabled.
666
carveout_base -= CARVEOUT_NVDEC_TSEC_ENABLE ? ALIGN(CARVEOUT_TSEC_SIZE, SZ_1M) : 0;
667
MC(MC_SECURITY_CARVEOUT5_BOM) = CARVEOUT_NVDEC_TSEC_ENABLE ? carveout_base : 0;
668
MC(MC_SECURITY_CARVEOUT5_BOM_HI) = 0x0;
669
MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = CARVEOUT_NVDEC_TSEC_ENABLE ? CARVEOUT_TSEC_SIZE / SZ_128K : 0;
670
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_TSEC | SEC_CARVEOUT_CA2_W_TSEC;
671
MC(MC_SECURITY_CARVEOUT5_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
672
SEC_CARVEOUT_CFG_RD_FALCON_HS |
673
SEC_CARVEOUT_CFG_WR_FALCON_HS |
674
SEC_CARVEOUT_CFG_APERTURE_ID(5) |
675
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
676
UPRINTF("GSC5: TSEC2 Carveout: %08X - %08X\n",
677
MC(MC_SECURITY_CARVEOUT5_BOM), MC(MC_SECURITY_CARVEOUT5_BOM) + MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) * SZ_128K);
678
679
UPRINTF("DRAM Bank 0 TOP: %08X\n", carveout_base);
680
681
// Save carveouts to lp0 pmc registers.
682
_l4t_sdram_lp0_save_params(t210b01);
683
}
684
685
static void _l4t_late_hw_config(bool t210b01)
686
{
687
// Reset System Counters.
688
for (u32 i = 0; i < SYSCTR0_COUNTERS; i += sizeof(u32))
689
SYSCTR0(SYSCTR0_COUNTERS_BASE + i) = 0;
690
691
/*
692
* PMIC config scratch register
693
*
694
* bit00: active cluster slow
695
* bit01: Set: max77621/max77812. Unset: OVR/OVR2.
696
* bit02-07: unused
697
* bit08-15: pmic cpu i2c address
698
* bit16:23: pmic cpu i2c en reg
699
* bit24:31: pmic cpu i2c en val
700
*/
701
PMC(APBDEV_PMC_SCRATCH201) = BIT(1);
702
703
// Clear PLLM override for SC7.
704
PMC(APBDEV_PMC_PLLP_WB0_OVERRIDE) &= ~PMC_PLLP_WB0_OVR_PLLM_OVR_ENABLE;
705
706
// Set spare reg to 0xE0000 and clear everything else.
707
if (t210b01 && (SYSREG(AHB_AHB_SPARE_REG) & 0xE0000000) != 0xE0000000)
708
SYSREG(AHB_AHB_SPARE_REG) = 0xE0000 << 12u;
709
710
// HDA loopback disable on prod.
711
PMC(APBDEV_PMC_STICKY_BITS) = PMC_STICKY_BITS_HDA_LPBK_DIS;
712
713
// Clear any MC error.
714
MC(MC_INTSTATUS) = MC(MC_INTSTATUS);
715
716
// Enable Wrap burst for BPMP, GPU and PCIE.
717
MSELECT(MSELECT_CONFIG) = (MSELECT(MSELECT_CONFIG) & (~(MSELECT_CFG_ERR_RESP_EN_GPU | MSELECT_CFG_ERR_RESP_EN_PCIE))) |
718
(MSELECT_CFG_WRAP_TO_INCR_GPU | MSELECT_CFG_WRAP_TO_INCR_PCIE | MSELECT_CFG_WRAP_TO_INCR_BPMP);
719
720
#if LOCK_PMC_REGISTERS
721
// Lock LP0 parameters and misc secure registers. Always happens on warmboot.
722
#if CARVEOUT_NVDEC_TSEC_ENABLE
723
pmc_scratch_lock(PMC_SEC_LOCK_CARVEOUTS_L4T | PMC_SEC_LOCK_SE_SRK);
724
#else
725
pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS | PMC_SEC_LOCK_MISC | PMC_SEC_LOCK_SE_SRK);
726
#endif
727
728
// Lock SE2 SRK and misc secure regs. Also lock writes on normal LP0 scratch regs.
729
if (t210b01)
730
pmc_scratch_lock(PMC_SEC_LOCK_MISC_B01 | PMC_SEC_LOCK_SE2_SRK_B01 | PMC_SEC_LOCK_LP0_PARAMS_B01);
731
#endif
732
}
733
734
static void _l4t_bpmpfw_b01_config(l4t_ctxt_t *ctxt)
735
{
736
char *ram_oc_txt = ctxt->ram_oc_txt;
737
u32 ram_oc_freq = ctxt->ram_oc_freq;
738
u32 ram_oc_opt = ctxt->ram_oc_opt;
739
u32 ram_id = fuse_read_dramid(false);
740
741
// Set default parameters.
742
*(u32 *)BPMPFW_B01_DTB_ADDR = 0;
743
*(u8 *)BPMPFW_B01_CC_INIT_OP = OP_TRAIN;
744
*(u32 *)BPMPFW_B01_CC_PT_TIME = 100;
745
746
#if DEBUG_LOG_BPMPFW
747
// Set default debug parameters.
748
*(u32 *)BPMPFW_B01_LOGLEVEL = 3;
749
*(u32 *)BPMPFW_B01_CC_DEBUG = 0x50000101;
750
751
// Set serial debug port.
752
if (*(u32 *)BPMPFW_B01_ADTB_BASE == DTB_MAGIC)
753
BPMPFW_B01_DTB_SET_SERIAL_PORT(ctxt->serial_port);
754
#endif
755
756
// Set and copy MTC tables.
757
u32 mtc_idx = mtc_table_idx_t210b01[ram_id];
758
for (u32 i = 0; i < 3; i++)
759
{
760
if (true)
761
minerva_sdmmc_la_program(BPMPFW_B01_MTC_TABLE_OFFSET(mtc_idx, i), true);
762
memcpy(BPMPFW_B01_DTB_EMC_TBL_OFFSET(i), BPMPFW_B01_MTC_TABLE_OFFSET(mtc_idx, i), BPMPFW_B01_MTC_FREQ_TABLE_SIZE);
763
}
764
765
// Always use Arachne Register Cell (ARC) for setting rated frequencies if no ram_oc is defined.
766
if (!ram_oc_freq)
767
{
768
if (ram_id >= LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ &&
769
ram_id <= LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE)
770
{
771
ram_oc_txt = "1866000";
772
ram_oc_freq = 1866000;
773
}
774
else
775
{
776
ram_oc_txt = "2133000";
777
ram_oc_freq = 2133000;
778
}
779
}
780
781
// Set DRAM voltage.
782
if (ctxt->ram_oc_vdd2)
783
max7762x_regulator_set_voltage(REGULATOR_SD1, ctxt->ram_oc_vdd2 * 1000);
784
if (ctxt->ram_oc_vddq)
785
max7762x_regulator_set_voltage(REGULATOR_RAM0, ctxt->ram_oc_vddq * 1000);
786
787
// A frequency of lower or equal with stock max will skip ARC.
788
if (ram_oc_freq > DRAM_T210B01_TBL_MAX_FREQ)
789
{
790
// Final table.
791
const u32 tbl_idx = BPMPFW_B01_DTB_EMC_ENTRIES - 1;
792
793
// Copy table and prep it for Arachne.
794
memcpy(BPMPFW_B01_DTB_EMC_TBL_OFFSET(tbl_idx), BPMPFW_B01_MTC_TABLE_OFFSET(mtc_idx, 2), BPMPFW_B01_MTC_FREQ_TABLE_SIZE);
795
796
BPMPFW_B01_DTB_EMC_TBL_SET_NAME(tbl_idx, ram_oc_txt);
797
BPMPFW_B01_DTB_EMC_TBL_SET_FREQ(tbl_idx, ram_oc_freq);
798
BPMPFW_B01_DTB_EMC_TBL_SET_OPTC(tbl_idx, ram_oc_opt);
799
800
// Enable table.
801
BPMPFW_B01_DTB_EMC_TBL_ENABLE(tbl_idx);
802
803
UPRINTF("RAM Frequency set to: %d KHz. Voltage: %d mV\n", ram_oc_freq, ctxt->ram_oc_vdd2);
804
}
805
806
// Save BPMP-FW entrypoint for TZ.
807
PMC(APBDEV_PMC_SCRATCH39) = BPMPFW_B01_ENTRYPOINT;
808
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE1_B01) |= BIT(15);
809
}
810
811
static int _l4t_sc7_exit_config(bool t210b01)
812
{
813
if (!t210b01)
814
{
815
// Apply Nintendo Switch (2017) RSA modulus to SC7-Exit firmware.
816
emmc_initialize(false);
817
pkg1_warmboot_rsa_mod(SC7EXIT_BASE);
818
emmc_end();
819
820
// Set SC7-Exit firmware address for bootrom to find.
821
PMC(APBDEV_PMC_SCRATCH1) = SC7EXIT_BASE;
822
}
823
else
824
{
825
// Get latest SC7-Exit if needed and setup PA id.
826
launch_ctxt_t hos_ctxt = {0};
827
if (pkg1_warmboot_config(&hos_ctxt, 0, 0, 0))
828
{
829
gfx_con.mute = false;
830
gfx_wputs("\nFailed to match warmboot with fuses!\nIf you continue, sleep wont work!");
831
832
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
833
834
if (!(btn_wait() & BTN_POWER))
835
return 1;
836
}
837
838
// Copy loaded warmboot fw to address if from storage.
839
if (hos_ctxt.warmboot)
840
memcpy((void *)SC7EXIT_B01_BASE, hos_ctxt.warmboot, hos_ctxt.warmboot_size);
841
842
// Set SC7-Exit firmware address for bootrom to find.
843
PMC(APBDEV_PMC_SECURE_SCRATCH119) = SC7EXIT_B01_BASE;
844
PMC(APBDEV_PMC_SEC_DISABLE8) |= BIT(30);
845
}
846
847
return 0;
848
}
849
850
static void _l4t_bl33_cfg_set_key(char *env, const char *key, const char *val)
851
{
852
strcat(env, key);
853
strcat(env, "=");
854
strcat(env, val);
855
strcat(env, "\n");
856
}
857
858
static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b01)
859
{
860
char *bl33_env = (char *)BL33_ENV_BASE;
861
bl33_env[0] = '\0';
862
char val[4] = {0};
863
864
// Set default SLD type.
865
ctxt->sld_type = true;
866
867
// Parse ini section and prepare BL33 env.
868
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
869
{
870
if (!strcmp("boot_prefixes", kv->key))
871
ctxt->path = kv->val;
872
else if (!strcmp("ram_oc", kv->key))
873
{
874
ctxt->ram_oc_txt = kv->val;
875
ctxt->ram_oc_freq = atoi(kv->val);
876
}
877
else if (!strcmp("ram_oc_vdd2", kv->key))
878
{
879
ctxt->ram_oc_vdd2 = atoi(kv->val);
880
881
if (t210b01 && ctxt->ram_oc_vdd2 > DRAM_VDD2_OC_MAX_VOLTAGE)
882
ctxt->ram_oc_vdd2 = DRAM_VDD2_OC_MAX_VOLTAGE;
883
else if (!t210b01 && ctxt->ram_oc_vdd2 > DRAM_VDD2Q_OC_MAX_VOLTAGE)
884
ctxt->ram_oc_vdd2 = DRAM_VDD2Q_OC_MAX_VOLTAGE;
885
else if (ctxt->ram_oc_vdd2 < DRAM_VDD2_OC_MIN_VOLTAGE)
886
ctxt->ram_oc_vdd2 = DRAM_VDD2_OC_MIN_VOLTAGE;
887
}
888
else if (!strcmp("ram_oc_vddq", kv->key))
889
{
890
ctxt->ram_oc_vddq = atoi(kv->val);
891
if (ctxt->ram_oc_vddq > DRAM_VDDQ_OC_MAX_VOLTAGE)
892
ctxt->ram_oc_vddq = DRAM_VDDQ_OC_MAX_VOLTAGE;
893
else if (ctxt->ram_oc_vddq < DRAM_VDDQ_OC_MIN_VOLTAGE)
894
ctxt->ram_oc_vddq = 0;
895
}
896
else if (!strcmp("ram_oc_opt", kv->key))
897
ctxt->ram_oc_opt = atoi(kv->val);
898
else if (!strcmp("uart_port", kv->key))
899
ctxt->serial_port = atoi(kv->val);
900
else if (!strcmp("sld_type", kv->key))
901
ctxt->sld_type = atoi(kv->val);
902
903
// Set key/val to BL33 env.
904
_l4t_bl33_cfg_set_key(bl33_env, kv->key, kv->val);
905
}
906
907
#ifdef DEBUG_UART_PORT
908
// Override port if bootloader UART debug is enabled.
909
ctxt->serial_port = DEBUG_UART_PORT + 1;
910
#endif
911
912
// Set r2p parameters.
913
if (entry_idx >= 10)
914
{
915
val[0] = '1';
916
val[1] = '0' + (entry_idx % 10);
917
}
918
else
919
val[0] = '0' + entry_idx;
920
_l4t_bl33_cfg_set_key(bl33_env, "autoboot", val);
921
922
// NULL terminate at single char for the next env sets.
923
val[1] = 0;
924
925
val[0] = '0' + is_list;
926
_l4t_bl33_cfg_set_key(bl33_env, "autoboot_list", val);
927
928
val[0] = '0' + L4T_LOADER_API_REV;
929
_l4t_bl33_cfg_set_key(bl33_env, "loader_rev", val);
930
931
// Enable BL33 memory env import.
932
*(u32 *)(BL33_ENV_MAGIC_OFFSET) = BL33_ENV_MAGIC;
933
934
// Set boot path.
935
sd_path = (char *)malloc(512);
936
sd_path_len = strlen(ctxt->path);
937
strcpy(sd_path, ctxt->path);
938
}
939
940
void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b01)
941
{
942
l4t_ctxt_t *ctxt = (l4t_ctxt_t *)TZ_PARAM_BASE;
943
memset(ctxt, 0, TZ_PARAM_SIZE);
944
945
gfx_con_setpos(0, 0);
946
947
// Parse config.
948
_l4t_set_config(ctxt, ini_sec, entry_idx, is_list, t210b01);
949
950
if (!ctxt->path)
951
{
952
_l4t_crit_error("Path missing", false);
953
return;
954
}
955
956
// Get MTC table.
957
ctxt->mtc_table = minerva_get_mtc_table();
958
if (!t210b01 && !ctxt->mtc_table)
959
{
960
_l4t_crit_error("Minerva missing", true);
961
return;
962
}
963
964
// Load BL31 (ATF/TrustZone fw).
965
if (!_l4t_sd_load(BL31_FW))
966
{
967
_l4t_crit_error("BL31 missing", false);
968
return;
969
}
970
971
// Load BL33 (U-BOOT/CBOOT).
972
if (!_l4t_sd_load(BL33_FW))
973
{
974
_l4t_crit_error("BL33 missing", false);
975
return;
976
}
977
978
// Set firmware path.
979
strcpy(sd_path, "bootloader/sys/l4t/");
980
sd_path_len = strlen(sd_path);
981
982
if (!t210b01)
983
{
984
// Load SC7-Entry firmware.
985
ctxt->sc7entry_size = _l4t_sd_load(SC7ENTRY_FW);
986
if (!ctxt->sc7entry_size)
987
{
988
_l4t_crit_error("loading SC7-Entry", true);
989
return;
990
}
991
992
// Load BPMP-FW. Does power management.
993
if (!_l4t_sd_load(BPMPFW_FW))
994
{
995
_l4t_crit_error("loading BPMP-FW", true);
996
return;
997
}
998
999
// Load SC7-Exit firmware.
1000
if (!_l4t_sd_load(SC7EXIT_FW))
1001
{
1002
_l4t_crit_error("loading SC7-Exit", true);
1003
return;
1004
}
1005
}
1006
else
1007
{
1008
// Load BPMP-FW. Manages SC7-Entry also.
1009
if (!_l4t_sd_load(BPMPFW_B01_FW))
1010
{
1011
_l4t_crit_error("loading BPMP-FW", true);
1012
return;
1013
}
1014
1015
// Load BPMP-FW MTC table.
1016
if (!_l4t_sd_load(BPMPFW_B01_MTC_TBL))
1017
{
1018
_l4t_crit_error("loading BPMP-FW MTC", true);
1019
return;
1020
}
1021
}
1022
1023
// Set SC7-Exit firmware address to PMC for bootrom and do further setup.
1024
if (_l4t_sc7_exit_config(t210b01))
1025
return;
1026
1027
// Done loading bootloaders/firmware.
1028
sd_end();
1029
1030
// We don't need AHB aperture open.
1031
mc_disable_ahb_redirect();
1032
1033
// Enable debug port.
1034
if (ctxt->serial_port)
1035
{
1036
pinmux_config_uart(ctxt->serial_port - 1);
1037
clock_enable_uart(ctxt->serial_port - 1);
1038
}
1039
1040
// Restore UARTB/C TX pins to SPIO.
1041
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
1042
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
1043
1044
// Configure BL33 parameters.
1045
if (*(u32 *)BL33_DTB_BASE == DTB_MAGIC)
1046
{
1047
// Defaults are for UARTA.
1048
char *bl33_serial_port = NULL;
1049
switch (ctxt->serial_port)
1050
{
1051
case 0: // Disable.
1052
break;
1053
case 1: // UARTA.
1054
bl33_serial_port = "70006000";
1055
break;
1056
case 2: // UARTB.
1057
bl33_serial_port = "70006040";
1058
break;
1059
case 3: // UARTC.
1060
bl33_serial_port = "70006200";
1061
break;
1062
}
1063
1064
if (bl33_serial_port)
1065
{
1066
BL33_DTB_SET_STDOUT_PATH(bl33_serial_port);
1067
BL33_DTB_SET_STDERR_PATH(bl33_serial_port);
1068
BL33_DTB_SET_UART_STATUS(ctxt->serial_port);
1069
}
1070
}
1071
1072
// Set BL31 params.
1073
ctxt->bl31_v1_params.hdr.type = PARAM_BL31;
1074
ctxt->bl31_v1_params.hdr.version = VERSION_1;
1075
ctxt->bl31_v1_params.hdr.size = sizeof(bl31_v1_params_t);
1076
ctxt->bl31_v1_params.hdr.attr = PARAM_EP_SECURE;
1077
ctxt->bl31_v1_params.bl33_ep_info = (u64)(u32)&ctxt->bl33_ep_info;
1078
1079
// Set BL33 params.
1080
ctxt->bl33_ep_info.hdr.type = PARAM_EP;
1081
ctxt->bl33_ep_info.hdr.version = VERSION_1;
1082
ctxt->bl33_ep_info.hdr.size = sizeof(entry_point_info_t);
1083
ctxt->bl33_ep_info.hdr.attr = PARAM_EP_NON_SECURE;
1084
ctxt->bl33_ep_info.pc = BL33_LOAD_BASE;
1085
ctxt->bl33_ep_info.spsr = SPSR_EL2T;
1086
1087
// Set Platform parameters.
1088
ctxt->bl31_plat_params.tzdram_base = TZDRAM_BASE;
1089
ctxt->bl31_plat_params.tzdram_size = TZDRAM_SIZE;
1090
#if DEBUG_LOG_ATF
1091
ctxt->bl31_plat_params.uart_id = ctxt->serial_port;
1092
#endif
1093
1094
if (!t210b01)
1095
{
1096
// Set SC7-Entry fw parameters. For now BPMP-FW is not used on T210.
1097
ctxt->bl31_plat_params.sc7entry_fw_base = SC7ENTRY_HDR_BASE;
1098
ctxt->bl31_plat_params.sc7entry_fw_size = ALIGN(ctxt->sc7entry_size + SC7ENTRY_HDR_SIZE, SZ_PAGE);
1099
}
1100
1101
// Enable below features.
1102
ctxt->bl31_plat_params.enable_extra_features = BL31_EXTRA_FEATURES_ENABLE;
1103
1104
if (!t210b01)
1105
{
1106
// Set R2P payload.
1107
reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + 0x7C);
1108
memcpy((u8 *)R2P_PAYLOAD_BASE, (u8 *)reloc->start, reloc->end - reloc->start);
1109
memset((u8 *)R2P_PAYLOAD_BASE + 0x94, 0, sizeof(boot_cfg_t)); // Clear Boot Config Storage.
1110
1111
// Set R2P payload fw parameters.
1112
ctxt->bl31_plat_params.r2p_payload_base = R2P_PAYLOAD_BASE;
1113
ctxt->bl31_plat_params.r2p_payload_size = ALIGN(reloc->end - reloc->start, SZ_PAGE);
1114
}
1115
1116
// Set PMC access security. NS is mandatory for T210B01.
1117
ctxt->bl31_plat_params.flags = FLAGS_PMC_NON_SECURE; // Unsecure it unconditionally to reduce SMC calls to a minimum.
1118
// Lift SC7 placement restrictions. Disables TZDRAM increased carveout too.
1119
ctxt->bl31_plat_params.flags |= FLAGS_SC7_NO_BASE_RESTRICTION;
1120
1121
// Prepare EMC table.
1122
if (ctxt->mtc_table)
1123
{
1124
// Set DRAM voltage.
1125
if (ctxt->ram_oc_vdd2)
1126
max7762x_regulator_set_voltage(REGULATOR_SD1, ctxt->ram_oc_vdd2 * 1000);
1127
1128
// Train the rest of the table, apply FSP WAR, set RAM to 800 MHz.
1129
minerva_prep_boot_l4t(ctxt->ram_oc_freq, ctxt->ram_oc_opt, true);
1130
1131
// Set emc table parameters and copy it.
1132
int table_entries = minerva_get_mtc_table_entries();
1133
ctxt->bl31_plat_params.emc_table_base = MTCTABLE_BASE;
1134
ctxt->bl31_plat_params.emc_table_size = sizeof(emc_table_t) * table_entries;
1135
memcpy((u32 *)MTCTABLE_BASE, ctxt->mtc_table, sizeof(emc_table_t) * table_entries);
1136
}
1137
1138
// Set and enable IRAM based BL31 config.
1139
PMC(APBDEV_PMC_SECURE_SCRATCH112) = PMC(APBDEV_PMC_SECURE_SCRATCH108);
1140
PMC(APBDEV_PMC_SECURE_SCRATCH114) = PMC(APBDEV_PMC_SECURE_SCRATCH109);
1141
PMC(APBDEV_PMC_SECURE_SCRATCH108) = (u32)&ctxt->bl31_v1_params;
1142
PMC(APBDEV_PMC_SECURE_SCRATCH109) = (u32)&ctxt->bl31_plat_params;
1143
PMC(APBDEV_PMC_SECURE_SCRATCH110) = BL31_IRAM_PARAMS;
1144
1145
// Set panel model.
1146
PMC(APBDEV_PMC_SECURE_SCRATCH113) = display_get_decoded_panel_id();
1147
1148
// Set charging limit parameters.
1149
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG)
1150
{
1151
int in_volt_lim = 0;
1152
bq24193_get_property(BQ24193_ChargeVoltageLimit, &in_volt_lim);
1153
1154
PMC(APBDEV_PMC_SECURE_SCRATCH113) |= in_volt_lim << 16;
1155
}
1156
1157
// Disable writes to above registers.
1158
PMC(APBDEV_PMC_SEC_DISABLE8) |= BIT(18) | BIT(16) | BIT(12) | BIT(10) | BIT(8);
1159
1160
// Set BPMP-FW parameters.
1161
if (t210b01)
1162
_l4t_bpmpfw_b01_config(ctxt);
1163
1164
// Set carveouts and save them to PMC for SC7 Exit.
1165
_l4t_mc_config_carveout(t210b01);
1166
1167
// Deinit any unneeded HW.
1168
hw_deinit(ctxt->sld_type);
1169
1170
// Do late hardware config.
1171
_l4t_late_hw_config(t210b01);
1172
1173
if (t210b01)
1174
{
1175
// Launch BL31.
1176
ccplex_boot_cpu0(TZDRAM_COLD_ENTRY, true);
1177
1178
// For T210B01, prep reset vector for SC7 save state and start BPMP-FW.
1179
EXCP_VEC(EVP_COP_RESET_VECTOR) = BPMPFW_B01_ENTRYPOINT;
1180
void (*bpmp_fw_ptr)() = (void *)BPMPFW_B01_ENTRYPOINT;
1181
(*bpmp_fw_ptr)();
1182
}
1183
else
1184
{
1185
// If T210, BPMP-FW runs BL31.
1186
void (*bpmp_fw_ptr)() = (void *)BPMPFW_ENTRYPOINT;
1187
(*bpmp_fw_ptr)();
1188
}
1189
1190
// Halt BPMP.
1191
while (true)
1192
bpmp_halt();
1193
}
1194
1195