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