summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/pci-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
-rw-r--r--arch/powerpc/kernel/pci-common.c66
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, &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();
}