1 /*
2  * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0.
5  *
6  * @Date: 2021-01-22 16:30:56
7  * @LastEditTime: 2021-05-24 14:35:53
8  * @LastEditors: Please set LastEditors
9  * @Description: In User Settings Edit
10  * @FilePath: \project_freertos\devices\ft2004\bsp\core\ft_asm.h
11  */
12 
13 #ifndef FT_AARCH32_ASM_H
14 #define FT_AARCH32_ASM_H
15 
16 #ifdef __cplusplus
17 extern "C"
18 {
19 #endif
20 
21 #include "ft_types.h"
22 
23 #define __ASM __asm
24 #define __STRINGIFY(x) #x
25 /* C语言实现MCR指令 */
26 #define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2)                                                                                                   \
27     __ASM volatile("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", "                                                                           \
28                                                                             "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \
29                    :                                                                                                                                       \
30                    : "r"(src)                                                                                                                              \
31                    : "memory");
32 
33 /* C语言实现MRC指令 */
34 #define __MRC(coproc, opcode_1, CRn, CRm, opcode_2)                                                                                                            \
35     ({                                                                                                                                                         \
36         u32 __dst;                                                                                                                                             \
37         __ASM volatile("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", "                                                                           \
38                                                                                 "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \
39                        : "=r"(__dst)::"memory");                                                                                                               \
40         __dst;                                                                                                                                                 \
41     })
42 
__get_VBAR(void)43     __attribute__((always_inline)) __STATIC_INLINE u32 __get_VBAR(void)
44     {
45         return __MRC(15, 0, 12, 0, 0);
46     }
47 
__set_VBAR(u32 vbar)48     __attribute__((always_inline)) __STATIC_INLINE void __set_VBAR(u32 vbar)
49     {
50         __MCR(15, 0, vbar, 12, 0, 0);
51     }
52 
sys_icc_igrpen0_set(u32 value)53     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen0_set(u32 value)
54     {
55         __MCR(15, 0, value, 12, 12, 6);
56     }
57 
sys_icc_igrpen0_get(void)58     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen0_get(void)
59     {
60         return __MRC(15, 0, 12, 12, 6);
61     }
62 
sys_icc_igrpen1_set(u32 value)63     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen1_set(u32 value)
64     {
65         __MCR(15, 0, value, 12, 12, 7);
66     }
67 
sys_icc_igrpen1_get(void)68     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen1_get(void)
69     {
70         return __MRC(15, 0, 12, 12, 7);
71     }
72 
sys_icc_ctlr_set(u32 value)73     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_ctlr_set(u32 value)
74     {
75         __MCR(15, 0, value, 12, 12, 4);
76     }
77 
sys_icc_ctlr_get(void)78     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_ctlr_get(void)
79     {
80         return __MRC(15, 0, 12, 12, 4);
81     }
82 
sys_icc_hppir0_get(void)83     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir0_get(void)
84     {
85         return __MRC(15, 0, 12, 8, 2);
86     }
87 
sys_icc_bpr_set(u32 value)88     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_bpr_set(u32 value)
89     {
90         __MCR(15, 0, value, 12, 12, 3);
91     }
92 
sys_icc_bpr_get(void)93     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_bpr_get(void)
94     {
95         return __MRC(15, 0, 12, 12, 3);
96     }
97 
sys_icc_hppir1_get(void)98     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir1_get(void)
99     {
100         return __MRC(15, 0, 12, 12, 2);
101     }
102 
sys_icc_eoir0_set(u32 value)103     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir0_set(u32 value)
104     {
105         __MCR(15, 0, value, 12, 8, 1);
106     }
107 
sys_icc_eoir1_set(u32 value)108     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir1_set(u32 value)
109     {
110         __MCR(15, 0, value, 12, 12, 1);
111     }
112 
sys_icc_pmr_set(u32 value)113     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_pmr_set(u32 value)
114     {
115         __MCR(15, 0, value, 4, 6, 0);
116     }
117 
sys_icc_pmr_get(void)118     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_pmr_get(void)
119     {
120         return __MRC(15, 0, 4, 6, 0);
121     }
122 
sys_icc_iar1_get(void)123     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_iar1_get(void)
124     {
125         return __MRC(15, 0, 12, 12, 0);
126     }
127 
sys_icc_sre_set(u32 value)128     __attribute__((always_inline)) __STATIC_INLINE void sys_icc_sre_set(u32 value)
129     {
130         __MCR(15, 0, value, 12, 12, 5);
131     }
132 
sys_icc_sre_get(void)133     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_sre_get(void)
134     {
135         return __MRC(15, 0, 12, 12, 5);
136     }
137 
sys_icc_rpr_get(void)138     __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_rpr_get(void)
139     {
140         return __MRC(15, 0, 12, 11, 3);
141     }
142 
143     /*   Generic Timer registers  */
144     /**
145      * @name: arm_aarch32_cntfrq_get
146      * @msg:  This register is provided so that software can discover the frequency of the system counter.
147      * @return {__STATIC_INLINEu32}:  frequency of the system counter
148      */
arm_aarch32_cntfrq_get(void)149     __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntfrq_get(void)
150     {
151         return __MRC(15, 0, 14, 0, 0);
152     }
153 
154     /**
155      * @name: arm_aarch32_cnthv_tval_get
156      * @msg:  Provides AArch32 access to the timer value for the EL2 virtual timer.
157      * @return {__STATIC_INLINEu32}: EL2 virtual timer Cnt.
158      */
arm_aarch32_cnthv_tval_get(void)159     __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_tval_get(void)
160     {
161         return __MRC(15, 0, 14, 3, 0);
162     }
163 
164     /**
165      * @name: arm_aarch32_cnthv_ctl_set
166      * @msg:  Provides AArch32 access to the control register for the EL2 virtual timer.
167      * @in param {u32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled.
168      *                  IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit.   1 Timer interrupt is masked by the IMASK bit.
169      *                  ISTATUS, bit [2]:  0 Timer condition is not met. 1 Timer condition is met. rea-only
170      */
arm_aarch32_cnthv_ctl_set(u32 RegValue)171     __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_ctl_set(u32 RegValue)
172     {
173         __MCR(15, 0, RegValue, 14, 3, 1);
174     }
175 
176     /**
177      * @name: arm_aarch32_cnthv_ctl_get
178      * @msg:  Provides AArch32 access to the control register for the EL2 virtual timer.
179      * @return {__STATIC_INLINEu32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled.
180      *                  IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit.   1 Timer interrupt is masked by the IMASK bit.
181      *                  ISTATUS, bit [2]:  0 Timer condition is not met. 1 Timer condition is met. read-only
182      */
arm_aarch32_cnthv_ctl_get(void)183     __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_ctl_get(void)
184     {
185         return __MRC(15, 0, 14, 3, 1);
186     }
187 
188     /**
189      * @name: arm_aarch32_cnthv_tval_set
190      * @msg:  Provides AArch32 access to the timer value for the EL2 virtual timer.
191      * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL2 virtual timer.
192      */
arm_aarch32_cnthv_tval_set(u32 RegValue)193     __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_tval_set(u32 RegValue)
194     {
195         __MCR(15, 0, RegValue, 14, 3, 0);
196     }
197 
198     /**
199      * @name: arm_aarch32_cntvct_get
200      * @msg:  Read the register that holds the 64-bit virtual count value. The virtual count value is equal to the physical count value visible in CNTPCT minus the virtual offset visible in CNTVOFF.
201      * @return {__STATIC_INLINEu64}Bits [63:0] Virtual count value.
202      */
arm_aarch32_cntvct_get(void)203     __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntvct_get(void)
204     {
205         /* "r0" --- low,
206         "r1" --- hi
207       */
208         u32 low;
209         u32 hi;
210         __asm__ volatile(
211             ".word 0xec510f1e \n" /* mrrc p15, 1, r0, r1, c14 */
212             "mov %0, r0 \n"
213             "mov %1, r1 \n"
214             : "=&r"(low), "=&r"(hi));
215         return (((u64)hi) << 32) | low;
216     }
217 
218     /* physical */
219 
220     /**
221      * @name: arm_aarch32_cntp_tval_get
222      * @msg:  Read the register that holds the timer value for the EL1 physical timer.
223      * @return {__STATIC_INLINEu32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer.
224      */
arm_aarch32_cntp_tval_get(void)225     __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_tval_get(void)
226     {
227         return __MRC(15, 0, 14, 2, 0);
228     }
229 
230     /**
231      * @name: arm_aarch32_cntp_tval_set
232      * @msg:  write the register that control register for the EL1 physical timer.
233      * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer.
234      */
arm_aarch32_cntp_tval_set(u32 RegValue)235     __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_tval_set(u32 RegValue)
236     {
237         __MCR(15, 0, RegValue, 14, 2, 0);
238     }
239 
240     /**
241      * @name: arm_aarch32_cntp_ctl_set
242      * @msg:  write the register that control register for the EL1 physical timer.
243      * @in param {u32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer.
244      */
arm_aarch32_cntp_ctl_set(u32 RegValue)245     __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_ctl_set(u32 RegValue)
246     {
247         __MCR(15, 0, RegValue, 14, 2, 1);
248     }
249 
250     /**
251      * @name: arm_aarch32_cntp_ctl_get
252      * @msg:  Read the register that control register for the EL1 physical timer.
253      * @return {__STATIC_INLINEu32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer.
254      */
arm_aarch32_cntp_ctl_get(void)255     __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_ctl_get(void)
256     {
257         return __MRC(15, 0, 14, 2, 1);
258     }
259 
260     /**
261      * @name: arm_aarch32_cntpct_get
262      * @msg:  Read the register that holds the 64-bit physical count value.
263      * @return {__STATIC_INLINEu64} CompareValue, bits [63:0] Physical count value.
264      */
arm_aarch32_cntpct_get(void)265     __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntpct_get(void)
266     {
267         /* "r0" --- low,
268         "r1" --- hi
269       */
270         u32 low;
271         u32 hi;
272         __asm__ volatile(
273 
274             ".word 0xec510f0e \n" /* mrrc p15, 0, r0, r1, c14 */
275             "mov %0, r0 \n"
276             "mov %1, r1 \n"
277             : "=&r"(low), "=&r"(hi));
278         return (((u64)hi) << 32) | low;
279     }
280 
281 #define IRQ_DISABLE()               \
282     __asm volatile("CPSID i" ::     \
283                        : "memory"); \
284     __asm volatile("DSB");          \
285     __asm volatile("ISB");
286 
287 #define IRQ_ENABLE()                \
288     __asm volatile("CPSIE i" ::     \
289                        : "memory"); \
290     __asm volatile("DSB");          \
291     __asm volatile("ISB");
292 
293     /* the exception stack without VFP registers */
294     struct ft_hw_exp_stack
295     {
296         u32 r0;
297         u32 r1;
298         u32 r2;
299         u32 r3;
300         u32 r4;
301         u32 r5;
302         u32 r6;
303         u32 r7;
304         u32 r8;
305         u32 r9;
306         u32 r10;
307         u32 fp;
308         u32 ip;
309         u32 sp;
310         u32 lr;
311         u32 pc;
312         u32 cpsr;
313     };
314 
315 #ifdef __cplusplus
316 }
317 #endif
318 
319 #endif // !
320