Home | History | Annotate | Download | only in asm-arm
      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)			\
     31 	: "ip", "lr", "cc");			\
     32 	smp_mb();				\
     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)			\
     52 	: "ip", "lr", "cc");			\
     53 	smp_mb();				\
     54 	ret;					\
     55 	})
     56 
     57 #define __up_op(ptr,wake)			\
     58 	({					\
     59 	smp_mb();				\
     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"				\
     67 "	cmp	lr, #0\n"			\
     68 "	movle	ip, %0\n"			\
     69 "	blle	" #wake				\
     70 	:					\
     71 	: "r" (ptr), "I" (1)			\
     72 	: "ip", "lr", "cc");			\
     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)		\
     98 	: "ip", "lr", "cc");			\
     99 	smp_mb();				\
    100 	})
    101 
    102 #define __up_op_write(ptr,wake)			\
    103 	({					\
    104 	smp_mb();				\
    105 	__asm__ __volatile__(			\
    106 	"@ up_op_write\n"			\
    107 "1:	ldrex	lr, [%0]\n"			\
    108 "	adds	lr, lr, %1\n"			\
    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)		\
    116 	: "ip", "lr", "cc");			\
    117 	})
    118 
    119 #define __down_op_read(ptr,fail)		\
    120 	__down_op(ptr, fail)
    121 
    122 #define __up_op_read(ptr,wake)			\
    123 	({					\
    124 	smp_mb();				\
    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)			\
    137 	: "ip", "lr", "cc");			\
    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)			\
    157 	: "ip", "lr", "cc");			\
    158 	smp_mb();				\
    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)			\
    179 	: "ip", "lr", "cc");			\
    180 	smp_mb();				\
    181 	ret;					\
    182 	})
    183 
    184 #define __up_op(ptr,wake)			\
    185 	({					\
    186 	smp_mb();				\
    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)			\
    200 	: "ip", "lr", "cc");			\
    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)		\
    227 	: "ip", "lr", "cc");			\
    228 	smp_mb();				\
    229 	})
    230 
    231 #define __up_op_write(ptr,wake)			\
    232 	({					\
    233 	__asm__ __volatile__(			\
    234 	"@ up_op_write\n"			\
    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)		\
    246 	: "ip", "lr", "cc");			\
    247 	smp_mb();				\
    248 	})
    249 
    250 #define __down_op_read(ptr,fail)		\
    251 	__down_op(ptr, fail)
    252 
    253 #define __up_op_read(ptr,wake)			\
    254 	({					\
    255 	smp_mb();				\
    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)			\
    269 	: "ip", "lr", "cc");			\
    270 	})
    271 
    272 #endif
    273 
    274 #endif
    275