--- v5
+++ v2
@@ -13,8 +13,8 @@
---
drivers/pci/controller/dwc/Kconfig | 9 +
drivers/pci/controller/dwc/Makefile | 1 +
- drivers/pci/controller/dwc/pcie-fu740.c | 308 ++++++++++++++++++++++++
- 3 files changed, 318 insertions(+)
+ drivers/pci/controller/dwc/pcie-fu740.c | 324 ++++++++++++++++++++++++
+ 3 files changed, 334 insertions(+)
create mode 100644 drivers/pci/controller/dwc/pcie-fu740.c
diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
@@ -49,10 +49,10 @@
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone.o
diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
new file mode 100644
-index 000000000000..f8abb08095aa
+index 000000000000..65ca4c212fc3
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-fu740.c
-@@ -0,0 +1,308 @@
+@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FU740 DesignWare PCIe Controller integration
@@ -72,14 +72,19 @@
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/of_device.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/resource.h>
++#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/reset.h>
++#include <linux/pm_domain.h>
++#include <linux/pm_runtime.h>
+
+#include "pcie-designware.h"
+
@@ -88,7 +93,7 @@
+struct fu740_pcie {
+ struct dw_pcie pci;
+ void __iomem *mgmt_base;
-+ struct gpio_desc *reset;
++ struct gpio_desc *perstn;
+ struct gpio_desc *pwren;
+ struct clk *pcie_aux;
+ struct reset_control *rst;
@@ -133,20 +138,20 @@
+#define PCIEX8MGMT_PHY_LANE2_BASE (PCIEX8MGMT_PHY_LANEN_DIG_ASIC_RX_OVRD_IN_3 + 0x100 * 2)
+#define PCIEX8MGMT_PHY_LANE3_BASE (PCIEX8MGMT_PHY_LANEN_DIG_ASIC_RX_OVRD_IN_3 + 0x100 * 3)
+
-+static void fu740_pcie_assert_reset(struct fu740_pcie *afp)
++static void fu740_pcie_assert_perstn(struct fu740_pcie *afp)
+{
+ /* Assert PERST_N GPIO */
-+ gpiod_set_value_cansleep(afp->reset, 0);
++ gpiod_set_value_cansleep(afp->perstn, 0);
+ /* Assert controller PERST_N */
+ writel_relaxed(0x0, afp->mgmt_base + PCIEX8MGMT_PERST_N);
+}
+
-+static void fu740_pcie_deassert_reset(struct fu740_pcie *afp)
++static void fu740_pcie_deassert_perstn(struct fu740_pcie *afp)
+{
+ /* Deassert controller PERST_N */
+ writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_PERST_N);
+ /* Deassert PERST_N GPIO */
-+ gpiod_set_value_cansleep(afp->reset, 1);
++ gpiod_set_value_cansleep(afp->perstn, 1);
+}
+
+static void fu740_pcie_power_on(struct fu740_pcie *afp)
@@ -160,11 +165,11 @@
+ msleep(100);
+}
+
-+static void fu740_pcie_drive_reset(struct fu740_pcie *afp)
-+{
-+ fu740_pcie_assert_reset(afp);
++static void fu740_pcie_drive_perstn(struct fu740_pcie *afp)
++{
++ fu740_pcie_assert_perstn(afp);
+ fu740_pcie_power_on(afp);
-+ fu740_pcie_deassert_reset(afp);
++ fu740_pcie_deassert_perstn(afp);
+}
+
+static void fu740_phyregwrite(const uint8_t phy, const uint16_t addr,
@@ -197,7 +202,7 @@
+ /* Wait for wait_idle */
+ ret = readl_poll_timeout(phy_cr_para_ack, val, val, 10, 5000);
+ if (ret)
-+ dev_warn(dev, "Wait for wait_idle state failed!\n");
++ dev_err(dev, "Wait for wait_ilde state failed!\n");
+
+ /* Clear */
+ writel_relaxed(0, phy_cr_para_wr_en);
@@ -205,7 +210,7 @@
+ /* Wait for ~wait_idle */
+ ret = readl_poll_timeout(phy_cr_para_ack, val, !val, 10, 5000);
+ if (ret)
-+ dev_warn(dev, "Wait for !wait_idle state failed!\n");
++ dev_err(dev, "Wait for !wait_ilde state failed!\n");
+}
+
+static void fu740_pcie_init_phy(struct fu740_pcie *afp)
@@ -231,13 +236,20 @@
+ fu740_phyregwrite(1, PCIEX8MGMT_PHY_LANE3_BASE, PCIEX8MGMT_PHY_INIT_VAL, afp);
+}
+
-+static int fu740_pcie_start_link(struct dw_pcie *pci)
-+{
-+ struct device *dev = pci->dev;
++static void fu740_pcie_ltssm_enable(struct device *dev)
++{
+ struct fu740_pcie *afp = dev_get_drvdata(dev);
+
+ /* Enable LTSSM */
+ writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
++}
++
++static int fu740_pcie_start_link(struct dw_pcie *pci)
++{
++ struct device *dev = pci->dev;
++
++ /* Start LTSSM. */
++ fu740_pcie_ltssm_enable(dev);
+ return 0;
+}
+
@@ -249,14 +261,12 @@
+ int ret;
+
+ /* Power on reset */
-+ fu740_pcie_drive_reset(afp);
++ fu740_pcie_drive_perstn(afp);
+
+ /* Enable pcieauxclk */
+ ret = clk_prepare_enable(afp->pcie_aux);
-+ if (ret) {
++ if (ret)
+ dev_err(dev, "unable to enable pcie_aux clock\n");
-+ return ret;
-+ }
+
+ /*
+ * Assert hold_phy_rst (hold the controller LTSSM in reset after
@@ -266,10 +276,8 @@
+
+ /* Deassert power_up_rst_n */
+ ret = reset_control_deassert(afp->rst);
-+ if (ret) {
++ if (ret)
+ dev_err(dev, "unable to deassert pcie_power_up_rst_n\n");
-+ return ret;
-+ }
+
+ fu740_pcie_init_phy(afp);
+
@@ -298,6 +306,7 @@
+ struct device *dev = &pdev->dev;
+ struct dw_pcie *pci;
+ struct fu740_pcie *afp;
++ int ret;
+
+ afp = devm_kzalloc(dev, sizeof(*afp), GFP_KERNEL);
+ if (!afp)
@@ -313,13 +322,16 @@
+ return PTR_ERR(afp->mgmt_base);
+
+ /* Fetch GPIOs */
-+ afp->reset = devm_gpiod_get_optional(dev, "reset-gpios", GPIOD_OUT_LOW);
-+ if (IS_ERR(afp->reset))
-+ return dev_err_probe(dev, PTR_ERR(afp->reset), "unable to get reset-gpios\n");
-+
++ afp->perstn = devm_gpiod_get_optional(dev, "perstn-gpios", GPIOD_OUT_LOW);
++ if (IS_ERR(afp->perstn)) {
++ dev_err(dev, "unable to get perstn-gpios\n");
++ return ret;
++ }
+ afp->pwren = devm_gpiod_get_optional(dev, "pwren-gpios", GPIOD_OUT_LOW);
-+ if (IS_ERR(afp->pwren))
-+ return dev_err_probe(dev, PTR_ERR(afp->pwren), "unable to get pwren-gpios\n");
++ if (IS_ERR(afp->pwren)) {
++ dev_err(dev, "unable to get pwren-gpios\n");
++ return ret;
++ }
+
+ /* Fetch clocks */
+ afp->pcie_aux = devm_clk_get(dev, "pcie_aux");
@@ -334,7 +346,11 @@
+
+ platform_set_drvdata(pdev, afp);
+
-+ return dw_pcie_host_init(&pci->pp);
++ ret = dw_pcie_host_init(&pci->pp);
++ if (ret < 0)
++ return ret;
++
++ return 0;
+}
+
+static void fu740_pcie_shutdown(struct platform_device *pdev)
@@ -342,7 +358,7 @@
+ struct fu740_pcie *afp = platform_get_drvdata(pdev);
+
+ /* Bring down link, so bootloader gets clean state in case of reboot */
-+ fu740_pcie_assert_reset(afp);
++ fu740_pcie_assert_perstn(afp);
+}
+
+static const struct of_device_id fu740_pcie_of_match[] = {