Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=140c1729a221dc6eacfcbf2a073dbf00fad13e43
Commit:     140c1729a221dc6eacfcbf2a073dbf00fad13e43
Parent:     4c1569949a756327aa0ad7aa15a62266b6a00c3e
Author:     Ralf Baechle <[EMAIL PROTECTED]>
AuthorDate: Thu Dec 7 15:35:43 2006 +0100
Committer:  Ralf Baechle <[EMAIL PROTECTED]>
CommitDate: Sun Feb 18 21:31:34 2007 +0000

    [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 <[EMAIL PROTECTED]>
---
 arch/mips/lib/Makefile    |    3 +-
 arch/mips/lib/iomap-pci.c |   74 +++++++++++
 arch/mips/lib/iomap.c     |  305 +++++++++++++++++++++++++++++++++------------
 arch/mips/pci/pci.c       |    8 ++
 include/asm-mips/io.h     |   29 +----
 include/asm-mips/pci.h    |    1 +
 6 files changed, 313 insertions(+), 107 deletions(-)

diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 5ad501b..9e5d985 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,7 +5,8 @@
 lib-y  += csum_partial.o memcpy.o memset.o promlib.o \
           strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 
-obj-y  += iomap.o
+obj-y                  += iomap.o
+obj-$(CONFIG_PCI)      += iomap-pci.o
 
 # libgcc-style stuff needed in the kernel
 lib-y += ashldi3.o ashrdi3.o lshrdi3.o
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
new file mode 100644
index 0000000..c11b249
--- /dev/null
+++ b/arch/mips/lib/iomap-pci.c
@@ -0,0 +1,74 @@
+/*
+ * Implement the default iomap interfaces
+ *
+ * (C) Copyright 2004 Linus Torvalds
+ * (C) Copyright 2006 Ralf Baechle <[EMAIL PROTECTED]>
+ * (C) Copyright 2007 MIPS Technologies, Inc.
+ *     written by Ralf Baechle <[EMAIL PROTECTED]>
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+static void __iomem *ioport_map_pci(struct pci_dev *dev,
+                                     unsigned long port, unsigned int nr)
+{
+       struct pci_controller *ctrl = dev->bus->sysdata;
+       unsigned long base = ctrl->io_map_base;
+
+       /* This will eventually become a BUG_ON but for now be gentle */
+       if (unlikely(!ctrl->io_map_base)) {
+               struct pci_bus *bus = dev->bus;
+               char name[8];
+
+               while (bus->parent)
+                       bus = bus->parent;
+
+               ctrl->io_map_base = base = mips_io_port_base;
+
+               sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
+               printk(KERN_WARNING "io_map_base of root PCI bus %s unset.  "
+                      "Trying to continue but you better\nfix this issue or "
+                      "report it to [EMAIL PROTECTED] or your "
+                      "vendor.\n", name);
+#ifdef CONFIG_PCI_DOMAINS
+               panic("To avoid data corruption io_map_base MUST be set with "
+                     "multiple PCI domains.");
+#endif
+       }
+
+       return (void __iomem *) (ctrl->io_map_base + port);
+}
+
+/*
+ * 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_pci(dev, start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       /* What? */
+       return NULL;
+}
+
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       iounmap(addr);
+}
+
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
dissimilarity index 86%
index f4ac5bb..d51d5cb 100644
--- a/arch/mips/lib/iomap.c
+++ b/arch/mips/lib/iomap.c
@@ -1,78 +1,227 @@
-/*
- *  iomap.c, Memory Mapped I/O routines for MIPS architecture.
- *
- *  This code is based on lib/iomap.c, by Linus Torvalds.
- *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <[EMAIL PROTECTED]>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-
-void __iomem *ioport_map(unsigned long port, unsigned int nr)
-{
-       unsigned long end;
-
-       end = port + nr - 1UL;
-       if (ioport_resource.start > port ||
-           ioport_resource.end < end || port > end)
-               return NULL;
-
-       return (void __iomem *)(mips_io_port_base + port);
-}
-
-void ioport_unmap(void __iomem *addr)
-{
-}
-EXPORT_SYMBOL(ioport_map);
-EXPORT_SYMBOL(ioport_unmap);
-
-void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
-{
-       unsigned long start, len, flags;
-
-       if (dev == NULL)
-               return NULL;
-
-       start = pci_resource_start(dev, bar);
-       len = pci_resource_len(dev, bar);
-       if (!start || !len)
-               return NULL;
-
-       if (maxlen != 0 && len > maxlen)
-               len = maxlen;
-
-       flags = pci_resource_flags(dev, bar);
-       if (flags & IORESOURCE_IO)
-               return ioport_map(start, len);
-       if (flags & IORESOURCE_MEM) {
-               if (flags & IORESOURCE_CACHEABLE)
-                       return ioremap_cachable(start, len);
-               return ioremap_nocache(start, len);
-       }
-
-       return NULL;
-}
-
-void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
-{
-       iounmap(addr);
-}
-EXPORT_SYMBOL(pci_iomap);
-EXPORT_SYMBOL(pci_iounmap);
+/*
+ * Implement the default iomap interfaces
+ *
+ * (C) Copyright 2004 Linus Torvalds
+ * (C) Copyright 2006 Ralf Baechle <[EMAIL PROTECTED]>
+ * (C) Copyright 2007 MIPS Technologies, Inc.
+ *     written by Ralf Baechle <[EMAIL PROTECTED]>
+ */
+#include <linux/pci.h>
+#include <linux/module.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.
+ */
+
+#define PIO_MASK       0x0ffffUL
+
+unsigned int ioread8(void __iomem *addr)
+{
+       return readb(addr);
+}
+
+EXPORT_SYMBOL(ioread8);
+
+unsigned int ioread16(void __iomem *addr)
+{
+       return readw(addr);
+}
+
+EXPORT_SYMBOL(ioread16);
+
+unsigned int ioread16be(void __iomem *addr)
+{
+       return be16_to_cpu(__raw_readw(addr));
+}
+
+EXPORT_SYMBOL(ioread16be);
+
+unsigned int ioread32(void __iomem *addr)
+{
+       return readl(addr);
+}
+
+EXPORT_SYMBOL(ioread32);
+
+unsigned int ioread32be(void __iomem *addr)
+{
+       return be32_to_cpu(__raw_readl(addr));
+}
+
+EXPORT_SYMBOL(ioread32be);
+
+void iowrite8(u8 val, void __iomem *addr)
+{
+       writeb(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite8);
+
+void iowrite16(u16 val, void __iomem *addr)
+{
+       writew(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite16);
+
+void iowrite16be(u16 val, void __iomem *addr)
+{
+       __raw_writew(cpu_to_be16(val), addr);
+}
+
+EXPORT_SYMBOL(iowrite16be);
+
+void iowrite32(u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite32);
+
+void iowrite32be(u32 val, void __iomem *addr)
+{
+       __raw_writel(cpu_to_be32(val), addr);
+}
+
+EXPORT_SYMBOL(iowrite32be);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+       while (--count >= 0) {
+               u8 data = __raw_readb(addr);
+               *dst = data;
+               dst++;
+       }
+}
+
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+       while (--count >= 0) {
+               u16 data = __raw_readw(addr);
+               *dst = data;
+               dst++;
+       }
+}
+
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+       while (--count >= 0) {
+               u32 data = __raw_readl(addr);
+               *dst = data;
+               dst++;
+       }
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writeb(*src, addr);
+               src++;
+       }
+}
+
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writew(*src, addr);
+               src++;
+       }
+}
+
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writel(*src, addr);
+               src++;
+       }
+}
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       mmio_insb(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread8_rep);
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       mmio_insw(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread16_rep);
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       mmio_insl(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       mmio_outsb(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite8_rep);
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       mmio_outsw(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite16_rep);
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       mmio_outsl(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite32_rep);
+
+/*
+ * Create a virtual mapping cookie for an IO port range
+ *
+ * This uses the same mapping are as the in/out family which has to be setup
+ * by the platform initialization code.
+ *
+ * Just to make matters somewhat more interesting on MIPS systems with
+ * multiple host bridge each will have it's own ioport address space.
+ */
+static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr)
+{
+       return (void __iomem *) (mips_io_port_base + port);
+}
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       if (port > PIO_MASK)
+               return NULL;
+
+       return ioport_map_legacy(port, nr);
+}
+
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+
+EXPORT_SYMBOL(ioport_unmap);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 5ace368..697a7e4 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -79,6 +79,14 @@ void __init register_pci_controller(struct pci_controller 
*hose)
 {
        *hose_tail = hose;
        hose_tail = &hose->next;
+
+       /*
+        * Do not panic here but later - this might hapen before console init.
+        */
+       if (!hose->io_map_base) {
+               printk(KERN_WARNING
+                      "registering PCI controller with io_map_base unset\n");
+       }
 }
 
 /* Most MIPS systems have straight-forward swizzling needs.  */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index b6a2eb8..92ec261 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -20,6 +20,7 @@
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm-generic/iomap.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/processor.h>
@@ -518,34 +519,6 @@ static inline void memcpy_toio(volatile void __iomem *dst, 
const void *src, int
 }
 
 /*
- * Memory Mapped I/O
- */
-#define ioread8(addr)          readb(addr)
-#define ioread16(addr)         readw(addr)
-#define ioread32(addr)         readl(addr)
-
-#define iowrite8(b,addr)       writeb(b,addr)
-#define iowrite16(w,addr)      writew(w,addr)
-#define iowrite32(l,addr)      writel(l,addr)
-
-#define ioread8_rep(a,b,c)     readsb(a,b,c)
-#define ioread16_rep(a,b,c)    readsw(a,b,c)
-#define ioread32_rep(a,b,c)    readsl(a,b,c)
-
-#define iowrite8_rep(a,b,c)    writesb(a,b,c)
-#define iowrite16_rep(a,b,c)   writesw(a,b,c)
-#define iowrite32_rep(a,b,c)   writesl(a,b,c)
-
-/* Create a virtual mapping cookie for an IO port range */
-extern void __iomem *ioport_map(unsigned long 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 *);
-
-/*
  * ISA space is 'always mapped' on currently supported MIPS systems, no need
  * to explicitly ioremap() it. The fact that the ISA IO space is mapped
  * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 7f0f120..3eea3ba 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -32,6 +32,7 @@ struct pci_controller {
        unsigned long mem_offset;
        struct resource *io_resource;
        unsigned long io_offset;
+       unsigned long io_map_base;
 
        unsigned int index;
        /* For compatibility with current (as of July 2003) pciutils
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to