aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_pci.c
diff options
context:
space:
mode:
authorMinghuan Lian <Minghuan.Lian@freescale.com>2012-09-24 01:50:52 -0400
committerKumar Gala <galak@kernel.crashing.org>2012-09-27 08:31:58 -0400
commit59c58c324a81cfb08c490384a7c292b82609673a (patch)
treec4dfb067e4ed4db88d1f5fac7d319ba7e0f70feb /arch/powerpc/sysdev/fsl_pci.c
parent7844663a31e97930e3949430573452ac245bfdd5 (diff)
powerpc/fsl-pci: use 'Header Type' to identify PCIE mode
The original code uses 'Programming Interface' field to judge if PCIE is EP or RC mode, however, some latest silicons do not support this functionality. According to PCIE specification, 'Header Type' offset 0x0e is used to indicate header type, so change code to use 'Header Type' field to judge PCIE mode. Because FSL PCI controller does not support 'Header Type', patch still uses 'Programming Interface' to identify PCI mode. Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_pci.c')
-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