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