]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/arm/cpu/armv8/fsl-lsch3/cpu.c
armv8/ls2085a: Fix generic timer clock source
[people/ms/u-boot.git] / arch / arm / cpu / armv8 / fsl-lsch3 / cpu.c
CommitLineData
2f78eae5
YS
1/*
2 * Copyright 2014 Freescale Semiconductor, Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <common.h>
8#include <asm/io.h>
9#include <asm/system.h>
10#include <asm/armv8/mmu.h>
11#include <asm/io.h>
12#include <asm/arch-fsl-lsch3/immap_lsch3.h>
422cb08a 13#include <fsl_debug_server.h>
7b3bd9a7 14#include <fsl-mc/fsl_mc.h>
2f78eae5 15#include "cpu.h"
40f8dec5 16#include "mp.h"
2f78eae5
YS
17#include "speed.h"
18
19DECLARE_GLOBAL_DATA_PTR;
20
21#ifndef CONFIG_SYS_DCACHE_OFF
22/*
23 * To start MMU before DDR is available, we create MMU table in SRAM.
24 * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three
25 * levels of translation tables here to cover 40-bit address space.
26 * We use 4KB granule size, with 40 bits physical address, T0SZ=24
27 * Level 0 IA[39], table address @0
28 * Level 1 IA[31:30], table address @01000, 0x2000
29 * Level 2 IA[29:21], table address @0x3000
30 */
31
32#define SECTION_SHIFT_L0 39UL
33#define SECTION_SHIFT_L1 30UL
34#define SECTION_SHIFT_L2 21UL
35#define BLOCK_SIZE_L0 0x8000000000UL
36#define BLOCK_SIZE_L1 (1 << SECTION_SHIFT_L1)
37#define BLOCK_SIZE_L2 (1 << SECTION_SHIFT_L2)
38#define CONFIG_SYS_IFC_BASE 0x30000000
39#define CONFIG_SYS_IFC_SIZE 0x10000000
40#define CONFIG_SYS_IFC_BASE2 0x500000000
41#define CONFIG_SYS_IFC_SIZE2 0x100000000
42#define TCR_EL2_PS_40BIT (2 << 16)
43#define LSCH3_VA_BITS (40)
44#define LSCH3_TCR (TCR_TG0_4K | \
45 TCR_EL2_PS_40BIT | \
46 TCR_SHARED_NON | \
47 TCR_ORGN_NC | \
48 TCR_IRGN_NC | \
49 TCR_T0SZ(LSCH3_VA_BITS))
50
51/*
52 * Final MMU
53 * Let's start from the same layout as early MMU and modify as needed.
54 * IFC regions will be cache-inhibit.
55 */
56#define FINAL_QBMAN_CACHED_MEM 0x818000000UL
57#define FINAL_QBMAN_CACHED_SIZE 0x4000000
58
59
60static inline void early_mmu_setup(void)
61{
62 int el;
63 u64 i;
64 u64 section_l1t0, section_l1t1, section_l2;
65 u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE;
66 u64 *level1_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000);
67 u64 *level1_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000);
68 u64 *level2_table = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000);
69
70
71 level0_table[0] =
72 (u64)level1_table_0 | PMD_TYPE_TABLE;
73 level0_table[1] =
74 (u64)level1_table_1 | PMD_TYPE_TABLE;
75
76 /*
77 * set level 1 table 0 to cache_inhibit, covering 0 to 512GB
78 * set level 1 table 1 to cache enabled, covering 512GB to 1TB
79 * set level 2 table to cache-inhibit, covering 0 to 1GB
80 */
81 section_l1t0 = 0;
82 section_l1t1 = BLOCK_SIZE_L0;
83 section_l2 = 0;
84 for (i = 0; i < 512; i++) {
85 set_pgtable_section(level1_table_0, i, section_l1t0,
86 MT_DEVICE_NGNRNE);
87 set_pgtable_section(level1_table_1, i, section_l1t1,
88 MT_NORMAL);
89 set_pgtable_section(level2_table, i, section_l2,
90 MT_DEVICE_NGNRNE);
91 section_l1t0 += BLOCK_SIZE_L1;
92 section_l1t1 += BLOCK_SIZE_L1;
93 section_l2 += BLOCK_SIZE_L2;
94 }
95
96 level1_table_0[0] =
97 (u64)level2_table | PMD_TYPE_TABLE;
98 level1_table_0[1] =
99 0x40000000 | PMD_SECT_AF | PMD_TYPE_SECT |
100 PMD_ATTRINDX(MT_DEVICE_NGNRNE);
101 level1_table_0[2] =
102 0x80000000 | PMD_SECT_AF | PMD_TYPE_SECT |
103 PMD_ATTRINDX(MT_NORMAL);
104 level1_table_0[3] =
105 0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT |
106 PMD_ATTRINDX(MT_NORMAL);
107
108 /* Rewrite table to enable cache */
109 set_pgtable_section(level2_table,
110 CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2,
111 CONFIG_SYS_FSL_OCRAM_BASE,
112 MT_NORMAL);
113 for (i = CONFIG_SYS_IFC_BASE >> SECTION_SHIFT_L2;
114 i < (CONFIG_SYS_IFC_BASE + CONFIG_SYS_IFC_SIZE)
115 >> SECTION_SHIFT_L2; i++) {
116 section_l2 = i << SECTION_SHIFT_L2;
117 set_pgtable_section(level2_table, i,
118 section_l2, MT_NORMAL);
119 }
120
121 el = current_el();
122 set_ttbr_tcr_mair(el, (u64)level0_table, LSCH3_TCR, MEMORY_ATTRIBUTES);
123 set_sctlr(get_sctlr() | CR_M);
124}
125
126/*
127 * This final tale looks similar to early table, but different in detail.
128 * These tables are in regular memory. Cache on IFC is disabled. One sub table
129 * is added to enable cache for QBMan.
130 */
131static inline void final_mmu_setup(void)
132{
133 int el;
134 u64 i, tbl_base, tbl_limit, section_base;
135 u64 section_l1t0, section_l1t1, section_l2;
136 u64 *level0_table = (u64 *)gd->arch.tlb_addr;
137 u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + 0x1000);
138 u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + 0x2000);
139 u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + 0x3000);
140 u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + 0x4000);
141
142
143 level0_table[0] =
144 (u64)level1_table_0 | PMD_TYPE_TABLE;
145 level0_table[1] =
146 (u64)level1_table_1 | PMD_TYPE_TABLE;
147
148 /*
149 * set level 1 table 0 to cache_inhibit, covering 0 to 512GB
150 * set level 1 table 1 to cache enabled, covering 512GB to 1TB
151 * set level 2 table 0 to cache-inhibit, covering 0 to 1GB
152 */
153 section_l1t0 = 0;
6c747f4a 154 section_l1t1 = BLOCK_SIZE_L0 | PMD_SECT_OUTER_SHARE;
2f78eae5
YS
155 section_l2 = 0;
156 for (i = 0; i < 512; i++) {
157 set_pgtable_section(level1_table_0, i, section_l1t0,
158 MT_DEVICE_NGNRNE);
159 set_pgtable_section(level1_table_1, i, section_l1t1,
160 MT_NORMAL);
161 set_pgtable_section(level2_table_0, i, section_l2,
162 MT_DEVICE_NGNRNE);
163 section_l1t0 += BLOCK_SIZE_L1;
164 section_l1t1 += BLOCK_SIZE_L1;
165 section_l2 += BLOCK_SIZE_L2;
166 }
167
168 level1_table_0[0] =
169 (u64)level2_table_0 | PMD_TYPE_TABLE;
170 level1_table_0[2] =
171 0x80000000 | PMD_SECT_AF | PMD_TYPE_SECT |
6c747f4a 172 PMD_SECT_OUTER_SHARE | PMD_ATTRINDX(MT_NORMAL);
2f78eae5
YS
173 level1_table_0[3] =
174 0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT |
6c747f4a 175 PMD_SECT_OUTER_SHARE | PMD_ATTRINDX(MT_NORMAL);
2f78eae5
YS
176
177 /* Rewrite table to enable cache */
178 set_pgtable_section(level2_table_0,
179 CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2,
180 CONFIG_SYS_FSL_OCRAM_BASE,
181 MT_NORMAL);
182
183 /*
184 * Fill in other part of tables if cache is needed
185 * If finer granularity than 1GB is needed, sub table
186 * should be created.
187 */
188 section_base = FINAL_QBMAN_CACHED_MEM & ~(BLOCK_SIZE_L1 - 1);
189 i = section_base >> SECTION_SHIFT_L1;
190 level1_table_0[i] = (u64)level2_table_1 | PMD_TYPE_TABLE;
191 section_l2 = section_base;
192 for (i = 0; i < 512; i++) {
193 set_pgtable_section(level2_table_1, i, section_l2,
194 MT_DEVICE_NGNRNE);
195 section_l2 += BLOCK_SIZE_L2;
196 }
197 tbl_base = FINAL_QBMAN_CACHED_MEM & (BLOCK_SIZE_L1 - 1);
198 tbl_limit = (FINAL_QBMAN_CACHED_MEM + FINAL_QBMAN_CACHED_SIZE) &
199 (BLOCK_SIZE_L1 - 1);
200 for (i = tbl_base >> SECTION_SHIFT_L2;
201 i < tbl_limit >> SECTION_SHIFT_L2; i++) {
202 section_l2 = section_base + (i << SECTION_SHIFT_L2);
203 set_pgtable_section(level2_table_1, i,
204 section_l2, MT_NORMAL);
205 }
206
207 /* flush new MMU table */
208 flush_dcache_range(gd->arch.tlb_addr,
209 gd->arch.tlb_addr + gd->arch.tlb_size);
210
211 /* point TTBR to the new table */
212 el = current_el();
213 asm volatile("dsb sy");
214 if (el == 1) {
215 asm volatile("msr ttbr0_el1, %0"
216 : : "r" ((u64)level0_table) : "memory");
217 } else if (el == 2) {
218 asm volatile("msr ttbr0_el2, %0"
219 : : "r" ((u64)level0_table) : "memory");
220 } else if (el == 3) {
221 asm volatile("msr ttbr0_el3, %0"
222 : : "r" ((u64)level0_table) : "memory");
223 } else {
224 hang();
225 }
226 asm volatile("isb");
227
228 /*
229 * MMU is already enabled, just need to invalidate TLB to load the
230 * new table. The new table is compatible with the current table, if
231 * MMU somehow walks through the new table before invalidation TLB,
232 * it still works. So we don't need to turn off MMU here.
233 */
234}
235
236int arch_cpu_init(void)
237{
238 icache_enable();
239 __asm_invalidate_dcache_all();
240 __asm_invalidate_tlb_all();
241 early_mmu_setup();
242 set_sctlr(get_sctlr() | CR_C);
243 return 0;
244}
245
2f78eae5
YS
246/*
247 * This function is called from lib/board.c.
248 * It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
249 * There is no need to disable d-cache for this operation.
250 */
251void enable_caches(void)
252{
253 final_mmu_setup();
254 __asm_invalidate_tlb_all();
255}
256#endif
257
258static inline u32 initiator_type(u32 cluster, int init_id)
259{
260 struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
261 u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK;
262 u32 type = in_le32(&gur->tp_ityp[idx]);
263
264 if (type & TP_ITYP_AV)
265 return type;
266
267 return 0;
268}
269
270u32 cpu_mask(void)
271{
272 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
273 int i = 0, count = 0;
274 u32 cluster, type, mask = 0;
275
276 do {
277 int j;
278 cluster = in_le32(&gur->tp_cluster[i].lower);
279 for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
280 type = initiator_type(cluster, j);
281 if (type) {
282 if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
283 mask |= 1 << count;
284 count++;
285 }
286 }
287 i++;
288 } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
289
290 return mask;
291}
292
293/*
294 * Return the number of cores on this SOC.
295 */
296int cpu_numcores(void)
297{
298 return hweight32(cpu_mask());
299}
300
301int fsl_qoriq_core_to_cluster(unsigned int core)
302{
303 struct ccsr_gur __iomem *gur =
304 (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
305 int i = 0, count = 0;
306 u32 cluster;
307
308 do {
309 int j;
310 cluster = in_le32(&gur->tp_cluster[i].lower);
311 for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
312 if (initiator_type(cluster, j)) {
313 if (count == core)
314 return i;
315 count++;
316 }
317 }
318 i++;
319 } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
320
321 return -1; /* cannot identify the cluster */
322}
323
324u32 fsl_qoriq_core_to_type(unsigned int core)
325{
326 struct ccsr_gur __iomem *gur =
327 (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
328 int i = 0, count = 0;
329 u32 cluster, type;
330
331 do {
332 int j;
333 cluster = in_le32(&gur->tp_cluster[i].lower);
334 for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
335 type = initiator_type(cluster, j);
336 if (type) {
337 if (count == core)
338 return type;
339 count++;
340 }
341 }
342 i++;
343 } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
344
345 return -1; /* cannot identify the cluster */
346}
347
348#ifdef CONFIG_DISPLAY_CPUINFO
349int print_cpuinfo(void)
350{
351 struct sys_info sysinfo;
352 char buf[32];
353 unsigned int i, core;
354 u32 type;
355
356 get_sys_info(&sysinfo);
357 puts("Clock Configuration:");
358 for_each_cpu(i, core, cpu_numcores(), cpu_mask()) {
359 if (!(i % 3))
360 puts("\n ");
361 type = TP_ITYP_VER(fsl_qoriq_core_to_type(core));
362 printf("CPU%d(%s):%-4s MHz ", core,
363 type == TY_ITYP_VER_A7 ? "A7 " :
364 (type == TY_ITYP_VER_A53 ? "A53" :
365 (type == TY_ITYP_VER_A57 ? "A57" : " ")),
366 strmhz(buf, sysinfo.freq_processor[core]));
367 }
368 printf("\n Bus: %-4s MHz ",
369 strmhz(buf, sysinfo.freq_systembus));
370 printf("DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus));
b87e6f88 371 printf(" DP-DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus2));
2f78eae5
YS
372 puts("\n");
373
374 return 0;
375}
376#endif
b940ca64
GR
377
378int cpu_eth_init(bd_t *bis)
379{
380 int error = 0;
381
382#ifdef CONFIG_FSL_MC_ENET
a2a55e51 383 error = fsl_mc_ldpaa_init(bis);
b940ca64
GR
384#endif
385 return error;
386}
40f8dec5 387
40f8dec5
YS
388int arch_early_init_r(void)
389{
390 int rv;
391 rv = fsl_lsch3_wake_seconday_cores();
392
393 if (rv)
394 printf("Did not wake secondary cores\n");
395
396 return 0;
397}
207774b2
YS
398
399int timer_init(void)
400{
401 u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
402 u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
403#ifdef COUNTER_FREQUENCY_REAL
404 unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
405
406 /* Update with accurate clock frequency */
407 asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
408#endif
409
410 /* Enable timebase for all clusters.
411 * It is safe to do so even some clusters are not enabled.
412 */
413 out_le32(cltbenr, 0xf);
414
415 /* Enable clock for timer
416 * This is a global setting.
417 */
418 out_le32(cntcr, 0x1);
419
420 return 0;
421}