1*11595172SStefan Kristiansson /* 2*11595172SStefan Kristiansson * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 3*11595172SStefan Kristiansson * 4*11595172SStefan Kristiansson * This file is licensed under the terms of the GNU General Public License 5*11595172SStefan Kristiansson * version 2. This program is licensed "as is" without any warranty of any 6*11595172SStefan Kristiansson * kind, whether express or implied. 7*11595172SStefan Kristiansson */ 8*11595172SStefan Kristiansson 9*11595172SStefan Kristiansson #ifndef __ASM_OPENRISC_CMPXCHG_H 10*11595172SStefan Kristiansson #define __ASM_OPENRISC_CMPXCHG_H 11*11595172SStefan Kristiansson 12*11595172SStefan Kristiansson #include <linux/types.h> 13*11595172SStefan Kristiansson 14*11595172SStefan Kristiansson /* 15*11595172SStefan Kristiansson * This function doesn't exist, so you'll get a linker error 16*11595172SStefan Kristiansson * if something tries to do an invalid cmpxchg(). 17*11595172SStefan Kristiansson */ 18*11595172SStefan Kristiansson extern void __cmpxchg_called_with_bad_pointer(void); 19*11595172SStefan Kristiansson 20*11595172SStefan Kristiansson #define __HAVE_ARCH_CMPXCHG 1 21*11595172SStefan Kristiansson 22*11595172SStefan Kristiansson static inline unsigned long 23*11595172SStefan Kristiansson __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) 24*11595172SStefan Kristiansson { 25*11595172SStefan Kristiansson if (size != 4) { 26*11595172SStefan Kristiansson __cmpxchg_called_with_bad_pointer(); 27*11595172SStefan Kristiansson return old; 28*11595172SStefan Kristiansson } 29*11595172SStefan Kristiansson 30*11595172SStefan Kristiansson __asm__ __volatile__( 31*11595172SStefan Kristiansson "1: l.lwa %0, 0(%1) \n" 32*11595172SStefan Kristiansson " l.sfeq %0, %2 \n" 33*11595172SStefan Kristiansson " l.bnf 2f \n" 34*11595172SStefan Kristiansson " l.nop \n" 35*11595172SStefan Kristiansson " l.swa 0(%1), %3 \n" 36*11595172SStefan Kristiansson " l.bnf 1b \n" 37*11595172SStefan Kristiansson " l.nop \n" 38*11595172SStefan Kristiansson "2: \n" 39*11595172SStefan Kristiansson : "=&r"(old) 40*11595172SStefan Kristiansson : "r"(ptr), "r"(old), "r"(new) 41*11595172SStefan Kristiansson : "cc", "memory"); 42*11595172SStefan Kristiansson 43*11595172SStefan Kristiansson return old; 44*11595172SStefan Kristiansson } 45*11595172SStefan Kristiansson 46*11595172SStefan Kristiansson #define cmpxchg(ptr, o, n) \ 47*11595172SStefan Kristiansson ({ \ 48*11595172SStefan Kristiansson (__typeof__(*(ptr))) __cmpxchg((ptr), \ 49*11595172SStefan Kristiansson (unsigned long)(o), \ 50*11595172SStefan Kristiansson (unsigned long)(n), \ 51*11595172SStefan Kristiansson sizeof(*(ptr))); \ 52*11595172SStefan Kristiansson }) 53*11595172SStefan Kristiansson 54*11595172SStefan Kristiansson /* 55*11595172SStefan Kristiansson * This function doesn't exist, so you'll get a linker error if 56*11595172SStefan Kristiansson * something tries to do an invalidly-sized xchg(). 57*11595172SStefan Kristiansson */ 58*11595172SStefan Kristiansson extern void __xchg_called_with_bad_pointer(void); 59*11595172SStefan Kristiansson 60*11595172SStefan Kristiansson static inline unsigned long __xchg(unsigned long val, volatile void *ptr, 61*11595172SStefan Kristiansson int size) 62*11595172SStefan Kristiansson { 63*11595172SStefan Kristiansson if (size != 4) { 64*11595172SStefan Kristiansson __xchg_called_with_bad_pointer(); 65*11595172SStefan Kristiansson return val; 66*11595172SStefan Kristiansson } 67*11595172SStefan Kristiansson 68*11595172SStefan Kristiansson __asm__ __volatile__( 69*11595172SStefan Kristiansson "1: l.lwa %0, 0(%1) \n" 70*11595172SStefan Kristiansson " l.swa 0(%1), %2 \n" 71*11595172SStefan Kristiansson " l.bnf 1b \n" 72*11595172SStefan Kristiansson " l.nop \n" 73*11595172SStefan Kristiansson : "=&r"(val) 74*11595172SStefan Kristiansson : "r"(ptr), "r"(val) 75*11595172SStefan Kristiansson : "cc", "memory"); 76*11595172SStefan Kristiansson 77*11595172SStefan Kristiansson return val; 78*11595172SStefan Kristiansson } 79*11595172SStefan Kristiansson 80*11595172SStefan Kristiansson #define xchg(ptr, with) \ 81*11595172SStefan Kristiansson ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), sizeof(*(ptr)))) 82*11595172SStefan Kristiansson 83*11595172SStefan Kristiansson #endif /* __ASM_OPENRISC_CMPXCHG_H */ 84