diff options
author | Bin Meng | 2018-10-15 02:21:16 -0700 |
---|---|---|
committer | Simon Glass | 2018-11-14 09:16:27 -0800 |
commit | 3bf9a8e8460f69022c85f30860911067e4aebca3 (patch) | |
tree | 7eb6577c4cf2a185851f8a4e52bf2cf0780f2af1 | |
parent | 2895c4b7d65e1a65f7d8804126f91ee91e8e2481 (diff) |
x86: Implement arch-specific io accessor routines
At present the generic io{read,write}{8,16,32} routines only support
MMIO access. With architecture like x86 that has a separate IO space,
these routines cannot be used to access I/O ports.
Implement x86-specific version to support both PIO and MMIO access,
so that drivers for multiple architectures can use these accessors
without the need to know whether it's MMIO or PIO.
These are ported from Linux kernel lib/iomap.c, with slight changes.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | arch/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/io.h | 66 |
2 files changed, 67 insertions, 0 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 1f2f407d64d..e822a0b27e3 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -120,6 +120,7 @@ config X86 select CREATE_ARCH_SYMLINK select DM select DM_PCI + select HAVE_ARCH_IOMAP select HAVE_PRIVATE_LIBGCC select OF_CONTROL select PCI diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index c05c6bf8a25..81def0afd30 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -241,6 +241,72 @@ static inline void sync(void) #define __iormb() dmb() #define __iowmb() dmb() +/* + * Read/write from/to an (offsettable) iomem cookie. It might be a PIO + * access or a MMIO access, these functions don't care. The info is + * encoded in the hardware mapping set up by the mapping functions + * (or the cookie itself, depending on implementation and hw). + * + * The generic routines don't assume any hardware mappings, and just + * encode the PIO/MMIO as part of the cookie. They coldly assume that + * the MMIO IO mappings are not in the low address range. + * + * Architectures for which this is not true can't use this generic + * implementation and should do their own copy. + */ + +/* + * We assume that all the low physical PIO addresses (0-0xffff) always + * PIO. That means we can do some sanity checks on the low bits, and + * don't need to just take things for granted. + */ +#define PIO_RESERVED 0x10000UL + +/* + * Ugly macros are a way of life. + */ +#define IO_COND(addr, is_pio, is_mmio) do { \ + unsigned long port = (unsigned long __force)addr; \ + if (port >= PIO_RESERVED) { \ + is_mmio; \ + } else { \ + is_pio; \ + } \ +} while (0) + +static inline u8 ioread8(const volatile void __iomem *addr) +{ + IO_COND(addr, return inb(port), return readb(addr)); + return 0xff; +} + +static inline u16 ioread16(const volatile void __iomem *addr) +{ + IO_COND(addr, return inw(port), return readw(addr)); + return 0xffff; +} + +static inline u32 ioread32(const volatile void __iomem *addr) +{ + IO_COND(addr, return inl(port), return readl(addr)); + return 0xffffffff; +} + +static inline void iowrite8(u8 value, volatile void __iomem *addr) +{ + IO_COND(addr, outb(value, port), writeb(value, addr)); +} + +static inline void iowrite16(u16 value, volatile void __iomem *addr) +{ + IO_COND(addr, outw(value, port), writew(value, addr)); +} + +static inline void iowrite32(u32 value, volatile void __iomem *addr) +{ + IO_COND(addr, outl(value, port), writel(value, addr)); +} + #include <asm-generic/io.h> #endif /* _ASM_IO_H */ |