Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1#ifndef _ASM_M32R_CMPXCHG_H
  2#define _ASM_M32R_CMPXCHG_H
  3
  4/*
  5 *  M32R version:
  6 *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  7 *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  8 */
  9
 10#include <linux/irqflags.h>
 11#include <asm/assembler.h>
 12#include <asm/dcache_clear.h>
 13
 14extern void  __xchg_called_with_bad_pointer(void);
 15
 16static __always_inline unsigned long
 17__xchg(unsigned long x, volatile void *ptr, int size)
 18{
 19	unsigned long flags;
 20	unsigned long tmp = 0;
 21
 22	local_irq_save(flags);
 23
 24	switch (size) {
 25#ifndef CONFIG_SMP
 26	case 1:
 27		__asm__ __volatile__ (
 28			"ldb	%0, @%2 \n\t"
 29			"stb	%1, @%2 \n\t"
 30			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 31		break;
 32	case 2:
 33		__asm__ __volatile__ (
 34			"ldh	%0, @%2 \n\t"
 35			"sth	%1, @%2 \n\t"
 36			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 37		break;
 38	case 4:
 39		__asm__ __volatile__ (
 40			"ld	%0, @%2 \n\t"
 41			"st	%1, @%2 \n\t"
 42			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 43		break;
 44#else  /* CONFIG_SMP */
 45	case 4:
 46		__asm__ __volatile__ (
 47			DCACHE_CLEAR("%0", "r4", "%2")
 48			"lock	%0, @%2;	\n\t"
 49			"unlock	%1, @%2;	\n\t"
 50			: "=&r" (tmp) : "r" (x), "r" (ptr)
 51			: "memory"
 52#ifdef CONFIG_CHIP_M32700_TS1
 53			, "r4"
 54#endif	/* CONFIG_CHIP_M32700_TS1 */
 55		);
 56		break;
 57#endif  /* CONFIG_SMP */
 58	default:
 59		__xchg_called_with_bad_pointer();
 60	}
 61
 62	local_irq_restore(flags);
 63
 64	return (tmp);
 65}
 66
 67#define xchg(ptr, x)							\
 68	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
 69
 70static __always_inline unsigned long
 71__xchg_local(unsigned long x, volatile void *ptr, int size)
 72{
 73	unsigned long flags;
 74	unsigned long tmp = 0;
 75
 76	local_irq_save(flags);
 77
 78	switch (size) {
 79	case 1:
 80		__asm__ __volatile__ (
 81			"ldb	%0, @%2 \n\t"
 82			"stb	%1, @%2 \n\t"
 83			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 84		break;
 85	case 2:
 86		__asm__ __volatile__ (
 87			"ldh	%0, @%2 \n\t"
 88			"sth	%1, @%2 \n\t"
 89			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 90		break;
 91	case 4:
 92		__asm__ __volatile__ (
 93			"ld	%0, @%2 \n\t"
 94			"st	%1, @%2 \n\t"
 95			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
 96		break;
 97	default:
 98		__xchg_called_with_bad_pointer();
 99	}
100
101	local_irq_restore(flags);
102
103	return (tmp);
104}
105
106#define xchg_local(ptr, x)						\
107	((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr),	\
108			sizeof(*(ptr))))
109
110#define __HAVE_ARCH_CMPXCHG	1
111
112static inline unsigned long
113__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
114{
115	unsigned long flags;
116	unsigned int retval;
117
118	local_irq_save(flags);
119	__asm__ __volatile__ (
120			DCACHE_CLEAR("%0", "r4", "%1")
121			M32R_LOCK" %0, @%1;	\n"
122		"	bne	%0, %2, 1f;	\n"
123			M32R_UNLOCK" %3, @%1;	\n"
124		"	bra	2f;		\n"
125                "       .fillinsn		\n"
126		"1:"
127			M32R_UNLOCK" %0, @%1;	\n"
128                "       .fillinsn		\n"
129		"2:"
130			: "=&r" (retval)
131			: "r" (p), "r" (old), "r" (new)
132			: "cbit", "memory"
133#ifdef CONFIG_CHIP_M32700_TS1
134			, "r4"
135#endif  /* CONFIG_CHIP_M32700_TS1 */
136		);
137	local_irq_restore(flags);
138
139	return retval;
140}
141
142static inline unsigned long
143__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
144			unsigned int new)
145{
146	unsigned long flags;
147	unsigned int retval;
148
149	local_irq_save(flags);
150	__asm__ __volatile__ (
151			DCACHE_CLEAR("%0", "r4", "%1")
152			"ld %0, @%1;		\n"
153		"	bne	%0, %2, 1f;	\n"
154			"st %3, @%1;		\n"
155		"	bra	2f;		\n"
156		"       .fillinsn		\n"
157		"1:"
158			"st %0, @%1;		\n"
159		"       .fillinsn		\n"
160		"2:"
161			: "=&r" (retval)
162			: "r" (p), "r" (old), "r" (new)
163			: "cbit", "memory"
164#ifdef CONFIG_CHIP_M32700_TS1
165			, "r4"
166#endif  /* CONFIG_CHIP_M32700_TS1 */
167		);
168	local_irq_restore(flags);
169
170	return retval;
171}
172
173/* This function doesn't exist, so you'll get a linker error
174   if something tries to do an invalid cmpxchg().  */
175extern void __cmpxchg_called_with_bad_pointer(void);
176
177static inline unsigned long
178__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
179{
180	switch (size) {
181	case 4:
182		return __cmpxchg_u32(ptr, old, new);
183#if 0	/* we don't have __cmpxchg_u64 */
184	case 8:
185		return __cmpxchg_u64(ptr, old, new);
186#endif /* 0 */
187	}
188	__cmpxchg_called_with_bad_pointer();
189	return old;
190}
191
192#define cmpxchg(ptr, o, n)						 \
193	((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o),	 \
194			(unsigned long)(n), sizeof(*(ptr))))
195
196#include <asm-generic/cmpxchg-local.h>
197
198static inline unsigned long __cmpxchg_local(volatile void *ptr,
199				      unsigned long old,
200				      unsigned long new, int size)
201{
202	switch (size) {
203	case 4:
204		return __cmpxchg_local_u32(ptr, old, new);
205	default:
206		return __cmpxchg_local_generic(ptr, old, new, size);
207	}
208
209	return old;
210}
211
212/*
213 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
214 * them available.
215 */
216#define cmpxchg_local(ptr, o, n)				  	    \
217	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	    \
218			(unsigned long)(n), sizeof(*(ptr))))
219#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
220
221#endif /* _ASM_M32R_CMPXCHG_H */