1 /*
2  * Copyright (c) 2022 IoT.bzh
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Armv8-R AArch32 architecture helpers.
7  *
8  */
9 
10 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_LIB_HELPERS_H_
11 #define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_LIB_HELPERS_H_
12 
13 #ifndef _ASMLANGUAGE
14 
15 #include <stdint.h>
16 
17 #define read_sysreg32(op1, CRn, CRm, op2)				\
18 ({									\
19 	uint32_t val;							\
20 	__asm__ volatile ("mrc p15, " #op1 ", %0, c" #CRn ", c"		\
21 			  #CRm ", " #op2 : "=r" (val) :: "memory");	\
22 	val;								\
23 })
24 
25 #define write_sysreg32(val, op1, CRn, CRm, op2)				\
26 ({									\
27 	__asm__ volatile ("mcr p15, " #op1 ", %0, c" #CRn ", c"		\
28 			  #CRm ", " #op2 :: "r" (val) : "memory");	\
29 })
30 
31 #define read_sysreg64(op1, CRm)						\
32 ({									\
33 	uint64_t val;							\
34 	__asm__ volatile ("mrrc p15, " #op1 ", %Q0, %R0, c"		\
35 			  #CRm : "=r" (val) :: "memory");		\
36 	val;								\
37 })
38 
39 #define write_sysreg64(val, op1, CRm)					\
40 ({									\
41 	__asm__ volatile ("mcrr p15, " #op1 ", %Q0, %R0, c"		\
42 			  #CRm :: "r" (val) : "memory");		\
43 })
44 
45 #define MAKE_REG_HELPER(reg, op1, CRn, CRm, op2)			\
46 	static ALWAYS_INLINE uint32_t read_##reg(void)			\
47 	{								\
48 		return read_sysreg32(op1, CRn, CRm, op2);		\
49 	}								\
50 	static ALWAYS_INLINE void write_##reg(uint32_t val)		\
51 	{								\
52 		write_sysreg32(val, op1, CRn, CRm, op2);		\
53 	}
54 
55 #define MAKE_REG64_HELPER(reg, op1, CRm)				\
56 	static ALWAYS_INLINE uint64_t read_##reg(void)			\
57 	{								\
58 		return read_sysreg64(op1, CRm);				\
59 	}								\
60 	static ALWAYS_INLINE void write_##reg(uint64_t val)		\
61 	{								\
62 		write_sysreg64(val, op1, CRm);				\
63 	}
64 
65 MAKE_REG_HELPER(mpuir,	     0, 0, 0, 4);
66 MAKE_REG_HELPER(mpidr,	     0, 0, 0, 5);
67 MAKE_REG_HELPER(sctlr,	     0, 1, 0, 0);
68 MAKE_REG_HELPER(prselr,	     0, 6, 2, 1);
69 MAKE_REG_HELPER(prbar,	     0, 6, 3, 0);
70 MAKE_REG_HELPER(prlar,	     0, 6, 3, 1);
71 MAKE_REG_HELPER(mair0,       0, 10, 2, 0);
72 MAKE_REG_HELPER(vbar,        0, 12, 0, 0);
73 MAKE_REG_HELPER(cntv_ctl,    0, 14,  3, 1);
74 MAKE_REG_HELPER(ctr,         0, 0, 0, 1);
75 MAKE_REG_HELPER(tpidruro,    0, 13, 0, 3);
76 MAKE_REG64_HELPER(ICC_SGI1R, 0, 12);
77 MAKE_REG64_HELPER(cntvct,    1, 14);
78 MAKE_REG64_HELPER(cntv_cval, 3, 14);
79 
80 /*
81  * GIC v3 compatibility macros:
82  * ARMv8 AArch32 profile has no mention of
83  * ELx in the register names.
84  * We define them anyway to reuse the GICv3 driver
85  * made for AArch64.
86  */
87 
88 /* ICC_PMR */
89 MAKE_REG_HELPER(ICC_PMR_EL1,     0, 4, 6, 0);
90 /* ICC_IAR1 */
91 MAKE_REG_HELPER(ICC_IAR1_EL1,    0, 12, 12, 0);
92 /* ICC_EOIR1 */
93 MAKE_REG_HELPER(ICC_EOIR1_EL1,   0, 12, 12, 1);
94 /* ICC_SRE */
95 MAKE_REG_HELPER(ICC_SRE_EL1,     0, 12, 12, 5);
96 /* ICC_IGRPEN1 */
97 MAKE_REG_HELPER(ICC_IGRPEN1_EL1, 0, 12, 12, 7);
98 
99 #define write_sysreg(val, reg) write_##reg(val)
100 #define read_sysreg(reg) read_##reg()
101 
102 #define sev()	__asm__ volatile("sev" : : : "memory")
103 #define wfe()	__asm__ volatile("wfe" : : : "memory")
104 
105 #endif /* !_ASMLANGUAGE */
106 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_LIB_HELPERS_H_ */
107