18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
38c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
48c2ecf20Sopenharmony_ci * for more details.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#ifndef __ASM_BARRIER_H
98c2ecf20Sopenharmony_ci#define __ASM_BARRIER_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/addrspace.h>
128c2ecf20Sopenharmony_ci#include <asm/sync.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic inline void __sync(void)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	asm volatile(__SYNC(full, always) ::: "memory");
178c2ecf20Sopenharmony_ci}
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic inline void rmb(void)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	asm volatile(__SYNC(rmb, always) ::: "memory");
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci#define rmb rmb
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic inline void wmb(void)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	asm volatile(__SYNC(wmb, always) ::: "memory");
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci#define wmb wmb
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define fast_mb()	__sync()
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define __fast_iob()				\
348c2ecf20Sopenharmony_ci	__asm__ __volatile__(			\
358c2ecf20Sopenharmony_ci		".set	push\n\t"		\
368c2ecf20Sopenharmony_ci		".set	noreorder\n\t"		\
378c2ecf20Sopenharmony_ci		"lw	$0,%0\n\t"		\
388c2ecf20Sopenharmony_ci		"nop\n\t"			\
398c2ecf20Sopenharmony_ci		".set	pop"			\
408c2ecf20Sopenharmony_ci		: /* no output */		\
418c2ecf20Sopenharmony_ci		: "m" (*(int *)CKSEG1)		\
428c2ecf20Sopenharmony_ci		: "memory")
438c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON
448c2ecf20Sopenharmony_ci# define fast_iob()	do { } while (0)
458c2ecf20Sopenharmony_ci#else /* ! CONFIG_CPU_CAVIUM_OCTEON */
468c2ecf20Sopenharmony_ci# ifdef CONFIG_SGI_IP28
478c2ecf20Sopenharmony_ci#  define fast_iob()				\
488c2ecf20Sopenharmony_ci	__asm__ __volatile__(			\
498c2ecf20Sopenharmony_ci		".set	push\n\t"		\
508c2ecf20Sopenharmony_ci		".set	noreorder\n\t"		\
518c2ecf20Sopenharmony_ci		"lw	$0,%0\n\t"		\
528c2ecf20Sopenharmony_ci		"sync\n\t"			\
538c2ecf20Sopenharmony_ci		"lw	$0,%0\n\t"		\
548c2ecf20Sopenharmony_ci		".set	pop"			\
558c2ecf20Sopenharmony_ci		: /* no output */		\
568c2ecf20Sopenharmony_ci		: "m" (*(int *)CKSEG1ADDR(0x1fa00004)) \
578c2ecf20Sopenharmony_ci		: "memory")
588c2ecf20Sopenharmony_ci# else
598c2ecf20Sopenharmony_ci#  define fast_iob()				\
608c2ecf20Sopenharmony_ci	do {					\
618c2ecf20Sopenharmony_ci		__sync();			\
628c2ecf20Sopenharmony_ci		__fast_iob();			\
638c2ecf20Sopenharmony_ci	} while (0)
648c2ecf20Sopenharmony_ci# endif
658c2ecf20Sopenharmony_ci#endif /* CONFIG_CPU_CAVIUM_OCTEON */
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_HAS_WB
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#include <asm/wbflush.h>
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#define mb()		wbflush()
728c2ecf20Sopenharmony_ci#define iob()		wbflush()
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#else /* !CONFIG_CPU_HAS_WB */
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#define mb()		fast_mb()
778c2ecf20Sopenharmony_ci#define iob()		fast_iob()
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#endif /* !CONFIG_CPU_HAS_WB */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#if defined(CONFIG_WEAK_ORDERING)
828c2ecf20Sopenharmony_ci# define __smp_mb()	__sync()
838c2ecf20Sopenharmony_ci# define __smp_rmb()	rmb()
848c2ecf20Sopenharmony_ci# define __smp_wmb()	wmb()
858c2ecf20Sopenharmony_ci#else
868c2ecf20Sopenharmony_ci# define __smp_mb()	barrier()
878c2ecf20Sopenharmony_ci# define __smp_rmb()	barrier()
888c2ecf20Sopenharmony_ci# define __smp_wmb()	barrier()
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/*
928c2ecf20Sopenharmony_ci * When LL/SC does imply order, it must also be a compiler barrier to avoid the
938c2ecf20Sopenharmony_ci * compiler from reordering where the CPU will not. When it does not imply
948c2ecf20Sopenharmony_ci * order, the compiler is also free to reorder across the LL/SC loop and
958c2ecf20Sopenharmony_ci * ordering will be done by smp_llsc_mb() and friends.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_ci#if defined(CONFIG_WEAK_REORDERING_BEYOND_LLSC) && defined(CONFIG_SMP)
988c2ecf20Sopenharmony_ci# define __WEAK_LLSC_MB		sync
998c2ecf20Sopenharmony_ci# define smp_llsc_mb() \
1008c2ecf20Sopenharmony_ci	__asm__ __volatile__(__stringify(__WEAK_LLSC_MB) : : :"memory")
1018c2ecf20Sopenharmony_ci# define __LLSC_CLOBBER
1028c2ecf20Sopenharmony_ci#else
1038c2ecf20Sopenharmony_ci# define __WEAK_LLSC_MB
1048c2ecf20Sopenharmony_ci# define smp_llsc_mb()		do { } while (0)
1058c2ecf20Sopenharmony_ci# define __LLSC_CLOBBER		"memory"
1068c2ecf20Sopenharmony_ci#endif
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON
1098c2ecf20Sopenharmony_ci#define smp_mb__before_llsc() smp_wmb()
1108c2ecf20Sopenharmony_ci#define __smp_mb__before_llsc() __smp_wmb()
1118c2ecf20Sopenharmony_ci/* Cause previous writes to become visible on all CPUs as soon as possible */
1128c2ecf20Sopenharmony_ci#define nudge_writes() __asm__ __volatile__(".set push\n\t"		\
1138c2ecf20Sopenharmony_ci					    ".set arch=octeon\n\t"	\
1148c2ecf20Sopenharmony_ci					    "syncw\n\t"			\
1158c2ecf20Sopenharmony_ci					    ".set pop" : : : "memory")
1168c2ecf20Sopenharmony_ci#else
1178c2ecf20Sopenharmony_ci#define smp_mb__before_llsc() smp_llsc_mb()
1188c2ecf20Sopenharmony_ci#define __smp_mb__before_llsc() smp_llsc_mb()
1198c2ecf20Sopenharmony_ci#define nudge_writes() mb()
1208c2ecf20Sopenharmony_ci#endif
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/*
1238c2ecf20Sopenharmony_ci * In the Loongson3 LL/SC workaround case, all of our LL/SC loops already have
1248c2ecf20Sopenharmony_ci * a completion barrier immediately preceding the LL instruction. Therefore we
1258c2ecf20Sopenharmony_ci * can skip emitting a barrier from __smp_mb__before_atomic().
1268c2ecf20Sopenharmony_ci */
1278c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS
1288c2ecf20Sopenharmony_ci# define __smp_mb__before_atomic()
1298c2ecf20Sopenharmony_ci#else
1308c2ecf20Sopenharmony_ci# define __smp_mb__before_atomic()	__smp_mb__before_llsc()
1318c2ecf20Sopenharmony_ci#endif
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci#define __smp_mb__after_atomic()	smp_llsc_mb()
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic inline void sync_ginv(void)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	asm volatile(__SYNC(ginv, always));
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#include <asm-generic/barrier.h>
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci#endif /* __ASM_BARRIER_H */
143