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