1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * arch/arm/cpu/armv8/rcar_gen3/lowlevel_init.S
4 *	This file is lowlevel initialize routine.
5 *
6 * (C) Copyright 2015 Renesas Electronics Corporation
7 *
8 * This file is based on the arch/arm/cpu/armv8/start.S
9 *
10 * (C) Copyright 2013
11 * David Feng <fenghua@phytium.com.cn>
12 */
13
14#include <asm-offsets.h>
15#include <config.h>
16#include <linux/linkage.h>
17#include <asm/macro.h>
18
19ENTRY(lowlevel_init)
20	mov	x29, lr			/* Save LR */
21
22#ifndef CONFIG_ARMV8_MULTIENTRY
23	/*
24	 * For single-entry systems the lowlevel init is very simple.
25	 */
26	ldr	x0, =GICD_BASE
27	bl	gic_init_secure
28
29#else /* CONFIG_ARMV8_MULTIENTRY is set */
30
31#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
32	branch_if_slave x0, 1f
33	ldr	x0, =GICD_BASE
34	bl	gic_init_secure
351:
36#if defined(CONFIG_GICV3)
37	ldr	x0, =GICR_BASE
38	bl	gic_init_secure_percpu
39#elif defined(CONFIG_GICV2)
40	ldr	x0, =GICD_BASE
41	ldr	x1, =GICC_BASE
42	bl	gic_init_secure_percpu
43#endif
44#endif
45
46	branch_if_master x0, x1, 2f
47
48	/*
49	 * Slave should wait for master clearing spin table.
50	 * This sync prevent salves observing incorrect
51	 * value of spin table and jumping to wrong place.
52	 */
53#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
54#ifdef CONFIG_GICV2
55	ldr	x0, =GICC_BASE
56#endif
57	bl	gic_wait_for_interrupt
58#endif
59
60	/*
61	 * All slaves will enter EL2 and optionally EL1.
62	 */
63	adr	x4, lowlevel_in_el2
64	ldr	x5, =ES_TO_AARCH64
65	bl	armv8_switch_to_el2
66
67lowlevel_in_el2:
68#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
69	adr	x4, lowlevel_in_el1
70	ldr	x5, =ES_TO_AARCH64
71	bl	armv8_switch_to_el1
72
73lowlevel_in_el1:
74#endif
75#endif /* CONFIG_ARMV8_MULTIENTRY */
76
77	bl      s_init
78
792:
80	mov	lr, x29			/* Restore LR */
81	ret
82ENDPROC(lowlevel_init)
83