aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-29 22:38:13 +0900
committerPaul Mundt <lethal@linux-sh.org>2010-01-29 22:38:13 +0900
commit320e68da59353fe6ad51b81f6865c4b674ad66ea (patch)
tree9fc7f0f07a6a656a6384736f17f7d52da9a9f79e
parentac8ab54a8e41a5ed0ee2161d45b6dc855490989f (diff)
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>
-rw-r--r--arch/sh/Kconfig4
-rw-r--r--arch/sh/drivers/pci/pci.c17
-rw-r--r--arch/sh/include/asm/pci.h13
3 files changed, 31 insertions, 3 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 352879c1b86..bae53831c06 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -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"
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 82e59bc6210..45a15cab01d 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -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);
}
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index f362d8a045e..d124a009889 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -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)
{