Indirect ISA port I/O accessing introduced, vendors can hook their own in/out function to general inb/outb. Drivers can access legacy ISA I/O port by inb/outb as it is done in x86 platform.
Signed-off-by: Rongrong Zou <zourongr...@gmail.com> --- arch/arm64/Kconfig.platforms | 5 ++- arch/arm64/include/asm/io.h | 78 ++++++++++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/setup.c | 5 +++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 4043c35..98ae206 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -127,5 +127,8 @@ config ARCH_ZYNQMP bool "Xilinx ZynqMP Family" help This enables support for Xilinx ZynqMP Family - +config ARM64_INDIRECT_PIO + bool "ARM64 Indirect port I/O" + help + This enables support for ARM64 indirect port I/O endmenu diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 44be1e0..0041f3b 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -193,6 +193,84 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); */ #define xlate_dev_kmem_ptr(p) p +#ifdef CONFIG_ARM64_INDIRECT_PIO +#define DEF_PCI_HOOK_pio(x) x +#else +#define DEF_PCI_HOOK_pio(x) NULL +#endif + +/* + * This value is equal to PCIBIOS_MIN_IO + */ +#define LEGACY_ISA_PORT_MAX 0x1000 + +extern struct arm64_isa_io { + u8 (*inb)(unsigned long port); + u16 (*inw)(unsigned long port); + u32 (*inl)(unsigned long port); + void (*outb)(u8 value, unsigned long port); + void (*outw)(u16 value, unsigned long port); + void (*outl)(u32 value, unsigned long port); +} arm64_isa_io; + +#define inb inb +static inline u8 inb(unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.inb) && + port < LEGACY_ISA_PORT_MAX) + return arm64_isa_io.inb(port); + return readb(PCI_IOBASE + port); +} + +#define inw inw +static inline u16 inw(unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.inw) && + port < LEGACY_ISA_PORT_MAX) + return arm64_isa_io.inw(port); + return readw(PCI_IOBASE + port); +} + +#define inl inl +static inline u32 inl(unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.inl) && + port < LEGACY_ISA_PORT_MAX) + return arm64_isa_io.inl(port); + return readl(PCI_IOBASE + port); +} + +#define outb outb +static inline void outb(u8 val, unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.outb) && + port < LEGACY_ISA_PORT_MAX) + arm64_isa_io.outb(val, port); + else + writeb(val, PCI_IOBASE + port); +} + +#define outw outw +static inline void outw(u16 val, unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.outw) && + port < LEGACY_ISA_PORT_MAX) + arm64_isa_io.outw(val, port); + else + writew(val, PCI_IOBASE + port); +} + +#define outl outl +static inline void outl(u32 val, unsigned long port) +{ + if (DEF_PCI_HOOK_pio(arm64_isa_io.outl) && + port < LEGACY_ISA_PORT_MAX) + arm64_isa_io.outl(val, port); + else + writel(val, PCI_IOBASE + port); +} + + #include <asm-generic/io.h> /* diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 8119479..c689dd7 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -381,3 +381,8 @@ static int __init topology_init(void) return 0; } subsys_initcall(topology_init); + +#if defined(CONFIG_ARM64_INDIRECT_PIO) +struct arm64_isa_io arm64_isa_io; +EXPORT_SYMBOL_GPL(arm64_isa_io); +#endif -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/