diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-09-12 21:32:00 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-09-12 21:32:00 -0700 |
| commit | e4dad07102ea55ff15353e415ba4edc89953e67c (patch) | |
| tree | c20a8a4832058dea8f520d8a2245be8f5ea0afc9 | |
| parent | b42897ce287f1b242ac217de88e325101c0138f2 (diff) | |
Add skeleton "generic IO mapping" infrastructure.
Jeff wants to use this to clean up SATA and some network drivers.
| -rw-r--r-- | arch/alpha/Kconfig | 4 | ||||
| -rw-r--r-- | arch/arm/Kconfig | 4 | ||||
| -rw-r--r-- | arch/i386/Kconfig | 4 | ||||
| -rw-r--r-- | arch/ia64/Kconfig | 4 | ||||
| -rw-r--r-- | arch/ppc/Kconfig | 4 | ||||
| -rw-r--r-- | arch/ppc64/Kconfig | 4 | ||||
| -rw-r--r-- | arch/x86_64/Kconfig | 4 | ||||
| -rw-r--r-- | include/asm-generic/iomap.h | 44 | ||||
| -rw-r--r-- | include/asm-i386/io.h | 2 | ||||
| -rw-r--r-- | include/asm-ppc64/io.h | 2 | ||||
| -rw-r--r-- | lib/Makefile | 1 | ||||
| -rw-r--r-- | lib/iomap.c | 110 |
12 files changed, 187 insertions, 0 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 541bd7965909..0e4855419a72 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -32,6 +32,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 95aa273cdacf..aa709d12ef58 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -63,6 +63,10 @@ config GENERIC_BUST_SPINLOCK config GENERIC_ISA_DMA bool +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" menu "System Type" diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 18c722a8e656..597a9969169e 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -29,6 +29,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" menu "Processor type and features" diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 4459907b0a8a..aa742c601da2 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -38,6 +38,10 @@ config EFI bool default y +config GENERIC_IOMAP + bool + default y + choice prompt "System type" default IA64_GENERIC diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 46139ac97563..81d55092fde0 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -35,6 +35,10 @@ config GENERIC_NVRAM bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" menu "Processor" diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index c11f5cc5605a..706c53f58d0f 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -24,6 +24,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + config HAVE_DEC_LOCK bool default y diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index a131337b9dac..6f55f43975c1 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -78,6 +78,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h new file mode 100644 index 000000000000..cbd9e7f03a2a --- /dev/null +++ b/include/asm-generic/iomap.h @@ -0,0 +1,44 @@ +#ifndef __GENERIC_IO_H +#define __GENERIC_IO_H + +#include <linux/linkage.h> + +/* + * These are the "generic" interfaces for doing new-style + * memory-mapped or PIO accesses. Architectures may do + * their own arch-optimized versions, these just act as + * wrappers around the old-style IO register access functions: + * read[bwl]/write[bwl]/in[bwl]/out[bwl] + * + * Don't include this directly, include it from <asm/io.h>. + */ + +/* + * 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 just encode the PIO/MMIO as part of the + * cookie, and 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. + */ +extern unsigned int fastcall ioread8(void __iomem *); +extern unsigned int fastcall ioread16(void __iomem *); +extern unsigned int fastcall ioread32(void __iomem *); + +extern void fastcall iowrite8(u8, void __iomem *); +extern void fastcall iowrite16(u16, void __iomem *); +extern void fastcall iowrite32(u32, void __iomem *); + +/* Create a virtual mapping cookie for an IO port range */ +extern void __iomem *ioport_map(unsigned int port, unsigned int nr); +extern void ioport_unmap(void __iomem *); + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +struct pci_dev; +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +extern void pci_iounmap(struct pci_dev *dev, void __iomem *); + +#endif diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h index 20a26b98ec6e..083e3b8f8c7f 100644 --- a/include/asm-i386/io.h +++ b/include/asm-i386/io.h @@ -45,6 +45,8 @@ #ifdef __KERNEL__ +#include <asm-generic/iomap.h> + #include <linux/vmalloc.h> /** diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h index 33c2dfff9815..1e9cd557352e 100644 --- a/include/asm-ppc64/io.h +++ b/include/asm-ppc64/io.h @@ -18,6 +18,8 @@ #include <asm/memory.h> #include <asm/delay.h> +#include <asm-generic/iomap.h> + #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c)) #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c)) #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c)) diff --git a/lib/Makefile b/lib/Makefile index b62c9ef212ed..bcd6e855e747 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -10,6 +10,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o +lib-$(CONFIG_GENERIC_IOMAP) += iomap.o ifneq ($(CONFIG_HAVE_DEC_LOCK),y) lib-y += dec_and_lock.o diff --git a/lib/iomap.c b/lib/iomap.c new file mode 100644 index 000000000000..0873451ac21b --- /dev/null +++ b/lib/iomap.c @@ -0,0 +1,110 @@ +/* + * Implement the default iomap interfaces + */ +#include <linux/pci.h> +#include <asm/io.h> + +/* + * 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 encode the physical PIO addresses (0-0xffff) into the + * pointer by offsetting them with a constant (0x10000) and + * assuming that all the low addresses are 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_OFFSET 0x10000 +#define PIO_MASK 0x0ffff +#define PIO_RESERVED 0x40000 + +/* + * Ugly macros are a way of life. + */ +#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET) + +#define IO_COND(addr, is_pio, is_mmio) do { \ + unsigned long port = (unsigned long __force)addr; \ + if (port < PIO_RESERVED) { \ + VERIFY_PIO(port); \ + port &= PIO_MASK; \ + is_pio; \ + } else { \ + is_mmio; \ + } \ +} while (0) + +unsigned int fastcall ioread8(void __iomem *addr) +{ + IO_COND(addr, return inb(port), return readb(addr)); +} +unsigned int fastcall ioread16(void __iomem *addr) +{ + IO_COND(addr, return inw(port), return readw(addr)); +} +unsigned int fastcall ioread32(void __iomem *addr) +{ + IO_COND(addr, return inl(port), return readl(addr)); +} + +void fastcall iowrite8(u8 val, void __iomem *addr) +{ + IO_COND(addr, outb(val,port), writeb(val, addr)); +} +void fastcall iowrite16(u16 val, void __iomem *addr) +{ + IO_COND(addr, outw(val,port), writew(val, addr)); +} +void fastcall iowrite32(u32 val, void __iomem *addr) +{ + IO_COND(addr, outl(val,port), writel(val, addr)); +} + +/* Create a virtual mapping cookie for an IO port range */ +void __iomem *ioport_map(unsigned int port, unsigned int nr) +{ + if (port > PIO_MASK) + return NULL; + return (void __iomem *) (unsigned long) (port + PIO_OFFSET); +} + +void ioport_unmap(void __iomem *addr) +{ + /* Nothing to do */ +} + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len || !start) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) { + if (flags & IORESOURCE_CACHEABLE) + return ioremap(start, len); + return ioremap_nocache(start, len); + } + /* What? */ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +{ + IO_COND(addr, /* nothing */, iounmap(addr)); +} |
