]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
41e5ee54 | 2 | /* |
d35831f6 | 3 | * Copyright (C) 2014-2016 Stefan Roese <[email protected]> |
41e5ee54 SR |
4 | */ |
5 | ||
6 | #include <common.h> | |
4d991cb3 | 7 | #include <ahci.h> |
9edefc27 | 8 | #include <cpu_func.h> |
691d719d | 9 | #include <init.h> |
cd93d625 | 10 | #include <linux/bitops.h> |
c05ed00a | 11 | #include <linux/delay.h> |
4d991cb3 | 12 | #include <linux/mbus.h> |
41e5ee54 | 13 | #include <asm/io.h> |
5730360e | 14 | #include <asm/pl310.h> |
41e5ee54 SR |
15 | #include <asm/arch/cpu.h> |
16 | #include <asm/arch/soc.h> | |
7f1adcd7 | 17 | #include <sdhci.h> |
41e5ee54 SR |
18 | |
19 | #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) | |
20 | #define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) | |
21 | ||
22 | static struct mbus_win windows[] = { | |
41e5ee54 | 23 | /* SPI */ |
8ed20d65 SR |
24 | { MBUS_SPI_BASE, MBUS_SPI_SIZE, |
25 | CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH }, | |
41e5ee54 SR |
26 | |
27 | /* NOR */ | |
8ed20d65 SR |
28 | { MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE, |
29 | CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM }, | |
0d0df46e CP |
30 | |
31 | #ifdef CONFIG_ARMADA_MSYS | |
32 | /* DFX */ | |
33 | { MBUS_DFX_BASE, MBUS_DFX_SIZE, CPU_TARGET_DFX, 0 }, | |
34 | #endif | |
41e5ee54 SR |
35 | }; |
36 | ||
42cc034f SR |
37 | void lowlevel_init(void) |
38 | { | |
39 | /* | |
40 | * Dummy implementation, we only need LOWLEVEL_INIT | |
41 | * on Armada to configure CP15 in start.S / cpu_init_cp15() | |
42 | */ | |
43 | } | |
44 | ||
35b65dd8 | 45 | void reset_cpu(void) |
41e5ee54 SR |
46 | { |
47 | struct mvebu_system_registers *reg = | |
48 | (struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE; | |
49 | ||
50 | writel(readl(®->rstoutn_mask) | 1, ®->rstoutn_mask); | |
51 | writel(readl(®->sys_soft_rst) | 1, ®->sys_soft_rst); | |
52 | while (1) | |
53 | ; | |
54 | } | |
55 | ||
9c6d3b7b SR |
56 | int mvebu_soc_family(void) |
57 | { | |
58 | u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; | |
59 | ||
6202953d PS |
60 | switch (devid) { |
61 | case SOC_MV78230_ID: | |
62 | case SOC_MV78260_ID: | |
63 | case SOC_MV78460_ID: | |
9c6d3b7b | 64 | return MVEBU_SOC_AXP; |
09e89ab4 SR |
65 | |
66 | case SOC_88F6720_ID: | |
67 | return MVEBU_SOC_A375; | |
68 | ||
6202953d PS |
69 | case SOC_88F6810_ID: |
70 | case SOC_88F6820_ID: | |
71 | case SOC_88F6828_ID: | |
9c6d3b7b | 72 | return MVEBU_SOC_A38X; |
0f8031a3 CP |
73 | |
74 | case SOC_98DX3236_ID: | |
75 | case SOC_98DX3336_ID: | |
76 | case SOC_98DX4251_ID: | |
77 | return MVEBU_SOC_MSYS; | |
6202953d | 78 | } |
09e89ab4 | 79 | |
9c6d3b7b SR |
80 | return MVEBU_SOC_UNKNOWN; |
81 | } | |
82 | ||
41e5ee54 | 83 | #if defined(CONFIG_DISPLAY_CPUINFO) |
d718bf2c | 84 | |
09e89ab4 SR |
85 | #if defined(CONFIG_ARMADA_375) |
86 | /* SAR frequency values for Armada 375 */ | |
87 | static const struct sar_freq_modes sar_freq_tab[] = { | |
88 | { 0, 0x0, 266, 133, 266 }, | |
89 | { 1, 0x0, 333, 167, 167 }, | |
90 | { 2, 0x0, 333, 167, 222 }, | |
91 | { 3, 0x0, 333, 167, 333 }, | |
92 | { 4, 0x0, 400, 200, 200 }, | |
93 | { 5, 0x0, 400, 200, 267 }, | |
94 | { 6, 0x0, 400, 200, 400 }, | |
95 | { 7, 0x0, 500, 250, 250 }, | |
96 | { 8, 0x0, 500, 250, 334 }, | |
97 | { 9, 0x0, 500, 250, 500 }, | |
98 | { 10, 0x0, 533, 267, 267 }, | |
99 | { 11, 0x0, 533, 267, 356 }, | |
100 | { 12, 0x0, 533, 267, 533 }, | |
101 | { 13, 0x0, 600, 300, 300 }, | |
102 | { 14, 0x0, 600, 300, 400 }, | |
103 | { 15, 0x0, 600, 300, 600 }, | |
104 | { 16, 0x0, 666, 333, 333 }, | |
105 | { 17, 0x0, 666, 333, 444 }, | |
106 | { 18, 0x0, 666, 333, 666 }, | |
107 | { 19, 0x0, 800, 400, 267 }, | |
108 | { 20, 0x0, 800, 400, 400 }, | |
109 | { 21, 0x0, 800, 400, 534 }, | |
110 | { 22, 0x0, 900, 450, 300 }, | |
111 | { 23, 0x0, 900, 450, 450 }, | |
112 | { 24, 0x0, 900, 450, 600 }, | |
113 | { 25, 0x0, 1000, 500, 500 }, | |
114 | { 26, 0x0, 1000, 500, 667 }, | |
115 | { 27, 0x0, 1000, 333, 500 }, | |
116 | { 28, 0x0, 400, 400, 400 }, | |
117 | { 29, 0x0, 1100, 550, 550 }, | |
118 | { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ | |
119 | }; | |
120 | #elif defined(CONFIG_ARMADA_38X) | |
d35831f6 | 121 | /* SAR frequency values for Armada 38x */ |
a9fc5a24 | 122 | static const struct sar_freq_modes sar_freq_tab[] = { |
0a91e1cc CP |
123 | { 0x0, 0x0, 666, 333, 333 }, |
124 | { 0x2, 0x0, 800, 400, 400 }, | |
125 | { 0x4, 0x0, 1066, 533, 533 }, | |
126 | { 0x6, 0x0, 1200, 600, 600 }, | |
127 | { 0x8, 0x0, 1332, 666, 666 }, | |
128 | { 0xc, 0x0, 1600, 800, 800 }, | |
129 | { 0x10, 0x0, 1866, 933, 933 }, | |
130 | { 0x13, 0x0, 2000, 1000, 933 }, | |
131 | { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ | |
d718bf2c | 132 | }; |
0d0df46e CP |
133 | #elif defined(CONFIG_ARMADA_MSYS) |
134 | static const struct sar_freq_modes sar_freq_tab[] = { | |
135 | { 0x0, 0x0, 400, 400, 400 }, | |
136 | { 0x2, 0x0, 667, 333, 667 }, | |
137 | { 0x3, 0x0, 800, 400, 800 }, | |
138 | { 0x5, 0x0, 800, 400, 800 }, | |
139 | { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ | |
140 | }; | |
d718bf2c | 141 | #else |
d35831f6 | 142 | /* SAR frequency values for Armada XP */ |
a9fc5a24 | 143 | static const struct sar_freq_modes sar_freq_tab[] = { |
d718bf2c SR |
144 | { 0xa, 0x5, 800, 400, 400 }, |
145 | { 0x1, 0x5, 1066, 533, 533 }, | |
146 | { 0x2, 0x5, 1200, 600, 600 }, | |
147 | { 0x2, 0x9, 1200, 600, 400 }, | |
148 | { 0x3, 0x5, 1333, 667, 667 }, | |
149 | { 0x4, 0x5, 1500, 750, 750 }, | |
150 | { 0x4, 0x9, 1500, 750, 500 }, | |
151 | { 0xb, 0x9, 1600, 800, 533 }, | |
152 | { 0xb, 0xa, 1600, 800, 640 }, | |
153 | { 0xb, 0x5, 1600, 800, 800 }, | |
154 | { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ | |
155 | }; | |
156 | #endif | |
157 | ||
158 | void get_sar_freq(struct sar_freq_modes *sar_freq) | |
159 | { | |
160 | u32 val; | |
161 | u32 freq; | |
162 | int i; | |
163 | ||
0d0df46e | 164 | #if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_MSYS) |
09e89ab4 SR |
165 | val = readl(CONFIG_SAR2_REG); /* SAR - Sample At Reset */ |
166 | #else | |
d718bf2c | 167 | val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */ |
09e89ab4 | 168 | #endif |
d718bf2c | 169 | freq = (val & SAR_CPU_FREQ_MASK) >> SAR_CPU_FREQ_OFFS; |
09e89ab4 | 170 | #if defined(SAR2_CPU_FREQ_MASK) |
d718bf2c SR |
171 | /* |
172 | * Shift CPU0 clock frequency select bit from SAR2 register | |
173 | * into correct position | |
174 | */ | |
175 | freq |= ((readl(CONFIG_SAR2_REG) & SAR2_CPU_FREQ_MASK) | |
176 | >> SAR2_CPU_FREQ_OFFS) << 3; | |
177 | #endif | |
178 | for (i = 0; sar_freq_tab[i].val != 0xff; i++) { | |
179 | if (sar_freq_tab[i].val == freq) { | |
0d0df46e | 180 | #if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS) |
d718bf2c SR |
181 | *sar_freq = sar_freq_tab[i]; |
182 | return; | |
183 | #else | |
184 | int k; | |
185 | u8 ffc; | |
186 | ||
187 | ffc = (val & SAR_FFC_FREQ_MASK) >> | |
188 | SAR_FFC_FREQ_OFFS; | |
189 | for (k = i; sar_freq_tab[k].ffc != 0xff; k++) { | |
190 | if (sar_freq_tab[k].ffc == ffc) { | |
191 | *sar_freq = sar_freq_tab[k]; | |
192 | return; | |
193 | } | |
194 | } | |
195 | i = k; | |
196 | #endif | |
197 | } | |
198 | } | |
199 | ||
200 | /* SAR value not found, return 0 for frequencies */ | |
201 | *sar_freq = sar_freq_tab[i - 1]; | |
202 | } | |
203 | ||
41e5ee54 SR |
204 | int print_cpuinfo(void) |
205 | { | |
206 | u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; | |
207 | u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff; | |
d718bf2c | 208 | struct sar_freq_modes sar_freq; |
41e5ee54 SR |
209 | |
210 | puts("SoC: "); | |
211 | ||
212 | switch (devid) { | |
6202953d PS |
213 | case SOC_MV78230_ID: |
214 | puts("MV78230-"); | |
215 | break; | |
bf0db8b8 SR |
216 | case SOC_MV78260_ID: |
217 | puts("MV78260-"); | |
218 | break; | |
41e5ee54 SR |
219 | case SOC_MV78460_ID: |
220 | puts("MV78460-"); | |
221 | break; | |
09e89ab4 SR |
222 | case SOC_88F6720_ID: |
223 | puts("MV88F6720-"); | |
224 | break; | |
9c6d3b7b SR |
225 | case SOC_88F6810_ID: |
226 | puts("MV88F6810-"); | |
41e5ee54 | 227 | break; |
9c6d3b7b SR |
228 | case SOC_88F6820_ID: |
229 | puts("MV88F6820-"); | |
41e5ee54 | 230 | break; |
9c6d3b7b SR |
231 | case SOC_88F6828_ID: |
232 | puts("MV88F6828-"); | |
41e5ee54 | 233 | break; |
0f8031a3 CP |
234 | case SOC_98DX3236_ID: |
235 | puts("98DX3236-"); | |
236 | break; | |
237 | case SOC_98DX3336_ID: | |
238 | puts("98DX3336-"); | |
239 | break; | |
240 | case SOC_98DX4251_ID: | |
241 | puts("98DX4251-"); | |
242 | break; | |
41e5ee54 | 243 | default: |
9c6d3b7b | 244 | puts("Unknown-"); |
41e5ee54 SR |
245 | break; |
246 | } | |
247 | ||
9c6d3b7b SR |
248 | if (mvebu_soc_family() == MVEBU_SOC_AXP) { |
249 | switch (revid) { | |
250 | case 1: | |
d718bf2c | 251 | puts("A0"); |
9c6d3b7b SR |
252 | break; |
253 | case 2: | |
d718bf2c | 254 | puts("B0"); |
9c6d3b7b SR |
255 | break; |
256 | default: | |
d718bf2c | 257 | printf("?? (%x)", revid); |
9c6d3b7b SR |
258 | break; |
259 | } | |
260 | } | |
261 | ||
09e89ab4 SR |
262 | if (mvebu_soc_family() == MVEBU_SOC_A375) { |
263 | switch (revid) { | |
264 | case MV_88F67XX_A0_ID: | |
265 | puts("A0"); | |
266 | break; | |
267 | default: | |
268 | printf("?? (%x)", revid); | |
269 | break; | |
270 | } | |
271 | } | |
272 | ||
9c6d3b7b SR |
273 | if (mvebu_soc_family() == MVEBU_SOC_A38X) { |
274 | switch (revid) { | |
275 | case MV_88F68XX_Z1_ID: | |
d718bf2c | 276 | puts("Z1"); |
9c6d3b7b SR |
277 | break; |
278 | case MV_88F68XX_A0_ID: | |
d718bf2c | 279 | puts("A0"); |
9c6d3b7b | 280 | break; |
d997ad03 CP |
281 | case MV_88F68XX_B0_ID: |
282 | puts("B0"); | |
283 | break; | |
9c6d3b7b | 284 | default: |
d718bf2c | 285 | printf("?? (%x)", revid); |
9c6d3b7b SR |
286 | break; |
287 | } | |
288 | } | |
289 | ||
0d0df46e CP |
290 | if (mvebu_soc_family() == MVEBU_SOC_MSYS) { |
291 | switch (revid) { | |
292 | case 3: | |
293 | puts("A0"); | |
294 | break; | |
295 | case 4: | |
296 | puts("A1"); | |
297 | break; | |
298 | default: | |
299 | printf("?? (%x)", revid); | |
300 | break; | |
301 | } | |
302 | } | |
303 | ||
d718bf2c SR |
304 | get_sar_freq(&sar_freq); |
305 | printf(" at %d MHz\n", sar_freq.p_clk); | |
306 | ||
41e5ee54 SR |
307 | return 0; |
308 | } | |
309 | #endif /* CONFIG_DISPLAY_CPUINFO */ | |
310 | ||
311 | /* | |
312 | * This function initialize Controller DRAM Fastpath windows. | |
313 | * It takes the CS size information from the 0x1500 scratch registers | |
314 | * and sets the correct windows sizes and base addresses accordingly. | |
315 | * | |
316 | * These values are set in the scratch registers by the Marvell | |
1670a154 CP |
317 | * DDR3 training code, which is executed by the SPL before the |
318 | * main payload (U-Boot) is executed. | |
41e5ee54 SR |
319 | */ |
320 | static void update_sdram_window_sizes(void) | |
321 | { | |
322 | u64 base = 0; | |
323 | u32 size, temp; | |
324 | int i; | |
325 | ||
326 | for (i = 0; i < SDRAM_MAX_CS; i++) { | |
327 | size = readl((MVEBU_SDRAM_SCRATCH + (i * 8))) & SDRAM_ADDR_MASK; | |
328 | if (size != 0) { | |
329 | size |= ~(SDRAM_ADDR_MASK); | |
330 | ||
331 | /* Set Base Address */ | |
332 | temp = (base & 0xFF000000ll) | ((base >> 32) & 0xF); | |
333 | writel(temp, MVEBU_SDRAM_BASE + DDR_BASE_CS_OFF(i)); | |
334 | ||
335 | /* | |
336 | * Check if out of max window size and resize | |
337 | * the window | |
338 | */ | |
339 | temp = (readl(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)) & | |
340 | ~(SDRAM_ADDR_MASK)) | 1; | |
341 | temp |= (size & SDRAM_ADDR_MASK); | |
342 | writel(temp, MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)); | |
343 | ||
344 | base += ((u64)size + 1); | |
345 | } else { | |
346 | /* | |
347 | * Disable window if not used, otherwise this | |
348 | * leads to overlapping enabled windows with | |
349 | * pretty strange results | |
350 | */ | |
351 | clrbits_le32(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i), 1); | |
352 | } | |
353 | } | |
354 | } | |
355 | ||
9f62b44e SR |
356 | void mmu_disable(void) |
357 | { | |
358 | asm volatile( | |
359 | "mrc p15, 0, r0, c1, c0, 0\n" | |
360 | "bic r0, #1\n" | |
361 | "mcr p15, 0, r0, c1, c0, 0\n"); | |
362 | } | |
363 | ||
41e5ee54 | 364 | #ifdef CONFIG_ARCH_CPU_INIT |
e1b078e0 KS |
365 | static void set_cbar(u32 addr) |
366 | { | |
367 | asm("mcr p15, 4, %0, c15, c0" : : "r" (addr)); | |
368 | } | |
369 | ||
dee40d26 SR |
370 | #define MV_USB_PHY_BASE (MVEBU_AXP_USB_BASE + 0x800) |
371 | #define MV_USB_PHY_PLL_REG(reg) (MV_USB_PHY_BASE | (((reg) & 0xF) << 2)) | |
372 | #define MV_USB_X3_BASE(addr) (MVEBU_AXP_USB_BASE | BIT(11) | \ | |
373 | (((addr) & 0xF) << 6)) | |
374 | #define MV_USB_X3_PHY_CHANNEL(dev, reg) (MV_USB_X3_BASE((dev) + 1) | \ | |
375 | (((reg) & 0xF) << 2)) | |
376 | ||
377 | static void setup_usb_phys(void) | |
378 | { | |
379 | int dev; | |
380 | ||
381 | /* | |
382 | * USB PLL init | |
383 | */ | |
384 | ||
385 | /* Setup PLL frequency */ | |
386 | /* USB REF frequency = 25 MHz */ | |
387 | clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0x3ff, 0x605); | |
388 | ||
389 | /* Power up PLL and PHY channel */ | |
ab8a4c6a | 390 | setbits_le32(MV_USB_PHY_PLL_REG(2), BIT(9)); |
dee40d26 SR |
391 | |
392 | /* Assert VCOCAL_START */ | |
ab8a4c6a | 393 | setbits_le32(MV_USB_PHY_PLL_REG(1), BIT(21)); |
dee40d26 SR |
394 | |
395 | mdelay(1); | |
396 | ||
397 | /* | |
398 | * USB PHY init (change from defaults) specific for 40nm (78X30 78X60) | |
399 | */ | |
400 | ||
401 | for (dev = 0; dev < 3; dev++) { | |
ab8a4c6a | 402 | setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), BIT(15)); |
dee40d26 SR |
403 | |
404 | /* Assert REG_RCAL_START in channel REG 1 */ | |
ab8a4c6a | 405 | setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12)); |
dee40d26 | 406 | udelay(40); |
ab8a4c6a | 407 | clrbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12)); |
dee40d26 SR |
408 | } |
409 | } | |
e1b078e0 | 410 | |
f4e6ec7d SR |
411 | /* |
412 | * This function is not called from the SPL U-Boot version | |
413 | */ | |
41e5ee54 SR |
414 | int arch_cpu_init(void) |
415 | { | |
42cc034f SR |
416 | struct pl310_regs *const pl310 = |
417 | (struct pl310_regs *)CONFIG_SYS_PL310_BASE; | |
418 | ||
cefd7642 SR |
419 | /* |
420 | * Only with disabled MMU its possible to switch the base | |
421 | * register address on Armada 38x. Without this the SDRAM | |
422 | * located at >= 0x4000.0000 is also not accessible, as its | |
423 | * still locked to cache. | |
424 | */ | |
425 | mmu_disable(); | |
cefd7642 SR |
426 | |
427 | /* Linux expects the internal registers to be at 0xf1000000 */ | |
428 | writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG); | |
429 | set_cbar(SOC_REGS_PHY_BASE + 0xC000); | |
430 | ||
cefd7642 SR |
431 | /* |
432 | * From this stage on, the SoC detection is working. As we have | |
433 | * configured the internal register base to the value used | |
434 | * in the macros / defines in the U-Boot header (soc.h). | |
435 | */ | |
42cc034f | 436 | |
c86d53fd SR |
437 | if (mvebu_soc_family() == MVEBU_SOC_A38X) { |
438 | /* | |
439 | * To fully release / unlock this area from cache, we need | |
440 | * to flush all caches and disable the L2 cache. | |
441 | */ | |
442 | icache_disable(); | |
443 | dcache_disable(); | |
444 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | |
445 | } | |
9f62b44e | 446 | |
41e5ee54 SR |
447 | /* |
448 | * We need to call mvebu_mbus_probe() before calling | |
449 | * update_sdram_window_sizes() as it disables all previously | |
450 | * configured mbus windows and then configures them as | |
451 | * required for U-Boot. Calling update_sdram_window_sizes() | |
452 | * without this configuration will not work, as the internal | |
453 | * registers can't be accessed reliably because of potenial | |
454 | * double mapping. | |
455 | * After updating the SDRAM access windows we need to call | |
456 | * mvebu_mbus_probe() again, as this now correctly configures | |
457 | * the SDRAM areas that are later used by the MVEBU drivers | |
458 | * (e.g. USB, NETA). | |
459 | */ | |
460 | ||
461 | /* | |
462 | * First disable all windows | |
463 | */ | |
464 | mvebu_mbus_probe(NULL, 0); | |
465 | ||
9c6d3b7b SR |
466 | if (mvebu_soc_family() == MVEBU_SOC_AXP) { |
467 | /* | |
468 | * Now the SDRAM access windows can be reconfigured using | |
469 | * the information in the SDRAM scratch pad registers | |
470 | */ | |
471 | update_sdram_window_sizes(); | |
472 | } | |
41e5ee54 SR |
473 | |
474 | /* | |
475 | * Finally the mbus windows can be configured with the | |
476 | * updated SDRAM sizes | |
477 | */ | |
478 | mvebu_mbus_probe(windows, ARRAY_SIZE(windows)); | |
479 | ||
2a0b7dc3 SR |
480 | if (mvebu_soc_family() == MVEBU_SOC_AXP) { |
481 | /* Enable GBE0, GBE1, LCD and NFC PUP */ | |
482 | clrsetbits_le32(ARMADA_XP_PUP_ENABLE, 0, | |
483 | GE0_PUP_EN | GE1_PUP_EN | LCD_PUP_EN | | |
484 | NAND_PUP_EN | SPI_PUP_EN); | |
dee40d26 SR |
485 | |
486 | /* Configure USB PLL and PHYs on AXP */ | |
487 | setup_usb_phys(); | |
2a0b7dc3 SR |
488 | } |
489 | ||
490 | /* Enable NAND and NAND arbiter */ | |
491 | clrsetbits_le32(MVEBU_SOC_DEV_MUX_REG, 0, NAND_EN | NAND_ARBITER_EN); | |
492 | ||
501c098a SR |
493 | /* Disable MBUS error propagation */ |
494 | clrsetbits_le32(SOC_COHERENCY_FABRIC_CTRL_REG, MBUS_ERR_PROP_EN, 0); | |
495 | ||
41e5ee54 SR |
496 | return 0; |
497 | } | |
498 | #endif /* CONFIG_ARCH_CPU_INIT */ | |
499 | ||
2a0b7dc3 SR |
500 | u32 mvebu_get_nand_clock(void) |
501 | { | |
d7b4731e CP |
502 | u32 reg; |
503 | ||
504 | if (mvebu_soc_family() == MVEBU_SOC_A38X) | |
505 | reg = MVEBU_DFX_DIV_CLK_CTRL(1); | |
689f9cf6 CP |
506 | else if (mvebu_soc_family() == MVEBU_SOC_MSYS) |
507 | reg = MVEBU_DFX_DIV_CLK_CTRL(8); | |
d7b4731e CP |
508 | else |
509 | reg = MVEBU_CORE_DIV_CLK_CTRL(1); | |
510 | ||
2a0b7dc3 | 511 | return CONFIG_SYS_MVEBU_PLL_CLOCK / |
d7b4731e | 512 | ((readl(reg) & |
2a0b7dc3 SR |
513 | NAND_ECC_DIVCKL_RATIO_MASK) >> NAND_ECC_DIVCKL_RATIO_OFFS); |
514 | } | |
515 | ||
41e5ee54 SR |
516 | /* |
517 | * SOC specific misc init | |
518 | */ | |
519 | #if defined(CONFIG_ARCH_MISC_INIT) | |
520 | int arch_misc_init(void) | |
521 | { | |
522 | /* Nothing yet, perhaps we need something here later */ | |
523 | return 0; | |
524 | } | |
525 | #endif /* CONFIG_ARCH_MISC_INIT */ | |
526 | ||
4ec9dd40 | 527 | #if defined(CONFIG_MMC_SDHCI_MV) && !defined(CONFIG_DM_MMC) |
b75d8dc5 | 528 | int board_mmc_init(struct bd_info *bis) |
7f1adcd7 SR |
529 | { |
530 | mv_sdh_init(MVEBU_SDIO_BASE, 0, 0, | |
531 | SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD); | |
532 | ||
533 | return 0; | |
534 | } | |
535 | #endif | |
536 | ||
4d991cb3 SR |
537 | #define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 |
538 | #define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 | |
539 | ||
540 | #define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4)) | |
541 | #define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4)) | |
542 | #define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4)) | |
543 | ||
544 | static void ahci_mvebu_mbus_config(void __iomem *base) | |
545 | { | |
546 | const struct mbus_dram_target_info *dram; | |
547 | int i; | |
548 | ||
f0aa1254 BS |
549 | /* mbus is not initialized in SPL; keep the ROM settings */ |
550 | if (IS_ENABLED(CONFIG_SPL_BUILD)) | |
551 | return; | |
552 | ||
4d991cb3 SR |
553 | dram = mvebu_mbus_dram_info(); |
554 | ||
555 | for (i = 0; i < 4; i++) { | |
556 | writel(0, base + AHCI_WINDOW_CTRL(i)); | |
557 | writel(0, base + AHCI_WINDOW_BASE(i)); | |
558 | writel(0, base + AHCI_WINDOW_SIZE(i)); | |
559 | } | |
560 | ||
561 | for (i = 0; i < dram->num_cs; i++) { | |
562 | const struct mbus_dram_window *cs = dram->cs + i; | |
563 | ||
564 | writel((cs->mbus_attr << 8) | | |
565 | (dram->mbus_dram_target_id << 4) | 1, | |
566 | base + AHCI_WINDOW_CTRL(i)); | |
567 | writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i)); | |
568 | writel(((cs->size - 1) & 0xffff0000), | |
569 | base + AHCI_WINDOW_SIZE(i)); | |
570 | } | |
571 | } | |
572 | ||
573 | static void ahci_mvebu_regret_option(void __iomem *base) | |
574 | { | |
575 | /* | |
576 | * Enable the regret bit to allow the SATA unit to regret a | |
577 | * request that didn't receive an acknowlegde and avoid a | |
578 | * deadlock | |
579 | */ | |
580 | writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR); | |
581 | writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA); | |
582 | } | |
583 | ||
4b11e5f6 | 584 | int board_ahci_enable(void) |
4d991cb3 | 585 | { |
4d991cb3 SR |
586 | ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE); |
587 | ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE); | |
4b11e5f6 BS |
588 | |
589 | return 0; | |
590 | } | |
591 | ||
592 | #ifdef CONFIG_SCSI_AHCI_PLAT | |
593 | void scsi_init(void) | |
594 | { | |
595 | printf("MVEBU SATA INIT\n"); | |
596 | board_ahci_enable(); | |
4d991cb3 SR |
597 | ahci_init((void __iomem *)MVEBU_SATA0_BASE); |
598 | } | |
599 | #endif | |
600 | ||
78aa018f JN |
601 | #ifdef CONFIG_USB_XHCI_MVEBU |
602 | #define USB3_MAX_WINDOWS 4 | |
603 | #define USB3_WIN_CTRL(w) (0x0 + ((w) * 8)) | |
604 | #define USB3_WIN_BASE(w) (0x4 + ((w) * 8)) | |
605 | ||
606 | static void xhci_mvebu_mbus_config(void __iomem *base, | |
607 | const struct mbus_dram_target_info *dram) | |
608 | { | |
609 | int i; | |
610 | ||
611 | for (i = 0; i < USB3_MAX_WINDOWS; i++) { | |
612 | writel(0, base + USB3_WIN_CTRL(i)); | |
613 | writel(0, base + USB3_WIN_BASE(i)); | |
614 | } | |
615 | ||
616 | for (i = 0; i < dram->num_cs; i++) { | |
617 | const struct mbus_dram_window *cs = dram->cs + i; | |
618 | ||
619 | /* Write size, attributes and target id to control register */ | |
620 | writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) | | |
621 | (dram->mbus_dram_target_id << 4) | 1, | |
622 | base + USB3_WIN_CTRL(i)); | |
623 | ||
624 | /* Write base address to base register */ | |
625 | writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(i)); | |
626 | } | |
627 | } | |
628 | ||
629 | int board_xhci_enable(fdt_addr_t base) | |
630 | { | |
631 | const struct mbus_dram_target_info *dram; | |
632 | ||
633 | printf("MVEBU XHCI INIT controller @ 0x%lx\n", base); | |
634 | ||
635 | dram = mvebu_mbus_dram_info(); | |
636 | xhci_mvebu_mbus_config((void __iomem *)base, dram); | |
637 | ||
638 | return 0; | |
639 | } | |
640 | #endif | |
641 | ||
41e5ee54 SR |
642 | void enable_caches(void) |
643 | { | |
60b75324 SR |
644 | /* Avoid problem with e.g. neta ethernet driver */ |
645 | invalidate_dcache_all(); | |
646 | ||
ebe78903 SR |
647 | /* |
648 | * Armada 375 still has some problems with d-cache enabled in the | |
649 | * ethernet driver (mvpp2). So lets keep the d-cache disabled | |
650 | * until this is solved. | |
651 | */ | |
652 | if (mvebu_soc_family() != MVEBU_SOC_A375) { | |
653 | /* Enable D-cache. I-cache is already enabled in start.S */ | |
654 | dcache_enable(); | |
655 | } | |
41e5ee54 | 656 | } |
3e5ce7ce SR |
657 | |
658 | void v7_outer_cache_enable(void) | |
659 | { | |
3e5ce7ce | 660 | if (mvebu_soc_family() == MVEBU_SOC_AXP) { |
c86d53fd SR |
661 | struct pl310_regs *const pl310 = |
662 | (struct pl310_regs *)CONFIG_SYS_PL310_BASE; | |
3e5ce7ce SR |
663 | u32 u; |
664 | ||
c86d53fd SR |
665 | /* The L2 cache is already disabled at this point */ |
666 | ||
3e5ce7ce SR |
667 | /* |
668 | * For Aurora cache in no outer mode, enable via the CP15 | |
669 | * coprocessor broadcasting of cache commands to L2. | |
670 | */ | |
671 | asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u)); | |
672 | u |= BIT(8); /* Set the FW bit */ | |
673 | asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u)); | |
674 | ||
675 | isb(); | |
676 | ||
677 | /* Enable the L2 cache */ | |
678 | setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | |
679 | } | |
680 | } | |
f0e8173a SR |
681 | |
682 | void v7_outer_cache_disable(void) | |
683 | { | |
684 | struct pl310_regs *const pl310 = | |
685 | (struct pl310_regs *)CONFIG_SYS_PL310_BASE; | |
686 | ||
687 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | |
688 | } |