diff mbox

[2/2] pci/layerscape: Add LS2085A MSI support

Message ID 1429091364-31939-3-git-send-email-Minghuan.Lian@freescale.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Minghuan Lian April 15, 2015, 9:49 a.m. UTC
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@freescale.com>
---
Depend on pci-layerscape-Add-LS2085A-PCIe-support.patch

 drivers/pci/host/pci-layerscape.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
diff mbox

Patch

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;