Define PCI_IOBASE for MIPS at the strat of kernel mapping segment.
That would allow virt address of I/O ports to be dynamicly mapped.
So we'll be able to combine multiple MMIO ranges into I/O ports
and thus we can take advantage of logic_pio mechanism.
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig | 3 ++
arch/mips/include/asm/io.h | 36 ++++++++++++++++-----
arch/mips/include/asm/mach-generic/spaces.h | 13 ++++++--
arch/mips/kernel/setup.c | 2 ++
arch/mips/lib/iomap-pci.c | 2 +-
5 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0519ca9f00f9..4e5308178649 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -3149,6 +3149,9 @@ config PCI_DRIVERS_LEGACY
select NO_GENERIC_PCI_IOPORT_MAP
select PCI_DOMAINS if PCI
+config PCI_IO_VMMAP
+ def_bool n
+
#
# ISA support is now enabled via select. Too many systems still have the one
# or other ISA chip on the board that users don't know about so don't expect
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 346fffd9e972..f15ddcd27f35 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -51,17 +51,36 @@
/* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
+/*
+ * On MIPS I/O ports are memory mapped, so we access them using normal
+ * load/store instructions.
+ */
+#ifdef CONFIG_PCI_IO_VMMAP
+/*
+ * I/O port access primitives for dymatic I/O ports mapping.
+ *
+ * We'll create kmap for I/O ports in this space.
+ */
+#define arch_has_dev_port() (1)
+#define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
+#define PCI_IOBASE ((void __iomem *)PCI_IO_START)
+#define IOPORT_RW_BASE PCI_IO_START
+
+#else
+
#define IO_SPACE_LIMIT 0xffff
/*
- * On MIPS I/O ports are memory mapped, so we access them using normal
- * load/store instructions. mips_io_port_base is the virtual address to
- * which all ports are being mapped. For sake of efficiency some code
- * assumes that this is an address that can be loaded with a single lui
- * instruction, so the lower 16 bits must be zero. Should be true on
- * on any sane architecture; generic code does not use this assumption.
+ * I/O port access primitives for fixed I/O ports mapping.
+ *
+ * mips_io_port_base is the virtual address to which all ports are
+ * being mapped. For sake of efficiency some code assumes that this
+ * is an address that can be loaded with a single lui, instruction, so
+ * the lower 16 bits must be zero. Should be true on on any sane architecture;
+ * generic code does not use this assumption.
*/
extern unsigned long mips_io_port_base;
+#define IOPORT_RW_BASE mips_io_port_base
static inline void set_io_port_base(unsigned long base)
{
@@ -78,6 +97,7 @@ static inline void set_io_port_base(unsigned long base)
#define PIO_OFFSET mips_io_port_base
#define PIO_MASK IO_SPACE_LIMIT
#define PIO_RESERVED 0x0UL
+#endif
/*
* Enforce in-order execution of data I/O. In the MIPS architecture
@@ -308,7 +328,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \
else \
war_io_reorder_wmb(); \
\
- __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
+ __addr = (void *)__swizzle_addr_##bwlq(IOPORT_RW_BASE + port); \
\
__val = pfx##ioswab##bwlq(__addr, val); \
\
@@ -323,7 +343,7 @@ static inline type pfx##in##bwlq##p(unsigned long port) \
volatile type *__addr; \
type __val; \
\
- __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
+ __addr = (void *)__swizzle_addr_##bwlq(IOPORT_RW_BASE + port); \
\
BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
\
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index 89162740951a..a39714c5fd7b 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -103,15 +103,24 @@
#endif
#endif
+#ifdef CONFIG_PCI_IO_VMMAP
+#define PCI_IO_SIZE SZ_16M
+#else
+#define PCI_IO_SIZE 0
+#endif
+
#ifdef CONFIG_64BIT
/*
* TLB refill handlers also map the vmalloc area into xuseg. Avoid
* the first couple of pages so NULL pointer dereferences will still
* reliably trap.
*/
-#define VMALLOC_START (MAP_BASE + (2 * PAGE_SIZE))
+#define PCI_IO_START (MAP_BASE + (2 * PAGE_SIZE))
#else
-#define VMALLOC_START MAP_BASE
+#define PCI_IO_START MAP_BASE
#endif
+#define PCI_IO_END (PCI_IO_START + PCI_IO_SIZE)
+#define VMALLOC_START PCI_IO_END
+
#endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8db533cd816c..99225539de3c 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -73,12 +73,14 @@ static const char builtin_cmdline[] __initconst = CONFIG_CMDLINE;
static const char builtin_cmdline[] __initconst = "";
#endif
+#ifndef CONFIG_PCI_IO_VMMAP
/*
* mips_io_port_base is the begin of the address space to which x86 style
* I/O ports are mapped.
*/
unsigned long mips_io_port_base = -1;
EXPORT_SYMBOL(mips_io_port_base);
+#endif
static struct resource code_resource = { .name = "Kernel code", };
static struct resource data_resource = { .name = "Kernel data", };
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
index 210f5a95ecb1..f28924aaac1d 100644
--- a/arch/mips/lib/iomap-pci.c
+++ b/arch/mips/lib/iomap-pci.c
@@ -27,7 +27,7 @@ void __iomem *__pci_ioport_map(struct pci_dev *dev,
while (bus->parent)
bus = bus->parent;
- ctrl->io_map_base = base = mips_io_port_base;
+ ctrl->io_map_base = base = IOPORT_RW_BASE;
sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
printk(KERN_WARNING "io_map_base of root PCI bus %s unset. "
--
2.26.0.rc2