Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/include/asm-arm/locks.h | |
3 | * | |
4 | * Copyright (C) 2000 Russell King | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * Interrupt safe locking assembler. | |
11 | */ | |
12 | #ifndef __ASM_PROC_LOCKS_H | |
13 | #define __ASM_PROC_LOCKS_H | |
14 | ||
15 | #if __LINUX_ARM_ARCH__ >= 6 | |
16 | ||
17 | #define __down_op(ptr,fail) \ | |
18 | ({ \ | |
19 | __asm__ __volatile__( \ | |
20 | "@ down_op\n" \ | |
21 | "1: ldrex lr, [%0]\n" \ | |
22 | " sub lr, lr, %1\n" \ | |
23 | " strex ip, lr, [%0]\n" \ | |
24 | " teq ip, #0\n" \ | |
25 | " bne 1b\n" \ | |
26 | " teq lr, #0\n" \ | |
27 | " movmi ip, %0\n" \ | |
28 | " blmi " #fail \ | |
29 | : \ | |
30 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 RK |
31 | : "ip", "lr", "cc"); \ |
32 | smp_mb(); \ | |
1da177e4 LT |
33 | }) |
34 | ||
35 | #define __down_op_ret(ptr,fail) \ | |
36 | ({ \ | |
37 | unsigned int ret; \ | |
38 | __asm__ __volatile__( \ | |
39 | "@ down_op_ret\n" \ | |
40 | "1: ldrex lr, [%1]\n" \ | |
41 | " sub lr, lr, %2\n" \ | |
42 | " strex ip, lr, [%1]\n" \ | |
43 | " teq ip, #0\n" \ | |
44 | " bne 1b\n" \ | |
45 | " teq lr, #0\n" \ | |
46 | " movmi ip, %1\n" \ | |
47 | " movpl ip, #0\n" \ | |
48 | " blmi " #fail "\n" \ | |
49 | " mov %0, ip" \ | |
50 | : "=&r" (ret) \ | |
51 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 RK |
52 | : "ip", "lr", "cc"); \ |
53 | smp_mb(); \ | |
1da177e4 LT |
54 | ret; \ |
55 | }) | |
56 | ||
57 | #define __up_op(ptr,wake) \ | |
58 | ({ \ | |
6d9b37a3 | 59 | smp_mb(); \ |
1da177e4 LT |
60 | __asm__ __volatile__( \ |
61 | "@ up_op\n" \ | |
62 | "1: ldrex lr, [%0]\n" \ | |
63 | " add lr, lr, %1\n" \ | |
64 | " strex ip, lr, [%0]\n" \ | |
65 | " teq ip, #0\n" \ | |
66 | " bne 1b\n" \ | |
4e8fd22b | 67 | " cmp lr, #0\n" \ |
1da177e4 LT |
68 | " movle ip, %0\n" \ |
69 | " blle " #wake \ | |
70 | : \ | |
71 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 | 72 | : "ip", "lr", "cc"); \ |
1da177e4 LT |
73 | }) |
74 | ||
75 | /* | |
76 | * The value 0x01000000 supports up to 128 processors and | |
77 | * lots of processes. BIAS must be chosen such that sub'ing | |
78 | * BIAS once per CPU will result in the long remaining | |
79 | * negative. | |
80 | */ | |
81 | #define RW_LOCK_BIAS 0x01000000 | |
82 | #define RW_LOCK_BIAS_STR "0x01000000" | |
83 | ||
84 | #define __down_op_write(ptr,fail) \ | |
85 | ({ \ | |
86 | __asm__ __volatile__( \ | |
87 | "@ down_op_write\n" \ | |
88 | "1: ldrex lr, [%0]\n" \ | |
89 | " sub lr, lr, %1\n" \ | |
90 | " strex ip, lr, [%0]\n" \ | |
91 | " teq ip, #0\n" \ | |
92 | " bne 1b\n" \ | |
93 | " teq lr, #0\n" \ | |
94 | " movne ip, %0\n" \ | |
95 | " blne " #fail \ | |
96 | : \ | |
97 | : "r" (ptr), "I" (RW_LOCK_BIAS) \ | |
6d9b37a3 RK |
98 | : "ip", "lr", "cc"); \ |
99 | smp_mb(); \ | |
1da177e4 LT |
100 | }) |
101 | ||
102 | #define __up_op_write(ptr,wake) \ | |
103 | ({ \ | |
6d9b37a3 | 104 | smp_mb(); \ |
1da177e4 | 105 | __asm__ __volatile__( \ |
9b15c6c4 | 106 | "@ up_op_write\n" \ |
1da177e4 | 107 | "1: ldrex lr, [%0]\n" \ |
4e8fd22b | 108 | " adds lr, lr, %1\n" \ |
1da177e4 LT |
109 | " strex ip, lr, [%0]\n" \ |
110 | " teq ip, #0\n" \ | |
111 | " bne 1b\n" \ | |
112 | " movcs ip, %0\n" \ | |
113 | " blcs " #wake \ | |
114 | : \ | |
115 | : "r" (ptr), "I" (RW_LOCK_BIAS) \ | |
6d9b37a3 | 116 | : "ip", "lr", "cc"); \ |
1da177e4 LT |
117 | }) |
118 | ||
119 | #define __down_op_read(ptr,fail) \ | |
120 | __down_op(ptr, fail) | |
121 | ||
122 | #define __up_op_read(ptr,wake) \ | |
123 | ({ \ | |
6d9b37a3 | 124 | smp_mb(); \ |
1da177e4 LT |
125 | __asm__ __volatile__( \ |
126 | "@ up_op_read\n" \ | |
127 | "1: ldrex lr, [%0]\n" \ | |
128 | " add lr, lr, %1\n" \ | |
129 | " strex ip, lr, [%0]\n" \ | |
130 | " teq ip, #0\n" \ | |
131 | " bne 1b\n" \ | |
132 | " teq lr, #0\n" \ | |
133 | " moveq ip, %0\n" \ | |
134 | " bleq " #wake \ | |
135 | : \ | |
136 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 | 137 | : "ip", "lr", "cc"); \ |
1da177e4 LT |
138 | }) |
139 | ||
140 | #else | |
141 | ||
142 | #define __down_op(ptr,fail) \ | |
143 | ({ \ | |
144 | __asm__ __volatile__( \ | |
145 | "@ down_op\n" \ | |
146 | " mrs ip, cpsr\n" \ | |
147 | " orr lr, ip, #128\n" \ | |
148 | " msr cpsr_c, lr\n" \ | |
149 | " ldr lr, [%0]\n" \ | |
150 | " subs lr, lr, %1\n" \ | |
151 | " str lr, [%0]\n" \ | |
152 | " msr cpsr_c, ip\n" \ | |
153 | " movmi ip, %0\n" \ | |
154 | " blmi " #fail \ | |
155 | : \ | |
156 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 RK |
157 | : "ip", "lr", "cc"); \ |
158 | smp_mb(); \ | |
1da177e4 LT |
159 | }) |
160 | ||
161 | #define __down_op_ret(ptr,fail) \ | |
162 | ({ \ | |
163 | unsigned int ret; \ | |
164 | __asm__ __volatile__( \ | |
165 | "@ down_op_ret\n" \ | |
166 | " mrs ip, cpsr\n" \ | |
167 | " orr lr, ip, #128\n" \ | |
168 | " msr cpsr_c, lr\n" \ | |
169 | " ldr lr, [%1]\n" \ | |
170 | " subs lr, lr, %2\n" \ | |
171 | " str lr, [%1]\n" \ | |
172 | " msr cpsr_c, ip\n" \ | |
173 | " movmi ip, %1\n" \ | |
174 | " movpl ip, #0\n" \ | |
175 | " blmi " #fail "\n" \ | |
176 | " mov %0, ip" \ | |
177 | : "=&r" (ret) \ | |
178 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 RK |
179 | : "ip", "lr", "cc"); \ |
180 | smp_mb(); \ | |
1da177e4 LT |
181 | ret; \ |
182 | }) | |
183 | ||
184 | #define __up_op(ptr,wake) \ | |
185 | ({ \ | |
6d9b37a3 | 186 | smp_mb(); \ |
1da177e4 LT |
187 | __asm__ __volatile__( \ |
188 | "@ up_op\n" \ | |
189 | " mrs ip, cpsr\n" \ | |
190 | " orr lr, ip, #128\n" \ | |
191 | " msr cpsr_c, lr\n" \ | |
192 | " ldr lr, [%0]\n" \ | |
193 | " adds lr, lr, %1\n" \ | |
194 | " str lr, [%0]\n" \ | |
195 | " msr cpsr_c, ip\n" \ | |
196 | " movle ip, %0\n" \ | |
197 | " blle " #wake \ | |
198 | : \ | |
199 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 | 200 | : "ip", "lr", "cc"); \ |
1da177e4 LT |
201 | }) |
202 | ||
203 | /* | |
204 | * The value 0x01000000 supports up to 128 processors and | |
205 | * lots of processes. BIAS must be chosen such that sub'ing | |
206 | * BIAS once per CPU will result in the long remaining | |
207 | * negative. | |
208 | */ | |
209 | #define RW_LOCK_BIAS 0x01000000 | |
210 | #define RW_LOCK_BIAS_STR "0x01000000" | |
211 | ||
212 | #define __down_op_write(ptr,fail) \ | |
213 | ({ \ | |
214 | __asm__ __volatile__( \ | |
215 | "@ down_op_write\n" \ | |
216 | " mrs ip, cpsr\n" \ | |
217 | " orr lr, ip, #128\n" \ | |
218 | " msr cpsr_c, lr\n" \ | |
219 | " ldr lr, [%0]\n" \ | |
220 | " subs lr, lr, %1\n" \ | |
221 | " str lr, [%0]\n" \ | |
222 | " msr cpsr_c, ip\n" \ | |
223 | " movne ip, %0\n" \ | |
224 | " blne " #fail \ | |
225 | : \ | |
226 | : "r" (ptr), "I" (RW_LOCK_BIAS) \ | |
6d9b37a3 RK |
227 | : "ip", "lr", "cc"); \ |
228 | smp_mb(); \ | |
1da177e4 LT |
229 | }) |
230 | ||
231 | #define __up_op_write(ptr,wake) \ | |
232 | ({ \ | |
233 | __asm__ __volatile__( \ | |
9b15c6c4 | 234 | "@ up_op_write\n" \ |
1da177e4 LT |
235 | " mrs ip, cpsr\n" \ |
236 | " orr lr, ip, #128\n" \ | |
237 | " msr cpsr_c, lr\n" \ | |
238 | " ldr lr, [%0]\n" \ | |
239 | " adds lr, lr, %1\n" \ | |
240 | " str lr, [%0]\n" \ | |
241 | " msr cpsr_c, ip\n" \ | |
242 | " movcs ip, %0\n" \ | |
243 | " blcs " #wake \ | |
244 | : \ | |
245 | : "r" (ptr), "I" (RW_LOCK_BIAS) \ | |
6d9b37a3 RK |
246 | : "ip", "lr", "cc"); \ |
247 | smp_mb(); \ | |
1da177e4 LT |
248 | }) |
249 | ||
250 | #define __down_op_read(ptr,fail) \ | |
251 | __down_op(ptr, fail) | |
252 | ||
253 | #define __up_op_read(ptr,wake) \ | |
254 | ({ \ | |
6d9b37a3 | 255 | smp_mb(); \ |
1da177e4 LT |
256 | __asm__ __volatile__( \ |
257 | "@ up_op_read\n" \ | |
258 | " mrs ip, cpsr\n" \ | |
259 | " orr lr, ip, #128\n" \ | |
260 | " msr cpsr_c, lr\n" \ | |
261 | " ldr lr, [%0]\n" \ | |
262 | " adds lr, lr, %1\n" \ | |
263 | " str lr, [%0]\n" \ | |
264 | " msr cpsr_c, ip\n" \ | |
265 | " moveq ip, %0\n" \ | |
266 | " bleq " #wake \ | |
267 | : \ | |
268 | : "r" (ptr), "I" (1) \ | |
6d9b37a3 | 269 | : "ip", "lr", "cc"); \ |
1da177e4 LT |
270 | }) |
271 | ||
272 | #endif | |
273 | ||
274 | #endif |