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 18static inline 19unsigned 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 39static 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 */ 71struct __xchg_dummy { unsigned long a[100]; }; 72#define __xg(x) ((struct __xchg_dummy *)(x)) 73 74static inline 75unsigned 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 */ 90static 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