diff options
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 0f4181272311..4fee63cb53ff 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -38,6 +38,7 @@ #include <asm/eeh.h> static DEFINE_SPINLOCK(hose_spinlock); +LIST_HEAD(hose_list); /* XXX kill that some day ... */ static int global_phb_number; /* Global phb counter */ @@ -49,7 +50,7 @@ resource_size_t isa_mem_base; unsigned int ppc_pci_flags = 0; -static struct dma_mapping_ops *pci_dma_ops; +static struct dma_mapping_ops *pci_dma_ops = &dma_direct_ops; void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) { @@ -113,19 +114,24 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } +static resource_size_t pcibios_io_size(const struct pci_controller *hose) +{ +#ifdef CONFIG_PPC64 + return hose->pci_io_size; +#else + return hose->io_resource.end - hose->io_resource.start + 1; +#endif +} + int pcibios_vaddr_is_ioport(void __iomem *address) { int ret = 0; struct pci_controller *hose; - unsigned long size; + resource_size_t size; spin_lock(&hose_spinlock); list_for_each_entry(hose, &hose_list, list_node) { -#ifdef CONFIG_PPC64 - size = hose->pci_io_size; -#else - size = hose->io_resource.end - hose->io_resource.start + 1; -#endif + size = pcibios_io_size(hose); if (address >= hose->io_base_virt && address < (hose->io_base_virt + size)) { ret = 1; @@ -136,6 +142,29 @@ int pcibios_vaddr_is_ioport(void __iomem *address) return ret; } +unsigned long pci_address_to_pio(phys_addr_t address) +{ + struct pci_controller *hose; + resource_size_t size; + unsigned long ret = ~0; + + spin_lock(&hose_spinlock); + list_for_each_entry(hose, &hose_list, list_node) { + size = pcibios_io_size(hose); + if (address >= hose->io_base_phys && + address < (hose->io_base_phys + size)) { + unsigned long base = + (unsigned long)hose->io_base_virt - _IO_BASE; + ret = base + (address - hose->io_base_phys); + break; + } + } + spin_unlock(&hose_spinlock); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_address_to_pio); + /* * Return the domain number for this bus. */ @@ -1337,12 +1366,17 @@ static void __init pcibios_allocate_resources(int pass) for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); - for (idx = 0; idx < 6; idx++) { + for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { r = &dev->resource[idx]; if (r->parent) /* Already allocated */ continue; if (!r->flags || (r->flags & IORESOURCE_UNSET)) continue; /* Not assigned at all */ + /* We only allocate ROMs on pass 1 just in case they + * have been screwed up by firmware + */ + if (idx == PCI_ROM_RESOURCE ) + disabled = 1; if (r->flags & IORESOURCE_IO) disabled = !(command & PCI_COMMAND_IO); else @@ -1353,17 +1387,19 @@ static void __init pcibios_allocate_resources(int pass) if (pass) continue; r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & IORESOURCE_ROM_ENABLE) { + if (r->flags) { /* Turn the ROM off, leave the resource region, * but keep it unregistered. */ u32 reg; - pr_debug("PCI: Switching off ROM of %s\n", - pci_name(dev)); - r->flags &= ~IORESOURCE_ROM_ENABLE; pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, - reg & ~PCI_ROM_ADDRESS_ENABLE); + if (reg & PCI_ROM_ADDRESS_ENABLE) { + pr_debug("PCI: Switching off ROM of %s\n", + pci_name(dev)); + r->flags &= ~IORESOURCE_ROM_ENABLE; + pci_write_config_dword(dev, dev->rom_base_reg, + reg & ~PCI_ROM_ADDRESS_ENABLE); + } } } } @@ -1453,7 +1489,7 @@ void __init pcibios_resource_survey(void) * we proceed to assigning things that were left unassigned */ if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { - pr_debug("PCI: Assigning unassigned resouces...\n"); + pr_debug("PCI: Assigning unassigned resources...\n"); pci_assign_unassigned_resources(); } |