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; 63*d41584aeSKunihiko Hayashi const struct uniphier_pcie_ep_soc_data *data; 64*d41584aeSKunihiko Hayashi }; 65*d41584aeSKunihiko Hayashi 66*d41584aeSKunihiko Hayashi struct uniphier_pcie_ep_soc_data { 67*d41584aeSKunihiko Hayashi bool has_gio; 68*d41584aeSKunihiko Hayashi void (*init)(struct uniphier_pcie_ep_priv *priv); 69*d41584aeSKunihiko Hayashi int (*wait)(struct uniphier_pcie_ep_priv *priv); 70*d41584aeSKunihiko Hayashi const struct pci_epc_features features; 718d7e33d6SKunihiko Hayashi }; 728d7e33d6SKunihiko Hayashi 738d7e33d6SKunihiko Hayashi #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev) 748d7e33d6SKunihiko Hayashi 758d7e33d6SKunihiko Hayashi static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_ep_priv *priv, 768d7e33d6SKunihiko Hayashi bool enable) 778d7e33d6SKunihiko Hayashi { 788d7e33d6SKunihiko Hayashi u32 val; 798d7e33d6SKunihiko Hayashi 808d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_READY_CTRL); 818d7e33d6SKunihiko Hayashi if (enable) 828d7e33d6SKunihiko Hayashi val |= PCL_APP_LTSSM_ENABLE; 838d7e33d6SKunihiko Hayashi else 848d7e33d6SKunihiko Hayashi val &= ~PCL_APP_LTSSM_ENABLE; 858d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_READY_CTRL); 868d7e33d6SKunihiko Hayashi } 878d7e33d6SKunihiko Hayashi 888d7e33d6SKunihiko Hayashi static void uniphier_pcie_phy_reset(struct uniphier_pcie_ep_priv *priv, 898d7e33d6SKunihiko Hayashi bool assert) 908d7e33d6SKunihiko Hayashi { 918d7e33d6SKunihiko Hayashi u32 val; 928d7e33d6SKunihiko Hayashi 938d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_RSTCTRL2); 948d7e33d6SKunihiko Hayashi if (assert) 958d7e33d6SKunihiko Hayashi val |= PCL_RSTCTRL_PHY_RESET; 968d7e33d6SKunihiko Hayashi else 978d7e33d6SKunihiko Hayashi val &= ~PCL_RSTCTRL_PHY_RESET; 988d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_RSTCTRL2); 998d7e33d6SKunihiko Hayashi } 1008d7e33d6SKunihiko Hayashi 101*d41584aeSKunihiko Hayashi static void uniphier_pcie_pro5_init_ep(struct uniphier_pcie_ep_priv *priv) 1028d7e33d6SKunihiko Hayashi { 1038d7e33d6SKunihiko Hayashi u32 val; 1048d7e33d6SKunihiko Hayashi 1058d7e33d6SKunihiko Hayashi /* set EP mode */ 1068d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_MODE); 1078d7e33d6SKunihiko Hayashi val |= PCL_MODE_REGEN | PCL_MODE_REGVAL; 1088d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_MODE); 1098d7e33d6SKunihiko Hayashi 1108d7e33d6SKunihiko Hayashi /* clock request */ 1118d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_CLK_CTRL); 1128d7e33d6SKunihiko Hayashi val &= ~PCL_APP_CLK_REQ; 1138d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_CLK_CTRL); 1148d7e33d6SKunihiko Hayashi 1158d7e33d6SKunihiko Hayashi /* deassert PIPE3 and AXI reset */ 1168d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_RSTCTRL0); 1178d7e33d6SKunihiko Hayashi val |= PCL_RSTCTRL_AXI_REG | PCL_RSTCTRL_AXI_SLAVE 1188d7e33d6SKunihiko Hayashi | PCL_RSTCTRL_AXI_MASTER | PCL_RSTCTRL_PIPE3; 1198d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_RSTCTRL0); 1208d7e33d6SKunihiko Hayashi 1218d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, false); 1228d7e33d6SKunihiko Hayashi 1238d7e33d6SKunihiko Hayashi msleep(100); 1248d7e33d6SKunihiko Hayashi } 1258d7e33d6SKunihiko Hayashi 1268d7e33d6SKunihiko Hayashi static int uniphier_pcie_start_link(struct dw_pcie *pci) 1278d7e33d6SKunihiko Hayashi { 1288d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1298d7e33d6SKunihiko Hayashi 1308d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, true); 1318d7e33d6SKunihiko Hayashi 1328d7e33d6SKunihiko Hayashi return 0; 1338d7e33d6SKunihiko Hayashi } 1348d7e33d6SKunihiko Hayashi 1358d7e33d6SKunihiko Hayashi static void uniphier_pcie_stop_link(struct dw_pcie *pci) 1368d7e33d6SKunihiko Hayashi { 1378d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1388d7e33d6SKunihiko Hayashi 1398d7e33d6SKunihiko Hayashi uniphier_pcie_ltssm_enable(priv, false); 1408d7e33d6SKunihiko Hayashi } 1418d7e33d6SKunihiko Hayashi 1428d7e33d6SKunihiko Hayashi static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep) 1438d7e33d6SKunihiko Hayashi { 1448d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1458d7e33d6SKunihiko Hayashi enum pci_barno bar; 1468d7e33d6SKunihiko Hayashi 1478d7e33d6SKunihiko Hayashi for (bar = BAR_0; bar <= BAR_5; bar++) 1488d7e33d6SKunihiko Hayashi dw_pcie_ep_reset_bar(pci, bar); 1498d7e33d6SKunihiko Hayashi } 1508d7e33d6SKunihiko Hayashi 1518d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep) 1528d7e33d6SKunihiko Hayashi { 1538d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1548d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1558d7e33d6SKunihiko Hayashi u32 val; 1568d7e33d6SKunihiko Hayashi 1578d7e33d6SKunihiko Hayashi /* 1588d7e33d6SKunihiko Hayashi * This makes pulse signal to send INTx to the RC, so this should 1598d7e33d6SKunihiko Hayashi * be cleared as soon as possible. This sequence is covered with 1608d7e33d6SKunihiko Hayashi * mutex in pci_epc_raise_irq(). 1618d7e33d6SKunihiko Hayashi */ 1628d7e33d6SKunihiko Hayashi /* assert INTx */ 1638d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_INTX); 1648d7e33d6SKunihiko Hayashi val |= PCL_APP_INTX_SYS_INT; 1658d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_INTX); 1668d7e33d6SKunihiko Hayashi 1678d7e33d6SKunihiko Hayashi udelay(PCL_INTX_WIDTH_USEC); 1688d7e33d6SKunihiko Hayashi 1698d7e33d6SKunihiko Hayashi /* deassert INTx */ 1708d7e33d6SKunihiko Hayashi val &= ~PCL_APP_INTX_SYS_INT; 1718d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_INTX); 1728d7e33d6SKunihiko Hayashi 1738d7e33d6SKunihiko Hayashi return 0; 1748d7e33d6SKunihiko Hayashi } 1758d7e33d6SKunihiko Hayashi 1768d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, 1778d7e33d6SKunihiko Hayashi u8 func_no, u16 interrupt_num) 1788d7e33d6SKunihiko Hayashi { 1798d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1808d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 1818d7e33d6SKunihiko Hayashi u32 val; 1828d7e33d6SKunihiko Hayashi 1838d7e33d6SKunihiko Hayashi val = FIELD_PREP(PCL_APP_VEN_MSI_TC_MASK, func_no) 1848d7e33d6SKunihiko Hayashi | FIELD_PREP(PCL_APP_VEN_MSI_VECTOR_MASK, interrupt_num - 1); 1858d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_MSI0); 1868d7e33d6SKunihiko Hayashi 1878d7e33d6SKunihiko Hayashi val = readl(priv->base + PCL_APP_MSI1); 1888d7e33d6SKunihiko Hayashi val |= PCL_APP_MSI_REQ; 1898d7e33d6SKunihiko Hayashi writel(val, priv->base + PCL_APP_MSI1); 1908d7e33d6SKunihiko Hayashi 1918d7e33d6SKunihiko Hayashi return 0; 1928d7e33d6SKunihiko Hayashi } 1938d7e33d6SKunihiko Hayashi 1948d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 1958d7e33d6SKunihiko Hayashi enum pci_epc_irq_type type, 1968d7e33d6SKunihiko Hayashi u16 interrupt_num) 1978d7e33d6SKunihiko Hayashi { 1988d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 1998d7e33d6SKunihiko Hayashi 2008d7e33d6SKunihiko Hayashi switch (type) { 2018d7e33d6SKunihiko Hayashi case PCI_EPC_IRQ_LEGACY: 2028d7e33d6SKunihiko Hayashi return uniphier_pcie_ep_raise_legacy_irq(ep); 2038d7e33d6SKunihiko Hayashi case PCI_EPC_IRQ_MSI: 2048d7e33d6SKunihiko Hayashi return uniphier_pcie_ep_raise_msi_irq(ep, func_no, 2058d7e33d6SKunihiko Hayashi interrupt_num); 2068d7e33d6SKunihiko Hayashi default: 2078d7e33d6SKunihiko Hayashi dev_err(pci->dev, "UNKNOWN IRQ type (%d)\n", type); 2088d7e33d6SKunihiko Hayashi } 2098d7e33d6SKunihiko Hayashi 2108d7e33d6SKunihiko Hayashi return 0; 2118d7e33d6SKunihiko Hayashi } 2128d7e33d6SKunihiko Hayashi 2138d7e33d6SKunihiko Hayashi static const struct pci_epc_features* 2148d7e33d6SKunihiko Hayashi uniphier_pcie_get_features(struct dw_pcie_ep *ep) 2158d7e33d6SKunihiko Hayashi { 2168d7e33d6SKunihiko Hayashi struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 2178d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci); 2188d7e33d6SKunihiko Hayashi 219*d41584aeSKunihiko Hayashi return &priv->data->features; 2208d7e33d6SKunihiko Hayashi } 2218d7e33d6SKunihiko Hayashi 2228d7e33d6SKunihiko Hayashi static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = { 2238d7e33d6SKunihiko Hayashi .ep_init = uniphier_pcie_ep_init, 2248d7e33d6SKunihiko Hayashi .raise_irq = uniphier_pcie_ep_raise_irq, 2258d7e33d6SKunihiko Hayashi .get_features = uniphier_pcie_get_features, 2268d7e33d6SKunihiko Hayashi }; 2278d7e33d6SKunihiko Hayashi 2288d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_enable(struct uniphier_pcie_ep_priv *priv) 2298d7e33d6SKunihiko Hayashi { 2308d7e33d6SKunihiko Hayashi int ret; 2318d7e33d6SKunihiko Hayashi 2328d7e33d6SKunihiko Hayashi ret = clk_prepare_enable(priv->clk); 2338d7e33d6SKunihiko Hayashi if (ret) 2348d7e33d6SKunihiko Hayashi return ret; 2358d7e33d6SKunihiko Hayashi 2368d7e33d6SKunihiko Hayashi ret = clk_prepare_enable(priv->clk_gio); 2378d7e33d6SKunihiko Hayashi if (ret) 2388d7e33d6SKunihiko Hayashi goto out_clk_disable; 2398d7e33d6SKunihiko Hayashi 2408d7e33d6SKunihiko Hayashi ret = reset_control_deassert(priv->rst); 2418d7e33d6SKunihiko Hayashi if (ret) 2428d7e33d6SKunihiko Hayashi goto out_clk_gio_disable; 2438d7e33d6SKunihiko Hayashi 2448d7e33d6SKunihiko Hayashi ret = reset_control_deassert(priv->rst_gio); 2458d7e33d6SKunihiko Hayashi if (ret) 2468d7e33d6SKunihiko Hayashi goto out_rst_assert; 2478d7e33d6SKunihiko Hayashi 248*d41584aeSKunihiko Hayashi if (priv->data->init) 249*d41584aeSKunihiko Hayashi priv->data->init(priv); 2508d7e33d6SKunihiko Hayashi 2518d7e33d6SKunihiko Hayashi uniphier_pcie_phy_reset(priv, true); 2528d7e33d6SKunihiko Hayashi 2538d7e33d6SKunihiko Hayashi ret = phy_init(priv->phy); 2548d7e33d6SKunihiko Hayashi if (ret) 2558d7e33d6SKunihiko Hayashi goto out_rst_gio_assert; 2568d7e33d6SKunihiko Hayashi 2578d7e33d6SKunihiko Hayashi uniphier_pcie_phy_reset(priv, false); 2588d7e33d6SKunihiko Hayashi 259*d41584aeSKunihiko Hayashi if (priv->data->wait) { 260*d41584aeSKunihiko Hayashi ret = priv->data->wait(priv); 261*d41584aeSKunihiko Hayashi if (ret) 262*d41584aeSKunihiko Hayashi goto out_phy_exit; 263*d41584aeSKunihiko Hayashi } 264*d41584aeSKunihiko Hayashi 2658d7e33d6SKunihiko Hayashi return 0; 2668d7e33d6SKunihiko Hayashi 267*d41584aeSKunihiko Hayashi out_phy_exit: 268*d41584aeSKunihiko Hayashi phy_exit(priv->phy); 2698d7e33d6SKunihiko Hayashi out_rst_gio_assert: 2708d7e33d6SKunihiko Hayashi reset_control_assert(priv->rst_gio); 2718d7e33d6SKunihiko Hayashi out_rst_assert: 2728d7e33d6SKunihiko Hayashi reset_control_assert(priv->rst); 2738d7e33d6SKunihiko Hayashi out_clk_gio_disable: 2748d7e33d6SKunihiko Hayashi clk_disable_unprepare(priv->clk_gio); 2758d7e33d6SKunihiko Hayashi out_clk_disable: 2768d7e33d6SKunihiko Hayashi clk_disable_unprepare(priv->clk); 2778d7e33d6SKunihiko Hayashi 2788d7e33d6SKunihiko Hayashi return ret; 2798d7e33d6SKunihiko Hayashi } 2808d7e33d6SKunihiko Hayashi 2818d7e33d6SKunihiko Hayashi static const struct dw_pcie_ops dw_pcie_ops = { 2828d7e33d6SKunihiko Hayashi .start_link = uniphier_pcie_start_link, 2838d7e33d6SKunihiko Hayashi .stop_link = uniphier_pcie_stop_link, 2848d7e33d6SKunihiko Hayashi }; 2858d7e33d6SKunihiko Hayashi 2868d7e33d6SKunihiko Hayashi static int uniphier_pcie_ep_probe(struct platform_device *pdev) 2878d7e33d6SKunihiko Hayashi { 2888d7e33d6SKunihiko Hayashi struct device *dev = &pdev->dev; 2898d7e33d6SKunihiko Hayashi struct uniphier_pcie_ep_priv *priv; 2908d7e33d6SKunihiko Hayashi int ret; 2918d7e33d6SKunihiko Hayashi 2928d7e33d6SKunihiko Hayashi priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2938d7e33d6SKunihiko Hayashi if (!priv) 2948d7e33d6SKunihiko Hayashi return -ENOMEM; 2958d7e33d6SKunihiko Hayashi 296*d41584aeSKunihiko Hayashi priv->data = of_device_get_match_data(dev); 297*d41584aeSKunihiko Hayashi if (WARN_ON(!priv->data)) 2988d7e33d6SKunihiko Hayashi return -EINVAL; 2998d7e33d6SKunihiko Hayashi 3008d7e33d6SKunihiko Hayashi priv->pci.dev = dev; 3018d7e33d6SKunihiko Hayashi priv->pci.ops = &dw_pcie_ops; 3028d7e33d6SKunihiko Hayashi 3038d7e33d6SKunihiko Hayashi priv->base = devm_platform_ioremap_resource_byname(pdev, "link"); 3048d7e33d6SKunihiko Hayashi if (IS_ERR(priv->base)) 3058d7e33d6SKunihiko Hayashi return PTR_ERR(priv->base); 3068d7e33d6SKunihiko Hayashi 307*d41584aeSKunihiko Hayashi if (priv->data->has_gio) { 3088d7e33d6SKunihiko Hayashi priv->clk_gio = devm_clk_get(dev, "gio"); 3098d7e33d6SKunihiko Hayashi if (IS_ERR(priv->clk_gio)) 3108d7e33d6SKunihiko Hayashi return PTR_ERR(priv->clk_gio); 3118d7e33d6SKunihiko Hayashi 3128d7e33d6SKunihiko Hayashi priv->rst_gio = devm_reset_control_get_shared(dev, "gio"); 3138d7e33d6SKunihiko Hayashi if (IS_ERR(priv->rst_gio)) 3148d7e33d6SKunihiko Hayashi return PTR_ERR(priv->rst_gio); 315*d41584aeSKunihiko Hayashi } 3168d7e33d6SKunihiko Hayashi 3178d7e33d6SKunihiko Hayashi priv->clk = devm_clk_get(dev, "link"); 3188d7e33d6SKunihiko Hayashi if (IS_ERR(priv->clk)) 3198d7e33d6SKunihiko Hayashi return PTR_ERR(priv->clk); 3208d7e33d6SKunihiko Hayashi 3218d7e33d6SKunihiko Hayashi priv->rst = devm_reset_control_get_shared(dev, "link"); 3228d7e33d6SKunihiko Hayashi if (IS_ERR(priv->rst)) 3238d7e33d6SKunihiko Hayashi return PTR_ERR(priv->rst); 3248d7e33d6SKunihiko Hayashi 3258d7e33d6SKunihiko Hayashi priv->phy = devm_phy_optional_get(dev, "pcie-phy"); 3268d7e33d6SKunihiko Hayashi if (IS_ERR(priv->phy)) { 3278d7e33d6SKunihiko Hayashi ret = PTR_ERR(priv->phy); 3288d7e33d6SKunihiko Hayashi dev_err(dev, "Failed to get phy (%d)\n", ret); 3298d7e33d6SKunihiko Hayashi return ret; 3308d7e33d6SKunihiko Hayashi } 3318d7e33d6SKunihiko Hayashi 3328d7e33d6SKunihiko Hayashi platform_set_drvdata(pdev, priv); 3338d7e33d6SKunihiko Hayashi 3348d7e33d6SKunihiko Hayashi ret = uniphier_pcie_ep_enable(priv); 3358d7e33d6SKunihiko Hayashi if (ret) 3368d7e33d6SKunihiko Hayashi return ret; 3378d7e33d6SKunihiko Hayashi 338a0fd361dSRob Herring priv->pci.ep.ops = &uniphier_pcie_ep_ops; 339a0fd361dSRob Herring return dw_pcie_ep_init(&priv->pci.ep); 3408d7e33d6SKunihiko Hayashi } 3418d7e33d6SKunihiko Hayashi 342*d41584aeSKunihiko Hayashi static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = { 343*d41584aeSKunihiko Hayashi .has_gio = true, 344*d41584aeSKunihiko Hayashi .init = uniphier_pcie_pro5_init_ep, 345*d41584aeSKunihiko Hayashi .wait = NULL, 346*d41584aeSKunihiko Hayashi .features = { 3478d7e33d6SKunihiko Hayashi .linkup_notifier = false, 3488d7e33d6SKunihiko Hayashi .msi_capable = true, 3498d7e33d6SKunihiko Hayashi .msix_capable = false, 3508d7e33d6SKunihiko Hayashi .align = 1 << 16, 3518d7e33d6SKunihiko Hayashi .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4), 3528d7e33d6SKunihiko Hayashi .reserved_bar = BIT(BAR_4), 353*d41584aeSKunihiko Hayashi }, 3548d7e33d6SKunihiko Hayashi }; 3558d7e33d6SKunihiko Hayashi 3568d7e33d6SKunihiko Hayashi static const struct of_device_id uniphier_pcie_ep_match[] = { 3578d7e33d6SKunihiko Hayashi { 3588d7e33d6SKunihiko Hayashi .compatible = "socionext,uniphier-pro5-pcie-ep", 3598d7e33d6SKunihiko Hayashi .data = &uniphier_pro5_data, 3608d7e33d6SKunihiko Hayashi }, 3618d7e33d6SKunihiko Hayashi { /* sentinel */ }, 3628d7e33d6SKunihiko Hayashi }; 3638d7e33d6SKunihiko Hayashi 3648d7e33d6SKunihiko Hayashi static struct platform_driver uniphier_pcie_ep_driver = { 3658d7e33d6SKunihiko Hayashi .probe = uniphier_pcie_ep_probe, 3668d7e33d6SKunihiko Hayashi .driver = { 3678d7e33d6SKunihiko Hayashi .name = "uniphier-pcie-ep", 3688d7e33d6SKunihiko Hayashi .of_match_table = uniphier_pcie_ep_match, 3698d7e33d6SKunihiko Hayashi .suppress_bind_attrs = true, 3708d7e33d6SKunihiko Hayashi }, 3718d7e33d6SKunihiko Hayashi }; 3728d7e33d6SKunihiko Hayashi builtin_platform_driver(uniphier_pcie_ep_driver); 373