x86: Implement arch-specific io accessor routines
authorBin Meng <bmeng.cn@gmail.com>
Mon, 15 Oct 2018 09:21:16 +0000 (02:21 -0700)
committerSimon Glass <sjg@chromium.org>
Wed, 14 Nov 2018 17:16:27 +0000 (09:16 -0800)
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>
arch/Kconfig
arch/x86/include/asm/io.h

index 1f2f407d64dd2a7cca3425fcd293e0c74f885371..e822a0b27e354ad7ec1a1f4093ace51628745b33 100644 (file)
@@ -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
index c05c6bf8a25fd50582907012808c8cede0fc33bb..81def0afd30063af862f3daeb81eed312ae7814e 100644 (file)
@@ -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 */