]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
d60a2099 WH |
2 | /* |
3 | * Copyright 2014 Freescale Semiconductor, Inc. | |
8976556a | 4 | * Copyright 2021 NXP |
d60a2099 WH |
5 | */ |
6 | ||
d678a59d | 7 | #include <common.h> |
62270f43 | 8 | #include <cpu_func.h> |
691d719d | 9 | #include <init.h> |
90526e9f | 10 | #include <net.h> |
2189d5f1 | 11 | #include <vsprintf.h> |
d60a2099 | 12 | #include <asm/arch/clock.h> |
401d1c4f | 13 | #include <asm/global_data.h> |
d60a2099 WH |
14 | #include <asm/io.h> |
15 | #include <asm/arch/immap_ls102xa.h> | |
636ef956 ML |
16 | #include <asm/cache.h> |
17 | #include <asm/system.h> | |
d60a2099 WH |
18 | #include <tsec.h> |
19 | #include <netdev.h> | |
20 | #include <fsl_esdhc.h> | |
f861f51c FE |
21 | #include <config.h> |
22 | #include <fsl_wdog.h> | |
c05ed00a | 23 | #include <linux/delay.h> |
8976556a | 24 | #include <dm.h> |
d60a2099 | 25 | |
306fa012 | 26 | #include "fsl_epu.h" |
27 | ||
9f076be7 | 28 | #define DCSR_RCPM2_BLOCK_OFFSET 0x223000 |
29 | #define DCSR_RCPM2_CPMFSMCR0 0x400 | |
30 | #define DCSR_RCPM2_CPMFSMSR0 0x404 | |
31 | #define DCSR_RCPM2_CPMFSMCR1 0x414 | |
32 | #define DCSR_RCPM2_CPMFSMSR1 0x418 | |
33 | #define CPMFSMSR_FSM_STATE_MASK 0x7f | |
34 | ||
d60a2099 WH |
35 | DECLARE_GLOBAL_DATA_PTR; |
36 | ||
10015025 | 37 | #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) |
636ef956 ML |
38 | |
39 | /* | |
40 | * Bit[1] of the descriptor indicates the descriptor type, | |
41 | * and bit[0] indicates whether the descriptor is valid. | |
42 | */ | |
43 | #define PMD_TYPE_TABLE 0x3 | |
44 | #define PMD_TYPE_SECT 0x1 | |
45 | ||
46 | /* AttrIndx[2:0] */ | |
47 | #define PMD_ATTRINDX(t) ((t) << 2) | |
48 | ||
49 | /* Section */ | |
50 | #define PMD_SECT_AF (1 << 10) | |
51 | ||
52 | #define BLOCK_SIZE_L1 (1UL << 30) | |
53 | #define BLOCK_SIZE_L2 (1UL << 21) | |
54 | ||
55 | /* TTBCR flags */ | |
56 | #define TTBCR_EAE (1 << 31) | |
57 | #define TTBCR_T0SZ(x) ((x) << 0) | |
58 | #define TTBCR_T1SZ(x) ((x) << 16) | |
59 | #define TTBCR_USING_TTBR0 (TTBCR_T0SZ(0) | TTBCR_T1SZ(0)) | |
60 | #define TTBCR_IRGN0_NC (0 << 8) | |
61 | #define TTBCR_IRGN0_WBWA (1 << 8) | |
62 | #define TTBCR_IRGN0_WT (2 << 8) | |
63 | #define TTBCR_IRGN0_WBNWA (3 << 8) | |
64 | #define TTBCR_IRGN0_MASK (3 << 8) | |
65 | #define TTBCR_ORGN0_NC (0 << 10) | |
66 | #define TTBCR_ORGN0_WBWA (1 << 10) | |
67 | #define TTBCR_ORGN0_WT (2 << 10) | |
68 | #define TTBCR_ORGN0_WBNWA (3 << 10) | |
69 | #define TTBCR_ORGN0_MASK (3 << 10) | |
70 | #define TTBCR_SHARED_NON (0 << 12) | |
71 | #define TTBCR_SHARED_OUTER (2 << 12) | |
72 | #define TTBCR_SHARED_INNER (3 << 12) | |
73 | #define TTBCR_EPD0 (0 << 7) | |
74 | #define TTBCR (TTBCR_SHARED_NON | \ | |
75 | TTBCR_ORGN0_NC | \ | |
76 | TTBCR_IRGN0_NC | \ | |
77 | TTBCR_USING_TTBR0 | \ | |
78 | TTBCR_EAE) | |
79 | ||
80 | /* | |
81 | * Memory region attributes for LPAE (defined in pgtable): | |
82 | * | |
83 | * n = AttrIndx[2:0] | |
84 | * | |
85 | * n MAIR | |
86 | * UNCACHED 000 00000000 | |
87 | * BUFFERABLE 001 01000100 | |
88 | * DEV_WC 001 01000100 | |
89 | * WRITETHROUGH 010 10101010 | |
90 | * WRITEBACK 011 11101110 | |
91 | * DEV_CACHED 011 11101110 | |
92 | * DEV_SHARED 100 00000100 | |
93 | * DEV_NONSHARED 100 00000100 | |
94 | * unused 101 | |
95 | * unused 110 | |
96 | * WRITEALLOC 111 11111111 | |
97 | */ | |
98 | #define MT_MAIR0 0xeeaa4400 | |
99 | #define MT_MAIR1 0xff000004 | |
100 | #define MT_STRONLY_ORDER 0 | |
101 | #define MT_NORMAL_NC 1 | |
102 | #define MT_DEVICE_MEM 4 | |
103 | #define MT_NORMAL 7 | |
104 | ||
105 | /* The phy_addr must be aligned to 4KB */ | |
106 | static inline void set_pgtable(u32 *page_table, u32 index, u32 phy_addr) | |
107 | { | |
108 | u32 value = phy_addr | PMD_TYPE_TABLE; | |
109 | ||
110 | page_table[2 * index] = value; | |
111 | page_table[2 * index + 1] = 0; | |
112 | } | |
113 | ||
114 | /* The phy_addr must be aligned to 4KB */ | |
115 | static inline void set_pgsection(u32 *page_table, u32 index, u64 phy_addr, | |
116 | u32 memory_type) | |
117 | { | |
118 | u64 value; | |
119 | ||
120 | value = phy_addr | PMD_TYPE_SECT | PMD_SECT_AF; | |
121 | value |= PMD_ATTRINDX(memory_type); | |
122 | page_table[2 * index] = value & 0xFFFFFFFF; | |
123 | page_table[2 * index + 1] = (value >> 32) & 0xFFFFFFFF; | |
124 | } | |
125 | ||
126 | /* | |
127 | * Start MMU after DDR is available, we create MMU table in DRAM. | |
128 | * The base address of TTLB is gd->arch.tlb_addr. We use two | |
129 | * levels of translation tables here to cover 40-bit address space. | |
130 | * | |
131 | * The TTLBs are located at PHY 2G~4G. | |
132 | * | |
133 | * VA mapping: | |
134 | * | |
135 | * ------- <---- 0GB | |
136 | * | | | |
137 | * | | | |
138 | * |-------| <---- 0x24000000 | |
139 | * |///////| ===> 192MB VA map for PCIe1 with offset 0x40_0000_0000 | |
140 | * |-------| <---- 0x300000000 | |
141 | * | | | |
142 | * |-------| <---- 0x34000000 | |
143 | * |///////| ===> 192MB VA map for PCIe2 with offset 0x48_0000_0000 | |
144 | * |-------| <---- 0x40000000 | |
145 | * | | | |
146 | * |-------| <---- 0x80000000 DDR0 space start | |
147 | * |\\\\\\\| | |
148 | *.|\\\\\\\| ===> 2GB VA map for 2GB DDR0 Memory space | |
149 | * |\\\\\\\| | |
150 | * ------- <---- 4GB DDR0 space end | |
151 | */ | |
152 | static void mmu_setup(void) | |
153 | { | |
154 | u32 *level0_table = (u32 *)gd->arch.tlb_addr; | |
155 | u32 *level1_table = (u32 *)(gd->arch.tlb_addr + 0x1000); | |
156 | u64 va_start = 0; | |
157 | u32 reg; | |
158 | int i; | |
159 | ||
160 | /* Level 0 Table 2-3 are used to map DDR */ | |
161 | set_pgsection(level0_table, 3, 3 * BLOCK_SIZE_L1, MT_NORMAL); | |
162 | set_pgsection(level0_table, 2, 2 * BLOCK_SIZE_L1, MT_NORMAL); | |
163 | /* Level 0 Table 1 is used to map device */ | |
164 | set_pgsection(level0_table, 1, 1 * BLOCK_SIZE_L1, MT_DEVICE_MEM); | |
165 | /* Level 0 Table 0 is used to map device including PCIe MEM */ | |
166 | set_pgtable(level0_table, 0, (u32)level1_table); | |
167 | ||
168 | /* Level 1 has 512 entries */ | |
169 | for (i = 0; i < 512; i++) { | |
170 | /* Mapping for PCIe 1 */ | |
ecc8d425 TR |
171 | if (va_start >= CFG_SYS_PCIE1_VIRT_ADDR && |
172 | va_start < (CFG_SYS_PCIE1_VIRT_ADDR + | |
173 | CFG_SYS_PCIE_MMAP_SIZE)) | |
636ef956 | 174 | set_pgsection(level1_table, i, |
ecc8d425 | 175 | CFG_SYS_PCIE1_PHYS_BASE + va_start, |
636ef956 ML |
176 | MT_DEVICE_MEM); |
177 | /* Mapping for PCIe 2 */ | |
ecc8d425 TR |
178 | else if (va_start >= CFG_SYS_PCIE2_VIRT_ADDR && |
179 | va_start < (CFG_SYS_PCIE2_VIRT_ADDR + | |
180 | CFG_SYS_PCIE_MMAP_SIZE)) | |
636ef956 | 181 | set_pgsection(level1_table, i, |
ecc8d425 | 182 | CFG_SYS_PCIE2_PHYS_BASE + va_start, |
636ef956 ML |
183 | MT_DEVICE_MEM); |
184 | else | |
185 | set_pgsection(level1_table, i, | |
186 | va_start, | |
187 | MT_DEVICE_MEM); | |
188 | va_start += BLOCK_SIZE_L2; | |
189 | } | |
190 | ||
191 | asm volatile("dsb sy;isb"); | |
192 | asm volatile("mcr p15, 0, %0, c2, c0, 2" /* Write RT to TTBCR */ | |
193 | : : "r" (TTBCR) : "memory"); | |
194 | asm volatile("mcrr p15, 0, %0, %1, c2" /* TTBR 0 */ | |
195 | : : "r" ((u32)level0_table), "r" (0) : "memory"); | |
196 | asm volatile("mcr p15, 0, %0, c10, c2, 0" /* write MAIR 0 */ | |
197 | : : "r" (MT_MAIR0) : "memory"); | |
198 | asm volatile("mcr p15, 0, %0, c10, c2, 1" /* write MAIR 1 */ | |
199 | : : "r" (MT_MAIR1) : "memory"); | |
200 | ||
201 | /* Set the access control to all-supervisor */ | |
202 | asm volatile("mcr p15, 0, %0, c3, c0, 0" | |
203 | : : "r" (~0)); | |
204 | ||
205 | /* Enable the mmu */ | |
206 | reg = get_cr(); | |
207 | set_cr(reg | CR_M); | |
208 | } | |
209 | ||
210 | /* | |
211 | * This function is called from lib/board.c. It recreates MMU | |
212 | * table in main memory. MMU and i/d-cache are enabled here. | |
213 | */ | |
214 | void enable_caches(void) | |
215 | { | |
216 | /* Invalidate all TLB */ | |
217 | mmu_page_table_flush(gd->arch.tlb_addr, | |
218 | gd->arch.tlb_addr + gd->arch.tlb_size); | |
219 | /* Set up and enable mmu */ | |
220 | mmu_setup(); | |
221 | ||
222 | /* Invalidate & Enable d-cache */ | |
223 | invalidate_dcache_all(); | |
224 | set_cr(get_cr() | CR_C); | |
225 | } | |
10015025 | 226 | #endif /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */ |
636ef956 | 227 | |
0c028a03 SL |
228 | |
229 | uint get_svr(void) | |
230 | { | |
6cc04547 | 231 | struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); |
0c028a03 SL |
232 | |
233 | return in_be32(&gur->svr); | |
234 | } | |
235 | ||
d60a2099 WH |
236 | #if defined(CONFIG_DISPLAY_CPUINFO) |
237 | int print_cpuinfo(void) | |
238 | { | |
239 | char buf1[32], buf2[32]; | |
6cc04547 | 240 | struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); |
d60a2099 WH |
241 | unsigned int svr, major, minor, ver, i; |
242 | ||
243 | svr = in_be32(&gur->svr); | |
244 | major = SVR_MAJ(svr); | |
245 | minor = SVR_MIN(svr); | |
246 | ||
247 | puts("CPU: Freescale LayerScape "); | |
248 | ||
249 | ver = SVR_SOC_VER(svr); | |
250 | switch (ver) { | |
251 | case SOC_VER_SLS1020: | |
252 | puts("SLS1020"); | |
253 | break; | |
254 | case SOC_VER_LS1020: | |
255 | puts("LS1020"); | |
256 | break; | |
257 | case SOC_VER_LS1021: | |
258 | puts("LS1021"); | |
259 | break; | |
260 | case SOC_VER_LS1022: | |
261 | puts("LS1022"); | |
262 | break; | |
263 | default: | |
264 | puts("Unknown"); | |
265 | break; | |
266 | } | |
267 | ||
268 | if (IS_E_PROCESSOR(svr) && (ver != SOC_VER_SLS1020)) | |
269 | puts("E"); | |
270 | ||
271 | printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); | |
272 | ||
273 | puts("Clock Configuration:"); | |
274 | ||
275 | printf("\n CPU0(ARMV7):%-4s MHz, ", strmhz(buf1, gd->cpu_clk)); | |
276 | printf("\n Bus:%-4s MHz, ", strmhz(buf1, gd->bus_clk)); | |
277 | printf("DDR:%-4s MHz (%s MT/s data rate), ", | |
278 | strmhz(buf1, gd->mem_clk/2), strmhz(buf2, gd->mem_clk)); | |
279 | puts("\n"); | |
280 | ||
281 | /* Display the RCW, so that no one gets confused as to what RCW | |
282 | * we're actually using for this boot. | |
283 | */ | |
284 | puts("Reset Configuration Word (RCW):"); | |
285 | for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { | |
286 | u32 rcw = in_be32(&gur->rcwsr[i]); | |
287 | ||
288 | if ((i % 4) == 0) | |
289 | printf("\n %08x:", i * 4); | |
290 | printf(" %08x", rcw); | |
291 | } | |
292 | puts("\n"); | |
293 | ||
294 | return 0; | |
295 | } | |
296 | #endif | |
297 | ||
d60a2099 | 298 | #ifdef CONFIG_FSL_ESDHC |
b75d8dc5 | 299 | int cpu_mmc_init(struct bd_info *bis) |
d60a2099 WH |
300 | { |
301 | return fsl_esdhc_mmc_init(bis); | |
302 | } | |
303 | #endif | |
304 | ||
306fa012 | 305 | int arch_cpu_init(void) |
306 | { | |
65cc0e2a | 307 | void *epu_base = (void *)(CFG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); |
9f076be7 | 308 | void *rcpm2_base = |
65cc0e2a | 309 | (void *)(CFG_SYS_DCSRBAR + DCSR_RCPM2_BLOCK_OFFSET); |
6cc04547 | 310 | struct ccsr_scfg *scfg = (void *)CFG_SYS_FSL_SCFG_ADDR; |
9f076be7 | 311 | u32 state; |
312 | ||
19dba8bf HZ |
313 | icache_enable(); |
314 | ||
9f076be7 | 315 | /* |
316 | * The RCPM FSM state may not be reset after power-on. | |
317 | * So, reset them. | |
318 | */ | |
319 | state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR0) & | |
320 | CPMFSMSR_FSM_STATE_MASK; | |
321 | if (state != 0) { | |
322 | out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x80); | |
323 | out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x0); | |
324 | } | |
325 | ||
326 | state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR1) & | |
327 | CPMFSMSR_FSM_STATE_MASK; | |
328 | if (state != 0) { | |
329 | out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x80); | |
330 | out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x0); | |
331 | } | |
306fa012 | 332 | |
333 | /* | |
334 | * After wakeup from deep sleep, Clear EPU registers | |
335 | * as early as possible to prevent from possible issue. | |
336 | * It's also safe to clear at normal boot. | |
337 | */ | |
338 | fsl_epu_clean(epu_base); | |
339 | ||
5757e06c | 340 | setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR); |
341 | ||
306fa012 | 342 | return 0; |
343 | } | |
290e6e92 | 344 | |
104d6fb6 | 345 | #ifdef CONFIG_ARMV7_NONSEC |
290e6e92 XL |
346 | /* Set the address at which the secondary core starts from.*/ |
347 | void smp_set_core_boot_addr(unsigned long addr, int corenr) | |
348 | { | |
6cc04547 | 349 | struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); |
290e6e92 XL |
350 | |
351 | out_be32(&gur->scratchrw[0], addr); | |
352 | } | |
353 | ||
354 | /* Release the secondary core from holdoff state and kick it */ | |
355 | void smp_kick_all_cpus(void) | |
356 | { | |
6cc04547 | 357 | struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); |
290e6e92 XL |
358 | |
359 | out_be32(&gur->brrl, 0x2); | |
6f0586e6 WD |
360 | |
361 | /* | |
362 | * LS1 STANDBYWFE is not captured outside the ARM module in the soc. | |
363 | * So add a delay to wait bootrom execute WFE. | |
364 | */ | |
365 | udelay(1); | |
366 | ||
367 | asm volatile("sev"); | |
290e6e92 XL |
368 | } |
369 | #endif | |
f861f51c | 370 | |
35b65dd8 | 371 | void reset_cpu(void) |
f861f51c FE |
372 | { |
373 | struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; | |
374 | ||
375 | clrbits_be16(&wdog->wcr, WCR_SRS); | |
376 | ||
377 | while (1) { | |
378 | /* | |
379 | * Let the watchdog trigger | |
380 | */ | |
381 | } | |
382 | } | |
a1399534 AW |
383 | |
384 | void arch_preboot_os(void) | |
385 | { | |
386 | unsigned long ctrl; | |
387 | ||
388 | /* Disable PL1 Physical Timer */ | |
389 | asm("mrc p15, 0, %0, c14, c2, 1" : "=r" (ctrl)); | |
390 | ctrl &= ~ARCH_TIMER_CTRL_ENABLE; | |
391 | asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl)); | |
392 | } | |
8976556a GJ |
393 | |
394 | #ifdef CONFIG_ARCH_MISC_INIT | |
395 | int arch_misc_init(void) | |
396 | { | |
397 | if (IS_ENABLED(CONFIG_FSL_CAAM)) { | |
398 | struct udevice *dev; | |
399 | int ret; | |
400 | ||
401 | ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev); | |
402 | if (ret) | |
cda8f873 | 403 | printf("Failed to initialize caam_jr: %d\n", ret); |
8976556a GJ |
404 | } |
405 | ||
406 | return 0; | |
407 | } | |
408 | #endif |