Prechádzať zdrojové kódy

sh: support PCI domains.

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>
Paul Mundt 15 rokov pred
rodič
commit
320e68da59
3 zmenil súbory, kde vykonal 31 pridanie a 3 odobranie
  1. 4 0
      arch/sh/Kconfig
  2. 15 2
      arch/sh/drivers/pci/pci.c
  3. 12 1
      arch/sh/include/asm/pci.h

+ 4 - 0
arch/sh/Kconfig

@@ -826,11 +826,15 @@ config MAPLE
 config PCI
 config PCI
 	bool "PCI support"
 	bool "PCI support"
 	depends on SYS_SUPPORTS_PCI
 	depends on SYS_SUPPORTS_PCI
+	select PCI_DOMAINS
 	help
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  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
 	  bus system, i.e. the way the CPU talks to the other stuff inside
 	  your box. If you have PCI, say Y, otherwise N.
 	  your box. If you have PCI, say Y, otherwise N.
 
 
+config PCI_DOMAINS
+	bool
+
 source "drivers/pci/pcie/Kconfig"
 source "drivers/pci/pcie/Kconfig"
 
 
 source "drivers/pci/Kconfig"
 source "drivers/pci/Kconfig"

+ 15 - 2
arch/sh/drivers/pci/pci.c

@@ -33,15 +33,22 @@ static int pci_initialized;
 static void __devinit pcibios_scanbus(struct pci_channel *hose)
 static void __devinit pcibios_scanbus(struct pci_channel *hose)
 {
 {
 	static int next_busno;
 	static int next_busno;
+	static int need_domain_info;
 	struct pci_bus *bus;
 	struct pci_bus *bus;
 
 
 	bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
 	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) {
 	if (bus) {
 		next_busno = bus->subordinate + 1;
 		next_busno = bus->subordinate + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
 		   reserve some space for bridges. */
-		if (next_busno > 224)
+		if (next_busno > 224) {
 			next_busno = 0;
 			next_busno = 0;
+			need_domain_info = 1;
+		}
 
 
 		pci_bus_size_bridges(bus);
 		pci_bus_size_bridges(bus);
 		pci_bus_assign_resources(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;
 	struct pci_channel *chan = dev->sysdata;
 
 
-	if (!chan->io_map_base)
+	if (unlikely(!chan->io_map_base)) {
 		chan->io_map_base = generic_io_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);
 	return (void __iomem *)(chan->io_map_base + port);
 }
 }
 
 

+ 12 - 1
arch/sh/include/asm/pci.h

@@ -15,6 +15,7 @@
  */
  */
 struct pci_channel {
 struct pci_channel {
 	struct pci_channel	*next;
 	struct pci_channel	*next;
+	struct pci_bus		*bus;
 
 
 	struct pci_ops		*pci_ops;
 	struct pci_ops		*pci_ops;
 	struct resource		*io_resource;
 	struct resource		*io_resource;
@@ -24,8 +25,10 @@ struct pci_channel {
 	unsigned long		mem_offset;
 	unsigned long		mem_offset;
 
 
 	unsigned long		reg_base;
 	unsigned long		reg_base;
-
 	unsigned long		io_map_base;
 	unsigned long		io_map_base;
+
+	unsigned int		index;
+	unsigned int		need_domain_info;
 };
 };
 
 
 extern void register_pci_controller(struct pci_channel *hose);
 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,
 extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 				    struct pci_bus_region *region);
 				    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 ...  */
 /* Chances are this interrupt is wired PC-style ...  */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
 {