xref: /rk3399_rockchip-uboot/arch/arm/include/asm/macro.h (revision 59a9cfdd16ad7ab14f22697bf1e049c6bea0d3e2)
1819833afSPeter Tyser /*
2819833afSPeter Tyser  * include/asm-arm/macro.h
3819833afSPeter Tyser  *
4819833afSPeter Tyser  * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
5819833afSPeter Tyser  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
7819833afSPeter Tyser  */
8819833afSPeter Tyser 
9819833afSPeter Tyser #ifndef __ASM_ARM_MACRO_H__
10819833afSPeter Tyser #define __ASM_ARM_MACRO_H__
11819833afSPeter Tyser #ifdef __ASSEMBLY__
12819833afSPeter Tyser 
13819833afSPeter Tyser /*
14819833afSPeter Tyser  * These macros provide a convenient way to write 8, 16 and 32 bit data
15819833afSPeter Tyser  * to any address.
16819833afSPeter Tyser  * Registers r4 and r5 are used, any data in these registers are
17819833afSPeter Tyser  * overwritten by the macros.
18819833afSPeter Tyser  * The macros are valid for any ARM architecture, they do not implement
19819833afSPeter Tyser  * any memory barriers so caution is recommended when using these when the
20819833afSPeter Tyser  * caches are enabled or on a multi-core system.
21819833afSPeter Tyser  */
22819833afSPeter Tyser 
23819833afSPeter Tyser .macro	write32, addr, data
24819833afSPeter Tyser 	ldr	r4, =\addr
25819833afSPeter Tyser 	ldr	r5, =\data
26819833afSPeter Tyser 	str	r5, [r4]
27819833afSPeter Tyser .endm
28819833afSPeter Tyser 
29819833afSPeter Tyser .macro	write16, addr, data
30819833afSPeter Tyser 	ldr	r4, =\addr
31819833afSPeter Tyser 	ldrh	r5, =\data
32819833afSPeter Tyser 	strh	r5, [r4]
33819833afSPeter Tyser .endm
34819833afSPeter Tyser 
35819833afSPeter Tyser .macro	write8, addr, data
36819833afSPeter Tyser 	ldr	r4, =\addr
37819833afSPeter Tyser 	ldrb	r5, =\data
38819833afSPeter Tyser 	strb	r5, [r4]
39819833afSPeter Tyser .endm
40819833afSPeter Tyser 
41819833afSPeter Tyser /*
42819833afSPeter Tyser  * This macro generates a loop that can be used for delays in the code.
43819833afSPeter Tyser  * Register r4 is used, any data in this register is overwritten by the
44819833afSPeter Tyser  * macro.
45819833afSPeter Tyser  * The macro is valid for any ARM architeture. The actual time spent in the
46819833afSPeter Tyser  * loop will vary from CPU to CPU though.
47819833afSPeter Tyser  */
48819833afSPeter Tyser 
49819833afSPeter Tyser .macro	wait_timer, time
50819833afSPeter Tyser 	ldr	r4, =\time
51819833afSPeter Tyser 1:
52819833afSPeter Tyser 	nop
53819833afSPeter Tyser 	subs	r4, r4, #1
54819833afSPeter Tyser 	bcs	1b
55819833afSPeter Tyser .endm
56819833afSPeter Tyser 
570ae76531SDavid Feng #ifdef CONFIG_ARM64
580ae76531SDavid Feng /*
590ae76531SDavid Feng  * Register aliases.
600ae76531SDavid Feng  */
610ae76531SDavid Feng lr	.req	x30
620ae76531SDavid Feng 
630ae76531SDavid Feng /*
640ae76531SDavid Feng  * Branch according to exception level
650ae76531SDavid Feng  */
660ae76531SDavid Feng .macro	switch_el, xreg, el3_label, el2_label, el1_label
670ae76531SDavid Feng 	mrs	\xreg, CurrentEL
680ae76531SDavid Feng 	cmp	\xreg, 0xc
690ae76531SDavid Feng 	b.eq	\el3_label
700ae76531SDavid Feng 	cmp	\xreg, 0x8
710ae76531SDavid Feng 	b.eq	\el2_label
720ae76531SDavid Feng 	cmp	\xreg, 0x4
730ae76531SDavid Feng 	b.eq	\el1_label
740ae76531SDavid Feng .endm
750ae76531SDavid Feng 
760ae76531SDavid Feng /*
770ae76531SDavid Feng  * Branch if current processor is a slave,
780ae76531SDavid Feng  * choose processor with all zero affinity value as the master.
790ae76531SDavid Feng  */
800ae76531SDavid Feng .macro	branch_if_slave, xreg, slave_label
810ae76531SDavid Feng 	mrs	\xreg, mpidr_el1
820ae76531SDavid Feng 	tst	\xreg, #0xff		/* Test Affinity 0 */
830ae76531SDavid Feng 	b.ne	\slave_label
840ae76531SDavid Feng 	lsr	\xreg, \xreg, #8
850ae76531SDavid Feng 	tst	\xreg, #0xff		/* Test Affinity 1 */
860ae76531SDavid Feng 	b.ne	\slave_label
870ae76531SDavid Feng 	lsr	\xreg, \xreg, #8
880ae76531SDavid Feng 	tst	\xreg, #0xff		/* Test Affinity 2 */
890ae76531SDavid Feng 	b.ne	\slave_label
900ae76531SDavid Feng 	lsr	\xreg, \xreg, #16
910ae76531SDavid Feng 	tst	\xreg, #0xff		/* Test Affinity 3 */
920ae76531SDavid Feng 	b.ne	\slave_label
930ae76531SDavid Feng .endm
940ae76531SDavid Feng 
950ae76531SDavid Feng /*
960ae76531SDavid Feng  * Branch if current processor is a master,
970ae76531SDavid Feng  * choose processor with all zero affinity value as the master.
980ae76531SDavid Feng  */
990ae76531SDavid Feng .macro	branch_if_master, xreg1, xreg2, master_label
1000ae76531SDavid Feng 	mrs	\xreg1, mpidr_el1
1010ae76531SDavid Feng 	lsr	\xreg2, \xreg1, #32
1020ae76531SDavid Feng 	lsl	\xreg1, \xreg1, #40
1030ae76531SDavid Feng 	lsr	\xreg1, \xreg1, #40
1040ae76531SDavid Feng 	orr	\xreg1, \xreg1, \xreg2
1050ae76531SDavid Feng 	cbz	\xreg1, \master_label
1060ae76531SDavid Feng .endm
1070ae76531SDavid Feng 
10840f8dec5SYork Sun .macro armv8_switch_to_el2_m, xreg1
10940f8dec5SYork Sun 	/* 64bit EL2 | HCE | SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1 */
11040f8dec5SYork Sun 	mov	\xreg1, #0x5b1
11140f8dec5SYork Sun 	msr	scr_el3, \xreg1
11240f8dec5SYork Sun 	msr	cptr_el3, xzr		/* Disable coprocessor traps to EL3 */
11340f8dec5SYork Sun 	mov	\xreg1, #0x33ff
11440f8dec5SYork Sun 	msr	cptr_el2, \xreg1	/* Disable coprocessor traps to EL2 */
11540f8dec5SYork Sun 
11640f8dec5SYork Sun 	/* Initialize SCTLR_EL2
11740f8dec5SYork Sun 	 *
11840f8dec5SYork Sun 	 * setting RES1 bits (29,28,23,22,18,16,11,5,4) to 1
11940f8dec5SYork Sun 	 * and RES0 bits (31,30,27,26,24,21,20,17,15-13,10-6) +
12040f8dec5SYork Sun 	 * EE,WXN,I,SA,C,A,M to 0
12140f8dec5SYork Sun 	 */
12240f8dec5SYork Sun 	mov	\xreg1, #0x0830
12340f8dec5SYork Sun 	movk	\xreg1, #0x30C5, lsl #16
12440f8dec5SYork Sun 	msr	sctlr_el2, \xreg1
12540f8dec5SYork Sun 
12640f8dec5SYork Sun 	/* Return to the EL2_SP2 mode from EL3 */
12740f8dec5SYork Sun 	mov	\xreg1, sp
12840f8dec5SYork Sun 	msr	sp_el2, \xreg1		/* Migrate SP */
12940f8dec5SYork Sun 	mrs	\xreg1, vbar_el3
13040f8dec5SYork Sun 	msr	vbar_el2, \xreg1	/* Migrate VBAR */
13140f8dec5SYork Sun 	mov	\xreg1, #0x3c9
13240f8dec5SYork Sun 	msr	spsr_el3, \xreg1	/* EL2_SP2 | D | A | I | F */
13340f8dec5SYork Sun 	msr	elr_el3, lr
13440f8dec5SYork Sun 	eret
13540f8dec5SYork Sun .endm
13640f8dec5SYork Sun 
13740f8dec5SYork Sun .macro armv8_switch_to_el1_m, xreg1, xreg2
13840f8dec5SYork Sun 	/* Initialize Generic Timers */
13940f8dec5SYork Sun 	mrs	\xreg1, cnthctl_el2
14040f8dec5SYork Sun 	orr	\xreg1, \xreg1, #0x3	/* Enable EL1 access to timers */
14140f8dec5SYork Sun 	msr	cnthctl_el2, \xreg1
14240f8dec5SYork Sun 	msr	cntvoff_el2, xzr
14340f8dec5SYork Sun 
14440f8dec5SYork Sun 	/* Initilize MPID/MPIDR registers */
14540f8dec5SYork Sun 	mrs	\xreg1, midr_el1
14640f8dec5SYork Sun 	mrs	\xreg2, mpidr_el1
14740f8dec5SYork Sun 	msr	vpidr_el2, \xreg1
14840f8dec5SYork Sun 	msr	vmpidr_el2, \xreg2
14940f8dec5SYork Sun 
15040f8dec5SYork Sun 	/* Disable coprocessor traps */
15140f8dec5SYork Sun 	mov	\xreg1, #0x33ff
15240f8dec5SYork Sun 	msr	cptr_el2, \xreg1	/* Disable coprocessor traps to EL2 */
15340f8dec5SYork Sun 	msr	hstr_el2, xzr		/* Disable coprocessor traps to EL2 */
15440f8dec5SYork Sun 	mov	\xreg1, #3 << 20
15540f8dec5SYork Sun 	msr	cpacr_el1, \xreg1	/* Enable FP/SIMD at EL1 */
15640f8dec5SYork Sun 
15740f8dec5SYork Sun 	/* Initialize HCR_EL2 */
15840f8dec5SYork Sun 	mov	\xreg1, #(1 << 31)		/* 64bit EL1 */
15940f8dec5SYork Sun 	orr	\xreg1, \xreg1, #(1 << 29)	/* Disable HVC */
16040f8dec5SYork Sun 	msr	hcr_el2, \xreg1
16140f8dec5SYork Sun 
16240f8dec5SYork Sun 	/* SCTLR_EL1 initialization
16340f8dec5SYork Sun 	 *
16440f8dec5SYork Sun 	 * setting RES1 bits (29,28,23,22,20,11) to 1
16540f8dec5SYork Sun 	 * and RES0 bits (31,30,27,21,17,13,10,6) +
16640f8dec5SYork Sun 	 * UCI,EE,EOE,WXN,nTWE,nTWI,UCT,DZE,I,UMA,SED,ITD,
16740f8dec5SYork Sun 	 * CP15BEN,SA0,SA,C,A,M to 0
16840f8dec5SYork Sun 	 */
16940f8dec5SYork Sun 	mov	\xreg1, #0x0800
17040f8dec5SYork Sun 	movk	\xreg1, #0x30d0, lsl #16
17140f8dec5SYork Sun 	msr	sctlr_el1, \xreg1
17240f8dec5SYork Sun 
17340f8dec5SYork Sun 	/* Return to the EL1_SP1 mode from EL2 */
17440f8dec5SYork Sun 	mov	\xreg1, sp
17540f8dec5SYork Sun 	msr	sp_el1, \xreg1		/* Migrate SP */
17640f8dec5SYork Sun 	mrs	\xreg1, vbar_el2
17740f8dec5SYork Sun 	msr	vbar_el1, \xreg1	/* Migrate VBAR */
17840f8dec5SYork Sun 	mov	\xreg1, #0x3c5
17940f8dec5SYork Sun 	msr	spsr_el2, \xreg1	/* EL1_SP1 | D | A | I | F */
18040f8dec5SYork Sun 	msr	elr_el2, lr
18140f8dec5SYork Sun 	eret
18240f8dec5SYork Sun .endm
18340f8dec5SYork Sun 
18440f8dec5SYork Sun #if defined(CONFIG_GICV3)
18540f8dec5SYork Sun .macro gic_wait_for_interrupt_m xreg1
18640f8dec5SYork Sun 0 :	wfi
18740f8dec5SYork Sun 	mrs     \xreg1, ICC_IAR1_EL1
18840f8dec5SYork Sun 	msr     ICC_EOIR1_EL1, \xreg1
18940f8dec5SYork Sun 	cbnz    \xreg1, 0b
19040f8dec5SYork Sun .endm
19140f8dec5SYork Sun #elif defined(CONFIG_GICV2)
19240f8dec5SYork Sun .macro gic_wait_for_interrupt_m xreg1, wreg2
19340f8dec5SYork Sun 0 :	wfi
19440f8dec5SYork Sun 	ldr     \wreg2, [\xreg1, GICC_AIAR]
19540f8dec5SYork Sun 	str     \wreg2, [\xreg1, GICC_AEOIR]
196*59a9cfddSYehuda Yitschak 	and	\wreg2, \wreg2, #0x3ff
19740f8dec5SYork Sun 	cbnz    \wreg2, 0b
19840f8dec5SYork Sun .endm
19940f8dec5SYork Sun #endif
20040f8dec5SYork Sun 
2010ae76531SDavid Feng #endif /* CONFIG_ARM64 */
2020ae76531SDavid Feng 
203819833afSPeter Tyser #endif /* __ASSEMBLY__ */
204819833afSPeter Tyser #endif /* __ASM_ARM_MACRO_H__ */
205