linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / include / asm-m32r / system.h
index cca922a..d6a2c61 100644 (file)
@@ -7,9 +7,11 @@
  * for more details.
  *
  * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
+#include <asm/assembler.h>
 
 #ifdef __KERNEL__
 
        last = __last; \
 } while(0)
 
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
 /* Interrupt Control */
-#if !defined(CONFIG_CHIP_M32102)
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
 #define local_irq_enable() \
        __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
 #define local_irq_disable() \
        __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
-#else  /* CONFIG_CHIP_M32102 */
-static __inline__ void local_irq_enable(void)
+#else  /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
+static inline void local_irq_enable(void)
 {
        unsigned long tmpreg;
        __asm__ __volatile__(
@@ -83,7 +95,7 @@ static __inline__ void local_irq_enable(void)
        : "=&r" (tmpreg) : : "cbit", "memory");
 }
 
-static __inline__ void local_irq_disable(void)
+static inline void local_irq_disable(void)
 {
        unsigned long tmpreg0, tmpreg1;
        __asm__ __volatile__(
@@ -94,7 +106,7 @@ static __inline__ void local_irq_disable(void)
                "mvtc   %0, psw \n\t"
        : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
 }
-#endif /* CONFIG_CHIP_M32102 */
+#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
 
 #define local_save_flags(x) \
        __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
@@ -103,13 +115,13 @@ static __inline__ void local_irq_disable(void)
        __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
                : "r" (x) : "cbit", "memory")
 
-#if !defined(CONFIG_CHIP_M32102)
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
 #define local_irq_save(x)                              \
        __asm__ __volatile__(                           \
                "mvfc   %0, psw;                \n\t"   \
                "clrpsw #0x40 -> nop;           \n\t"   \
                : "=r" (x) : /* no input */ : "memory")
-#else  /* CONFIG_CHIP_M32102 */
+#else  /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
 #define local_irq_save(x)                              \
        ({                                              \
                unsigned long tmpreg;                   \
@@ -122,7 +134,7 @@ static __inline__ void local_irq_disable(void)
                        : "=r" (x), "=&r" (tmpreg)      \
                        : : "cbit", "memory");          \
        })
-#endif /* CONFIG_CHIP_M32102 */
+#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
 
 #define irqs_disabled()                                        \
        ({                                              \
@@ -131,8 +143,6 @@ static __inline__ void local_irq_disable(void)
                !(flags & 0x40);                        \
        })
 
-#endif  /* __KERNEL__ */
-
 #define nop()  __asm__ __volatile__ ("nop" : : )
 
 #define xchg(ptr,x) \
@@ -212,6 +222,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" %0, @%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.
  *
@@ -219,11 +290,7 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
  * rmb() prevents loads being reordered across this point.
  * wmb() prevents stores being reordered across this point.
  */
-#if 0
-#define mb()   __asm__ __volatile__ ("push r0; \n\t pop r0;" : : : "memory")
-#else
-#define mb()   __asm__ __volatile__ ("" : : : "memory")
-#endif
+#define mb()   barrier()
 #define rmb()  mb()
 #define wmb()  mb()
 
@@ -297,5 +364,6 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
-#endif  /* _ASM_M32R_SYSTEM_H */
+#define arch_align_stack(x) (x)
 
+#endif  /* _ASM_M32R_SYSTEM_H */