blob: 25b4fbd294e3c3501890da62023151e631ecee01 [file] [log] [blame]
Peng Fan5c2218a2021-08-07 16:00:31 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2021 NXP
4 */
5
Peng Fan72530162021-08-07 16:00:33 +08006#include <asm/io.h>
7#include <asm/arch/clock.h>
8#include <asm/arch/imx-regs.h>
Peng Fan5c2218a2021-08-07 16:00:31 +08009#include <asm/arch/sys_proto.h>
Peng Fanb15705a2021-08-07 16:00:35 +080010#include <asm/armv8/mmu.h>
Peng Fan72530162021-08-07 16:00:33 +080011#include <asm/mach-imx/boot_mode.h>
Ye Li88044c72021-08-07 16:01:01 +080012#include <asm/global_data.h>
Ye Li6dd43022021-08-07 16:00:48 +080013#include <efi_loader.h>
Simon Glassfc557362022-03-04 08:43:05 -070014#include <event.h>
Ye Li6dd43022021-08-07 16:00:48 +080015#include <spl.h>
Peng Fan9c87e462021-08-07 16:00:59 +080016#include <asm/arch/rdc.h>
Ye Li853cc9d2021-08-07 16:00:55 +080017#include <asm/arch/s400_api.h>
18#include <asm/arch/mu_hal.h>
19#include <cpu_func.h>
20#include <asm/setup.h>
Ye Li7bea5b02021-08-07 16:01:00 +080021#include <dm.h>
22#include <dm/device-internal.h>
23#include <dm/lists.h>
24#include <dm/uclass.h>
25#include <dm/device.h>
26#include <dm/uclass-internal.h>
Ye Li72012622021-10-29 09:46:15 +080027#include <fuse.h>
Alice Guof2c4a392021-10-29 09:46:32 +080028#include <thermal.h>
Ye Li2e9f15c2022-04-06 14:30:08 +080029#include <linux/iopoll.h>
Peng Fan5c2218a2021-08-07 16:00:31 +080030
Peng Fanb15705a2021-08-07 16:00:35 +080031DECLARE_GLOBAL_DATA_PTR;
32
Ye Li7a71c612021-08-07 16:00:39 +080033struct rom_api *g_rom_api = (struct rom_api *)0x1980;
34
Ye Li88044c72021-08-07 16:01:01 +080035enum boot_device get_boot_device(void)
36{
37 volatile gd_t *pgd = gd;
38 int ret;
39 u32 boot;
40 u16 boot_type;
41 u8 boot_instance;
42 enum boot_device boot_dev = SD1_BOOT;
43
44 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
45 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
46 set_gd(pgd);
47
48 if (ret != ROM_API_OKAY) {
49 puts("ROMAPI: failure at query_boot_info\n");
50 return -1;
51 }
52
53 boot_type = boot >> 16;
54 boot_instance = (boot >> 8) & 0xff;
55
56 switch (boot_type) {
57 case BT_DEV_TYPE_SD:
58 boot_dev = boot_instance + SD1_BOOT;
59 break;
60 case BT_DEV_TYPE_MMC:
61 boot_dev = boot_instance + MMC1_BOOT;
62 break;
63 case BT_DEV_TYPE_NAND:
64 boot_dev = NAND_BOOT;
65 break;
66 case BT_DEV_TYPE_FLEXSPINOR:
67 boot_dev = QSPI_BOOT;
68 break;
69 case BT_DEV_TYPE_USB:
70 boot_dev = USB_BOOT;
71 break;
72 default:
73 break;
74 }
75
76 return boot_dev;
77}
78
79bool is_usb_boot(void)
80{
81 return get_boot_device() == USB_BOOT;
82}
83
84#ifdef CONFIG_ENV_IS_IN_MMC
85__weak int board_mmc_get_env_dev(int devno)
86{
87 return devno;
88}
89
90int mmc_get_env_dev(void)
91{
92 volatile gd_t *pgd = gd;
93 int ret;
94 u32 boot;
95 u16 boot_type;
96 u8 boot_instance;
97
98 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
99 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
100 set_gd(pgd);
101
102 if (ret != ROM_API_OKAY) {
103 puts("ROMAPI: failure at query_boot_info\n");
104 return CONFIG_SYS_MMC_ENV_DEV;
105 }
106
107 boot_type = boot >> 16;
108 boot_instance = (boot >> 8) & 0xff;
109
110 /* If not boot from sd/mmc, use default value */
111 if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
112 return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
113
114 return board_mmc_get_env_dev(boot_instance);
115}
116#endif
117
Peng Fan5c2218a2021-08-07 16:00:31 +0800118u32 get_cpu_rev(void)
119{
120 return (MXC_CPU_IMX8ULP << 12) | CHIP_REV_1_0;
121}
Peng Fan72530162021-08-07 16:00:33 +0800122
123enum bt_mode get_boot_mode(void)
124{
125 u32 bt0_cfg = 0;
126
Ye Li0e358052021-08-07 16:01:07 +0800127 bt0_cfg = readl(SIM_SEC_BASE_ADDR + 0x24);
Peng Fan72530162021-08-07 16:00:33 +0800128 bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK);
129
130 if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) {
131 /* No low power boot */
132 if (bt0_cfg & BT0CFG_DUALBOOT_MASK)
133 return DUAL_BOOT;
134 else
135 return SINGLE_BOOT;
136 }
137
138 return LOW_POWER_BOOT;
139}
140
Ye Li2e9f15c2022-04-06 14:30:08 +0800141bool m33_image_booted(void)
142{
143 u32 gp6;
144
145 /* DGO_GP6 */
146 gp6 = readl(SIM_SEC_BASE_ADDR + 0x28);
147 if (gp6 & BIT(5))
148 return true;
149
150 return false;
151}
152
153int m33_image_handshake(ulong timeout_ms)
154{
155 u32 fsr;
156 int ret;
157 ulong timeout_us = timeout_ms * 1000;
158
Ye Li2e9f15c2022-04-06 14:30:08 +0800159 /* Notify m33 that it's ready to do init srtm(enable mu receive interrupt and so on) */
160 setbits_le32(MU0_B_BASE_ADDR + 0x100, BIT(0)); /* set FCR F0 flag of MU0_MUB */
161
162 /*
163 * Wait m33 to set FCR F0 flag of MU0_MUA
164 * Clear FCR F0 flag of MU0_MUB after m33 has set FCR F0 flag of MU0_MUA
165 */
166 ret = readl_poll_sleep_timeout(MU0_B_BASE_ADDR + 0x104, fsr, fsr & BIT(0), 10, timeout_us);
167 if (!ret)
168 clrbits_le32(MU0_B_BASE_ADDR + 0x100, BIT(0));
169
170 return ret;
171}
172
Peng Fanaf4f3b32021-08-07 16:00:34 +0800173#define CMC_SRS_TAMPER BIT(31)
174#define CMC_SRS_SECURITY BIT(30)
175#define CMC_SRS_TZWDG BIT(29)
176#define CMC_SRS_JTAG_RST BIT(28)
177#define CMC_SRS_CORE1 BIT(16)
178#define CMC_SRS_LOCKUP BIT(15)
179#define CMC_SRS_SW BIT(14)
180#define CMC_SRS_WDG BIT(13)
181#define CMC_SRS_PIN_RESET BIT(8)
182#define CMC_SRS_WARM BIT(4)
183#define CMC_SRS_HVD BIT(3)
184#define CMC_SRS_LVD BIT(2)
185#define CMC_SRS_POR BIT(1)
186#define CMC_SRS_WUP BIT(0)
187
Peng Fanaf4f3b32021-08-07 16:00:34 +0800188static char *get_reset_cause(char *ret)
189{
190 u32 cause1, cause = 0, srs = 0;
Peng Fanb15705a2021-08-07 16:00:35 +0800191 void __iomem *reg_ssrs = (void __iomem *)(CMC1_BASE_ADDR + 0x88);
192 void __iomem *reg_srs = (void __iomem *)(CMC1_BASE_ADDR + 0x80);
Peng Fanaf4f3b32021-08-07 16:00:34 +0800193
194 if (!ret)
195 return "null";
196
197 srs = readl(reg_srs);
198 cause1 = readl(reg_ssrs);
199
Peng Fan0d720e22021-08-07 16:01:06 +0800200 cause = srs & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM);
Peng Fanaf4f3b32021-08-07 16:00:34 +0800201
202 switch (cause) {
203 case CMC_SRS_POR:
204 sprintf(ret, "%s", "POR");
205 break;
206 case CMC_SRS_WUP:
207 sprintf(ret, "%s", "WUP");
208 break;
209 case CMC_SRS_WARM:
Peng Fan0d720e22021-08-07 16:01:06 +0800210 cause = srs & (CMC_SRS_WDG | CMC_SRS_SW |
Peng Fanaf4f3b32021-08-07 16:00:34 +0800211 CMC_SRS_JTAG_RST);
212 switch (cause) {
213 case CMC_SRS_WDG:
214 sprintf(ret, "%s", "WARM-WDG");
215 break;
216 case CMC_SRS_SW:
217 sprintf(ret, "%s", "WARM-SW");
218 break;
219 case CMC_SRS_JTAG_RST:
220 sprintf(ret, "%s", "WARM-JTAG");
221 break;
222 default:
223 sprintf(ret, "%s", "WARM-UNKN");
224 break;
225 }
226 break;
227 default:
Peng Fan0d720e22021-08-07 16:01:06 +0800228 sprintf(ret, "%s-%X", "UNKN", srs);
Peng Fanaf4f3b32021-08-07 16:00:34 +0800229 break;
230 }
231
232 debug("[%X] SRS[%X] %X - ", cause1, srs, srs ^ cause1);
233 return ret;
234}
235
Peng Fan72530162021-08-07 16:00:33 +0800236#if defined(CONFIG_DISPLAY_CPUINFO)
237const char *get_imx_type(u32 imxtype)
238{
239 return "8ULP";
240}
241
242int print_cpuinfo(void)
243{
244 u32 cpurev;
245 char cause[18];
246
247 cpurev = get_cpu_rev();
248
Ye Lif012ceb2021-10-29 09:46:24 +0800249 printf("CPU: i.MX%s rev%d.%d at %d MHz\n",
Peng Fan72530162021-08-07 16:00:33 +0800250 get_imx_type((cpurev & 0xFF000) >> 12),
251 (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0,
252 mxc_get_clock(MXC_ARM_CLK) / 1000000);
253
Alice Guof2c4a392021-10-29 09:46:32 +0800254#if defined(CONFIG_IMX_PMC_TEMPERATURE)
255 struct udevice *udev;
256 int ret, temp;
257
258 ret = uclass_get_device(UCLASS_THERMAL, 0, &udev);
259 if (!ret) {
260 ret = thermal_get_temp(udev, &temp);
261 if (!ret)
262 printf("CPU current temperature: %d\n", temp);
263 else
264 debug(" - failed to get CPU current temperature\n");
265 } else {
266 debug(" - failed to get CPU current temperature\n");
267 }
268#endif
269
Peng Fanaf4f3b32021-08-07 16:00:34 +0800270 printf("Reset cause: %s\n", get_reset_cause(cause));
271
Peng Fan72530162021-08-07 16:00:33 +0800272 printf("Boot mode: ");
273 switch (get_boot_mode()) {
274 case LOW_POWER_BOOT:
275 printf("Low power boot\n");
276 break;
277 case DUAL_BOOT:
278 printf("Dual boot\n");
279 break;
280 case SINGLE_BOOT:
281 default:
282 printf("Single boot\n");
283 break;
284 }
285
286 return 0;
287}
288#endif
Peng Fanb15705a2021-08-07 16:00:35 +0800289
Peng Fanc84bc102021-08-07 16:00:49 +0800290#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
291#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
292#define REFRESH_WORD0 0xA602 /* 1st refresh word */
293#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
294
295static void disable_wdog(void __iomem *wdog_base)
296{
297 u32 val_cs = readl(wdog_base + 0x00);
298
299 if (!(val_cs & 0x80))
300 return;
301
302 dmb();
303 __raw_writel(REFRESH_WORD0, (wdog_base + 0x04)); /* Refresh the CNT */
304 __raw_writel(REFRESH_WORD1, (wdog_base + 0x04));
305 dmb();
306
307 if (!(val_cs & 800)) {
308 dmb();
309 __raw_writel(UNLOCK_WORD0, (wdog_base + 0x04));
310 __raw_writel(UNLOCK_WORD1, (wdog_base + 0x04));
311 dmb();
312
313 while (!(readl(wdog_base + 0x00) & 0x800))
314 ;
315 }
316 writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
317 writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
318 writel(0x120, (wdog_base + 0x00)); /* Disable it and set update */
319
320 while (!(readl(wdog_base + 0x00) & 0x400))
321 ;
322}
323
Peng Fanb15705a2021-08-07 16:00:35 +0800324void init_wdog(void)
325{
Peng Fanc84bc102021-08-07 16:00:49 +0800326 disable_wdog((void __iomem *)WDG3_RBASE);
Peng Fanb15705a2021-08-07 16:00:35 +0800327}
328
329static struct mm_region imx8ulp_arm64_mem_map[] = {
330 {
331 /* ROM */
332 .virt = 0x0,
333 .phys = 0x0,
334 .size = 0x40000UL,
335 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
336 PTE_BLOCK_OUTER_SHARE
337 },
338 {
339 /* FLEXSPI0 */
340 .virt = 0x04000000,
341 .phys = 0x04000000,
342 .size = 0x08000000UL,
343 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
344 PTE_BLOCK_NON_SHARE |
345 PTE_BLOCK_PXN | PTE_BLOCK_UXN
346 },
347 {
348 /* SSRAM (align with 2M) */
349 .virt = 0x1FE00000UL,
350 .phys = 0x1FE00000UL,
351 .size = 0x400000UL,
352 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
353 PTE_BLOCK_OUTER_SHARE |
354 PTE_BLOCK_PXN | PTE_BLOCK_UXN
355 }, {
356 /* SRAM1 (align with 2M) */
357 .virt = 0x21000000UL,
358 .phys = 0x21000000UL,
359 .size = 0x200000UL,
360 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
361 PTE_BLOCK_OUTER_SHARE |
362 PTE_BLOCK_PXN | PTE_BLOCK_UXN
363 }, {
364 /* SRAM0 (align with 2M) */
365 .virt = 0x22000000UL,
366 .phys = 0x22000000UL,
367 .size = 0x200000UL,
368 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
369 PTE_BLOCK_OUTER_SHARE |
370 PTE_BLOCK_PXN | PTE_BLOCK_UXN
371 }, {
372 /* Peripherals */
373 .virt = 0x27000000UL,
374 .phys = 0x27000000UL,
375 .size = 0x3000000UL,
376 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
377 PTE_BLOCK_NON_SHARE |
378 PTE_BLOCK_PXN | PTE_BLOCK_UXN
379 }, {
380 /* Peripherals */
381 .virt = 0x2D000000UL,
382 .phys = 0x2D000000UL,
383 .size = 0x1600000UL,
384 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
385 PTE_BLOCK_NON_SHARE |
386 PTE_BLOCK_PXN | PTE_BLOCK_UXN
387 }, {
388 /* FLEXSPI1-2 */
389 .virt = 0x40000000UL,
390 .phys = 0x40000000UL,
391 .size = 0x40000000UL,
392 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
393 PTE_BLOCK_NON_SHARE |
394 PTE_BLOCK_PXN | PTE_BLOCK_UXN
395 }, {
396 /* DRAM1 */
397 .virt = 0x80000000UL,
398 .phys = 0x80000000UL,
399 .size = PHYS_SDRAM_SIZE,
400 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
401 PTE_BLOCK_OUTER_SHARE
402 }, {
403 /*
404 * empty entrie to split table entry 5
405 * if needed when TEEs are used
406 */
407 0,
408 }, {
409 /* List terminator */
410 0,
411 }
412};
413
414struct mm_region *mem_map = imx8ulp_arm64_mem_map;
415
Ji Luo2fd258c2022-04-06 14:30:28 +0800416static unsigned int imx8ulp_find_dram_entry_in_mem_map(void)
417{
418 int i;
419
420 for (i = 0; i < ARRAY_SIZE(imx8ulp_arm64_mem_map); i++)
421 if (imx8ulp_arm64_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE)
422 return i;
423
424 hang(); /* Entry not found, this must never happen. */
425}
426
Peng Fanb15705a2021-08-07 16:00:35 +0800427/* simplify the page table size to enhance boot speed */
428#define MAX_PTE_ENTRIES 512
429#define MAX_MEM_MAP_REGIONS 16
430u64 get_page_table_size(void)
431{
432 u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
433 u64 size = 0;
434
435 /*
436 * For each memory region, the max table size:
437 * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
438 */
439 size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
440
441 /*
442 * We need to duplicate our page table once to have an emergency pt to
443 * resort to when splitting page tables later on
444 */
445 size *= 2;
446
447 /*
448 * We may need to split page tables later on if dcache settings change,
449 * so reserve up to 4 (random pick) page tables for that.
450 */
451 size += one_pt * 4;
452
453 return size;
454}
455
456void enable_caches(void)
457{
Ji Luo2fd258c2022-04-06 14:30:28 +0800458 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */
459 if (rom_pointer[1]) {
460 /*
461 * TEE are loaded, So the ddr bank structures
462 * have been modified update mmu table accordingly
463 */
464 int i = 0;
465 int entry = imx8ulp_find_dram_entry_in_mem_map();
466 u64 attrs = imx8ulp_arm64_mem_map[entry].attrs;
467
468 while (i < CONFIG_NR_DRAM_BANKS &&
469 entry < ARRAY_SIZE(imx8ulp_arm64_mem_map)) {
470 if (gd->bd->bi_dram[i].start == 0)
471 break;
472 imx8ulp_arm64_mem_map[entry].phys = gd->bd->bi_dram[i].start;
473 imx8ulp_arm64_mem_map[entry].virt = gd->bd->bi_dram[i].start;
474 imx8ulp_arm64_mem_map[entry].size = gd->bd->bi_dram[i].size;
475 imx8ulp_arm64_mem_map[entry].attrs = attrs;
476 debug("Added memory mapping (%d): %llx %llx\n", entry,
477 imx8ulp_arm64_mem_map[entry].phys, imx8ulp_arm64_mem_map[entry].size);
478 i++; entry++;
479 }
480 }
Peng Fanb15705a2021-08-07 16:00:35 +0800481
482 icache_enable();
483 dcache_enable();
484}
485
Ji Luo2fd258c2022-04-06 14:30:28 +0800486__weak int board_phys_sdram_size(phys_size_t *size)
487{
488 if (!size)
489 return -EINVAL;
490
491 *size = PHYS_SDRAM_SIZE;
492 return 0;
493}
494
Peng Fanb15705a2021-08-07 16:00:35 +0800495int dram_init(void)
496{
Ji Luo2fd258c2022-04-06 14:30:28 +0800497 unsigned int entry = imx8ulp_find_dram_entry_in_mem_map();
498 phys_size_t sdram_size;
499 int ret;
500
501 ret = board_phys_sdram_size(&sdram_size);
502 if (ret)
503 return ret;
504
505 /* rom_pointer[1] contains the size of TEE occupies */
506 if (rom_pointer[1])
507 gd->ram_size = sdram_size - rom_pointer[1];
508 else
509 gd->ram_size = sdram_size;
510
511 /* also update the SDRAM size in the mem_map used externally */
512 imx8ulp_arm64_mem_map[entry].size = sdram_size;
513 return 0;
514}
515
516int dram_init_banksize(void)
517{
518 int bank = 0;
519 int ret;
520 phys_size_t sdram_size;
521
522 ret = board_phys_sdram_size(&sdram_size);
523 if (ret)
524 return ret;
525
526 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
527 if (rom_pointer[1]) {
528 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
529 phys_size_t optee_size = (size_t)rom_pointer[1];
530
531 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
532 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_size)) {
533 if (++bank >= CONFIG_NR_DRAM_BANKS) {
534 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
535 return -1;
536 }
537
538 gd->bd->bi_dram[bank].start = optee_start + optee_size;
539 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
540 sdram_size - gd->bd->bi_dram[bank].start;
541 }
542 } else {
543 gd->bd->bi_dram[bank].size = sdram_size;
544 }
Peng Fanb15705a2021-08-07 16:00:35 +0800545
546 return 0;
547}
548
Ji Luo2fd258c2022-04-06 14:30:28 +0800549phys_size_t get_effective_memsize(void)
550{
551 /* return the first bank as effective memory */
552 if (rom_pointer[1])
553 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
554
555 return gd->ram_size;
556}
557
Tom Riniae21e7f2021-08-30 09:16:29 -0400558#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
Peng Fanb15705a2021-08-07 16:00:35 +0800559void get_board_serial(struct tag_serialnr *serialnr)
560{
Ye Li7bea5b02021-08-07 16:01:00 +0800561 u32 uid[4];
562 u32 res;
563 int ret;
564
565 ret = ahab_read_common_fuse(1, uid, 4, &res);
566 if (ret)
567 printf("ahab read fuse failed %d, 0x%x\n", ret, res);
568 else
569 printf("UID 0x%x,0x%x,0x%x,0x%x\n", uid[0], uid[1], uid[2], uid[3]);
570
571 serialnr->low = uid[0];
572 serialnr->high = uid[3];
Peng Fanb15705a2021-08-07 16:00:35 +0800573}
574#endif
575
Ye Li6ee435eb2021-08-07 16:00:50 +0800576static void set_core0_reset_vector(u32 entry)
Peng Fanb15705a2021-08-07 16:00:35 +0800577{
Ye Li6dd43022021-08-07 16:00:48 +0800578 /* Update SIM1 DGO8 for reset vector base */
Ye Li6ee435eb2021-08-07 16:00:50 +0800579 writel(entry, SIM1_BASE_ADDR + 0x5c);
Ye Li6dd43022021-08-07 16:00:48 +0800580
581 /* set update bit */
582 setbits_le32(SIM1_BASE_ADDR + 0x8, 0x1 << 24);
583
584 /* polling the ack */
585 while ((readl(SIM1_BASE_ADDR + 0x8) & (0x1 << 26)) == 0)
586 ;
587
588 /* clear the update */
589 clrbits_le32(SIM1_BASE_ADDR + 0x8, (0x1 << 24));
590
591 /* clear the ack by set 1 */
592 setbits_le32(SIM1_BASE_ADDR + 0x8, (0x1 << 26));
Ye Li6ee435eb2021-08-07 16:00:50 +0800593}
594
Peng Fan9c87e462021-08-07 16:00:59 +0800595static int trdc_set_access(void)
Peng Fanb5c41b12021-08-07 16:00:58 +0800596{
597 /*
Peng Fan9c87e462021-08-07 16:00:59 +0800598 * TRDC mgr + 4 MBC + 2 MRC.
599 * S400 should already configure when release RDC
600 * A35 only map non-secure region for pbridge0 and 1, set sec_access to false
Peng Fanb5c41b12021-08-07 16:00:58 +0800601 */
Peng Fan9c87e462021-08-07 16:00:59 +0800602 trdc_mbc_set_access(2, 7, 0, 49, false);
603 trdc_mbc_set_access(2, 7, 0, 50, false);
604 trdc_mbc_set_access(2, 7, 0, 51, false);
605 trdc_mbc_set_access(2, 7, 0, 52, false);
606 trdc_mbc_set_access(2, 7, 0, 53, false);
607 trdc_mbc_set_access(2, 7, 0, 54, false);
Peng Fanb5c41b12021-08-07 16:00:58 +0800608
Peng Fan9c87e462021-08-07 16:00:59 +0800609 /* CGC0: PBridge0 slot 47 */
610 trdc_mbc_set_access(2, 7, 0, 47, false);
Peng Fanb5c41b12021-08-07 16:00:58 +0800611
Peng Fan9c87e462021-08-07 16:00:59 +0800612 /* Iomuxc0: : PBridge1 slot 33 */
613 trdc_mbc_set_access(2, 7, 1, 33, false);
Peng Fanb5c41b12021-08-07 16:00:58 +0800614
Ye Lid325d372021-10-29 09:46:20 +0800615 /* flexspi0 */
616 trdc_mrc_region_set_access(0, 7, 0x04000000, 0x0c000000, false);
Ye Li27666ca2021-10-29 09:46:21 +0800617
618 /* tpm0: PBridge1 slot 21 */
619 trdc_mbc_set_access(2, 7, 1, 21, false);
620 /* lpi2c0: PBridge1 slot 24 */
621 trdc_mbc_set_access(2, 7, 1, 24, false);
Peng Fanb5c41b12021-08-07 16:00:58 +0800622 return 0;
623}
624
Ye Liec10a802022-04-06 14:30:17 +0800625void lpav_configure(bool lpav_to_m33)
Ye Li43819eb2021-10-29 09:46:16 +0800626{
Ye Liec10a802022-04-06 14:30:17 +0800627 if (!lpav_to_m33)
628 setbits_le32(SIM_SEC_BASE_ADDR + 0x44, BIT(7)); /* LPAV to APD */
Ye Li43819eb2021-10-29 09:46:16 +0800629
Peng Fanfa609b42021-10-29 09:46:17 +0800630 /* PXP/GPU 2D/3D/DCNANO/MIPI_DSI/EPDC/HIFI4 to APD */
631 setbits_le32(SIM_SEC_BASE_ADDR + 0x4c, 0x7F);
Ye Li43819eb2021-10-29 09:46:16 +0800632
633 /* LPAV slave/dma2 ch allocation and request allocation to APD */
634 writel(0x1f, SIM_SEC_BASE_ADDR + 0x50);
635 writel(0xffffffff, SIM_SEC_BASE_ADDR + 0x54);
636 writel(0x003fffff, SIM_SEC_BASE_ADDR + 0x58);
Ye Li715cfa02021-10-29 09:46:23 +0800637}
Ye Lia0311552021-10-29 09:46:22 +0800638
Ye Li133f8b82021-10-29 09:46:25 +0800639void load_lposc_fuse(void)
640{
641 int ret;
642 u32 val = 0, val2 = 0, reg;
643
644 ret = fuse_read(25, 0, &val);
645 if (ret)
646 return; /* failed */
647
648 ret = fuse_read(25, 1, &val2);
649 if (ret)
650 return; /* failed */
651
652 /* LPOSCCTRL */
653 reg = readl(0x2802f304);
654 reg &= ~0xff;
655 reg |= (val & 0xff);
656 writel(reg, 0x2802f304);
657}
658
Ye Li715cfa02021-10-29 09:46:23 +0800659void set_lpav_qos(void)
660{
Ye Lia0311552021-10-29 09:46:22 +0800661 /* Set read QoS of dcnano on LPAV NIC */
662 writel(0xf, 0x2e447100);
Ye Li43819eb2021-10-29 09:46:16 +0800663}
664
Ye Li6ee435eb2021-08-07 16:00:50 +0800665int arch_cpu_init(void)
666{
667 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
Ye Li72012622021-10-29 09:46:15 +0800668 u32 val = 0;
669 int ret;
670 bool rdc_en = true; /* Default assume DBD_EN is set */
671
Peng Fan21bda432022-04-06 14:30:27 +0800672 /* Enable System Reset Interrupt using WDOG_AD */
673 setbits_le32(CMC1_BASE_ADDR + 0x8C, BIT(13));
674 /* Clear AD_PERIPH Power switch domain out of reset interrupt flag */
675 setbits_le32(CMC1_BASE_ADDR + 0x70, BIT(4));
676
677 if (readl(CMC1_BASE_ADDR + 0x90) & BIT(13)) {
678 /* Clear System Reset Interrupt Flag Register of WDOG_AD */
679 setbits_le32(CMC1_BASE_ADDR + 0x90, BIT(13));
680 /* Reset WDOG to clear reset request */
681 pcc_reset_peripheral(3, WDOG3_PCC3_SLOT, true);
682 pcc_reset_peripheral(3, WDOG3_PCC3_SLOT, false);
683 }
684
Ye Li853cc9d2021-08-07 16:00:55 +0800685 /* Disable wdog */
686 init_wdog();
687
Ye Li72012622021-10-29 09:46:15 +0800688 /* Read DBD_EN fuse */
689 ret = fuse_read(8, 1, &val);
690 if (!ret)
691 rdc_en = !!(val & 0x4000);
692
Peng Fanb5c41b12021-08-07 16:00:58 +0800693 if (get_boot_mode() == SINGLE_BOOT) {
Ye Li72012622021-10-29 09:46:15 +0800694 if (rdc_en)
695 release_rdc(RDC_TRDC);
696
Peng Fanb5c41b12021-08-07 16:00:58 +0800697 trdc_set_access();
Ye Liec10a802022-04-06 14:30:17 +0800698 lpav_configure(false);
699 } else {
700 lpav_configure(true);
Peng Fanb5c41b12021-08-07 16:00:58 +0800701 }
Peng Fanfa55b212021-08-07 16:00:57 +0800702
Ye Li72012622021-10-29 09:46:15 +0800703 /* Release xrdc, then allow A35 to write SRAM2 */
704 if (rdc_en)
705 release_rdc(RDC_XRDC);
706
Ye Li853cc9d2021-08-07 16:00:55 +0800707 xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00);
708
Peng Fan4cdb3a32022-04-06 14:30:12 +0800709 clock_init_early();
Ye Li6ee435eb2021-08-07 16:00:50 +0800710 } else {
711 /* reconfigure core0 reset vector to ROM */
712 set_core0_reset_vector(0x1000);
713 }
714
715 return 0;
716}
717
Simon Glassfc557362022-03-04 08:43:05 -0700718static int imx8ulp_check_mu(void *ctx, struct event *event)
Ye Li7bea5b02021-08-07 16:01:00 +0800719{
720 struct udevice *devp;
721 int node, ret;
722
723 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8ulp-mu");
724
725 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
726 if (ret) {
727 printf("could not get S400 mu %d\n", ret);
728 return ret;
729 }
730
731 return 0;
732}
Simon Glassfc557362022-03-04 08:43:05 -0700733EVENT_SPY(EVT_DM_POST_INIT, imx8ulp_check_mu);
Ye Li7bea5b02021-08-07 16:01:00 +0800734
Ye Li6ee435eb2021-08-07 16:00:50 +0800735#if defined(CONFIG_SPL_BUILD)
736__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
737{
738 debug("image entry point: 0x%lx\n", spl_image->entry_point);
739
740 set_core0_reset_vector((u32)spl_image->entry_point);
Ye Li6dd43022021-08-07 16:00:48 +0800741
742 /* Enable the 512KB cache */
743 setbits_le32(SIM1_BASE_ADDR + 0x30, (0x1 << 4));
744
745 /* reset core */
746 setbits_le32(SIM1_BASE_ADDR + 0x30, (0x1 << 16));
747
748 while (1)
749 ;
750}
751#endif
Peng Fanfa6ae052021-08-07 16:01:03 +0800752
753void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
754{
Ye Li992b0ae2021-10-29 09:46:28 +0800755 u32 val[2] = {};
756 int ret;
757
758 ret = fuse_read(5, 3, &val[0]);
759 if (ret)
760 goto err;
761
762 ret = fuse_read(5, 4, &val[1]);
763 if (ret)
764 goto err;
765
766 mac[0] = val[0];
767 mac[1] = val[0] >> 8;
768 mac[2] = val[0] >> 16;
769 mac[3] = val[0] >> 24;
770 mac[4] = val[1];
771 mac[5] = val[1] >> 8;
772
773 debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
774 __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
775 return;
776err:
Peng Fanfa6ae052021-08-07 16:01:03 +0800777 memset(mac, 0, 6);
Ye Li992b0ae2021-10-29 09:46:28 +0800778 printf("%s: fuse read err: %d\n", __func__, ret);
Peng Fanfa6ae052021-08-07 16:01:03 +0800779}
Ye Li479fd4a2021-08-07 16:01:08 +0800780
781int (*card_emmc_is_boot_part_en)(void) = (void *)0x67cc;
782u32 spl_arch_boot_image_offset(u32 image_offset, u32 rom_bt_dev)
783{
784 /* Hard code for eMMC image_offset on 8ULP ROM, need fix by ROM, temp workaround */
785 if (((rom_bt_dev >> 16) & 0xff) == BT_DEV_TYPE_MMC && card_emmc_is_boot_part_en())
786 image_offset = 0;
787
788 return image_offset;
789}