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