blob: cddcdc2d20dfcf09969ea2f276e29eae8ce51959 [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>
Peng Fan5c2218a2021-08-07 16:00:31 +080012
Peng Fanb15705a2021-08-07 16:00:35 +080013DECLARE_GLOBAL_DATA_PTR;
14
Ye Li7a71c612021-08-07 16:00:39 +080015struct rom_api *g_rom_api = (struct rom_api *)0x1980;
16
Peng Fan5c2218a2021-08-07 16:00:31 +080017u32 get_cpu_rev(void)
18{
19 return (MXC_CPU_IMX8ULP << 12) | CHIP_REV_1_0;
20}
Peng Fan72530162021-08-07 16:00:33 +080021
22enum bt_mode get_boot_mode(void)
23{
24 u32 bt0_cfg = 0;
25
Ye Li0be116e2021-08-07 16:00:47 +080026 bt0_cfg = readl(CMC1_BASE_ADDR + 0xa0);
Peng Fan72530162021-08-07 16:00:33 +080027 bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK);
28
29 if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) {
30 /* No low power boot */
31 if (bt0_cfg & BT0CFG_DUALBOOT_MASK)
32 return DUAL_BOOT;
33 else
34 return SINGLE_BOOT;
35 }
36
37 return LOW_POWER_BOOT;
38}
39
Peng Fanaf4f3b32021-08-07 16:00:34 +080040#define CMC_SRS_TAMPER BIT(31)
41#define CMC_SRS_SECURITY BIT(30)
42#define CMC_SRS_TZWDG BIT(29)
43#define CMC_SRS_JTAG_RST BIT(28)
44#define CMC_SRS_CORE1 BIT(16)
45#define CMC_SRS_LOCKUP BIT(15)
46#define CMC_SRS_SW BIT(14)
47#define CMC_SRS_WDG BIT(13)
48#define CMC_SRS_PIN_RESET BIT(8)
49#define CMC_SRS_WARM BIT(4)
50#define CMC_SRS_HVD BIT(3)
51#define CMC_SRS_LVD BIT(2)
52#define CMC_SRS_POR BIT(1)
53#define CMC_SRS_WUP BIT(0)
54
55static u32 reset_cause = -1;
56
57static char *get_reset_cause(char *ret)
58{
59 u32 cause1, cause = 0, srs = 0;
Peng Fanb15705a2021-08-07 16:00:35 +080060 void __iomem *reg_ssrs = (void __iomem *)(CMC1_BASE_ADDR + 0x88);
61 void __iomem *reg_srs = (void __iomem *)(CMC1_BASE_ADDR + 0x80);
Peng Fanaf4f3b32021-08-07 16:00:34 +080062
63 if (!ret)
64 return "null";
65
66 srs = readl(reg_srs);
67 cause1 = readl(reg_ssrs);
68
69 reset_cause = cause1;
70
71 cause = cause1 & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM);
72
73 switch (cause) {
74 case CMC_SRS_POR:
75 sprintf(ret, "%s", "POR");
76 break;
77 case CMC_SRS_WUP:
78 sprintf(ret, "%s", "WUP");
79 break;
80 case CMC_SRS_WARM:
81 cause = cause1 & (CMC_SRS_WDG | CMC_SRS_SW |
82 CMC_SRS_JTAG_RST);
83 switch (cause) {
84 case CMC_SRS_WDG:
85 sprintf(ret, "%s", "WARM-WDG");
86 break;
87 case CMC_SRS_SW:
88 sprintf(ret, "%s", "WARM-SW");
89 break;
90 case CMC_SRS_JTAG_RST:
91 sprintf(ret, "%s", "WARM-JTAG");
92 break;
93 default:
94 sprintf(ret, "%s", "WARM-UNKN");
95 break;
96 }
97 break;
98 default:
99 sprintf(ret, "%s-%X", "UNKN", cause1);
100 break;
101 }
102
103 debug("[%X] SRS[%X] %X - ", cause1, srs, srs ^ cause1);
104 return ret;
105}
106
Peng Fan72530162021-08-07 16:00:33 +0800107#if defined(CONFIG_DISPLAY_CPUINFO)
108const char *get_imx_type(u32 imxtype)
109{
110 return "8ULP";
111}
112
113int print_cpuinfo(void)
114{
115 u32 cpurev;
116 char cause[18];
117
118 cpurev = get_cpu_rev();
119
120 printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n",
121 get_imx_type((cpurev & 0xFF000) >> 12),
122 (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0,
123 mxc_get_clock(MXC_ARM_CLK) / 1000000);
124
Peng Fanaf4f3b32021-08-07 16:00:34 +0800125 printf("Reset cause: %s\n", get_reset_cause(cause));
126
Peng Fan72530162021-08-07 16:00:33 +0800127 printf("Boot mode: ");
128 switch (get_boot_mode()) {
129 case LOW_POWER_BOOT:
130 printf("Low power boot\n");
131 break;
132 case DUAL_BOOT:
133 printf("Dual boot\n");
134 break;
135 case SINGLE_BOOT:
136 default:
137 printf("Single boot\n");
138 break;
139 }
140
141 return 0;
142}
143#endif
Peng Fanb15705a2021-08-07 16:00:35 +0800144
145void init_wdog(void)
146{
147 /* TODO */
148}
149
150static struct mm_region imx8ulp_arm64_mem_map[] = {
151 {
152 /* ROM */
153 .virt = 0x0,
154 .phys = 0x0,
155 .size = 0x40000UL,
156 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
157 PTE_BLOCK_OUTER_SHARE
158 },
159 {
160 /* FLEXSPI0 */
161 .virt = 0x04000000,
162 .phys = 0x04000000,
163 .size = 0x08000000UL,
164 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
165 PTE_BLOCK_NON_SHARE |
166 PTE_BLOCK_PXN | PTE_BLOCK_UXN
167 },
168 {
169 /* SSRAM (align with 2M) */
170 .virt = 0x1FE00000UL,
171 .phys = 0x1FE00000UL,
172 .size = 0x400000UL,
173 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
174 PTE_BLOCK_OUTER_SHARE |
175 PTE_BLOCK_PXN | PTE_BLOCK_UXN
176 }, {
177 /* SRAM1 (align with 2M) */
178 .virt = 0x21000000UL,
179 .phys = 0x21000000UL,
180 .size = 0x200000UL,
181 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
182 PTE_BLOCK_OUTER_SHARE |
183 PTE_BLOCK_PXN | PTE_BLOCK_UXN
184 }, {
185 /* SRAM0 (align with 2M) */
186 .virt = 0x22000000UL,
187 .phys = 0x22000000UL,
188 .size = 0x200000UL,
189 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
190 PTE_BLOCK_OUTER_SHARE |
191 PTE_BLOCK_PXN | PTE_BLOCK_UXN
192 }, {
193 /* Peripherals */
194 .virt = 0x27000000UL,
195 .phys = 0x27000000UL,
196 .size = 0x3000000UL,
197 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
198 PTE_BLOCK_NON_SHARE |
199 PTE_BLOCK_PXN | PTE_BLOCK_UXN
200 }, {
201 /* Peripherals */
202 .virt = 0x2D000000UL,
203 .phys = 0x2D000000UL,
204 .size = 0x1600000UL,
205 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
206 PTE_BLOCK_NON_SHARE |
207 PTE_BLOCK_PXN | PTE_BLOCK_UXN
208 }, {
209 /* FLEXSPI1-2 */
210 .virt = 0x40000000UL,
211 .phys = 0x40000000UL,
212 .size = 0x40000000UL,
213 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
214 PTE_BLOCK_NON_SHARE |
215 PTE_BLOCK_PXN | PTE_BLOCK_UXN
216 }, {
217 /* DRAM1 */
218 .virt = 0x80000000UL,
219 .phys = 0x80000000UL,
220 .size = PHYS_SDRAM_SIZE,
221 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
222 PTE_BLOCK_OUTER_SHARE
223 }, {
224 /*
225 * empty entrie to split table entry 5
226 * if needed when TEEs are used
227 */
228 0,
229 }, {
230 /* List terminator */
231 0,
232 }
233};
234
235struct mm_region *mem_map = imx8ulp_arm64_mem_map;
236
237/* simplify the page table size to enhance boot speed */
238#define MAX_PTE_ENTRIES 512
239#define MAX_MEM_MAP_REGIONS 16
240u64 get_page_table_size(void)
241{
242 u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
243 u64 size = 0;
244
245 /*
246 * For each memory region, the max table size:
247 * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
248 */
249 size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
250
251 /*
252 * We need to duplicate our page table once to have an emergency pt to
253 * resort to when splitting page tables later on
254 */
255 size *= 2;
256
257 /*
258 * We may need to split page tables later on if dcache settings change,
259 * so reserve up to 4 (random pick) page tables for that.
260 */
261 size += one_pt * 4;
262
263 return size;
264}
265
266void enable_caches(void)
267{
268 /* TODO: add TEE memmap region */
269
270 icache_enable();
271 dcache_enable();
272}
273
274int dram_init(void)
275{
276 gd->ram_size = PHYS_SDRAM_SIZE;
277
278 return 0;
279}
280
281#ifdef CONFIG_SERIAL_TAG
282void get_board_serial(struct tag_serialnr *serialnr)
283{
284 /* TODO */
285}
286#endif
287
288int arch_cpu_init(void)
289{
Peng Fan690eea12021-08-07 16:00:45 +0800290 if (IS_ENABLED(CONFIG_SPL_BUILD))
291 clock_init();
292
Peng Fanb15705a2021-08-07 16:00:35 +0800293 return 0;
294}