Commit 1e5748c2 authored by Ray Jui's avatar Ray Jui Committed by Lorenzo Pieralisi

PCI: iproc: Disable MSI parsing in certain PAXC blocks

The internal MSI parsing logic in certain revisions of PAXC root
complexes does not work properly and can cause corruptions on the
writes transactions so they need to be disabled.
Signed-off-by: default avatarRay Jui <ray.jui@broadcom.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: default avatarScott Branden <scott.branden@broadcom.com>
Reviewed-by: default avatarOza Pawandeep <poza@codeaurora.org>
parent 3bc70825
...@@ -1197,10 +1197,22 @@ static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) ...@@ -1197,10 +1197,22 @@ static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
return ret; return ret;
} }
static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr,
bool enable)
{ {
u32 val; u32 val;
if (!enable) {
/*
* Disable PAXC MSI steering. All write transfers will be
* treated as non-MSI transfers
*/
val = iproc_pcie_read_reg(pcie, IPROC_PCIE_MSI_EN_CFG);
val &= ~MSI_ENABLE_CFG;
iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_EN_CFG, val);
return;
}
/* /*
* Program bits [43:13] of address of GITS_TRANSLATER register into * Program bits [43:13] of address of GITS_TRANSLATER register into
* bits [30:0] of the MSI base address register. In fact, in all iProc * bits [30:0] of the MSI base address register. In fact, in all iProc
...@@ -1254,7 +1266,7 @@ static int iproc_pcie_msi_steer(struct iproc_pcie *pcie, ...@@ -1254,7 +1266,7 @@ static int iproc_pcie_msi_steer(struct iproc_pcie *pcie,
return ret; return ret;
break; break;
case IPROC_PCIE_PAXC_V2: case IPROC_PCIE_PAXC_V2:
iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr); iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr, true);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -1480,6 +1492,24 @@ int iproc_pcie_remove(struct iproc_pcie *pcie) ...@@ -1480,6 +1492,24 @@ int iproc_pcie_remove(struct iproc_pcie *pcie)
} }
EXPORT_SYMBOL(iproc_pcie_remove); EXPORT_SYMBOL(iproc_pcie_remove);
/*
* The MSI parsing logic in certain revisions of Broadcom PAXC based root
* complex does not work and needs to be disabled
*/
static void quirk_paxc_disable_msi_parsing(struct pci_dev *pdev)
{
struct iproc_pcie *pcie = iproc_data(pdev->bus);
if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
iproc_pcie_paxc_v2_msi_steer(pcie, 0, false);
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0,
quirk_paxc_disable_msi_parsing);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd802,
quirk_paxc_disable_msi_parsing);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804,
quirk_paxc_disable_msi_parsing);
MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>"); MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver"); MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment