[PATCH 2/2] pci/layerscape: Add LS2085A MSI support
Minghuan Lian
Minghuan.Lian at freescale.com
Wed Apr 15 02:49:24 PDT 2015
Freescale LS2085A uses GICv3 ITS to provide MSI functionality,
but it only supports 64 isolation context identifiers. So, all
the PCIe devices inserted to the same PCIe controller will share
the fixed ICID.
Signed-off-by: Minghuan Lian <Minghuan.Lian at freescale.com>
---
Depend on pci-layerscape-Add-LS2085A-PCIe-support.patch
drivers/pci/host/pci-layerscape.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index 15c5e47..1f317ca 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -30,20 +30,38 @@
/* PEX LUT registers */
#define PCIE_LUT_BASE 0x80000
+#define PCIE_LUT_PEXLCR 0x024 /* PEX LUT Control Register */
+#define PCIE_LUT_UDR(n) (0x800 + (n) * 8)
+#define PCIE_LUT_LDR(n) (0x804 + (n) * 8)
+#define PCIE_LUT_MASK_ALL 0xffff
+#define PCIE_LUT_DR_NUM 32
+#define PCIE_LUT_ENABLE (0x1 << 31)
#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug register */
#define PCIE_ATU_NUM 6
+#define PCIE_MSI_MAX_NUM 64
+#define PCIE_ICID_BASE 1
+
struct ls_pcie {
struct dw_pcie_port pp;
void __iomem *regs;
void __iomem *lut;
struct regmap *scfg;
int index;
+ int icid;
};
#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
+void arch_msi_share_devid_update(struct pci_dev *pdev, u32 *dev_id, u32 *nvesc)
+{
+ struct ls_pcie *pcie = to_ls_pcie(pdev->bus->sysdata);
+
+ *dev_id = pcie->icid;
+ *nvesc = PCIE_MSI_MAX_NUM;
+}
+
static int ls1_pcie_link_up(struct dw_pcie_port *pp)
{
struct ls_pcie *pcie = to_ls_pcie(pp);
@@ -136,6 +154,12 @@ static int ls2_pcie_host_init(struct dw_pcie_port *pp)
dw_pcie_dbi_write(pp, val, PCI_HEADER_TYPE & ~0x3);
dw_pcie_dbi_write(pp, 0, PCIE_DBI_RO_WR_EN);
+ /* Set LUT. All request ID will map to a static ICID */
+ iowrite32(pcie->icid, pcie->lut + PCIE_LUT_PEXLCR);
+ iowrite32(PCIE_LUT_MASK_ALL, pcie->lut + PCIE_LUT_UDR(0));
+ iowrite32(PCIE_LUT_ENABLE | pcie->icid,
+ pcie->lut + PCIE_LUT_LDR(0));
+
if (!ls2_pcie_link_up(pp))
dev_err(pp->dev, "phy link never came up\n");
@@ -159,6 +183,7 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
const struct of_device_id *match;
struct ls_pcie *pcie;
struct resource *res;
+ static int ls_pcie_num;
int ret;
match = of_match_device(ls_pcie_of_match, &pdev->dev);
@@ -177,6 +202,8 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
}
pcie->lut = pcie->regs + PCIE_LUT_BASE;
+ pcie->index = ls_pcie_num++;
+ pcie->icid = PCIE_ICID_BASE + pcie->index;
pcie->pp.dev = &pdev->dev;
pcie->pp.dbi = pcie->regs;
pcie->pp.dw_ops = (struct dw_host_ops *)match->data;
--
1.9.1
More information about the linux-arm-kernel
mailing list