1/* SPDX-License-Identifier: GPL-2.0+ */
2
3#include <config.h>
4#include <linux/linkage.h>
5#include <asm/system.h>
6#include <asm/pl310.h>
7
8ENTRY(arch_very_early_init)
9#ifdef CONFIG_ARMADA_38X
10	/*
11	 * Only with disabled MMU its possible to switch the base
12	 * register address on Armada 38x. Without this the SDRAM
13	 * located at >= 0x4000.0000 is also not accessible, as its
14	 * still locked to cache.
15	 *
16	 * So to fully release / unlock this area from cache, we need
17	 * to first flush all caches, then disable the MMU and
18	 * disable the L2 cache.
19	 */
20
21	/* Invalidate L1 I/D */
22	mov	r0, #0			@ set up for MCR
23	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
24	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
25	mcr	p15, 0, r0, c7, c5, 6	@ invalidate BP array
26	mcr	p15, 0, r0, c7, c10, 4	@ DSB
27	mcr	p15, 0, r0, c7, c5, 4	@ ISB
28
29	/* Disable MMU */
30	mrc	p15, 0, r0, c1, c0, 0
31	bic	r0, #CR_M
32	mcr	p15, 0, r0, c1, c0, 0
33
34	/*
35	 * Disable L2 cache
36	 *
37	 * NOTE: Internal registers are still at address INTREG_BASE_ADDR_REG
38	 *       but CFG_SYS_PL310_BASE is already calculated from base
39	 *       address SOC_REGS_PHY_BASE.
40	 */
41	ldr	r1, =(CFG_SYS_PL310_BASE - SOC_REGS_PHY_BASE + INTREG_BASE_ADDR_REG)
42	ldr	r0, [r1, #L2X0_CTRL_OFF]
43	bic	r0, #L2X0_CTRL_EN
44	str	r0, [r1, #L2X0_CTRL_OFF]
45#endif
46
47	/* Move internal registers from INTREG_BASE_ADDR_REG to SOC_REGS_PHY_BASE */
48	ldr	r0, =SOC_REGS_PHY_BASE
49	ldr	r1, =INTREG_BASE_ADDR_REG
50	str	r0, [r1]
51	add	r0, r0, #0xC000
52	mcr	p15, 4, r0, c15, c0
53
54	bx lr
55ENDPROC(arch_very_early_init)
56