Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MIPS] Iomap implementation.

This implementation has support for the concept of one separate ioport
address space by PCI domain. A pointer to the virtual address where
the port space of a domain has been mapped has been added to struct
pci_controller and systems should be fixed to fill in this value. For
single domain systems this will be the same value as passed to
set_io_port_base().

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+297 -91
+2 -1
arch/mips/lib/Makefile
··· 5 5 lib-y += csum_partial.o memcpy.o memset.o promlib.o \ 6 6 strlen_user.o strncpy_user.o strnlen_user.o uncached.o 7 7 8 - obj-y += iomap.o 8 + obj-y += iomap.o 9 + obj-$(CONFIG_PCI) += iomap-pci.o 9 10 10 11 # libgcc-style stuff needed in the kernel 11 12 lib-y += ashldi3.o ashrdi3.o lshrdi3.o
+74
arch/mips/lib/iomap-pci.c
··· 1 + /* 2 + * Implement the default iomap interfaces 3 + * 4 + * (C) Copyright 2004 Linus Torvalds 5 + * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org> 6 + * (C) Copyright 2007 MIPS Technologies, Inc. 7 + * written by Ralf Baechle <ralf@linux-mips.org> 8 + */ 9 + #include <linux/pci.h> 10 + #include <linux/module.h> 11 + #include <asm/io.h> 12 + 13 + static void __iomem *ioport_map_pci(struct pci_dev *dev, 14 + unsigned long port, unsigned int nr) 15 + { 16 + struct pci_controller *ctrl = dev->bus->sysdata; 17 + unsigned long base = ctrl->io_map_base; 18 + 19 + /* This will eventually become a BUG_ON but for now be gentle */ 20 + if (unlikely(!ctrl->io_map_base)) { 21 + struct pci_bus *bus = dev->bus; 22 + char name[8]; 23 + 24 + while (bus->parent) 25 + bus = bus->parent; 26 + 27 + ctrl->io_map_base = base = mips_io_port_base; 28 + 29 + sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); 30 + printk(KERN_WARNING "io_map_base of root PCI bus %s unset. " 31 + "Trying to continue but you better\nfix this issue or " 32 + "report it to linux-mips@linux-mips.org or your " 33 + "vendor.\n", name); 34 + #ifdef CONFIG_PCI_DOMAINS 35 + panic("To avoid data corruption io_map_base MUST be set with " 36 + "multiple PCI domains."); 37 + #endif 38 + } 39 + 40 + return (void __iomem *) (ctrl->io_map_base + port); 41 + } 42 + 43 + /* 44 + * Create a virtual mapping cookie for a PCI BAR (memory or IO) 45 + */ 46 + void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) 47 + { 48 + unsigned long start = pci_resource_start(dev, bar); 49 + unsigned long len = pci_resource_len(dev, bar); 50 + unsigned long flags = pci_resource_flags(dev, bar); 51 + 52 + if (!len || !start) 53 + return NULL; 54 + if (maxlen && len > maxlen) 55 + len = maxlen; 56 + if (flags & IORESOURCE_IO) 57 + return ioport_map_pci(dev, start, len); 58 + if (flags & IORESOURCE_MEM) { 59 + if (flags & IORESOURCE_CACHEABLE) 60 + return ioremap(start, len); 61 + return ioremap_nocache(start, len); 62 + } 63 + /* What? */ 64 + return NULL; 65 + } 66 + 67 + EXPORT_SYMBOL(pci_iomap); 68 + 69 + void pci_iounmap(struct pci_dev *dev, void __iomem * addr) 70 + { 71 + iounmap(addr); 72 + } 73 + 74 + EXPORT_SYMBOL(pci_iounmap);
+211 -62
arch/mips/lib/iomap.c
··· 1 1 /* 2 - * iomap.c, Memory Mapped I/O routines for MIPS architecture. 2 + * Implement the default iomap interfaces 3 3 * 4 - * This code is based on lib/iomap.c, by Linus Torvalds. 5 - * 6 - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License as published by 10 - * the Free Software Foundation; either version 2 of the License, or 11 - * (at your option) any later version. 12 - * 13 - * This program is distributed in the hope that it will be useful, 14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 - * GNU General Public License for more details. 17 - * 18 - * You should have received a copy of the GNU General Public License 19 - * along with this program; if not, write to the Free Software 20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 4 + * (C) Copyright 2004 Linus Torvalds 5 + * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org> 6 + * (C) Copyright 2007 MIPS Technologies, Inc. 7 + * written by Ralf Baechle <ralf@linux-mips.org> 21 8 */ 22 - #include <linux/ioport.h> 23 - #include <linux/module.h> 24 9 #include <linux/pci.h> 25 - 10 + #include <linux/module.h> 26 11 #include <asm/io.h> 12 + 13 + /* 14 + * Read/write from/to an (offsettable) iomem cookie. It might be a PIO 15 + * access or a MMIO access, these functions don't care. The info is 16 + * encoded in the hardware mapping set up by the mapping functions 17 + * (or the cookie itself, depending on implementation and hw). 18 + * 19 + * The generic routines don't assume any hardware mappings, and just 20 + * encode the PIO/MMIO as part of the cookie. They coldly assume that 21 + * the MMIO IO mappings are not in the low address range. 22 + * 23 + * Architectures for which this is not true can't use this generic 24 + * implementation and should do their own copy. 25 + */ 26 + 27 + #define PIO_MASK 0x0ffffUL 28 + 29 + unsigned int ioread8(void __iomem *addr) 30 + { 31 + return readb(addr); 32 + } 33 + 34 + EXPORT_SYMBOL(ioread8); 35 + 36 + unsigned int ioread16(void __iomem *addr) 37 + { 38 + return readw(addr); 39 + } 40 + 41 + EXPORT_SYMBOL(ioread16); 42 + 43 + unsigned int ioread16be(void __iomem *addr) 44 + { 45 + return be16_to_cpu(__raw_readw(addr)); 46 + } 47 + 48 + EXPORT_SYMBOL(ioread16be); 49 + 50 + unsigned int ioread32(void __iomem *addr) 51 + { 52 + return readl(addr); 53 + } 54 + 55 + EXPORT_SYMBOL(ioread32); 56 + 57 + unsigned int ioread32be(void __iomem *addr) 58 + { 59 + return be32_to_cpu(__raw_readl(addr)); 60 + } 61 + 62 + EXPORT_SYMBOL(ioread32be); 63 + 64 + void iowrite8(u8 val, void __iomem *addr) 65 + { 66 + writeb(val, addr); 67 + } 68 + 69 + EXPORT_SYMBOL(iowrite8); 70 + 71 + void iowrite16(u16 val, void __iomem *addr) 72 + { 73 + writew(val, addr); 74 + } 75 + 76 + EXPORT_SYMBOL(iowrite16); 77 + 78 + void iowrite16be(u16 val, void __iomem *addr) 79 + { 80 + __raw_writew(cpu_to_be16(val), addr); 81 + } 82 + 83 + EXPORT_SYMBOL(iowrite16be); 84 + 85 + void iowrite32(u32 val, void __iomem *addr) 86 + { 87 + writel(val, addr); 88 + } 89 + 90 + EXPORT_SYMBOL(iowrite32); 91 + 92 + void iowrite32be(u32 val, void __iomem *addr) 93 + { 94 + __raw_writel(cpu_to_be32(val), addr); 95 + } 96 + 97 + EXPORT_SYMBOL(iowrite32be); 98 + 99 + /* 100 + * These are the "repeat MMIO read/write" functions. 101 + * Note the "__raw" accesses, since we don't want to 102 + * convert to CPU byte order. We write in "IO byte 103 + * order" (we also don't have IO barriers). 104 + */ 105 + static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) 106 + { 107 + while (--count >= 0) { 108 + u8 data = __raw_readb(addr); 109 + *dst = data; 110 + dst++; 111 + } 112 + } 113 + 114 + static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) 115 + { 116 + while (--count >= 0) { 117 + u16 data = __raw_readw(addr); 118 + *dst = data; 119 + dst++; 120 + } 121 + } 122 + 123 + static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) 124 + { 125 + while (--count >= 0) { 126 + u32 data = __raw_readl(addr); 127 + *dst = data; 128 + dst++; 129 + } 130 + } 131 + 132 + static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) 133 + { 134 + while (--count >= 0) { 135 + __raw_writeb(*src, addr); 136 + src++; 137 + } 138 + } 139 + 140 + static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) 141 + { 142 + while (--count >= 0) { 143 + __raw_writew(*src, addr); 144 + src++; 145 + } 146 + } 147 + 148 + static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) 149 + { 150 + while (--count >= 0) { 151 + __raw_writel(*src, addr); 152 + src++; 153 + } 154 + } 155 + 156 + void ioread8_rep(void __iomem *addr, void *dst, unsigned long count) 157 + { 158 + mmio_insb(addr, dst, count); 159 + } 160 + 161 + EXPORT_SYMBOL(ioread8_rep); 162 + 163 + void ioread16_rep(void __iomem *addr, void *dst, unsigned long count) 164 + { 165 + mmio_insw(addr, dst, count); 166 + } 167 + 168 + EXPORT_SYMBOL(ioread16_rep); 169 + 170 + void ioread32_rep(void __iomem *addr, void *dst, unsigned long count) 171 + { 172 + mmio_insl(addr, dst, count); 173 + } 174 + 175 + EXPORT_SYMBOL(ioread32_rep); 176 + 177 + void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) 178 + { 179 + mmio_outsb(addr, src, count); 180 + } 181 + 182 + EXPORT_SYMBOL(iowrite8_rep); 183 + 184 + void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) 185 + { 186 + mmio_outsw(addr, src, count); 187 + } 188 + 189 + EXPORT_SYMBOL(iowrite16_rep); 190 + 191 + void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) 192 + { 193 + mmio_outsl(addr, src, count); 194 + } 195 + 196 + EXPORT_SYMBOL(iowrite32_rep); 197 + 198 + /* 199 + * Create a virtual mapping cookie for an IO port range 200 + * 201 + * This uses the same mapping are as the in/out family which has to be setup 202 + * by the platform initialization code. 203 + * 204 + * Just to make matters somewhat more interesting on MIPS systems with 205 + * multiple host bridge each will have it's own ioport address space. 206 + */ 207 + static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr) 208 + { 209 + return (void __iomem *) (mips_io_port_base + port); 210 + } 27 211 28 212 void __iomem *ioport_map(unsigned long port, unsigned int nr) 29 213 { 30 - unsigned long end; 31 - 32 - end = port + nr - 1UL; 33 - if (ioport_resource.start > port || 34 - ioport_resource.end < end || port > end) 214 + if (port > PIO_MASK) 35 215 return NULL; 36 216 37 - return (void __iomem *)(mips_io_port_base + port); 217 + return ioport_map_legacy(port, nr); 38 218 } 219 + 220 + EXPORT_SYMBOL(ioport_map); 39 221 40 222 void ioport_unmap(void __iomem *addr) 41 223 { 224 + /* Nothing to do */ 42 225 } 43 - EXPORT_SYMBOL(ioport_map); 226 + 44 227 EXPORT_SYMBOL(ioport_unmap); 45 - 46 - void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) 47 - { 48 - unsigned long start, len, flags; 49 - 50 - if (dev == NULL) 51 - return NULL; 52 - 53 - start = pci_resource_start(dev, bar); 54 - len = pci_resource_len(dev, bar); 55 - if (!start || !len) 56 - return NULL; 57 - 58 - if (maxlen != 0 && len > maxlen) 59 - len = maxlen; 60 - 61 - flags = pci_resource_flags(dev, bar); 62 - if (flags & IORESOURCE_IO) 63 - return ioport_map(start, len); 64 - if (flags & IORESOURCE_MEM) { 65 - if (flags & IORESOURCE_CACHEABLE) 66 - return ioremap_cachable(start, len); 67 - return ioremap_nocache(start, len); 68 - } 69 - 70 - return NULL; 71 - } 72 - 73 - void pci_iounmap(struct pci_dev *dev, void __iomem *addr) 74 - { 75 - iounmap(addr); 76 - } 77 - EXPORT_SYMBOL(pci_iomap); 78 - EXPORT_SYMBOL(pci_iounmap);
+8
arch/mips/pci/pci.c
··· 79 79 { 80 80 *hose_tail = hose; 81 81 hose_tail = &hose->next; 82 + 83 + /* 84 + * Do not panic here but later - this might hapen before console init. 85 + */ 86 + if (!hose->io_map_base) { 87 + printk(KERN_WARNING 88 + "registering PCI controller with io_map_base unset\n"); 89 + } 82 90 } 83 91 84 92 /* Most MIPS systems have straight-forward swizzling needs. */
+1 -28
include/asm-mips/io.h
··· 20 20 #include <asm/byteorder.h> 21 21 #include <asm/cpu.h> 22 22 #include <asm/cpu-features.h> 23 + #include <asm-generic/iomap.h> 23 24 #include <asm/page.h> 24 25 #include <asm/pgtable-bits.h> 25 26 #include <asm/processor.h> ··· 517 516 { 518 517 memcpy((void __force *) dst, src, count); 519 518 } 520 - 521 - /* 522 - * Memory Mapped I/O 523 - */ 524 - #define ioread8(addr) readb(addr) 525 - #define ioread16(addr) readw(addr) 526 - #define ioread32(addr) readl(addr) 527 - 528 - #define iowrite8(b,addr) writeb(b,addr) 529 - #define iowrite16(w,addr) writew(w,addr) 530 - #define iowrite32(l,addr) writel(l,addr) 531 - 532 - #define ioread8_rep(a,b,c) readsb(a,b,c) 533 - #define ioread16_rep(a,b,c) readsw(a,b,c) 534 - #define ioread32_rep(a,b,c) readsl(a,b,c) 535 - 536 - #define iowrite8_rep(a,b,c) writesb(a,b,c) 537 - #define iowrite16_rep(a,b,c) writesw(a,b,c) 538 - #define iowrite32_rep(a,b,c) writesl(a,b,c) 539 - 540 - /* Create a virtual mapping cookie for an IO port range */ 541 - extern void __iomem *ioport_map(unsigned long port, unsigned int nr); 542 - extern void ioport_unmap(void __iomem *); 543 - 544 - /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ 545 - struct pci_dev; 546 - extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); 547 - extern void pci_iounmap(struct pci_dev *dev, void __iomem *); 548 519 549 520 /* 550 521 * ISA space is 'always mapped' on currently supported MIPS systems, no need
+1
include/asm-mips/pci.h
··· 32 32 unsigned long mem_offset; 33 33 struct resource *io_resource; 34 34 unsigned long io_offset; 35 + unsigned long io_map_base; 35 36 36 37 unsigned int index; 37 38 /* For compatibility with current (as of July 2003) pciutils