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 | ||
