18d7e33d6SKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0 28d7e33d6SKunihiko Hayashi /* 38d7e33d6SKunihiko Hayashi * PCIe endpoint controller driver for UniPhier SoCs 48d7e33d6SKunihiko Hayashi * Copyright 2018 Socionext Inc. 58d7e33d6SKunihiko Hayashi * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 68d7e33d6SKunihiko Hayashi */ 78d7e33d6SKunihiko Hayashi 88d7e33d6SKunihiko Hayashi #include <linux/bitops.h> 98d7e33d6SKunihiko Hayashi #include <linux/bitfield.h> 108d7e33d6SKunihiko Hayashi #include <linux/clk.h> 118d7e33d6SKunihiko Hayashi #include <linux/delay.h> 128d7e33d6SKunihiko Hayashi #include <linux/init.h> 138d7e33d6SKunihiko Hayashi #include <linux/of_device.h> 148d7e33d6SKunihiko Hayashi #include <linux/pci.h> 158d7e33d6SKunihiko Hayashi #include <linux/phy/phy.h> 168d7e33d6SKunihiko Hayashi #include <linux/platform_device.h> 178d7e33d6SKunihiko Hayashi #include <linux/reset.h> 188d7e33d6SKunihiko Hayashi 198d7e33d6SKunihiko Hayashi #include "pcie-designware.h" 208d7e33d6SKunihiko Hayashi 218d7e33d6SKunihiko Hayashi /* Link Glue registers */ 228d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL0 0x0010 238d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_AXI_REG BIT(3) 248d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_AXI_SLAVE BIT(2) 258d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_AXI_MASTER BIT(1) 268d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_PIPE3 BIT(0) 278d7e33d6SKunihiko Hayashi 288d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL1 0x0020 298d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_PERST BIT(0) 308d7e33d6SKunihiko Hayashi 318d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL2 0x0024 328d7e33d6SKunihiko Hayashi #define PCL_RSTCTRL_PHY_RESET BIT(0) 338d7e33d6SKunihiko Hayashi 348d7e33d6SKunihiko Hayashi #define PCL_MODE 0x8000 358d7e33d6SKunihiko Hayashi #define PCL_MODE_REGEN BIT(8) 368d7e33d6SKunihiko Hayashi #define PCL_MODE_REGVAL BIT(0) 378d7e33d6SKunihiko Hayashi 388d7e33d6SKunihiko Hayashi #define PCL_APP_CLK_CTRL 0x8004 398d7e33d6SKunihiko Hayashi #define PCL_APP_CLK_REQ BIT(0) 408d7e33d6SKunihiko Hayashi 418d7e33d6SKunihiko Hayashi #define PCL_APP_READY_CTRL 0x8008 428d7e33d6SKunihiko Hayashi #define PCL_APP_LTSSM_ENABLE BIT(0) 438d7e33d6SKunihiko Hayashi 448d7e33d6SKunihiko Hayashi #define PCL_APP_MSI0 0x8040 458d7e33d6SKunihiko Hayashi #define PCL_APP_VEN_MSI_TC_MASK GENMASK(10, 8) 468d7e33d6SKunihiko Hayashi #define PCL_APP_VEN_MSI_VECTOR_MASK GENMASK(4, 0) 478d7e33d6SKunihiko Hayashi 488d7e33d6SKunihiko Hayashi #define PCL_APP_MSI1 0x8044 498d7e33d6SKunihiko Hayashi #define PCL_APP_MSI_REQ BIT(0) 508d7e33d6SKunihiko Hayashi 518d7e33d6SKunihiko Hayashi #define PCL_APP_INTX 0x8074 528d7e33d6SKunihiko Hayashi #define PCL_APP_INTX_SYS_INT BIT(0) 538d7e33d6SKunihiko Hayashi 548d7e33d6SKunihiko Hayashi /* assertion time of INTx in usec */ 558d7e33d6SKunihiko Hayashi #define PCL_INTX_WIDTH_USEC 30 568d7e33d6SKunihiko Hayashi 578d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv { 588d7e33d6SKunihiko Hayashi void __iomem *base; 598d7e33d6SKunihiko Hayashi struct dw_pcie pci; 608d7e33d6SKunihiko Hayashi struct clk *clk, *clk_gio; 618d7e33d6SKunihiko Hayashi struct reset_control *rst, *rst_gio; 628d7e33d6SKunihiko Hayashi struct phy *phy; 638d7e33d6SKunihiko Hayashi const struct pci_epc_features *features; 648d7e33d6SKunihiko Hayashi }; 658d7e33d6SKunihiko Hayashi 668d7e33d6SKunihiko Hayashi #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev) 678d7e33d6SKunihiko Hayashi 688d7e33d6SKunihiko Hayashi static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_ep_priv *priv, 698d7e33d6SKunihiko Hayashi bool enable) 708d7e33d6SKunihiko Hayashi { 718d7e33d6SKunihiko Hayashi u32 val; 728d7e33d6SKunihiko Hayashi 738d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_READY_CTRL); 748d7e33d6SKunihiko Hayashi if (enable) 758d7e33d6SKunihiko Hayashi val |= PCL_APP_LTSSM_ENABLE; 768d7e33d6SKunihiko Hayashi else 778d7e33d6SKunihiko Hayashi val &= ~PCL_APP_LTSSM_ENABLE; 788d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_READY_CTRL); 798d7e33d6SKunihiko Hayashi } 808d7e33d6SKunihiko Hayashi 818d7e33d6SKunihiko Hayashi static void uniphier_pcie_phy_reset(struct uniphier_pcie_ep_priv *priv, 828d7e33d6SKunihiko Hayashi bool assert) 838d7e33d6SKunihiko Hayashi { 848d7e33d6SKunihiko Hayashi u32 val; 858d7e33d6SKunihiko Hayashi 868d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_RSTCTRL2); 878d7e33d6SKunihiko Hayashi if (assert) 888d7e33d6SKunihiko Hayashi val |= PCL_RSTCTRL_PHY_RESET; 898d7e33d6SKunihiko Hayashi else 908d7e33d6SKunihiko Hayashi val &= ~PCL_RSTCTRL_PHY_RESET; 918d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_RSTCTRL2); 928d7e33d6SKunihiko Hayashi } 938d7e33d6SKunihiko Hayashi 948d7e33d6SKunihiko Hayashi static void uniphier_pcie_init_ep(struct uniphier_pcie_ep_priv *priv) 958d7e33d6SKunihiko Hayashi { 968d7e33d6SKunihiko Hayashi u32 val; 978d7e33d6SKunihiko Hayashi 988d7e33d6SKunihiko Hayashi /* set EP mode */ 998d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_MODE); 1008d7e33d6SKunihiko Hayashi val |= PCL_MODE_REGEN | PCL_MODE_REGVAL; 1018d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_MODE); 1028d7e33d6SKunihiko Hayashi 1038d7e33d6SKunihiko Hayashi /* clock request */ 1048d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_CLK_CTRL); 1058d7e33d6SKunihiko Hayashi val &= ~PCL_APP_CLK_REQ; 1068d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_CLK_CTRL); 1078d7e33d6SKunihiko Hayashi 1088d7e33d6SKunihiko Hayashi /* deassert PIPE3 and AXI reset */ 1098d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_RSTCTRL0); 1108d7e33d6SKunihiko Hayashi val |= PCL_RSTCTRL_AXI_REG | PCL_RSTCTRL_AXI_SLAVE 1118d7e33d6SKunihiko Hayashi | PCL_RSTCTRL_AXI_MASTER | PCL_RSTCTRL_PIPE3; 1128d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_RSTCTRL0); 1138d7e33d6SKunihiko Hayashi 1148d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, false); 1158d7e33d6SKunihiko Hayashi 1168d7e33d6SKunihiko Hayashi msleep(100); 1178d7e33d6SKunihiko Hayashi } 1188d7e33d6SKunihiko Hayashi 1198d7e33d6SKunihiko Hayashi static int uniphier_pcie_start_link(struct dw_pcie *pci) 1208d7e33d6SKunihiko Hayashi { 1218d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1228d7e33d6SKunihiko Hayashi 1238d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, true); 1248d7e33d6SKunihiko Hayashi 1258d7e33d6SKunihiko Hayashi return 0; 1268d7e33d6SKunihiko Hayashi } 1278d7e33d6SKunihiko Hayashi 1288d7e33d6SKunihiko Hayashi static void uniphier_pcie_stop_link(struct dw_pcie *pci) 1298d7e33d6SKunihiko Hayashi { 1308d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1318d7e33d6SKunihiko Hayashi 1328d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, false); 1338d7e33d6SKunihiko Hayashi } 1348d7e33d6SKunihiko Hayashi 1358d7e33d6SKunihiko Hayashi static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep) 1368d7e33d6SKunihiko Hayashi { 1378d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1388d7e33d6SKunihiko Hayashi enum pci_barno bar; 1398d7e33d6SKunihiko Hayashi 1408d7e33d6SKunihiko Hayashi for (bar = BAR_0; bar <= BAR_5; bar++) 1418d7e33d6SKunihiko Hayashi dw_pcie_ep_reset_bar(pci, bar); 1428d7e33d6SKunihiko Hayashi } 1438d7e33d6SKunihiko Hayashi 1448d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep) 1458d7e33d6SKunihiko Hayashi { 1468d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1478d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1488d7e33d6SKunihiko Hayashi u32 val; 1498d7e33d6SKunihiko Hayashi 1508d7e33d6SKunihiko Hayashi /* 1518d7e33d6SKunihiko Hayashi * This makes pulse signal to send INTx to the RC, so this should 1528d7e33d6SKunihiko Hayashi * be cleared as soon as possible. This sequence is covered with 1538d7e33d6SKunihiko Hayashi * mutex in pci_epc_raise_irq(). 1548d7e33d6SKunihiko Hayashi */ 1558d7e33d6SKunihiko Hayashi /* assert INTx */ 1568d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_INTX); 1578d7e33d6SKunihiko Hayashi val |= PCL_APP_INTX_SYS_INT; 1588d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_INTX); 1598d7e33d6SKunihiko Hayashi 1608d7e33d6SKunihiko Hayashi udelay(PCL_INTX_WIDTH_USEC); 1618d7e33d6SKunihiko Hayashi 1628d7e33d6SKunihiko Hayashi /* deassert INTx */ 1638d7e33d6SKunihiko Hayashi val &= ~PCL_APP_INTX_SYS_INT; 1648d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_INTX); 1658d7e33d6SKunihiko Hayashi 1668d7e33d6SKunihiko Hayashi return 0; 1678d7e33d6SKunihiko Hayashi } 1688d7e33d6SKunihiko Hayashi 1698d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, 1708d7e33d6SKunihiko Hayashi u8 func_no, u16 interrupt_num) 1718d7e33d6SKunihiko Hayashi { 1728d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1738d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1748d7e33d6SKunihiko Hayashi u32 val; 1758d7e33d6SKunihiko Hayashi 1768d7e33d6SKunihiko Hayashi val = FIELD_PREP(PCL_APP_VEN_MSI_TC_MASK, func_no) 1778d7e33d6SKunihiko Hayashi | FIELD_PREP(PCL_APP_VEN_MSI_VECTOR_MASK, interrupt_num - 1); 1788d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_MSI0); 1798d7e33d6SKunihiko Hayashi 1808d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_MSI1); 1818d7e33d6SKunihiko Hayashi val |= PCL_APP_MSI_REQ; 1828d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_MSI1); 1838d7e33d6SKunihiko Hayashi 1848d7e33d6SKunihiko Hayashi return 0; 1858d7e33d6SKunihiko Hayashi } 1868d7e33d6SKunihiko Hayashi 1878d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 1888d7e33d6SKunihiko Hayashi enum pci_epc_irq_type type, 1898d7e33d6SKunihiko Hayashi u16 interrupt_num) 1908d7e33d6SKunihiko Hayashi { 1918d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1928d7e33d6SKunihiko Hayashi 1938d7e33d6SKunihiko Hayashi switch (type) { 1948d7e33d6SKunihiko Hayashi case PCI_EPC_IRQ_LEGACY: 1958d7e33d6SKunihiko Hayashi return uniphier_pcie_ep_raise_legacy_irq(ep); 1968d7e33d6SKunihiko Hayashi case PCI_EPC_IRQ_MSI: 1978d7e33d6SKunihiko Hayashi return uniphier_pcie_ep_raise_msi_irq(ep, func_no, 1988d7e33d6SKunihiko Hayashi interrupt_num); 1998d7e33d6SKunihiko Hayashi default: 2008d7e33d6SKunihiko Hayashi dev_err(pci->dev, "UNKNOWN IRQ type (%d)\n", type); 2018d7e33d6SKunihiko Hayashi } 2028d7e33d6SKunihiko Hayashi 2038d7e33d6SKunihiko Hayashi return 0; 2048d7e33d6SKunihiko Hayashi } 2058d7e33d6SKunihiko Hayashi 2068d7e33d6SKunihiko Hayashi static const struct pci_epc_features* 2078d7e33d6SKunihiko Hayashi uniphier_pcie_get_features(struct dw_pcie_ep *ep) 2088d7e33d6SKunihiko Hayashi { 2098d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 2108d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 2118d7e33d6SKunihiko Hayashi 2128d7e33d6SKunihiko Hayashi return priv->features; 2138d7e33d6SKunihiko Hayashi } 2148d7e33d6SKunihiko Hayashi 2158d7e33d6SKunihiko Hayashi static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = { 2168d7e33d6SKunihiko Hayashi .ep_init = uniphier_pcie_ep_init, 2178d7e33d6SKunihiko Hayashi .raise_irq = uniphier_pcie_ep_raise_irq, 2188d7e33d6SKunihiko Hayashi .get_features = uniphier_pcie_get_features, 2198d7e33d6SKunihiko Hayashi }; 2208d7e33d6SKunihiko Hayashi 2218d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_enable(struct uniphier_pcie_ep_priv *priv) 2228d7e33d6SKunihiko Hayashi { 2238d7e33d6SKunihiko Hayashi int ret; 2248d7e33d6SKunihiko Hayashi 2258d7e33d6SKunihiko Hayashi ret = clk_prepare_enable(priv->clk); 2268d7e33d6SKunihiko Hayashi if (ret) 2278d7e33d6SKunihiko Hayashi return ret; 2288d7e33d6SKunihiko Hayashi 2298d7e33d6SKunihiko Hayashi ret = clk_prepare_enable(priv->clk_gio); 2308d7e33d6SKunihiko Hayashi if (ret) 2318d7e33d6SKunihiko Hayashi goto out_clk_disable; 2328d7e33d6SKunihiko Hayashi 2338d7e33d6SKunihiko Hayashi ret = reset_control_deassert(priv->rst); 2348d7e33d6SKunihiko Hayashi if (ret) 2358d7e33d6SKunihiko Hayashi goto out_clk_gio_disable; 2368d7e33d6SKunihiko Hayashi 2378d7e33d6SKunihiko Hayashi ret = reset_control_deassert(priv->rst_gio); 2388d7e33d6SKunihiko Hayashi if (ret) 2398d7e33d6SKunihiko Hayashi goto out_rst_assert; 2408d7e33d6SKunihiko Hayashi 2418d7e33d6SKunihiko Hayashi uniphier_pcie_init_ep(priv); 2428d7e33d6SKunihiko Hayashi 2438d7e33d6SKunihiko Hayashi uniphier_pcie_phy_reset(priv, true); 2448d7e33d6SKunihiko Hayashi 2458d7e33d6SKunihiko Hayashi ret = phy_init(priv->phy); 2468d7e33d6SKunihiko Hayashi if (ret) 2478d7e33d6SKunihiko Hayashi goto out_rst_gio_assert; 2488d7e33d6SKunihiko Hayashi 2498d7e33d6SKunihiko Hayashi uniphier_pcie_phy_reset(priv, false); 2508d7e33d6SKunihiko Hayashi 2518d7e33d6SKunihiko Hayashi return 0; 2528d7e33d6SKunihiko Hayashi 2538d7e33d6SKunihiko Hayashi out_rst_gio_assert: 2548d7e33d6SKunihiko Hayashi reset_control_assert(priv->rst_gio); 2558d7e33d6SKunihiko Hayashi out_rst_assert: 2568d7e33d6SKunihiko Hayashi reset_control_assert(priv->rst); 2578d7e33d6SKunihiko Hayashi out_clk_gio_disable: 2588d7e33d6SKunihiko Hayashi clk_disable_unprepare(priv->clk_gio); 2598d7e33d6SKunihiko Hayashi out_clk_disable: 2608d7e33d6SKunihiko Hayashi clk_disable_unprepare(priv->clk); 2618d7e33d6SKunihiko Hayashi 2628d7e33d6SKunihiko Hayashi return ret; 2638d7e33d6SKunihiko Hayashi } 2648d7e33d6SKunihiko Hayashi 2658d7e33d6SKunihiko Hayashi static const struct dw_pcie_ops dw_pcie_ops = { 2668d7e33d6SKunihiko Hayashi .start_link = uniphier_pcie_start_link, 2678d7e33d6SKunihiko Hayashi .stop_link = uniphier_pcie_stop_link, 2688d7e33d6SKunihiko Hayashi }; 2698d7e33d6SKunihiko Hayashi 2708d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_probe(struct platform_device *pdev) 2718d7e33d6SKunihiko Hayashi { 2728d7e33d6SKunihiko Hayashi struct device *dev = &pdev->dev; 2738d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv; 2748d7e33d6SKunihiko Hayashi int ret; 2758d7e33d6SKunihiko Hayashi 2768d7e33d6SKunihiko Hayashi priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2778d7e33d6SKunihiko Hayashi if (!priv) 2788d7e33d6SKunihiko Hayashi return -ENOMEM; 2798d7e33d6SKunihiko Hayashi 2808d7e33d6SKunihiko Hayashi priv->features = of_device_get_match_data(dev); 2818d7e33d6SKunihiko Hayashi if (WARN_ON(!priv->features)) 2828d7e33d6SKunihiko Hayashi return -EINVAL; 2838d7e33d6SKunihiko Hayashi 2848d7e33d6SKunihiko Hayashi priv->pci.dev = dev; 2858d7e33d6SKunihiko Hayashi priv->pci.ops = &dw_pcie_ops; 2868d7e33d6SKunihiko Hayashi 2878d7e33d6SKunihiko Hayashi priv->base = devm_platform_ioremap_resource_byname(pdev, "link"); 2888d7e33d6SKunihiko Hayashi if (IS_ERR(priv->base)) 2898d7e33d6SKunihiko Hayashi return PTR_ERR(priv->base); 2908d7e33d6SKunihiko Hayashi 2918d7e33d6SKunihiko Hayashi priv->clk_gio = devm_clk_get(dev, "gio"); 2928d7e33d6SKunihiko Hayashi if (IS_ERR(priv->clk_gio)) 2938d7e33d6SKunihiko Hayashi return PTR_ERR(priv->clk_gio); 2948d7e33d6SKunihiko Hayashi 2958d7e33d6SKunihiko Hayashi priv->rst_gio = devm_reset_control_get_shared(dev, "gio"); 2968d7e33d6SKunihiko Hayashi if (IS_ERR(priv->rst_gio)) 2978d7e33d6SKunihiko Hayashi return PTR_ERR(priv->rst_gio); 2988d7e33d6SKunihiko Hayashi 2998d7e33d6SKunihiko Hayashi priv->clk = devm_clk_get(dev, "link"); 3008d7e33d6SKunihiko Hayashi if (IS_ERR(priv->clk)) 3018d7e33d6SKunihiko Hayashi return PTR_ERR(priv->clk); 3028d7e33d6SKunihiko Hayashi 3038d7e33d6SKunihiko Hayashi priv->rst = devm_reset_control_get_shared(dev, "link"); 3048d7e33d6SKunihiko Hayashi if (IS_ERR(priv->rst)) 3058d7e33d6SKunihiko Hayashi return PTR_ERR(priv->rst); 3068d7e33d6SKunihiko Hayashi 3078d7e33d6SKunihiko Hayashi priv->phy = devm_phy_optional_get(dev, "pcie-phy"); 3088d7e33d6SKunihiko Hayashi if (IS_ERR(priv->phy)) { 3098d7e33d6SKunihiko Hayashi ret = PTR_ERR(priv->phy); 3108d7e33d6SKunihiko Hayashi dev_err(dev, "Failed to get phy (%d)\n", ret); 3118d7e33d6SKunihiko Hayashi return ret; 3128d7e33d6SKunihiko Hayashi } 3138d7e33d6SKunihiko Hayashi 3148d7e33d6SKunihiko Hayashi platform_set_drvdata(pdev, priv); 3158d7e33d6SKunihiko Hayashi 3168d7e33d6SKunihiko Hayashi ret = uniphier_pcie_ep_enable(priv); 3178d7e33d6SKunihiko Hayashi if (ret) 3188d7e33d6SKunihiko Hayashi return ret; 3198d7e33d6SKunihiko Hayashi 320*a0fd361dSRob Herring priv->pci.ep.ops = &uniphier_pcie_ep_ops; 321*a0fd361dSRob Herring return dw_pcie_ep_init(&priv->pci.ep); 3228d7e33d6SKunihiko Hayashi } 3238d7e33d6SKunihiko Hayashi 3248d7e33d6SKunihiko Hayashi static const struct pci_epc_features uniphier_pro5_data = { 3258d7e33d6SKunihiko Hayashi .linkup_notifier = false, 3268d7e33d6SKunihiko Hayashi .msi_capable = true, 3278d7e33d6SKunihiko Hayashi .msix_capable = false, 3288d7e33d6SKunihiko Hayashi .align = 1 << 16, 3298d7e33d6SKunihiko Hayashi .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4), 3308d7e33d6SKunihiko Hayashi .reserved_bar = BIT(BAR_4), 3318d7e33d6SKunihiko Hayashi }; 3328d7e33d6SKunihiko Hayashi 3338d7e33d6SKunihiko Hayashi static const struct of_device_id uniphier_pcie_ep_match[] = { 3348d7e33d6SKunihiko Hayashi { 3358d7e33d6SKunihiko Hayashi .compatible = "socionext,uniphier-pro5-pcie-ep", 3368d7e33d6SKunihiko Hayashi .data = &uniphier_pro5_data, 3378d7e33d6SKunihiko Hayashi }, 3388d7e33d6SKunihiko Hayashi { /* sentinel */ }, 3398d7e33d6SKunihiko Hayashi }; 3408d7e33d6SKunihiko Hayashi 3418d7e33d6SKunihiko Hayashi static struct platform_driver uniphier_pcie_ep_driver = { 3428d7e33d6SKunihiko Hayashi .probe = uniphier_pcie_ep_probe, 3438d7e33d6SKunihiko Hayashi .driver = { 3448d7e33d6SKunihiko Hayashi .name = "uniphier-pcie-ep", 3458d7e33d6SKunihiko Hayashi .of_match_table = uniphier_pcie_ep_match, 3468d7e33d6SKunihiko Hayashi .suppress_bind_attrs = true, 3478d7e33d6SKunihiko Hayashi }, 3488d7e33d6SKunihiko Hayashi }; 3498d7e33d6SKunihiko Hayashi builtin_platform_driver(uniphier_pcie_ep_driver); 350