blob: 8828a943183efac2028808e881c071aad4ad0f93 [file] [log] [blame]
Peng Fan331d40d2021-08-07 16:00:31 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2021 NXP
4 */
5
Peng Fan77c3b9c2021-08-07 16:00:33 +08006#include <asm/io.h>
7#include <asm/arch/clock.h>
8#include <asm/arch/imx-regs.h>
Peng Fan331d40d2021-08-07 16:00:31 +08009#include <asm/arch/sys_proto.h>
Peng Fan9ef89ea2021-08-07 16:00:35 +080010#include <asm/armv8/mmu.h>
Peng Fan77c3b9c2021-08-07 16:00:33 +080011#include <asm/mach-imx/boot_mode.h>
Ye Li610083e2021-08-07 16:00:48 +080012#include <efi_loader.h>
13#include <spl.h>
Peng Fan3912d4b2021-08-07 16:00:59 +080014#include <asm/arch/rdc.h>
Ye Liba472a22021-08-07 16:00:55 +080015#include <asm/arch/s400_api.h>
16#include <asm/arch/mu_hal.h>
17#include <cpu_func.h>
18#include <asm/setup.h>
Ye Lia7990a82021-08-07 16:01:00 +080019#include <dm.h>
20#include <dm/device-internal.h>
21#include <dm/lists.h>
22#include <dm/uclass.h>
23#include <dm/device.h>
24#include <dm/uclass-internal.h>
Peng Fan331d40d2021-08-07 16:00:31 +080025
Peng Fan9ef89ea2021-08-07 16:00:35 +080026DECLARE_GLOBAL_DATA_PTR;
27
Ye Li6f3858d2021-08-07 16:00:39 +080028struct rom_api *g_rom_api = (struct rom_api *)0x1980;
29
Peng Fan331d40d2021-08-07 16:00:31 +080030u32 get_cpu_rev(void)
31{
32 return (MXC_CPU_IMX8ULP << 12) | CHIP_REV_1_0;
33}
Peng Fan77c3b9c2021-08-07 16:00:33 +080034
35enum bt_mode get_boot_mode(void)
36{
37 u32 bt0_cfg = 0;
38
Ye Li981f0402021-08-07 16:00:47 +080039 bt0_cfg = readl(CMC1_BASE_ADDR + 0xa0);
Peng Fan77c3b9c2021-08-07 16:00:33 +080040 bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK);
41
42 if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) {
43 /* No low power boot */
44 if (bt0_cfg & BT0CFG_DUALBOOT_MASK)
45 return DUAL_BOOT;
46 else
47 return SINGLE_BOOT;
48 }
49
50 return LOW_POWER_BOOT;
51}
52
Peng Fanc17f5932021-08-07 16:00:34 +080053#define CMC_SRS_TAMPER BIT(31)
54#define CMC_SRS_SECURITY BIT(30)
55#define CMC_SRS_TZWDG BIT(29)
56#define CMC_SRS_JTAG_RST BIT(28)
57#define CMC_SRS_CORE1 BIT(16)
58#define CMC_SRS_LOCKUP BIT(15)
59#define CMC_SRS_SW BIT(14)
60#define CMC_SRS_WDG BIT(13)
61#define CMC_SRS_PIN_RESET BIT(8)
62#define CMC_SRS_WARM BIT(4)
63#define CMC_SRS_HVD BIT(3)
64#define CMC_SRS_LVD BIT(2)
65#define CMC_SRS_POR BIT(1)
66#define CMC_SRS_WUP BIT(0)
67
68static u32 reset_cause = -1;
69
70static char *get_reset_cause(char *ret)
71{
72 u32 cause1, cause = 0, srs = 0;
Peng Fan9ef89ea2021-08-07 16:00:35 +080073 void __iomem *reg_ssrs = (void __iomem *)(CMC1_BASE_ADDR + 0x88);
74 void __iomem *reg_srs = (void __iomem *)(CMC1_BASE_ADDR + 0x80);
Peng Fanc17f5932021-08-07 16:00:34 +080075
76 if (!ret)
77 return "null";
78
79 srs = readl(reg_srs);
80 cause1 = readl(reg_ssrs);
81
82 reset_cause = cause1;
83
84 cause = cause1 & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM);
85
86 switch (cause) {
87 case CMC_SRS_POR:
88 sprintf(ret, "%s", "POR");
89 break;
90 case CMC_SRS_WUP:
91 sprintf(ret, "%s", "WUP");
92 break;
93 case CMC_SRS_WARM:
94 cause = cause1 & (CMC_SRS_WDG | CMC_SRS_SW |
95 CMC_SRS_JTAG_RST);
96 switch (cause) {
97 case CMC_SRS_WDG:
98 sprintf(ret, "%s", "WARM-WDG");
99 break;
100 case CMC_SRS_SW:
101 sprintf(ret, "%s", "WARM-SW");
102 break;
103 case CMC_SRS_JTAG_RST:
104 sprintf(ret, "%s", "WARM-JTAG");
105 break;
106 default:
107 sprintf(ret, "%s", "WARM-UNKN");
108 break;
109 }
110 break;
111 default:
112 sprintf(ret, "%s-%X", "UNKN", cause1);
113 break;
114 }
115
116 debug("[%X] SRS[%X] %X - ", cause1, srs, srs ^ cause1);
117 return ret;
118}
119
Peng Fan77c3b9c2021-08-07 16:00:33 +0800120#if defined(CONFIG_DISPLAY_CPUINFO)
121const char *get_imx_type(u32 imxtype)
122{
123 return "8ULP";
124}
125
126int print_cpuinfo(void)
127{
128 u32 cpurev;
129 char cause[18];
130
131 cpurev = get_cpu_rev();
132
133 printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n",
134 get_imx_type((cpurev & 0xFF000) >> 12),
135 (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0,
136 mxc_get_clock(MXC_ARM_CLK) / 1000000);
137
Peng Fanc17f5932021-08-07 16:00:34 +0800138 printf("Reset cause: %s\n", get_reset_cause(cause));
139
Peng Fan77c3b9c2021-08-07 16:00:33 +0800140 printf("Boot mode: ");
141 switch (get_boot_mode()) {
142 case LOW_POWER_BOOT:
143 printf("Low power boot\n");
144 break;
145 case DUAL_BOOT:
146 printf("Dual boot\n");
147 break;
148 case SINGLE_BOOT:
149 default:
150 printf("Single boot\n");
151 break;
152 }
153
154 return 0;
155}
156#endif
Peng Fan9ef89ea2021-08-07 16:00:35 +0800157
Peng Fan3a01f722021-08-07 16:00:49 +0800158#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
159#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
160#define REFRESH_WORD0 0xA602 /* 1st refresh word */
161#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
162
163static void disable_wdog(void __iomem *wdog_base)
164{
165 u32 val_cs = readl(wdog_base + 0x00);
166
167 if (!(val_cs & 0x80))
168 return;
169
170 dmb();
171 __raw_writel(REFRESH_WORD0, (wdog_base + 0x04)); /* Refresh the CNT */
172 __raw_writel(REFRESH_WORD1, (wdog_base + 0x04));
173 dmb();
174
175 if (!(val_cs & 800)) {
176 dmb();
177 __raw_writel(UNLOCK_WORD0, (wdog_base + 0x04));
178 __raw_writel(UNLOCK_WORD1, (wdog_base + 0x04));
179 dmb();
180
181 while (!(readl(wdog_base + 0x00) & 0x800))
182 ;
183 }
184 writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
185 writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
186 writel(0x120, (wdog_base + 0x00)); /* Disable it and set update */
187
188 while (!(readl(wdog_base + 0x00) & 0x400))
189 ;
190}
191
Peng Fan9ef89ea2021-08-07 16:00:35 +0800192void init_wdog(void)
193{
Peng Fan3a01f722021-08-07 16:00:49 +0800194 disable_wdog((void __iomem *)WDG3_RBASE);
Peng Fan9ef89ea2021-08-07 16:00:35 +0800195}
196
197static struct mm_region imx8ulp_arm64_mem_map[] = {
198 {
199 /* ROM */
200 .virt = 0x0,
201 .phys = 0x0,
202 .size = 0x40000UL,
203 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
204 PTE_BLOCK_OUTER_SHARE
205 },
206 {
207 /* FLEXSPI0 */
208 .virt = 0x04000000,
209 .phys = 0x04000000,
210 .size = 0x08000000UL,
211 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
212 PTE_BLOCK_NON_SHARE |
213 PTE_BLOCK_PXN | PTE_BLOCK_UXN
214 },
215 {
216 /* SSRAM (align with 2M) */
217 .virt = 0x1FE00000UL,
218 .phys = 0x1FE00000UL,
219 .size = 0x400000UL,
220 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
221 PTE_BLOCK_OUTER_SHARE |
222 PTE_BLOCK_PXN | PTE_BLOCK_UXN
223 }, {
224 /* SRAM1 (align with 2M) */
225 .virt = 0x21000000UL,
226 .phys = 0x21000000UL,
227 .size = 0x200000UL,
228 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
229 PTE_BLOCK_OUTER_SHARE |
230 PTE_BLOCK_PXN | PTE_BLOCK_UXN
231 }, {
232 /* SRAM0 (align with 2M) */
233 .virt = 0x22000000UL,
234 .phys = 0x22000000UL,
235 .size = 0x200000UL,
236 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
237 PTE_BLOCK_OUTER_SHARE |
238 PTE_BLOCK_PXN | PTE_BLOCK_UXN
239 }, {
240 /* Peripherals */
241 .virt = 0x27000000UL,
242 .phys = 0x27000000UL,
243 .size = 0x3000000UL,
244 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
245 PTE_BLOCK_NON_SHARE |
246 PTE_BLOCK_PXN | PTE_BLOCK_UXN
247 }, {
248 /* Peripherals */
249 .virt = 0x2D000000UL,
250 .phys = 0x2D000000UL,
251 .size = 0x1600000UL,
252 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
253 PTE_BLOCK_NON_SHARE |
254 PTE_BLOCK_PXN | PTE_BLOCK_UXN
255 }, {
256 /* FLEXSPI1-2 */
257 .virt = 0x40000000UL,
258 .phys = 0x40000000UL,
259 .size = 0x40000000UL,
260 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
261 PTE_BLOCK_NON_SHARE |
262 PTE_BLOCK_PXN | PTE_BLOCK_UXN
263 }, {
264 /* DRAM1 */
265 .virt = 0x80000000UL,
266 .phys = 0x80000000UL,
267 .size = PHYS_SDRAM_SIZE,
268 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
269 PTE_BLOCK_OUTER_SHARE
270 }, {
271 /*
272 * empty entrie to split table entry 5
273 * if needed when TEEs are used
274 */
275 0,
276 }, {
277 /* List terminator */
278 0,
279 }
280};
281
282struct mm_region *mem_map = imx8ulp_arm64_mem_map;
283
284/* simplify the page table size to enhance boot speed */
285#define MAX_PTE_ENTRIES 512
286#define MAX_MEM_MAP_REGIONS 16
287u64 get_page_table_size(void)
288{
289 u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
290 u64 size = 0;
291
292 /*
293 * For each memory region, the max table size:
294 * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
295 */
296 size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
297
298 /*
299 * We need to duplicate our page table once to have an emergency pt to
300 * resort to when splitting page tables later on
301 */
302 size *= 2;
303
304 /*
305 * We may need to split page tables later on if dcache settings change,
306 * so reserve up to 4 (random pick) page tables for that.
307 */
308 size += one_pt * 4;
309
310 return size;
311}
312
313void enable_caches(void)
314{
315 /* TODO: add TEE memmap region */
316
317 icache_enable();
318 dcache_enable();
319}
320
321int dram_init(void)
322{
323 gd->ram_size = PHYS_SDRAM_SIZE;
324
325 return 0;
326}
327
328#ifdef CONFIG_SERIAL_TAG
329void get_board_serial(struct tag_serialnr *serialnr)
330{
Ye Lia7990a82021-08-07 16:01:00 +0800331 u32 uid[4];
332 u32 res;
333 int ret;
334
335 ret = ahab_read_common_fuse(1, uid, 4, &res);
336 if (ret)
337 printf("ahab read fuse failed %d, 0x%x\n", ret, res);
338 else
339 printf("UID 0x%x,0x%x,0x%x,0x%x\n", uid[0], uid[1], uid[2], uid[3]);
340
341 serialnr->low = uid[0];
342 serialnr->high = uid[3];
Peng Fan9ef89ea2021-08-07 16:00:35 +0800343}
344#endif
345
Ye Liaadd6ca2021-08-07 16:00:50 +0800346static void set_core0_reset_vector(u32 entry)
Peng Fan9ef89ea2021-08-07 16:00:35 +0800347{
Ye Li610083e2021-08-07 16:00:48 +0800348 /* Update SIM1 DGO8 for reset vector base */
Ye Liaadd6ca2021-08-07 16:00:50 +0800349 writel(entry, SIM1_BASE_ADDR + 0x5c);
Ye Li610083e2021-08-07 16:00:48 +0800350
351 /* set update bit */
352 setbits_le32(SIM1_BASE_ADDR + 0x8, 0x1 << 24);
353
354 /* polling the ack */
355 while ((readl(SIM1_BASE_ADDR + 0x8) & (0x1 << 26)) == 0)
356 ;
357
358 /* clear the update */
359 clrbits_le32(SIM1_BASE_ADDR + 0x8, (0x1 << 24));
360
361 /* clear the ack by set 1 */
362 setbits_le32(SIM1_BASE_ADDR + 0x8, (0x1 << 26));
Ye Liaadd6ca2021-08-07 16:00:50 +0800363}
364
Peng Fan3912d4b2021-08-07 16:00:59 +0800365static int trdc_set_access(void)
Peng Fana443ec22021-08-07 16:00:58 +0800366{
367 /*
Peng Fan3912d4b2021-08-07 16:00:59 +0800368 * TRDC mgr + 4 MBC + 2 MRC.
369 * S400 should already configure when release RDC
370 * A35 only map non-secure region for pbridge0 and 1, set sec_access to false
Peng Fana443ec22021-08-07 16:00:58 +0800371 */
Peng Fan3912d4b2021-08-07 16:00:59 +0800372 trdc_mbc_set_access(2, 7, 0, 49, false);
373 trdc_mbc_set_access(2, 7, 0, 50, false);
374 trdc_mbc_set_access(2, 7, 0, 51, false);
375 trdc_mbc_set_access(2, 7, 0, 52, false);
376 trdc_mbc_set_access(2, 7, 0, 53, false);
377 trdc_mbc_set_access(2, 7, 0, 54, false);
Peng Fana443ec22021-08-07 16:00:58 +0800378
Peng Fan3912d4b2021-08-07 16:00:59 +0800379 /* CGC0: PBridge0 slot 47 */
380 trdc_mbc_set_access(2, 7, 0, 47, false);
Peng Fana443ec22021-08-07 16:00:58 +0800381
Peng Fan3912d4b2021-08-07 16:00:59 +0800382 /* Iomuxc0: : PBridge1 slot 33 */
383 trdc_mbc_set_access(2, 7, 1, 33, false);
Peng Fana443ec22021-08-07 16:00:58 +0800384
385 return 0;
386}
387
Ye Liaadd6ca2021-08-07 16:00:50 +0800388int arch_cpu_init(void)
389{
390 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
Ye Liba472a22021-08-07 16:00:55 +0800391 /* Disable wdog */
392 init_wdog();
393
Peng Fana443ec22021-08-07 16:00:58 +0800394 if (get_boot_mode() == SINGLE_BOOT) {
Peng Fan3df56492021-08-07 16:00:57 +0800395 release_rdc(RDC_TRDC);
Peng Fana443ec22021-08-07 16:00:58 +0800396 trdc_set_access();
397 /* LPAV to APD */
398 setbits_le32(0x2802B044, BIT(7));
399 /* GPU 2D/3D to APD */
400 setbits_le32(0x2802B04C, BIT(1) | BIT(2));
401 }
Peng Fan3df56492021-08-07 16:00:57 +0800402
Ye Liba472a22021-08-07 16:00:55 +0800403 /* release xrdc, then allow A35 to write SRAM2 */
Peng Fan3df56492021-08-07 16:00:57 +0800404 release_rdc(RDC_XRDC);
Ye Liba472a22021-08-07 16:00:55 +0800405 xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00);
406
Ye Liaadd6ca2021-08-07 16:00:50 +0800407 clock_init();
408 } else {
409 /* reconfigure core0 reset vector to ROM */
410 set_core0_reset_vector(0x1000);
411 }
412
413 return 0;
414}
415
Ye Lia7990a82021-08-07 16:01:00 +0800416int arch_cpu_init_dm(void)
417{
418 struct udevice *devp;
419 int node, ret;
420
421 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8ulp-mu");
422
423 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
424 if (ret) {
425 printf("could not get S400 mu %d\n", ret);
426 return ret;
427 }
428
429 return 0;
430}
431
Ye Liaadd6ca2021-08-07 16:00:50 +0800432#if defined(CONFIG_SPL_BUILD)
433__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
434{
435 debug("image entry point: 0x%lx\n", spl_image->entry_point);
436
437 set_core0_reset_vector((u32)spl_image->entry_point);
Ye Li610083e2021-08-07 16:00:48 +0800438
439 /* Enable the 512KB cache */
440 setbits_le32(SIM1_BASE_ADDR + 0x30, (0x1 << 4));
441
442 /* reset core */
443 setbits_le32(SIM1_BASE_ADDR + 0x30, (0x1 << 16));
444
445 while (1)
446 ;
447}
448#endif