aboutsummaryrefslogtreecommitdiff
path: root/include/asm-m32r/system.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-m32r/system.h')
-rw-r--r--include/asm-m32r/system.h64
1 files changed, 62 insertions, 2 deletions
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 73348c3f858..5eee832b73a 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -11,6 +11,7 @@
*/
#include <linux/config.h>
+#include <asm/assembler.h>
#ifdef __KERNEL__
@@ -132,8 +133,6 @@ static inline void local_irq_disable(void)
!(flags & 0x40); \
})
-#endif /* __KERNEL__ */
-
#define nop() __asm__ __volatile__ ("nop" : : )
#define xchg(ptr,x) \
@@ -213,6 +212,67 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
return (tmp);
}
+#define __HAVE_ARCH_CMPXCHG 1
+
+static __inline__ unsigned long
+__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
+{
+ unsigned long flags;
+ unsigned int retval;
+
+ local_irq_save(flags);
+ __asm__ __volatile__ (
+ DCACHE_CLEAR("%0", "r4", "%1")
+ M32R_LOCK" %0, @%1; \n"
+ " bne %0, %2, 1f; \n"
+ M32R_UNLOCK" %3, @%1; \n"
+ " bra 2f; \n"
+ " .fillinsn \n"
+ "1:"
+ M32R_UNLOCK" %2, @%1; \n"
+ " .fillinsn \n"
+ "2:"
+ : "=&r" (retval)
+ : "r" (p), "r" (old), "r" (new)
+ : "cbit", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+ , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+ );
+ local_irq_restore(flags);
+
+ return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ switch (size) {
+ case 4:
+ return __cmpxchg_u32(ptr, old, new);
+#if 0 /* we don't have __cmpxchg_u64 */
+ case 8:
+ return __cmpxchg_u64(ptr, old, new);
+#endif /* 0 */
+ }
+ __cmpxchg_called_with_bad_pointer();
+ return old;
+}
+
+#define cmpxchg(ptr,o,n) \
+ ({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+ })
+
+#endif /* __KERNEL__ */
+
/*
* Memory barrier.
*