diff options
| -rw-r--r-- | include/asm-ppc/io.h | 89 | 
1 files changed, 55 insertions, 34 deletions
| diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index bbc9ba0be..03289bcc2 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -105,6 +105,11 @@ static inline void sync(void)  	__asm__ __volatile__ ("sync" : : : "memory");  } +static inline void isync(void) +{ +	__asm__ __volatile__ ("isync" : : : "memory"); +} +  /* Enforce in-order execution of data I/O.   * No distinction between read/write on PPC; use eieio for all three.   */ @@ -114,74 +119,90 @@ static inline void sync(void)  /*   * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + * + * Read operations have additional twi & isync to make sure the read + * is actually performed (i.e. the data has come back) before we start + * executing any following instructions.   */ -extern inline int in_8(volatile u8 *addr) +#define __iomem +extern inline int in_8(const volatile unsigned char __iomem *addr)  { -    int ret; +	int ret; -    __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); -    return ret; +	__asm__ __volatile__( +		"sync; lbz%U1%X1 %0,%1;\n" +		"twi 0,%0,0;\n" +		"isync" : "=r" (ret) : "m" (*addr)); +	return ret;  } -extern inline void out_8(volatile u8 *addr, int val) +extern inline void out_8(volatile unsigned char __iomem *addr, int val)  { -    __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +	__asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));  } -extern inline int in_le16(volatile u16 *addr) +extern inline int in_le16(const volatile unsigned short __iomem *addr)  { -    int ret; +	int ret; -    __asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) : -		  "r" (addr), "m" (*addr)); -    return ret; +	__asm__ __volatile__("sync; lhbrx %0,0,%1;\n" +			     "twi 0,%0,0;\n" +			     "isync" : "=r" (ret) : +			      "r" (addr), "m" (*addr)); +	return ret;  } -extern inline int in_be16(volatile u16 *addr) +extern inline int in_be16(const volatile unsigned short __iomem *addr)  { -    int ret; +	int ret; -    __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); -    return ret; +	__asm__ __volatile__("sync; lhz%U1%X1 %0,%1;\n" +			     "twi 0,%0,0;\n" +			     "isync" : "=r" (ret) : "m" (*addr)); +	return ret;  } -extern inline void out_le16(volatile u16 *addr, int val) +extern inline void out_le16(volatile unsigned short __iomem *addr, int val)  { -    __asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) : -		  "r" (val), "r" (addr)); +	__asm__ __volatile__("sync; sthbrx %1,0,%2" : "=m" (*addr) : +			      "r" (val), "r" (addr));  } -extern inline void out_be16(volatile u16 *addr, int val) +extern inline void out_be16(volatile unsigned short __iomem *addr, int val)  { -    __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +	__asm__ __volatile__("sync; sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));  } -extern inline unsigned in_le32(volatile u32 *addr) +extern inline unsigned in_le32(const volatile unsigned __iomem *addr)  { -    unsigned ret; +	unsigned ret; -    __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) : -		 "r" (addr), "m" (*addr)); -    return ret; +	__asm__ __volatile__("sync; lwbrx %0,0,%1;\n" +			     "twi 0,%0,0;\n" +			     "isync" : "=r" (ret) : +			     "r" (addr), "m" (*addr)); +	return ret;  } -extern inline unsigned in_be32(volatile u32 *addr) +extern inline unsigned in_be32(const volatile unsigned __iomem *addr)  { -    unsigned ret; +	unsigned ret; -    __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); -    return ret; +	__asm__ __volatile__("sync; lwz%U1%X1 %0,%1;\n" +			     "twi 0,%0,0;\n" +			     "isync" : "=r" (ret) : "m" (*addr)); +	return ret;  } -extern inline void out_le32(volatile unsigned *addr, int val) +extern inline void out_le32(volatile unsigned __iomem *addr, int val)  { -    __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) : -		 "r" (val), "r" (addr)); +	__asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) : +			     "r" (val), "r" (addr));  } -extern inline void out_be32(volatile unsigned *addr, int val) +extern inline void out_be32(volatile unsigned __iomem *addr, int val)  { -    __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +	__asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));  }  #endif |