Commit 9ab3a7a0 authored by Thierry Reding's avatar Thierry Reding

asm-generic/io.h: Implement generic {read,write}s*()

Currently driver writers need to use io{read,write}{8,16,32}_rep() when
accessing FIFO registers portably. This is bad for two reasons: it is
inconsistent with how other registers are accessed using the standard
{read,write}{b,w,l}() functions, which can lead to confusion. On some
architectures the io{read,write}*() functions also need to perform some
extra checks to determine whether an address is memory-mapped or refers
to I/O space. Drivers which can be expected to never use I/O can safely
use the {read,write}s{b,w,l,q}(), just like they use their non-string
variants and there's no need for these extra checks.

This patch implements generic versions of readsb(), readsw(), readsl(),
readsq(), writesb(), writesw(), writesl() and writesq(). Variants of
these string functions for I/O accesses (ins*() and outs*() as well as
ioread*_rep() and iowrite*_rep()) are now implemented in terms of the
new functions.

Going forward, {read,write}{,s}{b,w,l,q}() should be used consistently
by drivers for devices that will only ever be memory-mapped and hence
don't need to access I/O space, whereas io{read,write}{8,16,32}_rep()
should be used by drivers for devices that can be either memory-mapped
or I/O-mapped.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 9216efaf
...@@ -174,96 +174,137 @@ static inline void writeq(u64 value, volatile void __iomem *addr) ...@@ -174,96 +174,137 @@ static inline void writeq(u64 value, volatile void __iomem *addr)
#endif #endif
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
#ifndef insb /*
static inline void insb(unsigned long addr, void *buffer, int count) * {read,write}s{b,w,l,q}() repeatedly access the same memory address in
* native endianness in 8-, 16-, 32- or 64-bit chunks (@count times).
*/
#ifndef readsb
#define readsb readsb
static inline void readsb(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
u8 *buf = buffer; u8 *buf = buffer;
do { do {
u8 x = __raw_readb(addr + PCI_IOBASE); u8 x = __raw_readb(addr);
*buf++ = x; *buf++ = x;
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef insw #ifndef readsw
static inline void insw(unsigned long addr, void *buffer, int count) #define readsw readsw
static inline void readsw(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
u16 *buf = buffer; u16 *buf = buffer;
do { do {
u16 x = __raw_readw(addr + PCI_IOBASE); u16 x = __raw_readw(addr);
*buf++ = x; *buf++ = x;
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef insl #ifndef readsl
static inline void insl(unsigned long addr, void *buffer, int count) #define readsl readsl
static inline void readsl(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
u32 *buf = buffer; u32 *buf = buffer;
do { do {
u32 x = __raw_readl(addr + PCI_IOBASE); u32 x = __raw_readl(addr);
*buf++ = x; *buf++ = x;
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef outsb #ifdef CONFIG_64BIT
static inline void outsb(unsigned long addr, const void *buffer, int count) #ifndef readsq
#define readsq readsq
static inline void readsq(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{
if (count) {
u64 *buf = buffer;
do {
u64 x = __raw_readq(addr);
*buf++ = x;
} while (--count);
}
}
#endif
#endif /* CONFIG_64BIT */
#ifndef writesb
#define writesb writesb
static inline void writesb(volatile void __iomem *addr, const void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
const u8 *buf = buffer; const u8 *buf = buffer;
do { do {
__raw_writeb(*buf++, addr + PCI_IOBASE); __raw_writeb(*buf++, addr);
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef outsw #ifndef writesw
static inline void outsw(unsigned long addr, const void *buffer, int count) #define writesw writesw
static inline void writesw(volatile void __iomem *addr, const void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
const u16 *buf = buffer; const u16 *buf = buffer;
do { do {
__raw_writew(*buf++, addr + PCI_IOBASE); __raw_writew(*buf++, addr);
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef outsl #ifndef writesl
static inline void outsl(unsigned long addr, const void *buffer, int count) #define writesl writesl
static inline void writesl(volatile void __iomem *addr, const void *buffer,
unsigned int count)
{ {
if (count) { if (count) {
const u32 *buf = buffer; const u32 *buf = buffer;
do { do {
__raw_writel(*buf++, addr + PCI_IOBASE); __raw_writel(*buf++, addr);
} while (--count); } while (--count);
} }
} }
#endif #endif
#ifndef CONFIG_GENERIC_IOMAP #ifdef CONFIG_64BIT
#define ioread8_rep(p, dst, count) \ #ifndef writesq
insb((unsigned long) (p), (dst), (count)) #define writesq writesq
#define ioread16_rep(p, dst, count) \ static inline void writesq(volatile void __iomem *addr, const void *buffer,
insw((unsigned long) (p), (dst), (count)) unsigned int count)
#define ioread32_rep(p, dst, count) \ {
insl((unsigned long) (p), (dst), (count)) if (count) {
const u64 *buf = buffer;
#define iowrite8_rep(p, src, count) \
outsb((unsigned long) (p), (src), (count)) do {
#define iowrite16_rep(p, src, count) \ __raw_writeq(*buf++, addr);
outsw((unsigned long) (p), (src), (count)) } while (--count);
#define iowrite32_rep(p, src, count) \ }
outsl((unsigned long) (p), (src), (count)) }
#endif /* CONFIG_GENERIC_IOMAP */ #endif
#endif /* CONFIG_64BIT */
#ifndef PCI_IOBASE #ifndef PCI_IOBASE
#define PCI_IOBASE ((void __iomem *)0) #define PCI_IOBASE ((void __iomem *)0)
...@@ -375,6 +416,113 @@ static inline void outl_p(u32 value, unsigned long addr) ...@@ -375,6 +416,113 @@ static inline void outl_p(u32 value, unsigned long addr)
} }
#endif #endif
/*
* {in,out}s{b,w,l}{,_p}() are variants of the above that repeatedly access a
* single I/O port multiple times.
*/
#ifndef insb
#define insb insb
static inline void insb(unsigned long addr, void *buffer, unsigned int count)
{
readsb(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef insw
#define insw insw
static inline void insw(unsigned long addr, void *buffer, unsigned int count)
{
readsw(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef insl
#define insl insl
static inline void insl(unsigned long addr, void *buffer, unsigned int count)
{
readsl(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef outsb
#define outsb outsb
static inline void outsb(unsigned long addr, const void *buffer,
unsigned int count)
{
writesb(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef outsw
#define outsw outsw
static inline void outsw(unsigned long addr, const void *buffer,
unsigned int count)
{
writesw(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef outsl
#define outsl outsl
static inline void outsl(unsigned long addr, const void *buffer,
unsigned int count)
{
writesl(PCI_IOBASE + addr, buffer, count);
}
#endif
#ifndef insb_p
#define insb_p insb_p
static inline void insb_p(unsigned long addr, void *buffer, unsigned int count)
{
insb(addr, buffer, count);
}
#endif
#ifndef insw_p
#define insw_p insw_p
static inline void insw_p(unsigned long addr, void *buffer, unsigned int count)
{
insw(addr, buffer, count);
}
#endif
#ifndef insl_p
#define insl_p insl_p
static inline void insl_p(unsigned long addr, void *buffer, unsigned int count)
{
insl(addr, buffer, count);
}
#endif
#ifndef outsb_p
#define outsb_p outsb_p
static inline void outsb_p(unsigned long addr, const void *buffer,
unsigned int count)
{
outsb(addr, buffer, count);
}
#endif
#ifndef outsw_p
#define outsw_p outsw_p
static inline void outsw_p(unsigned long addr, const void *buffer,
unsigned int count)
{
outsw(addr, buffer, count);
}
#endif
#ifndef outsl_p
#define outsl_p outsl_p
static inline void outsl_p(unsigned long addr, const void *buffer,
unsigned int count)
{
outsl(addr, buffer, count);
}
#endif
#ifndef CONFIG_GENERIC_IOMAP #ifndef CONFIG_GENERIC_IOMAP
#ifndef ioread8 #ifndef ioread8
#define ioread8 ioread8 #define ioread8 ioread8
...@@ -455,6 +603,63 @@ static inline void iowrite32be(u32 value, volatile void __iomem *addr) ...@@ -455,6 +603,63 @@ static inline void iowrite32be(u32 value, volatile void __iomem *addr)
__raw_writel(__cpu_to_be32(value), addr); __raw_writel(__cpu_to_be32(value), addr);
} }
#endif #endif
#ifndef ioread8_rep
#define ioread8_rep ioread8_rep
static inline void ioread8_rep(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{
readsb(addr, buffer, count);
}
#endif
#ifndef ioread16_rep
#define ioread16_rep ioread16_rep
static inline void ioread16_rep(const volatile void __iomem *addr,
void *buffer, unsigned int count)
{
readsw(addr, buffer, count);
}
#endif
#ifndef ioread32_rep
#define ioread32_rep ioread32_rep
static inline void ioread32_rep(const volatile void __iomem *addr,
void *buffer, unsigned int count)
{
readsl(addr, buffer, count);
}
#endif
#ifndef iowrite8_rep
#define iowrite8_rep iowrite8_rep
static inline void iowrite8_rep(volatile void __iomem *addr,
const void *buffer,
unsigned int count)
{
writesb(addr, buffer, count);
}
#endif
#ifndef iowrite16_rep
#define iowrite16_rep iowrite16_rep
static inline void iowrite16_rep(volatile void __iomem *addr,
const void *buffer,
unsigned int count)
{
writesw(addr, buffer, count);
}
#endif
#ifndef iowrite32_rep
#define iowrite32_rep iowrite32_rep
static inline void iowrite32_rep(volatile void __iomem *addr,
const void *buffer,
unsigned int count)
{
writesl(addr, buffer, count);
}
#endif
#endif /* CONFIG_GENERIC_IOMAP */ #endif /* CONFIG_GENERIC_IOMAP */
#ifdef __KERNEL__ #ifdef __KERNEL__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment