RE: [PATCHv3 2/3] ARMv8: layerscape: add the pcie ep function support
From: "M.h. Lian" <minghuan.lian@nxp.com>
Date: 2017-11-10 03:30:35
Also in:
linux-arm-kernel, linux-devicetree, linux-pci, lkml
-----Original Message----- From: Bao Xiaowei [mailto:xiaowei.bao@nxp.com] Sent: Friday, November 10, 2017 10:49 AM To: robh+dt@kernel.org; mark.rutland@arm.com; catalin.marinas@arm.com; will.deacon@arm.com; bhelgaas@google.com; shawnguo@kernel.org; Madalin-cristian Bucur [off-list ref]; Sumit Garg [off-list ref]; Y.b. Lu [off-list ref]; hongtao.jia@nxp.com; Andy Tang [off-list ref]; Leo Li [off-list ref]; kishon@ti.com; jingoohan1@gmail.com; pbrobinson@gmail.com; songxiaowei@hisilicon.com; devicetree@vger.kernel.org; linux-arm- kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux- pci@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Z.q. Hou [off-list ref]; Mingkai Hu [off-list ref]; M.h. Lian [off-list ref] Cc: Xiaowei Bao <redacted> Subject: [PATCHv3 2/3] ARMv8: layerscape: add the pcie ep function suppor=
t
quoted hunk ↗ jump to hunk
=20 Add the pcie controller ep function support of layerscape base on pcie ep framework. =20 Signed-off-by: Bao Xiaowei <redacted> --- v2: - fix the ioremap function used but no ioumap issue - optimize the code structure - add code comments v3: - fix the msi outband window request failed issue =20 drivers/pci/dwc/pci-layerscape.c | 124 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 6 deletions(-) =20diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layer=
scape.c
quoted hunk ↗ jump to hunk
index 87fa486bee2c..d787375528eb 100644--- a/drivers/pci/dwc/pci-layerscape.c +++ b/drivers/pci/dwc/pci-layerscape.c@@ -34,7 +34,12 @@ /* PEX Internal Configuration Registers */ #define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1*/ =20 +#define PCIE_DBI2_BASE 0x1000 /* DBI2 base address*/ +#define PCIE_MSI_MSG_DATA_OFF 0x5c /* MSI Data register address*/ +#define PCIE_MSI_OB_SIZE 4096 +#define PCIE_MSI_ADDR_OFFSET (1024 * 1024) #define PCIE_IATU_NUM 6 +#define PCIE_EP_ADDR_SPACE_SIZE 0x100000000 =20 struct ls_pcie_drvdata { u32 lut_offset;@@ -44,12 +49,20 @@ struct ls_pcie_drvdata { const struct dw_pcie_ops *dw_pcie_ops; };=20 +struct ls_pcie_ep { + dma_addr_t msi_phys_addr; + void __iomem *msi_virt_addr; + u64 msi_msg_addr; + u16 msi_msg_data; +}; + struct ls_pcie { struct dw_pcie *pci; void __iomem *lut; struct regmap *scfg; const struct ls_pcie_drvdata *drvdata; int index; + struct ls_pcie_ep *pcie_ep; }; =20 #define to_ls_pcie(x) dev_get_drvdata((x)->dev)@@ -263,6 +276,100 @@ static const struct of_device_id ls_pcie_of_match[]=
=3D
{
{ },
};
=20
+static void ls_pcie_raise_msi_irq(struct ls_pcie_ep *pcie_ep) {
+ iowrite32(pcie_ep->msi_msg_data, pcie_ep->msi_virt_addr); }
+
+static int ls_pcie_raise_irq(struct dw_pcie_ep *ep,
+ enum pci_epc_irq_type type, u8 interrupt_num) {
+ struct dw_pcie *pci =3D to_dw_pcie_from_ep(ep);
+ struct ls_pcie *pcie =3D to_ls_pcie(pci);
+ struct ls_pcie_ep *pcie_ep =3D pcie->pcie_ep;
+ u32 free_win;
+
+ /* get the msi message address and msi message data */
+ pcie_ep->msi_msg_addr =3D ioread32(pci->dbi_base +
MSI_MESSAGE_ADDR_L32) |
+ (((u64)ioread32(pci->dbi_base + MSI_MESSAGE_ADDR_U32)) <<
32);
+ pcie_ep->msi_msg_data =3D ioread16(pci->dbi_base +
+PCIE_MSI_MSG_DATA_OFF);
+
+ /* request and config the outband window for msi */
+ free_win =3D find_first_zero_bit(&ep->ob_window_map,
+ sizeof(ep->ob_window_map));
+ if (free_win >=3D ep->num_ob_windows) {
+ dev_err(pci->dev, "no free outbound window\n");
+ return -ENOMEM;
+ }
+
+ dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM,
+ pcie_ep->msi_phys_addr,
+ pcie_ep->msi_msg_addr,
+ PCIE_MSI_OB_SIZE);
+
+ set_bit(free_win, &ep->ob_window_map);
+
+ /* generate the msi interrupt */
+ ls_pcie_raise_msi_irq(pcie_ep);
+
+ /* release the outband window of msi */
+ dw_pcie_disable_atu(pci, free_win, DW_PCIE_REGION_OUTBOUND);
+ clear_bit(free_win, &ep->ob_window_map);
+
+ return 0;
+}
+
+static struct dw_pcie_ep_ops pcie_ep_ops =3D {
+ .raise_irq =3D ls_pcie_raise_irq,
+};
+
+static int __init ls_add_pcie_ep(struct ls_pcie *pcie,
+ struct platform_device *pdev)
+{
+ struct dw_pcie *pci =3D pcie->pci;
+ struct device *dev =3D pci->dev;
+ struct dw_pcie_ep *ep;
+ struct ls_pcie_ep *pcie_ep;
+ struct resource *cfg_res;
+ int ret;
+
+ ep =3D &pci->ep;
+ ep->ops =3D &pcie_ep_ops;
+
+ pcie_ep =3D devm_kzalloc(dev, sizeof(*pcie_ep), GFP_KERNEL);
+ if (!pcie_ep)
+ return -ENOMEM;
+
+ pcie->pcie_ep =3D pcie_ep;
+
+ cfg_res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM,
"config");
+ if (cfg_res) {
+ ep->phys_base =3D cfg_res->start;
+ ep->addr_size =3D PCIE_EP_ADDR_SPACE_SIZE;
+ } else {
+ dev_err(dev, "missing *config* space\n");
+ return -ENODEV;
+ }
+
+ pcie_ep->msi_phys_addr =3D ep->phys_base + PCIE_MSI_ADDR_OFFSET;
+
+ pcie_ep->msi_virt_addr =3D ioremap(pcie_ep->msi_phys_addr,
+ PCIE_MSI_OB_SIZE);
+ if (!pcie_ep->msi_virt_addr) {
+ dev_err(dev, "failed to map MSI outbound region\n");
+ return -ENOMEM;
+ }
+
+ ret =3D dw_pcie_ep_init(ep);
+ if (ret) {
+ dev_err(dev, "failed to initialize endpoint\n");
+ return ret;
+ }
+
+ return 0;
+[Minghuan Lian] Remove unnecessary blank line.
quoted hunk ↗ jump to hunk
+} + static int __init ls_add_pcie_port(struct ls_pcie *pcie) { struct dw_pcie *pci =3D pcie->pci;@@ -309,16 +416,21 @@ static int __init ls_pcie_probe(struct platform_dev=
ice
*pdev)
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
=20
- pcie->lut =3D pci->dbi_base + pcie->drvdata->lut_offset;
+ pci->dbi_base2 =3D pci->dbi_base + PCIE_DBI2_BASE;
=20
- if (!ls_pcie_is_bridge(pcie))
- return -ENODEV;
+ pcie->lut =3D pci->dbi_base + pcie->drvdata->lut_offset;
=20
platform_set_drvdata(pdev, pcie);
=20
- ret =3D ls_add_pcie_port(pcie);
- if (ret < 0)
- return ret;
+ if (!ls_pcie_is_bridge(pcie)) {
+ ret =3D ls_add_pcie_ep(pcie, pdev);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret =3D ls_add_pcie_port(pcie);
+ if (ret < 0)
+ return ret;
+ }
=20
return 0;We can clean code like this: if (!ls_pcie_is_bridge(pcie))=20 ret =3D ls_add_pcie_ep(pcie, pdev); else=20 ret =3D ls_add_pcie_port(pcie); return ret;
} -- 2.14.1