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