162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright (C) 2015 Russell King
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This assembly is required to safely remap the physical address space
662306a36Sopenharmony_ci * for Keystone 2
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/linkage.h>
962306a36Sopenharmony_ci#include <linux/pgtable.h>
1062306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1162306a36Sopenharmony_ci#include <asm/cp15.h>
1262306a36Sopenharmony_ci#include <asm/page.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci	.section ".idmap.text", "ax"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define L1_ORDER 3
1762306a36Sopenharmony_ci#define L2_ORDER 3
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciENTRY(lpae_pgtables_remap_asm)
2062306a36Sopenharmony_ci	stmfd	sp!, {r4-r8, lr}
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	mrc	p15, 0, r8, c1, c0, 0		@ read control reg
2362306a36Sopenharmony_ci	bic	ip, r8, #CR_M			@ disable caches and MMU
2462306a36Sopenharmony_ci	mcr	p15, 0, ip, c1, c0, 0
2562306a36Sopenharmony_ci	dsb
2662306a36Sopenharmony_ci	isb
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* Update level 2 entries covering the kernel */
2962306a36Sopenharmony_ci	ldr	r6, =(_end - 1)
3062306a36Sopenharmony_ci	add	r7, r2, #0x1000
3162306a36Sopenharmony_ci	add	r6, r7, r6, lsr #SECTION_SHIFT - L2_ORDER
3262306a36Sopenharmony_ci	add	r7, r7, #KERNEL_OFFSET >> (SECTION_SHIFT - L2_ORDER)
3362306a36Sopenharmony_ci1:	ldrd	r4, r5, [r7]
3462306a36Sopenharmony_ci	adds	r4, r4, r0
3562306a36Sopenharmony_ci	adc	r5, r5, r1
3662306a36Sopenharmony_ci	strd	r4, r5, [r7], #1 << L2_ORDER
3762306a36Sopenharmony_ci	cmp	r7, r6
3862306a36Sopenharmony_ci	bls	1b
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	/* Update level 2 entries for the boot data */
4162306a36Sopenharmony_ci	add	r7, r2, #0x1000
4262306a36Sopenharmony_ci	movw	r3, #FDT_FIXED_BASE >> (SECTION_SHIFT - L2_ORDER)
4362306a36Sopenharmony_ci	add	r7, r7, r3
4462306a36Sopenharmony_ci	ldrd	r4, r5, [r7]
4562306a36Sopenharmony_ci	adds	r4, r4, r0
4662306a36Sopenharmony_ci	adc	r5, r5, r1
4762306a36Sopenharmony_ci	strd	r4, r5, [r7], #1 << L2_ORDER
4862306a36Sopenharmony_ci	ldrd	r4, r5, [r7]
4962306a36Sopenharmony_ci	adds	r4, r4, r0
5062306a36Sopenharmony_ci	adc	r5, r5, r1
5162306a36Sopenharmony_ci	strd	r4, r5, [r7]
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	/* Update level 1 entries */
5462306a36Sopenharmony_ci	mov	r6, #4
5562306a36Sopenharmony_ci	mov	r7, r2
5662306a36Sopenharmony_ci2:	ldrd	r4, r5, [r7]
5762306a36Sopenharmony_ci	adds	r4, r4, r0
5862306a36Sopenharmony_ci	adc	r5, r5, r1
5962306a36Sopenharmony_ci	strd	r4, r5, [r7], #1 << L1_ORDER
6062306a36Sopenharmony_ci	subs	r6, r6, #1
6162306a36Sopenharmony_ci	bne	2b
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	mrrc	p15, 0, r4, r5, c2		@ read TTBR0
6462306a36Sopenharmony_ci	adds	r4, r4, r0			@ update physical address
6562306a36Sopenharmony_ci	adc	r5, r5, r1
6662306a36Sopenharmony_ci	mcrr	p15, 0, r4, r5, c2		@ write back TTBR0
6762306a36Sopenharmony_ci	mrrc	p15, 1, r4, r5, c2		@ read TTBR1
6862306a36Sopenharmony_ci	adds	r4, r4, r0			@ update physical address
6962306a36Sopenharmony_ci	adc	r5, r5, r1
7062306a36Sopenharmony_ci	mcrr	p15, 1, r4, r5, c2		@ write back TTBR1
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	dsb
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	mov	ip, #0
7562306a36Sopenharmony_ci	mcr	p15, 0, ip, c7, c5, 0		@ I+BTB cache invalidate
7662306a36Sopenharmony_ci	mcr	p15, 0, ip, c8, c7, 0		@ local_flush_tlb_all()
7762306a36Sopenharmony_ci	dsb
7862306a36Sopenharmony_ci	isb
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	mcr	p15, 0, r8, c1, c0, 0		@ re-enable MMU
8162306a36Sopenharmony_ci	dsb
8262306a36Sopenharmony_ci	isb
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	ldmfd	sp!, {r4-r8, pc}
8562306a36Sopenharmony_ciENDPROC(lpae_pgtables_remap_asm)
86