• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2004-2011 Analog Devices Inc.
3  *
4  * Licensed under the GPL-2 or later.
5  */
6 
7 #ifndef __ARCH_BLACKFIN_CMPXCHG__
8 #define __ARCH_BLACKFIN_CMPXCHG__
9 
10 #ifdef CONFIG_SMP
11 
12 #include <linux/linkage.h>
13 
14 asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value);
15 asmlinkage unsigned long __raw_xchg_2_asm(volatile void *ptr, unsigned long value);
16 asmlinkage unsigned long __raw_xchg_4_asm(volatile void *ptr, unsigned long value);
17 asmlinkage unsigned long __raw_cmpxchg_1_asm(volatile void *ptr,
18 					unsigned long new, unsigned long old);
19 asmlinkage unsigned long __raw_cmpxchg_2_asm(volatile void *ptr,
20 					unsigned long new, unsigned long old);
21 asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr,
22 					unsigned long new, unsigned long old);
23 
__xchg(unsigned long x,volatile void * ptr,int size)24 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
25 				   int size)
26 {
27 	unsigned long tmp;
28 
29 	switch (size) {
30 	case 1:
31 		tmp = __raw_xchg_1_asm(ptr, x);
32 		break;
33 	case 2:
34 		tmp = __raw_xchg_2_asm(ptr, x);
35 		break;
36 	case 4:
37 		tmp = __raw_xchg_4_asm(ptr, x);
38 		break;
39 	}
40 
41 	return tmp;
42 }
43 
44 /*
45  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
46  * store NEW in MEM.  Return the initial value in MEM.  Success is
47  * indicated by comparing RETURN with OLD.
48  */
__cmpxchg(volatile void * ptr,unsigned long old,unsigned long new,int size)49 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
50 				      unsigned long new, int size)
51 {
52 	unsigned long tmp;
53 
54 	switch (size) {
55 	case 1:
56 		tmp = __raw_cmpxchg_1_asm(ptr, new, old);
57 		break;
58 	case 2:
59 		tmp = __raw_cmpxchg_2_asm(ptr, new, old);
60 		break;
61 	case 4:
62 		tmp = __raw_cmpxchg_4_asm(ptr, new, old);
63 		break;
64 	}
65 
66 	return tmp;
67 }
68 #define cmpxchg(ptr, o, n) \
69 	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
70 		(unsigned long)(n), sizeof(*(ptr))))
71 
72 #else /* !CONFIG_SMP */
73 
74 #include <mach/blackfin.h>
75 #include <asm/irqflags.h>
76 
77 struct __xchg_dummy {
78 	unsigned long a[100];
79 };
80 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
81 
__xchg(unsigned long x,volatile void * ptr,int size)82 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
83 				   int size)
84 {
85 	unsigned long tmp = 0;
86 	unsigned long flags;
87 
88 	flags = hard_local_irq_save();
89 
90 	switch (size) {
91 	case 1:
92 		__asm__ __volatile__
93 			("%0 = b%2 (z);\n\t"
94 			 "b%2 = %1;\n\t"
95 			 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
96 		break;
97 	case 2:
98 		__asm__ __volatile__
99 			("%0 = w%2 (z);\n\t"
100 			 "w%2 = %1;\n\t"
101 			 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
102 		break;
103 	case 4:
104 		__asm__ __volatile__
105 			("%0 = %2;\n\t"
106 			 "%2 = %1;\n\t"
107 			 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
108 		break;
109 	}
110 	hard_local_irq_restore(flags);
111 	return tmp;
112 }
113 
114 #include <asm-generic/cmpxchg-local.h>
115 
116 /*
117  * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
118  * them available.
119  */
120 #define cmpxchg_local(ptr, o, n)				  	       \
121 	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
122 			(unsigned long)(n), sizeof(*(ptr))))
123 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
124 
125 #define cmpxchg(ptr, o, n)	cmpxchg_local((ptr), (o), (n))
126 #define cmpxchg64(ptr, o, n)	cmpxchg64_local((ptr), (o), (n))
127 
128 #endif /* !CONFIG_SMP */
129 
130 #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
131 
132 #endif /* __ARCH_BLACKFIN_CMPXCHG__ */
133