xref: /openbmc/linux/arch/openrisc/include/asm/cmpxchg.h (revision 8af42949d1681379c1a97d230de9242c1f4f326a)
111595172SStefan Kristiansson /*
211595172SStefan Kristiansson  * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
311595172SStefan Kristiansson  *
411595172SStefan Kristiansson  * This file is licensed under the terms of the GNU General Public License
511595172SStefan Kristiansson  * version 2.  This program is licensed "as is" without any warranty of any
611595172SStefan Kristiansson  * kind, whether express or implied.
711595172SStefan Kristiansson  */
811595172SStefan Kristiansson 
911595172SStefan Kristiansson #ifndef __ASM_OPENRISC_CMPXCHG_H
1011595172SStefan Kristiansson #define __ASM_OPENRISC_CMPXCHG_H
1111595172SStefan Kristiansson 
1211595172SStefan Kristiansson #include  <linux/types.h>
1311595172SStefan Kristiansson 
1411595172SStefan Kristiansson /*
1511595172SStefan Kristiansson  * This function doesn't exist, so you'll get a linker error
1611595172SStefan Kristiansson  * if something tries to do an invalid cmpxchg().
1711595172SStefan Kristiansson  */
1811595172SStefan Kristiansson extern void __cmpxchg_called_with_bad_pointer(void);
1911595172SStefan Kristiansson 
2011595172SStefan Kristiansson #define __HAVE_ARCH_CMPXCHG 1
2111595172SStefan Kristiansson 
2211595172SStefan Kristiansson static inline unsigned long
2311595172SStefan Kristiansson __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
2411595172SStefan Kristiansson {
2511595172SStefan Kristiansson 	if (size != 4) {
2611595172SStefan Kristiansson 		__cmpxchg_called_with_bad_pointer();
2711595172SStefan Kristiansson 		return old;
2811595172SStefan Kristiansson 	}
2911595172SStefan Kristiansson 
3011595172SStefan Kristiansson 	__asm__ __volatile__(
3111595172SStefan Kristiansson 		"1:	l.lwa %0, 0(%1)		\n"
3211595172SStefan Kristiansson 		"	l.sfeq %0, %2		\n"
3311595172SStefan Kristiansson 		"	l.bnf 2f		\n"
3411595172SStefan Kristiansson 		"	 l.nop			\n"
3511595172SStefan Kristiansson 		"	l.swa 0(%1), %3		\n"
3611595172SStefan Kristiansson 		"	l.bnf 1b		\n"
3711595172SStefan Kristiansson 		"	 l.nop			\n"
3811595172SStefan Kristiansson 		"2:				\n"
3911595172SStefan Kristiansson 		: "=&r"(old)
4011595172SStefan Kristiansson 		: "r"(ptr), "r"(old), "r"(new)
4111595172SStefan Kristiansson 		: "cc", "memory");
4211595172SStefan Kristiansson 
4311595172SStefan Kristiansson 	return old;
4411595172SStefan Kristiansson }
4511595172SStefan Kristiansson 
4611595172SStefan Kristiansson #define cmpxchg(ptr, o, n)						\
4711595172SStefan Kristiansson 	({								\
4811595172SStefan Kristiansson 		(__typeof__(*(ptr))) __cmpxchg((ptr),			\
4911595172SStefan Kristiansson 					       (unsigned long)(o),	\
5011595172SStefan Kristiansson 					       (unsigned long)(n),	\
5111595172SStefan Kristiansson 					       sizeof(*(ptr)));		\
5211595172SStefan Kristiansson 	})
5311595172SStefan Kristiansson 
5411595172SStefan Kristiansson /*
5511595172SStefan Kristiansson  * This function doesn't exist, so you'll get a linker error if
5611595172SStefan Kristiansson  * something tries to do an invalidly-sized xchg().
5711595172SStefan Kristiansson  */
5811595172SStefan Kristiansson extern void __xchg_called_with_bad_pointer(void);
5911595172SStefan Kristiansson 
6011595172SStefan Kristiansson static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
6111595172SStefan Kristiansson 				   int size)
6211595172SStefan Kristiansson {
6311595172SStefan Kristiansson 	if (size != 4) {
6411595172SStefan Kristiansson 		__xchg_called_with_bad_pointer();
6511595172SStefan Kristiansson 		return val;
6611595172SStefan Kristiansson 	}
6711595172SStefan Kristiansson 
6811595172SStefan Kristiansson 	__asm__ __volatile__(
6911595172SStefan Kristiansson 		"1:	l.lwa %0, 0(%1)		\n"
7011595172SStefan Kristiansson 		"	l.swa 0(%1), %2		\n"
7111595172SStefan Kristiansson 		"	l.bnf 1b		\n"
7211595172SStefan Kristiansson 		"	 l.nop			\n"
7311595172SStefan Kristiansson 		: "=&r"(val)
7411595172SStefan Kristiansson 		: "r"(ptr), "r"(val)
7511595172SStefan Kristiansson 		: "cc", "memory");
7611595172SStefan Kristiansson 
7711595172SStefan Kristiansson 	return val;
7811595172SStefan Kristiansson }
7911595172SStefan Kristiansson 
8011595172SStefan Kristiansson #define xchg(ptr, with) 						\
81*8af42949SStafford Horne 	({								\
82*8af42949SStafford Horne 		(__typeof__(*(ptr))) __xchg((unsigned long)(with),	\
83*8af42949SStafford Horne 					    (ptr),			\
84*8af42949SStafford Horne 					    sizeof(*(ptr)));		\
85*8af42949SStafford Horne 	})
8611595172SStefan Kristiansson 
8711595172SStefan Kristiansson #endif /* __ASM_OPENRISC_CMPXCHG_H */
88