summaryrefslogtreecommitdiffstats
path: root/include/asm-frv/system.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-frv/system.h')
-rw-r--r--include/asm-frv/system.h70
1 files changed, 69 insertions, 1 deletions
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index 1166899317d7..be303b3eef40 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -13,7 +13,6 @@
#define _ASM_SYSTEM_H
#include <linux/linkage.h>
-#include <asm/atomic.h>
struct thread_struct;
@@ -197,4 +196,73 @@ extern void free_initmem(void);
#define arch_align_stack(x) (x)
+/*****************************************************************************/
+/*
+ * compare and conditionally exchange value with memory
+ * - if (*ptr == test) then orig = *ptr; *ptr = test;
+ * - if (*ptr != test) then orig = *ptr;
+ */
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define cmpxchg(ptr, test, new) \
+({ \
+ __typeof__(ptr) __xg_ptr = (ptr); \
+ __typeof__(*(ptr)) __xg_orig, __xg_tmp; \
+ __typeof__(*(ptr)) __xg_test = (test); \
+ __typeof__(*(ptr)) __xg_new = (new); \
+ \
+ switch (sizeof(__xg_orig)) { \
+ case 4: \
+ asm volatile( \
+ "0: \n" \
+ " orcc gr0,gr0,gr0,icc3 \n" \
+ " ckeq icc3,cc7 \n" \
+ " ld.p %M0,%1 \n" \
+ " orcr cc7,cc7,cc3 \n" \
+ " sub%I4cc %1,%4,%2,icc0 \n" \
+ " bne icc0,#0,1f \n" \
+ " cst.p %3,%M0 ,cc3,#1 \n" \
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
+ " beq icc3,#0,0b \n" \
+ "1: \n" \
+ : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
+ : "r"(__xg_new), "NPr"(__xg_test) \
+ : "memory", "cc7", "cc3", "icc3", "icc0" \
+ ); \
+ break; \
+ \
+ default: \
+ __xg_orig = 0; \
+ asm volatile("break"); \
+ break; \
+ } \
+ \
+ __xg_orig; \
+})
+
+#else
+
+extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
+
+#define cmpxchg(ptr, test, new) \
+({ \
+ __typeof__(ptr) __xg_ptr = (ptr); \
+ __typeof__(*(ptr)) __xg_orig; \
+ __typeof__(*(ptr)) __xg_test = (test); \
+ __typeof__(*(ptr)) __xg_new = (new); \
+ \
+ switch (sizeof(__xg_orig)) { \
+ case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
+ default: \
+ __xg_orig = 0; \
+ asm volatile("break"); \
+ break; \
+ } \
+ \
+ __xg_orig; \
+})
+
+#endif
+
+
#endif /* _ASM_SYSTEM_H */