xref: /openbmc/linux/arch/openrisc/include/asm/cmpxchg.h (revision 11595172537788f0007bfc16590aab18f2b9c40f)
1*11595172SStefan Kristiansson /*
2*11595172SStefan Kristiansson  * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
3*11595172SStefan Kristiansson  *
4*11595172SStefan Kristiansson  * This file is licensed under the terms of the GNU General Public License
5*11595172SStefan Kristiansson  * version 2.  This program is licensed "as is" without any warranty of any
6*11595172SStefan Kristiansson  * kind, whether express or implied.
7*11595172SStefan Kristiansson  */
8*11595172SStefan Kristiansson 
9*11595172SStefan Kristiansson #ifndef __ASM_OPENRISC_CMPXCHG_H
10*11595172SStefan Kristiansson #define __ASM_OPENRISC_CMPXCHG_H
11*11595172SStefan Kristiansson 
12*11595172SStefan Kristiansson #include  <linux/types.h>
13*11595172SStefan Kristiansson 
14*11595172SStefan Kristiansson /*
15*11595172SStefan Kristiansson  * This function doesn't exist, so you'll get a linker error
16*11595172SStefan Kristiansson  * if something tries to do an invalid cmpxchg().
17*11595172SStefan Kristiansson  */
18*11595172SStefan Kristiansson extern void __cmpxchg_called_with_bad_pointer(void);
19*11595172SStefan Kristiansson 
20*11595172SStefan Kristiansson #define __HAVE_ARCH_CMPXCHG 1
21*11595172SStefan Kristiansson 
22*11595172SStefan Kristiansson static inline unsigned long
23*11595172SStefan Kristiansson __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
24*11595172SStefan Kristiansson {
25*11595172SStefan Kristiansson 	if (size != 4) {
26*11595172SStefan Kristiansson 		__cmpxchg_called_with_bad_pointer();
27*11595172SStefan Kristiansson 		return old;
28*11595172SStefan Kristiansson 	}
29*11595172SStefan Kristiansson 
30*11595172SStefan Kristiansson 	__asm__ __volatile__(
31*11595172SStefan Kristiansson 		"1:	l.lwa %0, 0(%1)		\n"
32*11595172SStefan Kristiansson 		"	l.sfeq %0, %2		\n"
33*11595172SStefan Kristiansson 		"	l.bnf 2f		\n"
34*11595172SStefan Kristiansson 		"	 l.nop			\n"
35*11595172SStefan Kristiansson 		"	l.swa 0(%1), %3		\n"
36*11595172SStefan Kristiansson 		"	l.bnf 1b		\n"
37*11595172SStefan Kristiansson 		"	 l.nop			\n"
38*11595172SStefan Kristiansson 		"2:				\n"
39*11595172SStefan Kristiansson 		: "=&r"(old)
40*11595172SStefan Kristiansson 		: "r"(ptr), "r"(old), "r"(new)
41*11595172SStefan Kristiansson 		: "cc", "memory");
42*11595172SStefan Kristiansson 
43*11595172SStefan Kristiansson 	return old;
44*11595172SStefan Kristiansson }
45*11595172SStefan Kristiansson 
46*11595172SStefan Kristiansson #define cmpxchg(ptr, o, n)						\
47*11595172SStefan Kristiansson 	({								\
48*11595172SStefan Kristiansson 		(__typeof__(*(ptr))) __cmpxchg((ptr),			\
49*11595172SStefan Kristiansson 					       (unsigned long)(o),	\
50*11595172SStefan Kristiansson 					       (unsigned long)(n),	\
51*11595172SStefan Kristiansson 					       sizeof(*(ptr)));		\
52*11595172SStefan Kristiansson 	})
53*11595172SStefan Kristiansson 
54*11595172SStefan Kristiansson /*
55*11595172SStefan Kristiansson  * This function doesn't exist, so you'll get a linker error if
56*11595172SStefan Kristiansson  * something tries to do an invalidly-sized xchg().
57*11595172SStefan Kristiansson  */
58*11595172SStefan Kristiansson extern void __xchg_called_with_bad_pointer(void);
59*11595172SStefan Kristiansson 
60*11595172SStefan Kristiansson static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
61*11595172SStefan Kristiansson 				   int size)
62*11595172SStefan Kristiansson {
63*11595172SStefan Kristiansson 	if (size != 4) {
64*11595172SStefan Kristiansson 		__xchg_called_with_bad_pointer();
65*11595172SStefan Kristiansson 		return val;
66*11595172SStefan Kristiansson 	}
67*11595172SStefan Kristiansson 
68*11595172SStefan Kristiansson 	__asm__ __volatile__(
69*11595172SStefan Kristiansson 		"1:	l.lwa %0, 0(%1)		\n"
70*11595172SStefan Kristiansson 		"	l.swa 0(%1), %2		\n"
71*11595172SStefan Kristiansson 		"	l.bnf 1b		\n"
72*11595172SStefan Kristiansson 		"	 l.nop			\n"
73*11595172SStefan Kristiansson 		: "=&r"(val)
74*11595172SStefan Kristiansson 		: "r"(ptr), "r"(val)
75*11595172SStefan Kristiansson 		: "cc", "memory");
76*11595172SStefan Kristiansson 
77*11595172SStefan Kristiansson 	return val;
78*11595172SStefan Kristiansson }
79*11595172SStefan Kristiansson 
80*11595172SStefan Kristiansson #define xchg(ptr, with) \
81*11595172SStefan Kristiansson 	((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), sizeof(*(ptr))))
82*11595172SStefan Kristiansson 
83*11595172SStefan Kristiansson #endif /* __ASM_OPENRISC_CMPXCHG_H */
84