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