diff options
Diffstat (limited to 'arch/arc/include/asm/io.h')
| -rw-r--r-- | arch/arc/include/asm/io.h | 72 | 
1 files changed, 72 insertions, 0 deletions
| diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index c22b181e8206..2f39d9b3886e 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -12,6 +12,7 @@  #include <linux/types.h>  #include <asm/byteorder.h>  #include <asm/page.h> +#include <asm/unaligned.h>  #ifdef CONFIG_ISA_ARCV2  #include <asm/barrier.h> @@ -94,6 +95,42 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)  	return w;  } +/* + * {read,write}s{b,w,l}() repeatedly access the same IO address in + * native endianness in 8-, 16-, 32-bit chunks {into,from} memory, + * @count times + */ +#define __raw_readsx(t,f) \ +static inline void __raw_reads##f(const volatile void __iomem *addr,	\ +				  void *ptr, unsigned int count)	\ +{									\ +	bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;	\ +	u##t *buf = ptr;						\ +									\ +	if (!count)							\ +		return;							\ +									\ +	/* Some ARC CPU's don't support unaligned accesses */		\ +	if (is_aligned) {						\ +		do {							\ +			u##t x = __raw_read##f(addr);			\ +			*buf++ = x;					\ +		} while (--count);					\ +	} else {							\ +		do {							\ +			u##t x = __raw_read##f(addr);			\ +			put_unaligned(x, buf++);			\ +		} while (--count);					\ +	}								\ +} + +#define __raw_readsb __raw_readsb +__raw_readsx(8, b) +#define __raw_readsw __raw_readsw +__raw_readsx(16, w) +#define __raw_readsl __raw_readsl +__raw_readsx(32, l) +  #define __raw_writeb __raw_writeb  static inline void __raw_writeb(u8 b, volatile void __iomem *addr)  { @@ -126,6 +163,35 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)  } +#define __raw_writesx(t,f)						\ +static inline void __raw_writes##f(volatile void __iomem *addr, 	\ +				   const void *ptr, unsigned int count)	\ +{									\ +	bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;	\ +	const u##t *buf = ptr;						\ +									\ +	if (!count)							\ +		return;							\ +									\ +	/* Some ARC CPU's don't support unaligned accesses */		\ +	if (is_aligned) {						\ +		do {							\ +			__raw_write##f(*buf++, addr);			\ +		} while (--count);					\ +	} else {							\ +		do {							\ +			__raw_write##f(get_unaligned(buf++), addr);	\ +		} while (--count);					\ +	}								\ +} + +#define __raw_writesb __raw_writesb +__raw_writesx(8, b) +#define __raw_writesw __raw_writesw +__raw_writesx(16, w) +#define __raw_writesl __raw_writesl +__raw_writesx(32, l) +  /*   * MMIO can also get buffered/optimized in micro-arch, so barriers needed   * Based on ARM model for the typical use case @@ -141,10 +207,16 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)  #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })  #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })  #define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +#define readsb(p,d,l)		({ __raw_readsb(p,d,l); __iormb(); }) +#define readsw(p,d,l)		({ __raw_readsw(p,d,l); __iormb(); }) +#define readsl(p,d,l)		({ __raw_readsl(p,d,l); __iormb(); })  #define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })  #define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })  #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); }) +#define writesb(p,d,l)		({ __iowmb(); __raw_writesb(p,d,l); }) +#define writesw(p,d,l)		({ __iowmb(); __raw_writesw(p,d,l); }) +#define writesl(p,d,l)		({ __iowmb(); __raw_writesl(p,d,l); })  /*   * Relaxed API for drivers which can handle barrier ordering themselves | 
