aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c37
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
39static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) 39static 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
502no_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