1 /*
2  * Atomics xchg/cmpxchg for PKUnity SoC and UniCore ISA
3  *
4  * Copyright (C) 2001-2012 GUAN Xue-tao
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 #ifndef __UNICORE_CMPXCHG_H__
11 #define __UNICORE_CMPXCHG_H__
12 
13 /*
14  * Generate a link failure on undefined symbol if the pointer points to a value
15  * of unsupported size.
16  */
17 extern void __xchg_bad_pointer(void);
18 
__xchg(unsigned long x,volatile void * ptr,int size)19 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
20 		int size)
21 {
22 	unsigned long ret;
23 
24 	switch (size) {
25 	case 1:
26 		asm volatile("swapb	%0, %1, [%2]"
27 			: "=&r" (ret)
28 			: "r" (x), "r" (ptr)
29 			: "memory", "cc");
30 		break;
31 	case 4:
32 		asm volatile("swapw	%0, %1, [%2]"
33 			: "=&r" (ret)
34 			: "r" (x), "r" (ptr)
35 			: "memory", "cc");
36 		break;
37 	default:
38 		ret = __xchg_bad_pointer();
39 	}
40 
41 	return ret;
42 }
43 
44 #define xchg(ptr, x) \
45 	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
46 
47 #include <asm-generic/cmpxchg-local.h>
48 
49 /*
50  * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
51  * them available.
52  */
53 #define cmpxchg_local(ptr, o, n)					\
54 		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
55 		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
56 #define cmpxchg64_local(ptr, o, n)					\
57 		__cmpxchg64_local_generic((ptr), (o), (n))
58 
59 #include <asm-generic/cmpxchg.h>
60 
61 #endif /* __UNICORE_CMPXCHG_H__ */
62