Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Minghuan Lian and committed by
Kumar Gala
59c58c32 7844663a

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