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: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
9216efafc5
commit
9ab3a7a0d2
1 changed files with 237 additions and 32 deletions
|
@ -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) \
|
do {
|
||||||
outsb((unsigned long) (p), (src), (count))
|
__raw_writeq(*buf++, addr);
|
||||||
#define iowrite16_rep(p, src, count) \
|
} while (--count);
|
||||||
outsw((unsigned long) (p), (src), (count))
|
}
|
||||||
#define iowrite32_rep(p, src, count) \
|
}
|
||||||
outsl((unsigned long) (p), (src), (count))
|
#endif
|
||||||
#endif /* CONFIG_GENERIC_IOMAP */
|
#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)
|
||||||
}
|
}
|
||||||
#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)
|
||||||
__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__
|
||||||
|
|
Loading…
Add table
Reference in a new issue