aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinath Mannam <srinath.mannam@broadcom.com>2019-02-28 23:52:15 -0500
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2019-04-03 06:52:38 -0400
commit73b9e4d3309c540d9c855322e6ccedfa8ef698fc (patch)
tree64f6ef3084645e7f79904df787f1597068f13b7c
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
PCI: iproc: Add CRS check in config read
The IPROC PCIe host controller implementation returns CFG_RETRY_STATUS (0xffff0001) data when it receives a CRS completion, regardless of the address of the read or the CRS Software Visibility Enable bit. As a workaround the driver retries in software any read that returns CFG_RETRY_STATUS even though, for reads of registers that are not Vendor ID, the register value can correspond to CFG_RETRY_STATUS; this situation would cause a timeout and failure of reading a valid register value. IPROC PCIe host controller PAXB v2 has a register to show config read status flags like SC, UR, CRS and CA. Using this status flag, an extra check is added to confirm the CRS using status flags before reissuing a config read, fixing the issue. Signed-off-by: Srinath Mannam <srinath.mannam@broadcom.com> [lorenzo.pieralisi@arm.com: rewrote commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Acked-by: Scott Branden <scott.branden@broadcom.com>
-rw-r--r--drivers/pci/controller/pcie-iproc.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index c20fd6bd68fd..b88225577a8f 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -60,6 +60,10 @@
60#define APB_ERR_EN_SHIFT 0 60#define APB_ERR_EN_SHIFT 0
61#define APB_ERR_EN BIT(APB_ERR_EN_SHIFT) 61#define APB_ERR_EN BIT(APB_ERR_EN_SHIFT)
62 62
63#define CFG_RD_SUCCESS 0
64#define CFG_RD_UR 1
65#define CFG_RD_CRS 2
66#define CFG_RD_CA 3
63#define CFG_RETRY_STATUS 0xffff0001 67#define CFG_RETRY_STATUS 0xffff0001
64#define CFG_RETRY_STATUS_TIMEOUT_US 500000 /* 500 milliseconds */ 68#define CFG_RETRY_STATUS_TIMEOUT_US 500000 /* 500 milliseconds */
65 69
@@ -289,6 +293,9 @@ enum iproc_pcie_reg {
289 IPROC_PCIE_IARR4, 293 IPROC_PCIE_IARR4,
290 IPROC_PCIE_IMAP4, 294 IPROC_PCIE_IMAP4,
291 295
296 /* config read status */
297 IPROC_PCIE_CFG_RD_STATUS,
298
292 /* link status */ 299 /* link status */
293 IPROC_PCIE_LINK_STATUS, 300 IPROC_PCIE_LINK_STATUS,
294 301
@@ -350,6 +357,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = {
350 [IPROC_PCIE_IMAP3] = 0xe08, 357 [IPROC_PCIE_IMAP3] = 0xe08,
351 [IPROC_PCIE_IARR4] = 0xe68, 358 [IPROC_PCIE_IARR4] = 0xe68,
352 [IPROC_PCIE_IMAP4] = 0xe70, 359 [IPROC_PCIE_IMAP4] = 0xe70,
360 [IPROC_PCIE_CFG_RD_STATUS] = 0xee0,
353 [IPROC_PCIE_LINK_STATUS] = 0xf0c, 361 [IPROC_PCIE_LINK_STATUS] = 0xf0c,
354 [IPROC_PCIE_APB_ERR_EN] = 0xf40, 362 [IPROC_PCIE_APB_ERR_EN] = 0xf40,
355}; 363};
@@ -474,10 +482,12 @@ static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie,
474 return (pcie->base + offset); 482 return (pcie->base + offset);
475} 483}
476 484
477static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p) 485static unsigned int iproc_pcie_cfg_retry(struct iproc_pcie *pcie,
486 void __iomem *cfg_data_p)
478{ 487{
479 int timeout = CFG_RETRY_STATUS_TIMEOUT_US; 488 int timeout = CFG_RETRY_STATUS_TIMEOUT_US;
480 unsigned int data; 489 unsigned int data;
490 u32 status;
481 491
482 /* 492 /*
483 * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only 493 * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only
@@ -498,6 +508,15 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
498 */ 508 */
499 data = readl(cfg_data_p); 509 data = readl(cfg_data_p);
500 while (data == CFG_RETRY_STATUS && timeout--) { 510 while (data == CFG_RETRY_STATUS && timeout--) {
511 /*
512 * CRS state is set in CFG_RD status register
513 * This will handle the case where CFG_RETRY_STATUS is
514 * valid config data.
515 */
516 status = iproc_pcie_read_reg(pcie, IPROC_PCIE_CFG_RD_STATUS);
517 if (status != CFG_RD_CRS)
518 return data;
519
501 udelay(1); 520 udelay(1);
502 data = readl(cfg_data_p); 521 data = readl(cfg_data_p);
503 } 522 }
@@ -576,7 +595,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
576 if (!cfg_data_p) 595 if (!cfg_data_p)
577 return PCIBIOS_DEVICE_NOT_FOUND; 596 return PCIBIOS_DEVICE_NOT_FOUND;
578 597
579 data = iproc_pcie_cfg_retry(cfg_data_p); 598 data = iproc_pcie_cfg_retry(pcie, cfg_data_p);
580 599
581 *val = data; 600 *val = data;
582 if (size <= 2) 601 if (size <= 2)