diff options
Diffstat (limited to 'arch/metag/include/asm/barrier.h')
-rw-r--r-- | arch/metag/include/asm/barrier.h | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h new file mode 100644 index 000000000..d703d8e26 --- /dev/null +++ b/arch/metag/include/asm/barrier.h @@ -0,0 +1,107 @@ +#ifndef _ASM_METAG_BARRIER_H +#define _ASM_METAG_BARRIER_H + +#include <asm/metag_mem.h> + +#define nop() asm volatile ("NOP") + +#ifdef CONFIG_METAG_META21 + +/* HTP and above have a system event to fence writes */ +static inline void wr_fence(void) +{ + volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_FENCE; + barrier(); + *flushptr = 0; + barrier(); +} + +#else /* CONFIG_METAG_META21 */ + +/* + * ATP doesn't have system event to fence writes, so it is necessary to flush + * the processor write queues as well as possibly the write combiner (depending + * on the page being written). + * To ensure the write queues are flushed we do 4 writes to a system event + * register (in this case write combiner flush) which will also flush the write + * combiner. + */ +static inline void wr_fence(void) +{ + volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_COMBINE_FLUSH; + barrier(); + *flushptr = 0; + *flushptr = 0; + *flushptr = 0; + *flushptr = 0; + barrier(); +} + +#endif /* !CONFIG_METAG_META21 */ + +/* flush writes through the write combiner */ +#define mb() wr_fence() +#define rmb() barrier() +#define wmb() mb() + +#define dma_rmb() rmb() +#define dma_wmb() wmb() + +#ifndef CONFIG_SMP +#define fence() do { } while (0) +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#else + +#ifdef CONFIG_METAG_SMP_WRITE_REORDERING +/* + * Write to the atomic memory unlock system event register (command 0). This is + * needed before a write to shared memory in a critical section, to prevent + * external reordering of writes before the fence on other threads with writes + * after the fence on this thread (and to prevent the ensuing cache-memory + * incoherence). It is therefore ineffective if used after and on the same + * thread as a write. + */ +static inline void fence(void) +{ + volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK; + barrier(); + *flushptr = 0; + barrier(); +} +#define smp_mb() fence() +#define smp_rmb() fence() +#define smp_wmb() barrier() +#else +#define fence() do { } while (0) +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#endif +#endif + +#define read_barrier_depends() do { } while (0) +#define smp_read_barrier_depends() do { } while (0) + +#define set_mb(var, value) do { var = value; smp_mb(); } while (0) + +#define smp_store_release(p, v) \ +do { \ + compiletime_assert_atomic_type(*p); \ + smp_mb(); \ + ACCESS_ONCE(*p) = (v); \ +} while (0) + +#define smp_load_acquire(p) \ +({ \ + typeof(*p) ___p1 = ACCESS_ONCE(*p); \ + compiletime_assert_atomic_type(*p); \ + smp_mb(); \ + ___p1; \ +}) + +#define smp_mb__before_atomic() barrier() +#define smp_mb__after_atomic() barrier() + +#endif /* _ASM_METAG_BARRIER_H */ |