1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef __ASM_CSKY_CMPXCHG_H 4 #define __ASM_CSKY_CMPXCHG_H 5 6 #ifdef CONFIG_SMP 7 #include <linux/bug.h> 8 #include <asm/barrier.h> 9 10 #define __xchg_relaxed(new, ptr, size) \ 11 ({ \ 12 __typeof__(ptr) __ptr = (ptr); \ 13 __typeof__(new) __new = (new); \ 14 __typeof__(*(ptr)) __ret; \ 15 unsigned long tmp; \ 16 switch (size) { \ 17 case 2: { \ 18 u32 ret; \ 19 u32 shif = ((ulong)__ptr & 2) ? 16 : 0; \ 20 u32 mask = 0xffff << shif; \ 21 __ptr = (__typeof__(ptr))((ulong)__ptr & ~2); \ 22 __asm__ __volatile__ ( \ 23 "1: ldex.w %0, (%4)\n" \ 24 " and %1, %0, %2\n" \ 25 " or %1, %1, %3\n" \ 26 " stex.w %1, (%4)\n" \ 27 " bez %1, 1b\n" \ 28 : "=&r" (ret), "=&r" (tmp) \ 29 : "r" (~mask), \ 30 "r" ((u32)__new << shif), \ 31 "r" (__ptr) \ 32 : "memory"); \ 33 __ret = (__typeof__(*(ptr))) \ 34 ((ret & mask) >> shif); \ 35 break; \ 36 } \ 37 case 4: \ 38 asm volatile ( \ 39 "1: ldex.w %0, (%3) \n" \ 40 " mov %1, %2 \n" \ 41 " stex.w %1, (%3) \n" \ 42 " bez %1, 1b \n" \ 43 : "=&r" (__ret), "=&r" (tmp) \ 44 : "r" (__new), "r"(__ptr) \ 45 :); \ 46 break; \ 47 default: \ 48 BUILD_BUG(); \ 49 } \ 50 __ret; \ 51 }) 52 53 #define arch_xchg_relaxed(ptr, x) \ 54 (__xchg_relaxed((x), (ptr), sizeof(*(ptr)))) 55 56 #define __cmpxchg_relaxed(ptr, old, new, size) \ 57 ({ \ 58 __typeof__(ptr) __ptr = (ptr); \ 59 __typeof__(new) __new = (new); \ 60 __typeof__(new) __tmp; \ 61 __typeof__(old) __old = (old); \ 62 __typeof__(*(ptr)) __ret; \ 63 switch (size) { \ 64 case 4: \ 65 asm volatile ( \ 66 "1: ldex.w %0, (%3) \n" \ 67 " cmpne %0, %4 \n" \ 68 " bt 2f \n" \ 69 " mov %1, %2 \n" \ 70 " stex.w %1, (%3) \n" \ 71 " bez %1, 1b \n" \ 72 "2: \n" \ 73 : "=&r" (__ret), "=&r" (__tmp) \ 74 : "r" (__new), "r"(__ptr), "r"(__old) \ 75 :); \ 76 break; \ 77 default: \ 78 BUILD_BUG(); \ 79 } \ 80 __ret; \ 81 }) 82 83 #define arch_cmpxchg_relaxed(ptr, o, n) \ 84 (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr)))) 85 86 #define __cmpxchg_acquire(ptr, old, new, size) \ 87 ({ \ 88 __typeof__(ptr) __ptr = (ptr); \ 89 __typeof__(new) __new = (new); \ 90 __typeof__(new) __tmp; \ 91 __typeof__(old) __old = (old); \ 92 __typeof__(*(ptr)) __ret; \ 93 switch (size) { \ 94 case 4: \ 95 asm volatile ( \ 96 "1: ldex.w %0, (%3) \n" \ 97 " cmpne %0, %4 \n" \ 98 " bt 2f \n" \ 99 " mov %1, %2 \n" \ 100 " stex.w %1, (%3) \n" \ 101 " bez %1, 1b \n" \ 102 ACQUIRE_FENCE \ 103 "2: \n" \ 104 : "=&r" (__ret), "=&r" (__tmp) \ 105 : "r" (__new), "r"(__ptr), "r"(__old) \ 106 :); \ 107 break; \ 108 default: \ 109 BUILD_BUG(); \ 110 } \ 111 __ret; \ 112 }) 113 114 #define arch_cmpxchg_acquire(ptr, o, n) \ 115 (__cmpxchg_acquire((ptr), (o), (n), sizeof(*(ptr)))) 116 117 #define __cmpxchg(ptr, old, new, size) \ 118 ({ \ 119 __typeof__(ptr) __ptr = (ptr); \ 120 __typeof__(new) __new = (new); \ 121 __typeof__(new) __tmp; \ 122 __typeof__(old) __old = (old); \ 123 __typeof__(*(ptr)) __ret; \ 124 switch (size) { \ 125 case 4: \ 126 asm volatile ( \ 127 RELEASE_FENCE \ 128 "1: ldex.w %0, (%3) \n" \ 129 " cmpne %0, %4 \n" \ 130 " bt 2f \n" \ 131 " mov %1, %2 \n" \ 132 " stex.w %1, (%3) \n" \ 133 " bez %1, 1b \n" \ 134 FULL_FENCE \ 135 "2: \n" \ 136 : "=&r" (__ret), "=&r" (__tmp) \ 137 : "r" (__new), "r"(__ptr), "r"(__old) \ 138 :); \ 139 break; \ 140 default: \ 141 BUILD_BUG(); \ 142 } \ 143 __ret; \ 144 }) 145 146 #define arch_cmpxchg(ptr, o, n) \ 147 (__cmpxchg((ptr), (o), (n), sizeof(*(ptr)))) 148 149 #define arch_cmpxchg_local(ptr, o, n) \ 150 (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr)))) 151 #else 152 #include <asm-generic/cmpxchg.h> 153 #endif 154 155 #endif /* __ASM_CSKY_CMPXCHG_H */ 156