• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MN10300 Atomic xchg/cmpxchg operations
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #ifndef _ASM_CMPXCHG_H
12 #define _ASM_CMPXCHG_H
13 
14 #include <asm/irqflags.h>
15 
16 #ifdef CONFIG_SMP
17 #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
18 static inline
__xchg(volatile unsigned long * m,unsigned long val)19 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
20 {
21 	unsigned long status;
22 	unsigned long oldval;
23 
24 	asm volatile(
25 		"1:	mov	%4,(_AAR,%3)	\n"
26 		"	mov	(_ADR,%3),%1	\n"
27 		"	mov	%5,(_ADR,%3)	\n"
28 		"	mov	(_ADR,%3),%0	\n"	/* flush */
29 		"	mov	(_ASR,%3),%0	\n"
30 		"	or	%0,%0		\n"
31 		"	bne	1b		\n"
32 		: "=&r"(status), "=&r"(oldval), "=m"(*m)
33 		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
34 		: "memory", "cc");
35 
36 	return oldval;
37 }
38 
__cmpxchg(volatile unsigned long * m,unsigned long old,unsigned long new)39 static inline unsigned long __cmpxchg(volatile unsigned long *m,
40 				      unsigned long old, unsigned long new)
41 {
42 	unsigned long status;
43 	unsigned long oldval;
44 
45 	asm volatile(
46 		"1:	mov	%4,(_AAR,%3)	\n"
47 		"	mov	(_ADR,%3),%1	\n"
48 		"	cmp	%5,%1		\n"
49 		"	bne	2f		\n"
50 		"	mov	%6,(_ADR,%3)	\n"
51 		"2:	mov	(_ADR,%3),%0	\n"	/* flush */
52 		"	mov	(_ASR,%3),%0	\n"
53 		"	or	%0,%0		\n"
54 		"	bne	1b		\n"
55 		: "=&r"(status), "=&r"(oldval), "=m"(*m)
56 		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
57 		  "r"(old), "r"(new)
58 		: "memory", "cc");
59 
60 	return oldval;
61 }
62 #else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
63 #error "No SMP atomic operation support!"
64 #endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
65 
66 #else  /* CONFIG_SMP */
67 
68 /*
69  * Emulate xchg for non-SMP MN10300
70  */
71 struct __xchg_dummy { unsigned long a[100]; };
72 #define __xg(x) ((struct __xchg_dummy *)(x))
73 
74 static inline
__xchg(volatile unsigned long * m,unsigned long val)75 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
76 {
77 	unsigned long oldval;
78 	unsigned long flags;
79 
80 	flags = arch_local_cli_save();
81 	oldval = *m;
82 	*m = val;
83 	arch_local_irq_restore(flags);
84 	return oldval;
85 }
86 
87 /*
88  * Emulate cmpxchg for non-SMP MN10300
89  */
__cmpxchg(volatile unsigned long * m,unsigned long old,unsigned long new)90 static inline unsigned long __cmpxchg(volatile unsigned long *m,
91 				      unsigned long old, unsigned long new)
92 {
93 	unsigned long oldval;
94 	unsigned long flags;
95 
96 	flags = arch_local_cli_save();
97 	oldval = *m;
98 	if (oldval == old)
99 		*m = new;
100 	arch_local_irq_restore(flags);
101 	return oldval;
102 }
103 
104 #endif /* CONFIG_SMP */
105 
106 #define xchg(ptr, v)						\
107 	((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),	\
108 				     (unsigned long)(v)))
109 
110 #define cmpxchg(ptr, o, n)					\
111 	((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
112 					(unsigned long)(o),	\
113 					(unsigned long)(n)))
114 
115 #endif /* _ASM_CMPXCHG_H */
116