summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorZhao Qiang <B45475@freescale.com>2013-10-12 13:46:33 +0800
committerYork Sun <yorksun@freescale.com>2013-10-16 16:15:17 -0700
commit287df01e6aef0464c5e5bcbd7e87aa4ff1f24f5a (patch)
tree638da6ca13c77d494a81603d18ea9c1f7feddc25 /drivers/pci/pci.c
parent787964b8118b47a50bda796a315068639977c884 (diff)
downloadtalos-obmc-uboot-287df01e6aef0464c5e5bcbd7e87aa4ff1f24f5a.tar.gz
talos-obmc-uboot-287df01e6aef0464c5e5bcbd7e87aa4ff1f24f5a.zip
PCIe:change the method to get the address of a requested capability in configuration space.
Previously, the address of a requested capability is define like that "#define PCI_DCR 0x78" But, the addresses of capabilities is different with regard to PCIe revs. So this method is not flexible. Now a function to get the address of a requested capability is added and used. It can get the address dynamically by capability ID. The step of this function: 1. Read Status register in PCIe configuration space to confirm that Capabilities List is valid. 2. Find the address of Capabilities Pointer Register. 3. Find the address of requested capability from the first capability. Signed-off-by: Zhao Qiang <B45475@freescale.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2c071589b4..ed113bf402 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -722,3 +722,68 @@ void pci_init(void)
/* now call board specific pci_init()... */
pci_init_board();
}
+
+/* Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.
+ * */
+int pci_hose_find_capability(struct pci_controller *hose, pci_dev_t dev,
+ int cap)
+{
+ int pos;
+ u8 hdr_type;
+
+ pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &hdr_type);
+
+ pos = pci_hose_find_cap_start(hose, dev, hdr_type & 0x7F);
+
+ if (pos)
+ pos = pci_find_cap(hose, dev, pos, cap);
+
+ return pos;
+}
+
+/* Find the header pointer to the Capabilities*/
+int pci_hose_find_cap_start(struct pci_controller *hose, pci_dev_t dev,
+ u8 hdr_type)
+{
+ u16 status;
+
+ pci_hose_read_config_word(hose, dev, PCI_STATUS, &status);
+
+ if (!(status & PCI_STATUS_CAP_LIST))
+ return 0;
+
+ switch (hdr_type) {
+ case PCI_HEADER_TYPE_NORMAL:
+ case PCI_HEADER_TYPE_BRIDGE:
+ return PCI_CAPABILITY_LIST;
+ case PCI_HEADER_TYPE_CARDBUS:
+ return PCI_CB_CAPABILITY_LIST;
+ default:
+ return 0;
+ }
+}
+
+int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos, int cap)
+{
+ int ttl = PCI_FIND_CAP_TTL;
+ u8 id;
+ u8 next_pos;
+
+ while (ttl--) {
+ pci_hose_read_config_byte(hose, dev, pos, &next_pos);
+ if (next_pos < CAP_START_POS)
+ break;
+ next_pos &= ~3;
+ pos = (int) next_pos;
+ pci_hose_read_config_byte(hose, dev,
+ pos + PCI_CAP_LIST_ID, &id);
+ if (id == 0xff)
+ break;
+ if (id == cap)
+ return pos;
+ pos += PCI_CAP_LIST_NEXT;
+ }
+ return 0;
+}
OpenPOWER on IntegriCloud