[Docs] Added Information about Secure Monitor
[3rdparty/ote_partner/tlk.git] / arch / arm / include / arch / arm / ops.h
1 /*
2  * Copyright (c) 2008-2012 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #ifndef __ARCH_ARM_OPS_H
24 #define __ARCH_ARM_OPS_H
25
26 #ifndef ASSEMBLY
27
28 #include <compiler.h>
29 #include <reg.h>
30
31 #if ARM_ISA_ARMV7 || (ARM_ISA_ARMV6 && !__thumb__)
32 // override of some routines
33 __GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
34 {
35         __asm__("cpsie i");
36         CF;
37 }
38
39 __GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
40 {
41         __asm__("cpsid i");
42         CF;
43 }
44
45 __GNU_INLINE __ALWAYS_INLINE extern inline int atomic_add(volatile int *ptr, int val)
46 {
47         int old;
48         int temp;
49         int test;
50
51         do {
52                 __asm__ volatile(
53                     "ldrex      %[old], [%[ptr]]\n"
54                     "add        %[temp], %[old], %[val]\n"
55                     "strex      %[test], %[temp], [%[ptr]]\n"
56                     : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test)
57                     : [ptr]"r" (ptr), [val]"r" (val)
58                     : "memory");
59
60         } while (test != 0);
61
62         return old;
63 }
64
65 __GNU_INLINE __ALWAYS_INLINE extern inline int atomic_or(volatile int *ptr, int val)
66 {
67         int old;
68         int temp;
69         int test;
70
71         do {
72                 __asm__ volatile(
73                     "ldrex      %[old], [%[ptr]]\n"
74                     "orr        %[temp], %[old], %[val]\n"
75                     "strex      %[test], %[temp], [%[ptr]]\n"
76                     : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test)
77                     : [ptr]"r" (ptr), [val]"r" (val)
78                     : "memory");
79
80         } while (test != 0);
81
82         return old;
83 }
84
85 __GNU_INLINE __ALWAYS_INLINE extern inline int atomic_and(volatile int *ptr, int val)
86 {
87         int old;
88         int temp;
89         int test;
90
91         do {
92                 __asm__ volatile(
93                     "ldrex      %[old], [%[ptr]]\n"
94                     "and        %[temp], %[old], %[val]\n"
95                     "strex      %[test], %[temp], [%[ptr]]\n"
96                     : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test)
97                     : [ptr]"r" (ptr), [val]"r" (val)
98                     : "memory");
99
100         } while (test != 0);
101
102         return old;
103 }
104
105 __GNU_INLINE __ALWAYS_INLINE extern inline int atomic_swap(volatile int *ptr, int val)
106 {
107         int old;
108         int test;
109
110         do {
111                 __asm__ volatile(
112                     "ldrex      %[old], [%[ptr]]\n"
113                     "strex      %[test], %[val], [%[ptr]]\n"
114                     : [old]"=&r" (old), [test]"=&r" (test)
115                     : [ptr]"r" (ptr), [val]"r" (val)
116                     : "memory");
117
118         } while (test != 0);
119
120         return old;
121 }
122
123 __GNU_INLINE __ALWAYS_INLINE extern inline int atomic_cmpxhg(volatile int *ptr, int oldval, int newval)
124 {
125         int old;
126         int test;
127
128         do {
129                 __asm__ volatile(
130                     "ldrex      %[old], [%[ptr]]\n"
131                     "mov        %[test], #0\n"
132                     "teq        %[old], %[oldval]\n"
133 #if ARM_ISA_ARMV7M
134                     "bne        0f\n"
135                     "strex      %[test], %[newval], [%[ptr]]\n"
136                     "0:\n"
137 #else
138                     "strexeq %[test], %[newval], [%[ptr]]\n"
139 #endif
140                     : [old]"=&r" (old), [test]"=&r" (test)
141                     : [ptr]"r" (ptr), [oldval]"Ir" (oldval), [newval]"r" (newval)
142                     : "cc");
143
144         } while (test != 0);
145
146         return old;
147 }
148
149 __GNU_INLINE __ALWAYS_INLINE extern inline uint32_t arch_cycle_count(void)
150 {
151 #if ARM_CPU_CORTEX_M3
152 #define DWT_CYCCNT (0xE0001004)
153     return *REG32(DWT_CYCCNT);
154 #else
155         return 0;
156 #endif
157 }
158
159
160 #endif
161
162 #endif
163
164 #endif
165