OSDN Git Service

sh: support PCI domains.
authorPaul Mundt <lethal@linux-sh.org>
Fri, 29 Jan 2010 13:38:13 +0000 (22:38 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 29 Jan 2010 13:38:13 +0000 (22:38 +0900)
Newer SH parts are now commonly shipping with multiple controllers, so
we wire up PCI domain support to deal with them. Shamelessly cloned from
the MIPS implementation.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/Kconfig
arch/sh/drivers/pci/pci.c
arch/sh/include/asm/pci.h

index 352879c..bae5383 100644 (file)
@@ -826,11 +826,15 @@ config MAPLE
 config PCI
        bool "PCI support"
        depends on SYS_SUPPORTS_PCI
+       select PCI_DOMAINS
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
          your box. If you have PCI, say Y, otherwise N.
 
+config PCI_DOMAINS
+       bool
+
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
index 82e59bc..45a15ca 100644 (file)
@@ -33,15 +33,22 @@ static int pci_initialized;
 static void __devinit pcibios_scanbus(struct pci_channel *hose)
 {
        static int next_busno;
+       static int need_domain_info;
        struct pci_bus *bus;
 
        bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+       hose->bus = bus;
+
+       need_domain_info = need_domain_info || hose->index;
+       hose->need_domain_info = need_domain_info;
        if (bus) {
                next_busno = bus->subordinate + 1;
                /* Don't allow 8-bit bus number overflow inside the hose -
                   reserve some space for bridges. */
-               if (next_busno > 224)
+               if (next_busno > 224) {
                        next_busno = 0;
+                       need_domain_info = 1;
+               }
 
                pci_bus_size_bridges(bus);
                pci_bus_assign_resources(bus);
@@ -307,9 +314,15 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
 {
        struct pci_channel *chan = dev->sysdata;
 
-       if (!chan->io_map_base)
+       if (unlikely(!chan->io_map_base)) {
                chan->io_map_base = generic_io_base;
 
+               if (pci_domains_supported)
+                       panic("To avoid data corruption io_map_base MUST be "
+                             "set with multiple PCI domains.");
+       }
+
+
        return (void __iomem *)(chan->io_map_base + port);
 }
 
index f362d8a..d124a00 100644 (file)
@@ -15,6 +15,7 @@
  */
 struct pci_channel {
        struct pci_channel      *next;
+       struct pci_bus          *bus;
 
        struct pci_ops          *pci_ops;
        struct resource         *io_resource;
@@ -24,8 +25,10 @@ struct pci_channel {
        unsigned long           mem_offset;
 
        unsigned long           reg_base;
-
        unsigned long           io_map_base;
+
+       unsigned int            index;
+       unsigned int            need_domain_info;
 };
 
 extern void register_pci_controller(struct pci_channel *hose);
@@ -108,6 +111,14 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev,
 extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
                                    struct pci_bus_region *region);
 
+#define pci_domain_nr(bus) ((struct pci_channel *)(bus)->sysdata)->index
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+       struct pci_channel *hose = bus->sysdata;
+       return hose->need_domain_info;
+}
+
 /* Chances are this interrupt is wired PC-style ...  */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {