Merge master.kernel.org:/home/rmk/linux-2.6-arm
[wrt350n-kernel.git] / include / asm-arm26 / locks.h
blob81b3bda2ed005caa79d37a6c9cbb18fd65bede68
1 /*
2 * linux/include/asm-arm/proc-armo/locks.h
4 * Copyright (C) 2000 Russell King
5 * Fixes for 26 bit machines, (C) 2000 Dave Gilbert
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Interrupt safe locking assembler.
13 #ifndef __ASM_PROC_LOCKS_H
14 #define __ASM_PROC_LOCKS_H
16 /* Decrements by 1, fails if value < 0 */
17 #define __down_op(ptr,fail) \
18 ({ \
19 __asm__ __volatile__ ( \
20 "@ atomic down operation\n" \
21 " mov ip, pc\n" \
22 " orr lr, ip, #0x08000000\n" \
23 " teqp lr, #0\n" \
24 " ldr lr, [%0]\n" \
25 " and ip, ip, #0x0c000003\n" \
26 " subs lr, lr, #1\n" \
27 " str lr, [%0]\n" \
28 " orrmi ip, ip, #0x80000000 @ set N\n" \
29 " teqp ip, #0\n" \
30 " movmi ip, %0\n" \
31 " blmi " #fail \
32 : \
33 : "r" (ptr) \
34 : "ip", "lr", "cc"); \
37 #define __down_op_ret(ptr,fail) \
38 ({ \
39 unsigned int result; \
40 __asm__ __volatile__ ( \
41 " @ down_op_ret\n" \
42 " mov ip, pc\n" \
43 " orr lr, ip, #0x08000000\n" \
44 " teqp lr, #0\n" \
45 " ldr lr, [%1]\n" \
46 " and ip, ip, #0x0c000003\n" \
47 " subs lr, lr, #1\n" \
48 " str lr, [%1]\n" \
49 " orrmi ip, ip, #0x80000000 @ set N\n" \
50 " teqp ip, #0\n" \
51 " movmi ip, %1\n" \
52 " movpl ip, #0\n" \
53 " blmi " #fail "\n" \
54 " mov %0, ip" \
55 : "=&r" (result) \
56 : "r" (ptr) \
57 : "ip", "lr", "cc"); \
58 result; \
61 #define __up_op(ptr,wake) \
62 ({ \
63 __asm__ __volatile__ ( \
64 "@ up_op\n" \
65 " mov ip, pc\n" \
66 " orr lr, ip, #0x08000000\n" \
67 " teqp lr, #0\n" \
68 " ldr lr, [%0]\n" \
69 " and ip, ip, #0x0c000003\n" \
70 " adds lr, lr, #1\n" \
71 " str lr, [%0]\n" \
72 " orrle ip, ip, #0x80000000 @ set N - should this be mi ??? DAG ! \n" \
73 " teqp ip, #0\n" \
74 " movmi ip, %0\n" \
75 " blmi " #wake \
76 : \
77 : "r" (ptr) \
78 : "ip", "lr", "cc"); \
82 * The value 0x01000000 supports up to 128 processors and
83 * lots of processes. BIAS must be chosen such that sub'ing
84 * BIAS once per CPU will result in the long remaining
85 * negative.
87 #define RW_LOCK_BIAS 0x01000000
88 #define RW_LOCK_BIAS_STR "0x01000000"
90 /* Decrements by RW_LOCK_BIAS rather than 1, fails if value != 0 */
91 #define __down_op_write(ptr,fail) \
92 ({ \
93 __asm__ __volatile__( \
94 "@ down_op_write\n" \
95 " mov ip, pc\n" \
96 " orr lr, ip, #0x08000000\n" \
97 " teqp lr, #0\n" \
98 " and ip, ip, #0x0c000003\n" \
100 " ldr lr, [%0]\n" \
101 " subs lr, lr, %1\n" \
102 " str lr, [%0]\n" \
104 " orreq ip, ip, #0x40000000 @ set Z \n"\
105 " teqp ip, #0\n" \
106 " movne ip, %0\n" \
107 " blne " #fail \
109 : "r" (ptr), "I" (RW_LOCK_BIAS) \
110 : "ip", "lr", "cc"); \
113 /* Increments by RW_LOCK_BIAS, wakes if value >= 0 */
114 #define __up_op_write(ptr,wake) \
115 ({ \
116 __asm__ __volatile__( \
117 "@ up_op_read\n" \
118 " mov ip, pc\n" \
119 " orr lr, ip, #0x08000000\n" \
120 " teqp lr, #0\n" \
122 " ldr lr, [%0]\n" \
123 " and ip, ip, #0x0c000003\n" \
124 " adds lr, lr, %1\n" \
125 " str lr, [%0]\n" \
127 " orrcs ip, ip, #0x20000000 @ set C\n" \
128 " teqp ip, #0\n" \
129 " movcs ip, %0\n" \
130 " blcs " #wake \
132 : "r" (ptr), "I" (RW_LOCK_BIAS) \
133 : "ip", "lr", "cc"); \
136 #define __down_op_read(ptr,fail) \
137 __down_op(ptr, fail)
139 #define __up_op_read(ptr,wake) \
140 ({ \
141 __asm__ __volatile__( \
142 "@ up_op_read\n" \
143 " mov ip, pc\n" \
144 " orr lr, ip, #0x08000000\n" \
145 " teqp lr, #0\n" \
147 " ldr lr, [%0]\n" \
148 " and ip, ip, #0x0c000003\n" \
149 " adds lr, lr, %1\n" \
150 " str lr, [%0]\n" \
152 " orreq ip, ip, #0x40000000 @ Set Z \n" \
153 " teqp ip, #0\n" \
154 " moveq ip, %0\n" \
155 " bleq " #wake \
157 : "r" (ptr), "I" (1) \
158 : "ip", "lr", "cc"); \
161 #endif