1/*
2 *  linux/include/asm-arm/proc-armv/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#define __down_op(ptr,fail)			\
16	({					\
17	__asm__ __volatile__(			\
18	"@ down_op\n"				\
19"	mrs	ip, cpsr\n"			\
20"	orr	lr, ip, #128\n"			\
21"	msr	cpsr_c, lr\n"			\
22"	ldr	lr, [%0]\n"			\
23"	subs	lr, lr, %1\n"			\
24"	str	lr, [%0]\n"			\
25"	msr	cpsr_c, ip\n"			\
26"	movmi	ip, %0\n"			\
27"	blmi	" SYMBOL_NAME_STR(fail)		\
28	:					\
29	: "r" (ptr), "I" (1)			\
30	: "ip", "lr", "cc");			\
31	})
32
33#define __down_op_ret(ptr,fail)			\
34	({					\
35		unsigned int ret;		\
36	__asm__ __volatile__(			\
37	"@ down_op_ret\n"			\
38"	mrs	ip, cpsr\n"			\
39"	orr	lr, ip, #128\n"			\
40"	msr	cpsr_c, lr\n"			\
41"	ldr	lr, [%1]\n"			\
42"	subs	lr, lr, %2\n"			\
43"	str	lr, [%1]\n"			\
44"	msr	cpsr_c, ip\n"			\
45"	movmi	ip, %1\n"			\
46"	movpl	ip, #0\n"			\
47"	blmi	" SYMBOL_NAME_STR(fail) "\n"	\
48"	mov	%0, ip"				\
49	: "=&r" (ret)				\
50	: "r" (ptr), "I" (1)			\
51	: "ip", "lr", "cc");			\
52	ret;					\
53	})
54
55#define __up_op(ptr,wake)			\
56	({					\
57	__asm__ __volatile__(			\
58	"@ up_op\n"				\
59"	mrs	ip, cpsr\n"			\
60"	orr	lr, ip, #128\n"			\
61"	msr	cpsr_c, lr\n"			\
62"	ldr	lr, [%0]\n"			\
63"	adds	lr, lr, %1\n"			\
64"	str	lr, [%0]\n"			\
65"	msr	cpsr_c, ip\n"			\
66"	movle	ip, %0\n"			\
67"	blle	" SYMBOL_NAME_STR(wake)		\
68	:					\
69	: "r" (ptr), "I" (1)			\
70	: "ip", "lr", "cc");			\
71	})
72
73/*
74 * The value 0x01000000 supports up to 128 processors and
75 * lots of processes.  BIAS must be chosen such that sub'ing
76 * BIAS once per CPU will result in the long remaining
77 * negative.
78 */
79#define RW_LOCK_BIAS      0x01000000
80#define RW_LOCK_BIAS_STR "0x01000000"
81
82#define __down_op_write(ptr,fail)		\
83	({					\
84	__asm__ __volatile__(			\
85	"@ down_op_write\n"			\
86"	mrs	ip, cpsr\n"			\
87"	orr	lr, ip, #128\n"			\
88"	msr	cpsr_c, lr\n"			\
89"	ldr	lr, [%0]\n"			\
90"	subs	lr, lr, %1\n"			\
91"	str	lr, [%0]\n"			\
92"	msr	cpsr_c, ip\n"			\
93"	movne	ip, %0\n"			\
94"	blne	" SYMBOL_NAME_STR(fail)		\
95	:					\
96	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
97	: "ip", "lr", "cc");			\
98	})
99
100#define __up_op_write(ptr,wake)			\
101	({					\
102	__asm__ __volatile__(			\
103	"@ up_op_read\n"			\
104"	mrs	ip, cpsr\n"			\
105"	orr	lr, ip, #128\n"			\
106"	msr	cpsr_c, lr\n"			\
107"	ldr	lr, [%0]\n"			\
108"	adds	lr, lr, %1\n"			\
109"	str	lr, [%0]\n"			\
110"	msr	cpsr_c, ip\n"			\
111"	movcs	ip, %0\n"			\
112"	blcs	" SYMBOL_NAME_STR(wake)		\
113	:					\
114	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
115	: "ip", "lr", "cc");			\
116	})
117
118#define __down_op_read(ptr,fail)		\
119	__down_op(ptr, fail)
120
121#define __up_op_read(ptr,wake)			\
122	({					\
123	__asm__ __volatile__(			\
124	"@ up_op_read\n"			\
125"	mrs	ip, cpsr\n"			\
126"	orr	lr, ip, #128\n"			\
127"	msr	cpsr_c, lr\n"			\
128"	ldr	lr, [%0]\n"			\
129"	adds	lr, lr, %1\n"			\
130"	str	lr, [%0]\n"			\
131"	msr	cpsr_c, ip\n"			\
132"	moveq	ip, %0\n"			\
133"	bleq	" SYMBOL_NAME_STR(wake)		\
134	:					\
135	: "r" (ptr), "I" (1)			\
136	: "ip", "lr", "cc");			\
137	})
138
139#endif
140