xref: /openbmc/linux/arch/csky/include/asm/cmpxchg.h (revision f940dc0f)
1a0ae6280SGuo Ren /* SPDX-License-Identifier: GPL-2.0 */
2a0ae6280SGuo Ren 
3a0ae6280SGuo Ren #ifndef __ASM_CSKY_CMPXCHG_H
4a0ae6280SGuo Ren #define __ASM_CSKY_CMPXCHG_H
5a0ae6280SGuo Ren 
6c38425dfSGuo Ren #ifdef CONFIG_SMP
7*f940dc0fSGuo Ren #include <linux/bug.h>
8a0ae6280SGuo Ren #include <asm/barrier.h>
9a0ae6280SGuo Ren 
10c38425dfSGuo Ren #define __xchg_relaxed(new, ptr, size)				\
11a0ae6280SGuo Ren ({								\
12a0ae6280SGuo Ren 	__typeof__(ptr) __ptr = (ptr);				\
13a0ae6280SGuo Ren 	__typeof__(new) __new = (new);				\
14a0ae6280SGuo Ren 	__typeof__(*(ptr)) __ret;				\
15a0ae6280SGuo Ren 	unsigned long tmp;					\
16a0ae6280SGuo Ren 	switch (size) {						\
1745e15c1aSGuo Ren 	case 2: {						\
1845e15c1aSGuo Ren 		u32 ret;					\
1945e15c1aSGuo Ren 		u32 shif = ((ulong)__ptr & 2) ? 16 : 0;		\
2045e15c1aSGuo Ren 		u32 mask = 0xffff << shif;			\
2145e15c1aSGuo Ren 		__ptr = (__typeof__(ptr))((ulong)__ptr & ~2);	\
2245e15c1aSGuo Ren 		__asm__ __volatile__ (				\
2345e15c1aSGuo Ren 			"1:	ldex.w %0, (%4)\n"		\
2445e15c1aSGuo Ren 			"	and    %1, %0, %2\n"		\
2545e15c1aSGuo Ren 			"	or     %1, %1, %3\n"		\
2645e15c1aSGuo Ren 			"	stex.w %1, (%4)\n"		\
2745e15c1aSGuo Ren 			"	bez    %1, 1b\n"		\
2845e15c1aSGuo Ren 			: "=&r" (ret), "=&r" (tmp)		\
2945e15c1aSGuo Ren 			: "r" (~mask),				\
3045e15c1aSGuo Ren 			  "r" ((u32)__new << shif),		\
3145e15c1aSGuo Ren 			  "r" (__ptr)				\
3245e15c1aSGuo Ren 			: "memory");				\
3345e15c1aSGuo Ren 		__ret = (__typeof__(*(ptr)))			\
3445e15c1aSGuo Ren 			((ret & mask) >> shif);			\
3545e15c1aSGuo Ren 		break;						\
3645e15c1aSGuo Ren 	}							\
37a0ae6280SGuo Ren 	case 4:							\
38a0ae6280SGuo Ren 		asm volatile (					\
39a0ae6280SGuo Ren 		"1:	ldex.w		%0, (%3) \n"		\
40a0ae6280SGuo Ren 		"	mov		%1, %2   \n"		\
41a0ae6280SGuo Ren 		"	stex.w		%1, (%3) \n"		\
42a0ae6280SGuo Ren 		"	bez		%1, 1b   \n"		\
43a0ae6280SGuo Ren 			: "=&r" (__ret), "=&r" (tmp)		\
44a0ae6280SGuo Ren 			: "r" (__new), "r"(__ptr)		\
45a0ae6280SGuo Ren 			:);					\
46a0ae6280SGuo Ren 		break;						\
47a0ae6280SGuo Ren 	default:						\
48*f940dc0fSGuo Ren 		BUILD_BUG();					\
49a0ae6280SGuo Ren 	}							\
50a0ae6280SGuo Ren 	__ret;							\
51a0ae6280SGuo Ren })
52a0ae6280SGuo Ren 
53a5fb82d7SMark Rutland #define arch_xchg_relaxed(ptr, x) \
54c38425dfSGuo Ren 		(__xchg_relaxed((x), (ptr), sizeof(*(ptr))))
55a0ae6280SGuo Ren 
56c38425dfSGuo Ren #define __cmpxchg_relaxed(ptr, old, new, size)			\
57a0ae6280SGuo Ren ({								\
58a0ae6280SGuo Ren 	__typeof__(ptr) __ptr = (ptr);				\
59a0ae6280SGuo Ren 	__typeof__(new) __new = (new);				\
60a0ae6280SGuo Ren 	__typeof__(new) __tmp;					\
61a0ae6280SGuo Ren 	__typeof__(old) __old = (old);				\
62a0ae6280SGuo Ren 	__typeof__(*(ptr)) __ret;				\
63a0ae6280SGuo Ren 	switch (size) {						\
64a0ae6280SGuo Ren 	case 4:							\
65a0ae6280SGuo Ren 		asm volatile (					\
66a0ae6280SGuo Ren 		"1:	ldex.w		%0, (%3) \n"		\
67a0ae6280SGuo Ren 		"	cmpne		%0, %4   \n"		\
68a0ae6280SGuo Ren 		"	bt		2f       \n"		\
69a0ae6280SGuo Ren 		"	mov		%1, %2   \n"		\
70a0ae6280SGuo Ren 		"	stex.w		%1, (%3) \n"		\
71a0ae6280SGuo Ren 		"	bez		%1, 1b   \n"		\
72a0ae6280SGuo Ren 		"2:				 \n"		\
73a0ae6280SGuo Ren 			: "=&r" (__ret), "=&r" (__tmp)		\
74a0ae6280SGuo Ren 			: "r" (__new), "r"(__ptr), "r"(__old)	\
75a0ae6280SGuo Ren 			:);					\
76a0ae6280SGuo Ren 		break;						\
77a0ae6280SGuo Ren 	default:						\
78*f940dc0fSGuo Ren 		BUILD_BUG();					\
79a0ae6280SGuo Ren 	}							\
80a0ae6280SGuo Ren 	__ret;							\
81a0ae6280SGuo Ren })
82a0ae6280SGuo Ren 
83a5fb82d7SMark Rutland #define arch_cmpxchg_relaxed(ptr, o, n) \
84c38425dfSGuo Ren 	(__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
85c38425dfSGuo Ren 
86186f69b6SGuo Ren #define __cmpxchg_acquire(ptr, old, new, size)			\
87c38425dfSGuo Ren ({								\
88186f69b6SGuo Ren 	__typeof__(ptr) __ptr = (ptr);				\
89186f69b6SGuo Ren 	__typeof__(new) __new = (new);				\
90186f69b6SGuo Ren 	__typeof__(new) __tmp;					\
91186f69b6SGuo Ren 	__typeof__(old) __old = (old);				\
92c38425dfSGuo Ren 	__typeof__(*(ptr)) __ret;				\
93186f69b6SGuo Ren 	switch (size) {						\
94186f69b6SGuo Ren 	case 4:							\
95186f69b6SGuo Ren 		asm volatile (					\
96186f69b6SGuo Ren 		"1:	ldex.w		%0, (%3) \n"		\
97186f69b6SGuo Ren 		"	cmpne		%0, %4   \n"		\
98186f69b6SGuo Ren 		"	bt		2f       \n"		\
99186f69b6SGuo Ren 		"	mov		%1, %2   \n"		\
100186f69b6SGuo Ren 		"	stex.w		%1, (%3) \n"		\
101186f69b6SGuo Ren 		"	bez		%1, 1b   \n"		\
102186f69b6SGuo Ren 		ACQUIRE_FENCE					\
103186f69b6SGuo Ren 		"2:				 \n"		\
104186f69b6SGuo Ren 			: "=&r" (__ret), "=&r" (__tmp)		\
105186f69b6SGuo Ren 			: "r" (__new), "r"(__ptr), "r"(__old)	\
106186f69b6SGuo Ren 			:);					\
107186f69b6SGuo Ren 		break;						\
108186f69b6SGuo Ren 	default:						\
109*f940dc0fSGuo Ren 		BUILD_BUG();					\
110186f69b6SGuo Ren 	}							\
111c38425dfSGuo Ren 	__ret;							\
112c38425dfSGuo Ren })
113c38425dfSGuo Ren 
114186f69b6SGuo Ren #define arch_cmpxchg_acquire(ptr, o, n) \
115186f69b6SGuo Ren 	(__cmpxchg_acquire((ptr), (o), (n), sizeof(*(ptr))))
116186f69b6SGuo Ren 
117186f69b6SGuo Ren #define __cmpxchg(ptr, old, new, size)				\
118186f69b6SGuo Ren ({								\
119186f69b6SGuo Ren 	__typeof__(ptr) __ptr = (ptr);				\
120186f69b6SGuo Ren 	__typeof__(new) __new = (new);				\
121186f69b6SGuo Ren 	__typeof__(new) __tmp;					\
122186f69b6SGuo Ren 	__typeof__(old) __old = (old);				\
123186f69b6SGuo Ren 	__typeof__(*(ptr)) __ret;				\
124186f69b6SGuo Ren 	switch (size) {						\
125186f69b6SGuo Ren 	case 4:							\
126186f69b6SGuo Ren 		asm volatile (					\
127186f69b6SGuo Ren 		RELEASE_FENCE					\
128186f69b6SGuo Ren 		"1:	ldex.w		%0, (%3) \n"		\
129186f69b6SGuo Ren 		"	cmpne		%0, %4   \n"		\
130186f69b6SGuo Ren 		"	bt		2f       \n"		\
131186f69b6SGuo Ren 		"	mov		%1, %2   \n"		\
132186f69b6SGuo Ren 		"	stex.w		%1, (%3) \n"		\
133186f69b6SGuo Ren 		"	bez		%1, 1b   \n"		\
134186f69b6SGuo Ren 		FULL_FENCE					\
135186f69b6SGuo Ren 		"2:				 \n"		\
136186f69b6SGuo Ren 			: "=&r" (__ret), "=&r" (__tmp)		\
137186f69b6SGuo Ren 			: "r" (__new), "r"(__ptr), "r"(__old)	\
138186f69b6SGuo Ren 			:);					\
139186f69b6SGuo Ren 		break;						\
140186f69b6SGuo Ren 	default:						\
141*f940dc0fSGuo Ren 		BUILD_BUG();					\
142186f69b6SGuo Ren 	}							\
143186f69b6SGuo Ren 	__ret;							\
144186f69b6SGuo Ren })
145186f69b6SGuo Ren 
146186f69b6SGuo Ren #define arch_cmpxchg(ptr, o, n)					\
147186f69b6SGuo Ren 	(__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))
148186f69b6SGuo Ren 
149186f69b6SGuo Ren #define arch_cmpxchg_local(ptr, o, n)				\
150186f69b6SGuo Ren 	(__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
151a0ae6280SGuo Ren #else
152a0ae6280SGuo Ren #include <asm-generic/cmpxchg.h>
153a0ae6280SGuo Ren #endif
154a0ae6280SGuo Ren 
155a0ae6280SGuo Ren #endif /* __ASM_CSKY_CMPXCHG_H */
156