aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRay Jui <ray.jui@broadcom.com>2018-06-11 20:21:04 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-07-13 06:43:49 -0400
commit3bc70825e4361eaedffeb4e85e1b2774547e66a0 (patch)
tree4ff1aa99fe80012477495427e5bd1568859edb02
parentb95e2cd021938d2c3455fd2fce69b4845de0b85f (diff)
PCI: iproc: Fix up corrupted PAXC root complex config registers
On certain versions of Broadcom PAXC based root complexes, certain regions of the configuration space are corrupted. As a result, it prevents the Linux PCIe stack from traversing the linked list of the capability registers completely and therefore the root complex is not advertised as "PCIe capable". This prevents the correct PCIe RID from being parsed in the kernel PCIe stack. A correct RID is required for mapping to a stream ID from the SMMU or the device ID from the GICv3 ITS. This patch fixes up the issue by manually populating the related PCIe capabilities. Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
-rw-r--r--drivers/pci/controller/pcie-iproc.c65
-rw-r--r--drivers/pci/controller/pcie-iproc.h3
2 files changed, 62 insertions, 6 deletions
diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 3c76c5fa4f32..680f6b170845 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -85,6 +85,8 @@
85#define IMAP_VALID_SHIFT 0 85#define IMAP_VALID_SHIFT 0
86#define IMAP_VALID BIT(IMAP_VALID_SHIFT) 86#define IMAP_VALID BIT(IMAP_VALID_SHIFT)
87 87
88#define IPROC_PCI_PM_CAP 0x48
89#define IPROC_PCI_PM_CAP_MASK 0xffff
88#define IPROC_PCI_EXP_CAP 0xac 90#define IPROC_PCI_EXP_CAP 0xac
89 91
90#define IPROC_PCIE_REG_INVALID 0xffff 92#define IPROC_PCIE_REG_INVALID 0xffff
@@ -375,6 +377,17 @@ static const u16 iproc_pcie_reg_paxc_v2[] = {
375 [IPROC_PCIE_CFG_DATA] = 0x1fc, 377 [IPROC_PCIE_CFG_DATA] = 0x1fc,
376}; 378};
377 379
380/*
381 * List of device IDs of controllers that have corrupted capability list that
382 * require SW fixup
383 */
384static const u16 iproc_pcie_corrupt_cap_did[] = {
385 0x16cd,
386 0x16f0,
387 0xd802,
388 0xd804
389};
390
378static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) 391static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
379{ 392{
380 struct iproc_pcie *pcie = bus->sysdata; 393 struct iproc_pcie *pcie = bus->sysdata;
@@ -495,6 +508,49 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
495 return data; 508 return data;
496} 509}
497 510
511static void iproc_pcie_fix_cap(struct iproc_pcie *pcie, int where, u32 *val)
512{
513 u32 i, dev_id;
514
515 switch (where & ~0x3) {
516 case PCI_VENDOR_ID:
517 dev_id = *val >> 16;
518
519 /*
520 * Activate fixup for those controllers that have corrupted
521 * capability list registers
522 */
523 for (i = 0; i < ARRAY_SIZE(iproc_pcie_corrupt_cap_did); i++)
524 if (dev_id == iproc_pcie_corrupt_cap_did[i])
525 pcie->fix_paxc_cap = true;
526 break;
527
528 case IPROC_PCI_PM_CAP:
529 if (pcie->fix_paxc_cap) {
530 /* advertise PM, force next capability to PCIe */
531 *val &= ~IPROC_PCI_PM_CAP_MASK;
532 *val |= IPROC_PCI_EXP_CAP << 8 | PCI_CAP_ID_PM;
533 }
534 break;
535
536 case IPROC_PCI_EXP_CAP:
537 if (pcie->fix_paxc_cap) {
538 /* advertise root port, version 2, terminate here */
539 *val = (PCI_EXP_TYPE_ROOT_PORT << 4 | 2) << 16 |
540 PCI_CAP_ID_EXP;
541 }
542 break;
543
544 case IPROC_PCI_EXP_CAP + PCI_EXP_RTCTL:
545 /* Don't advertise CRS SV support */
546 *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
547 break;
548
549 default:
550 break;
551 }
552}
553
498static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn, 554static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
499 int where, int size, u32 *val) 555 int where, int size, u32 *val)
500{ 556{
@@ -509,13 +565,10 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
509 /* root complex access */ 565 /* root complex access */
510 if (busno == 0) { 566 if (busno == 0) {
511 ret = pci_generic_config_read32(bus, devfn, where, size, val); 567 ret = pci_generic_config_read32(bus, devfn, where, size, val);
512 if (ret != PCIBIOS_SUCCESSFUL) 568 if (ret == PCIBIOS_SUCCESSFUL)
513 return ret; 569 iproc_pcie_fix_cap(pcie, where, val);
514 570
515 /* Don't advertise CRS SV support */ 571 return ret;
516 if ((where & ~0x3) == IPROC_PCI_EXP_CAP + PCI_EXP_RTCTL)
517 *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
518 return PCIBIOS_SUCCESSFUL;
519 } 572 }
520 573
521 cfg_data_p = iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where); 574 cfg_data_p = iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where);
diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h
index 814b600b383a..9d5cfeea3046 100644
--- a/drivers/pci/controller/pcie-iproc.h
+++ b/drivers/pci/controller/pcie-iproc.h
@@ -60,6 +60,8 @@ struct iproc_msi;
60 * @ep_is_internal: indicates an internal emulated endpoint device is connected 60 * @ep_is_internal: indicates an internal emulated endpoint device is connected
61 * @has_apb_err_disable: indicates the controller can be configured to prevent 61 * @has_apb_err_disable: indicates the controller can be configured to prevent
62 * unsupported request from being forwarded as an APB bus error 62 * unsupported request from being forwarded as an APB bus error
63 * @fix_paxc_cap: indicates the controller has corrupted capability list in its
64 * config space registers and requires SW based fixup
63 * 65 *
64 * @need_ob_cfg: indicates SW needs to configure the outbound mapping window 66 * @need_ob_cfg: indicates SW needs to configure the outbound mapping window
65 * @ob: outbound mapping related parameters 67 * @ob: outbound mapping related parameters
@@ -85,6 +87,7 @@ struct iproc_pcie {
85 int (*map_irq)(const struct pci_dev *, u8, u8); 87 int (*map_irq)(const struct pci_dev *, u8, u8);
86 bool ep_is_internal; 88 bool ep_is_internal;
87 bool has_apb_err_disable; 89 bool has_apb_err_disable;
90 bool fix_paxc_cap;
88 91
89 bool need_ob_cfg; 92 bool need_ob_cfg;
90 struct iproc_pcie_ob ob; 93 struct iproc_pcie_ob ob;