diff options
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 3d6f4d8b2e90..ffb93ae9379b 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -38,15 +38,15 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci; | |||
38 | 38 | ||
39 | static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) | 39 | static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) |
40 | { | 40 | { |
41 | u8 progif; | 41 | u8 hdr_type; |
42 | 42 | ||
43 | /* if we aren't a PCIe don't bother */ | 43 | /* if we aren't a PCIe don't bother */ |
44 | if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) | 44 | if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) |
45 | return; | 45 | return; |
46 | 46 | ||
47 | /* if we aren't in host mode don't bother */ | 47 | /* if we aren't in host mode don't bother */ |
48 | pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); | 48 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type); |
49 | if (progif & 0x1) | 49 | if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) |
50 | return; | 50 | return; |
51 | 51 | ||
52 | dev->class = PCI_CLASS_BRIDGE_PCI << 8; | 52 | dev->class = PCI_CLASS_BRIDGE_PCI << 8; |
@@ -427,7 +427,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) | |||
427 | struct pci_controller *hose; | 427 | struct pci_controller *hose; |
428 | struct resource rsrc; | 428 | struct resource rsrc; |
429 | const int *bus_range; | 429 | const int *bus_range; |
430 | u8 progif; | 430 | u8 hdr_type, progif; |
431 | 431 | ||
432 | if (!of_device_is_available(dev)) { | 432 | if (!of_device_is_available(dev)) { |
433 | pr_warning("%s: disabled\n", dev->full_name); | 433 | pr_warning("%s: disabled\n", dev->full_name); |
@@ -459,15 +459,17 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) | |||
459 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, | 459 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, |
460 | PPC_INDIRECT_TYPE_BIG_ENDIAN); | 460 | PPC_INDIRECT_TYPE_BIG_ENDIAN); |
461 | 461 | ||
462 | early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif); | 462 | if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { |
463 | if ((progif & 1) == 1) { | 463 | /* For PCIE read HEADER_TYPE to identify controler mode */ |
464 | /* unmap cfg_data & cfg_addr separately if not on same page */ | 464 | early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); |
465 | if (((unsigned long)hose->cfg_data & PAGE_MASK) != | 465 | if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) |
466 | ((unsigned long)hose->cfg_addr & PAGE_MASK)) | 466 | goto no_bridge; |
467 | iounmap(hose->cfg_data); | 467 | |
468 | iounmap(hose->cfg_addr); | 468 | } else { |
469 | pcibios_free_controller(hose); | 469 | /* For PCI read PROG to identify controller mode */ |
470 | return -ENODEV; | 470 | early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif); |
471 | if ((progif & 1) == 1) | ||
472 | goto no_bridge; | ||
471 | } | 473 | } |
472 | 474 | ||
473 | setup_pci_cmd(hose); | 475 | setup_pci_cmd(hose); |
@@ -496,6 +498,15 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) | |||
496 | setup_pci_atmu(hose, &rsrc); | 498 | setup_pci_atmu(hose, &rsrc); |
497 | 499 | ||
498 | return 0; | 500 | return 0; |
501 | |||
502 | no_bridge: | ||
503 | /* unmap cfg_data & cfg_addr separately if not on same page */ | ||
504 | if (((unsigned long)hose->cfg_data & PAGE_MASK) != | ||
505 | ((unsigned long)hose->cfg_addr & PAGE_MASK)) | ||
506 | iounmap(hose->cfg_data); | ||
507 | iounmap(hose->cfg_addr); | ||
508 | pcibios_free_controller(hose); | ||
509 | return -ENODEV; | ||
499 | } | 510 | } |
500 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ | 511 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ |
501 | 512 | ||