From ee930fffee469d076998274a2ca55e13dc1efb67 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 08:50:54 +0000
Subject: [PATCH] enable tun/tap/iptables

---
 kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c | 1091 +++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 829 insertions(+), 262 deletions(-)

diff --git a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 33b6dc3..e22295e 100644
--- a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -8,12 +8,14 @@
  * Author: Simon Xue <xxm@rock-chips.com>
  */
 
+#include <dt-bindings/phy/phy.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
@@ -29,6 +31,7 @@
 #include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/phy/phy.h>
+#include <linux/phy/pcie.h>
 #include <linux/platform_device.h>
 #include <linux/poll.h>
 #include <linux/regmap.h>
@@ -50,15 +53,11 @@
 	RK_PCIE_RC_TYPE,
 };
 
-struct reset_bulk_data	{
-	const char *id;
-	struct reset_control *rst;
-};
-
 #define RK_PCIE_DBG			0
 
 #define PCIE_DMA_OFFSET			0x380000
 
+#define PCIE_DMA_CTRL_OFF		0x8
 #define PCIE_DMA_WR_ENB			0xc
 #define PCIE_DMA_WR_CTRL_LO		0x200
 #define PCIE_DMA_WR_CTRL_HI		0x204
@@ -102,6 +101,8 @@
 
 #define PCIE_CAP_LINK_CONTROL2_LINK_STATUS	0xa0
 
+#define PCIE_CLIENT_INTR_STATUS_MSG_RX	0x04
+#define PME_TO_ACK			(BIT(9) | BIT(25))
 #define PCIE_CLIENT_INTR_STATUS_LEGACY	0x08
 #define PCIE_CLIENT_INTR_STATUS_MISC	0x10
 #define PCIE_CLIENT_INTR_MASK_LEGACY	0x1c
@@ -109,12 +110,21 @@
 #define MASK_LEGACY_INT(x)		(0x00110011 << x)
 #define UNMASK_LEGACY_INT(x)		(0x00110000 << x)
 #define PCIE_CLIENT_INTR_MASK		0x24
+#define PCIE_CLIENT_POWER		0x2c
+#define READY_ENTER_L23			BIT(3)
+#define PCIE_CLIENT_MSG_GEN		0x34
+#define PME_TURN_OFF			(BIT(4) | BIT(20))
 #define PCIE_CLIENT_GENERAL_DEBUG	0x104
 #define PCIE_CLIENT_HOT_RESET_CTRL	0x180
+#define PCIE_LTSSM_APP_DLY1_EN		BIT(0)
+#define PCIE_LTSSM_APP_DLY2_EN		BIT(1)
+#define PCIE_LTSSM_APP_DLY1_DONE	BIT(2)
+#define PCIE_LTSSM_APP_DLY2_DONE	BIT(3)
 #define PCIE_LTSSM_ENABLE_ENHANCE	BIT(4)
 #define PCIE_CLIENT_LTSSM_STATUS	0x300
 #define SMLH_LINKUP			BIT(16)
 #define RDLH_LINKUP			BIT(17)
+#define PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN 0x154
 #define PCIE_CLIENT_DBG_FIFO_MODE_CON	0x310
 #define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
 #define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
@@ -122,20 +132,32 @@
 #define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
 #define PCIE_CLIENT_DBG_FIFO_STATUS	0x350
 #define PCIE_CLIENT_DBG_TRANSITION_DATA	0xffff0000
-#define PCIE_CLIENT_DBF_EN		0xffff0003
+#define PCIE_CLIENT_DBF_EN		0xffff0007
 
 #define PCIE_PHY_LINKUP			BIT(0)
 #define PCIE_DATA_LINKUP		BIT(1)
 
-#define PCIE_RESBAR_CTRL_REG0_REG	0x2a8
+#define PCIE_TYPE0_HDR_DBI2_OFFSET	0x100000
 #define PCIE_SB_BAR0_MASK_REG		0x100010
 
 #define PCIE_PL_ORDER_RULE_CTRL_OFF	0x8B4
+#define RK_PCIE_L2_TMOUT_US		5000
+#define RK_PCIE_HOTRESET_TMOUT_US	10000
+#define RK_PCIE_ENUM_HW_RETRYIES	2
+
+enum rk_pcie_ltssm_code {
+	S_L0 = 0x11,
+	S_L0S = 0x12,
+	S_L1_IDLE = 0x14,
+	S_L2_IDLE = 0x15,
+	S_MAX = 0x1f,
+};
 
 struct rk_pcie {
 	struct dw_pcie			*pci;
 	enum rk_pcie_device_mode	mode;
 	enum phy_mode			phy_mode;
+	int				phy_sub_mode;
 	unsigned char			bar_to_atu[6];
 	phys_addr_t			*outbound_addr;
 	unsigned long			*ib_window_map;
@@ -146,9 +168,10 @@
 	void __iomem			*apb_base;
 	struct phy			*phy;
 	struct clk_bulk_data		*clks;
+	struct reset_control		*rsts;
 	unsigned int			clk_cnt;
-	struct reset_bulk_data		*rsts;
 	struct gpio_desc		*rst_gpio;
+	u32				perst_inactive_ms;
 	struct gpio_desc		*prsnt_gpio;
 	phys_addr_t			mem_start;
 	size_t				mem_size;
@@ -157,15 +180,22 @@
 	struct regmap			*pmu_grf;
 	struct dma_trx_obj		*dma_obj;
 	bool				in_suspend;
-	bool                            skip_scan_in_resume;
+	bool				skip_scan_in_resume;
 	bool				is_rk1808;
 	bool				is_signal_test;
 	bool				bifurcation;
+	bool				supports_clkreq;
 	struct regulator		*vpcie3v3;
 	struct irq_domain		*irq_domain;
 	raw_spinlock_t			intx_lock;
+	u16				aspm;
+	u32				l1ss_ctl1;
 	struct dentry			*debugfs;
 	u32				msi_vector_num;
+	struct workqueue_struct		*hot_rst_wq;
+	struct work_struct		hot_rst_work;
+	u32				comp_prst[2];
+	u32				intx;
 };
 
 struct rk_pcie_of_data {
@@ -174,7 +204,8 @@
 };
 
 #define to_rk_pcie(x)	dev_get_drvdata((x)->dev)
-static const struct dev_pm_ops rockchip_dw_pcie_pm_ops;
+static int rk_pcie_disable_power(struct rk_pcie *rk_pcie);
+static int rk_pcie_enable_power(struct rk_pcie *rk_pcie);
 
 static int rk_pcie_read(void __iomem *addr, int size, u32 *val)
 {
@@ -259,12 +290,154 @@
 	return 0;
 }
 
+static void rk_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
+{
+	int ret;
+
+	if (pci->ops->write_dbi) {
+		pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);
+		return;
+	}
+
+	ret = dw_pcie_write(pci->atu_base + reg, 4, val);
+	if (ret)
+		dev_err(pci->dev, "Write ATU address failed\n");
+}
+
+static void rk_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
+				     u32 val)
+{
+	u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+
+	rk_pcie_writel_atu(pci, offset + reg, val);
+}
+
+static u32 rk_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
+{
+	int ret;
+	u32 val;
+
+	if (pci->ops->read_dbi)
+		return pci->ops->read_dbi(pci, pci->atu_base, reg, 4);
+
+	ret = dw_pcie_read(pci->atu_base + reg, 4, &val);
+	if (ret)
+		dev_err(pci->dev, "Read ATU address failed\n");
+
+	return val;
+}
+
+static u32 rk_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
+{
+	u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+
+	return rk_pcie_readl_atu(pci, offset + reg);
+}
+
+static int rk_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
+					   int index, int bar, u64 cpu_addr,
+					   enum dw_pcie_as_type as_type)
+{
+	int type;
+	u32 retries, val;
+
+	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+				 lower_32_bits(cpu_addr));
+	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+				 upper_32_bits(cpu_addr));
+
+	switch (as_type) {
+	case DW_PCIE_AS_MEM:
+		type = PCIE_ATU_TYPE_MEM;
+		break;
+	case DW_PCIE_AS_IO:
+		type = PCIE_ATU_TYPE_IO;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type |
+				 PCIE_ATU_FUNC_NUM(func_no));
+	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+				 PCIE_ATU_FUNC_NUM_MATCH_EN |
+				 PCIE_ATU_ENABLE |
+				 PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
+
+	/*
+	 * Make sure ATU enable takes effect before any subsequent config
+	 * and I/O accesses.
+	 */
+	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+		val = rk_pcie_readl_ib_unroll(pci, index,
+					      PCIE_ATU_UNR_REGION_CTRL2);
+		if (val & PCIE_ATU_ENABLE)
+			return 0;
+
+		mdelay(LINK_WAIT_IATU);
+	}
+	dev_err(pci->dev, "Inbound iATU is not being enabled\n");
+
+	return -EBUSY;
+}
+
+
+static int rk_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
+				    int bar, u64 cpu_addr,
+				    enum dw_pcie_as_type as_type)
+{
+	int type;
+	u32 retries, val;
+
+	if (pci->iatu_unroll_enabled)
+		return rk_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
+						       cpu_addr, as_type);
+
+	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
+			   index);
+	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, lower_32_bits(cpu_addr));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, upper_32_bits(cpu_addr));
+
+	switch (as_type) {
+	case DW_PCIE_AS_MEM:
+		type = PCIE_ATU_TYPE_MEM;
+		break;
+	case DW_PCIE_AS_IO:
+		type = PCIE_ATU_TYPE_IO;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
+			   PCIE_ATU_FUNC_NUM(func_no));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE |
+			   PCIE_ATU_FUNC_NUM_MATCH_EN |
+			   PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
+
+	/*
+	 * Make sure ATU enable takes effect before any subsequent config
+	 * and I/O accesses.
+	 */
+	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+		val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
+		if (val & PCIE_ATU_ENABLE)
+			return 0;
+
+		mdelay(LINK_WAIT_IATU);
+	}
+	dev_err(pci->dev, "Inbound iATU is not being enabled\n");
+
+	return -EBUSY;
+}
+
 static int rk_pcie_ep_inbound_atu(struct rk_pcie *rk_pcie,
 				enum pci_barno bar, dma_addr_t cpu_addr,
 				enum dw_pcie_as_type as_type)
 {
 	int ret;
 	u32 free_win;
+	u8 func_no = 0x0;
 
 	if (rk_pcie->in_suspend) {
 		free_win = rk_pcie->bar_to_atu[bar];
@@ -277,8 +450,8 @@
 		}
 	}
 
-	ret = dw_pcie_prog_inbound_atu(rk_pcie->pci, free_win, bar, cpu_addr,
-				       as_type);
+	ret = rk_pcie_prog_inbound_atu(rk_pcie->pci, func_no, free_win, bar,
+				       cpu_addr, as_type);
 	if (ret < 0) {
 		dev_err(rk_pcie->pci->dev, "Failed to program IB window\n");
 		return ret;
@@ -291,6 +464,105 @@
 	set_bit(free_win, rk_pcie->ib_window_map);
 
 	return 0;
+}
+
+static void rk_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
+				     u32 val)
+{
+	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+
+	rk_pcie_writel_atu(pci, offset + reg, val);
+}
+
+static u32 rk_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
+{
+	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+
+	return rk_pcie_readl_atu(pci, offset + reg);
+}
+
+static void rk_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
+					     int index, int type,
+					     u64 cpu_addr, u64 pci_addr,
+					     u32 size)
+{
+	u32 retries, val;
+	u64 limit_addr = cpu_addr + size - 1;
+
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
+				 lower_32_bits(cpu_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
+				 upper_32_bits(cpu_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_LIMIT,
+				 lower_32_bits(limit_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_LIMIT,
+				 upper_32_bits(limit_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+				 lower_32_bits(pci_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+				 upper_32_bits(pci_addr));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
+				 type | PCIE_ATU_FUNC_NUM(func_no));
+	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+				 PCIE_ATU_ENABLE);
+
+	/*
+	 * Make sure ATU enable takes effect before any subsequent config
+	 * and I/O accesses.
+	 */
+	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+		val = rk_pcie_readl_ob_unroll(pci, index,
+					      PCIE_ATU_UNR_REGION_CTRL2);
+		if (val & PCIE_ATU_ENABLE)
+			return;
+
+		mdelay(LINK_WAIT_IATU);
+	}
+	dev_err(pci->dev, "Outbound iATU is not being enabled\n");
+}
+
+static void rk_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
+				int type, u64 cpu_addr, u64 pci_addr, u32 size)
+{
+	u32 retries, val;
+
+	if (pci->ops->cpu_addr_fixup)
+		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
+
+	if (pci->iatu_unroll_enabled) {
+		rk_pcie_prog_outbound_atu_unroll(pci, 0x0, index, type,
+						 cpu_addr, pci_addr, size);
+		return;
+	}
+
+	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
+			   PCIE_ATU_REGION_OUTBOUND | index);
+	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
+			   lower_32_bits(cpu_addr));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
+			   upper_32_bits(cpu_addr));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
+			   lower_32_bits(cpu_addr + size - 1));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
+			   lower_32_bits(pci_addr));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
+			   upper_32_bits(pci_addr));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
+			   PCIE_ATU_FUNC_NUM(0x0));
+	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
+
+	/*
+	 * Make sure ATU enable takes effect before any subsequent config
+	 * and I/O accesses.
+	 */
+	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+		val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
+		if (val & PCIE_ATU_ENABLE)
+			return;
+
+		mdelay(LINK_WAIT_IATU);
+	}
+	dev_err(pci->dev, "Outbound iATU is not being enabled\n");
 }
 
 static int rk_pcie_ep_outbound_atu(struct rk_pcie *rk_pcie,
@@ -311,7 +583,7 @@
 		}
 	}
 
-	dw_pcie_prog_outbound_atu(rk_pcie->pci, free_win, PCIE_ATU_TYPE_MEM,
+	rk_pcie_prog_outbound_atu(rk_pcie->pci, free_win, PCIE_ATU_TYPE_MEM,
 				  phys_addr, pci_addr, size);
 
 	if (rk_pcie->in_suspend)
@@ -368,6 +640,28 @@
 	return 0;
 }
 
+#if defined(CONFIG_PCIEASPM)
+static void disable_aspm_l1ss(struct rk_pcie *rk_pcie)
+{
+	u32 val, cfg_link_cap_l1sub;
+
+	val = dw_pcie_find_ext_capability(rk_pcie->pci, PCI_EXT_CAP_ID_L1SS);
+	if (!val) {
+		dev_err(rk_pcie->pci->dev, "can't find l1ss cap\n");
+
+		return;
+	}
+
+	cfg_link_cap_l1sub = val + PCI_L1SS_CAP;
+
+	val = dw_pcie_readl_dbi(rk_pcie->pci, cfg_link_cap_l1sub);
+	val &= ~(PCI_L1SS_CAP_ASPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_2 | PCI_L1SS_CAP_L1_PM_SS);
+	dw_pcie_writel_dbi(rk_pcie->pci, cfg_link_cap_l1sub, val);
+}
+#else
+static inline void disable_aspm_l1ss(struct rk_pcie *rk_pcie) { return; }
+#endif
+
 static inline void rk_pcie_set_mode(struct rk_pcie *rk_pcie)
 {
 	switch (rk_pcie->mode) {
@@ -375,6 +669,14 @@
 		rk_pcie_writel_apb(rk_pcie, 0x0, 0xf00000);
 		break;
 	case RK_PCIE_RC_TYPE:
+		if (rk_pcie->supports_clkreq) {
+			/* Application is ready to have reference clock removed */
+			rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_POWER, 0x00010001);
+		} else {
+			/* Pull down CLKREQ# to assert the connecting CLOCK_GEN OE */
+			rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_POWER, 0x30011000);
+			disable_aspm_l1ss(rk_pcie);
+		}
 		rk_pcie_writel_apb(rk_pcie, 0x0, 0xf00040);
 		/*
 		 * Disable order rule for CPL can't pass halted P queue.
@@ -404,28 +706,10 @@
 	rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C);
 }
 
-static int rk_pcie_link_up(struct dw_pcie *pci)
-{
-	struct rk_pcie *rk_pcie = to_rk_pcie(pci);
-	u32 val;
-
-	if (rk_pcie->is_rk1808) {
-		val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG);
-		if ((val & (PCIE_PHY_LINKUP | PCIE_DATA_LINKUP)) == 0x3 &&
-		    ((val & GENMASK(15, 10)) >> 10) == 0x11)
-			return 1;
-	} else {
-		val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS);
-		if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000)
-			return 1;
-	}
-
-	return 0;
-}
-
 static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
 {
-#if RK_PCIE_DBG
+	if (!IS_ENABLED(CONFIG_DEBUG_FS))
+		return;
 	if (rk_pcie->is_rk1808 == true)
 		return;
 
@@ -439,7 +723,6 @@
 			   PCIE_CLIENT_DBG_TRANSITION_DATA);
 	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
 			   PCIE_CLIENT_DBF_EN);
-#endif
 }
 
 static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
@@ -461,6 +744,8 @@
 	int retries, power;
 	struct rk_pcie *rk_pcie = to_rk_pcie(pci);
 	bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj;
+	int hw_retries = 0;
+	u32 ltssm;
 
 	/*
 	 * For standard RC, even if the link has been setup by firmware,
@@ -472,80 +757,113 @@
 		return 0;
 	}
 
-	rk_pcie_disable_ltssm(rk_pcie);
-	rk_pcie_link_status_clear(rk_pcie);
-	rk_pcie_enable_debug(rk_pcie);
+	for (hw_retries = 0; hw_retries < RK_PCIE_ENUM_HW_RETRYIES; hw_retries++) {
+		/* Rest the device */
+		gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0);
 
-	/* Enable client reset or link down interrupt */
-	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000);
+		rk_pcie_disable_ltssm(rk_pcie);
+		rk_pcie_link_status_clear(rk_pcie);
+		rk_pcie_enable_debug(rk_pcie);
 
-	/* Enable LTSSM */
-	rk_pcie_enable_ltssm(rk_pcie);
+		/* Enable client reset or link down interrupt */
+		rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000);
 
-	/*
-	 * In resume routine, function devices' resume function must be late after
-	 * controllers'. Some devices, such as Wi-Fi, need special IO setting before
-	 * finishing training. So there must be timeout here. These kinds of devices
-	 * need rescan devices by its driver when used. So no need to waste time waiting
-	 * for training pass.
-	 */
-	if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) {
-		rfkill_get_wifi_power_state(&power);
-		if (!power) {
-			gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
-			return 0;
+		/* Enable LTSSM */
+		rk_pcie_enable_ltssm(rk_pcie);
+
+		/*
+		 * In resume routine, function devices' resume function must be late after
+		 * controllers'. Some devices, such as Wi-Fi, need special IO setting before
+		 * finishing training. So there must be timeout here. These kinds of devices
+		 * need rescan devices by its driver when used. So no need to waste time waiting
+		 * for training pass.
+		 */
+		if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) {
+			rfkill_get_wifi_power_state(&power);
+			if (!power) {
+				gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
+				return 0;
+			}
 		}
-	}
 
-	/*
-	 * PCIe requires the refclk to be stable for 100µs prior to releasing
-	 * PERST and T_PVPERL (Power stable to PERST# inactive) should be a
-	 * minimum of 100ms.  See table 2-4 in section 2.6.2 AC, the PCI Express
-	 * Card Electromechanical Specification 3.0. So 100ms in total is the min
-	 * requuirement here. We add a 1s for sake of hoping everthings work fine.
-	 */
-	msleep(1000);
-	gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
+		/*
+		 * PCIe requires the refclk to be stable for 100µs prior to releasing
+		 * PERST and T_PVPERL (Power stable to PERST# inactive) should be a
+		 * minimum of 100ms.  See table 2-4 in section 2.6.2 AC, the PCI Express
+		 * Card Electromechanical Specification 3.0. So 100ms in total is the min
+		 * requuirement here. We add a 200ms by default for sake of hoping everthings
+		 * work fine. If it doesn't, please add more in DT node by add rockchip,perst-inactive-ms.
+		 */
+		msleep(rk_pcie->perst_inactive_ms);
+		gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
 
-	/*
-	 * Add this 1ms delay because we observe link is always up stably after it and
-	 * could help us save 20ms for scanning devices.
-	 */
-	 usleep_range(1000, 1100);
+		/*
+		 * Add this 1ms delay because we observe link is always up stably after it and
+		 * could help us save 20ms for scanning devices.
+		 */
+		usleep_range(1000, 1100);
 
-	for (retries = 0; retries < 10; retries++) {
-		if (dw_pcie_link_up(pci)) {
-			/*
-			 * We may be here in case of L0 in Gen1. But if EP is capable
-			 * of Gen2 or Gen3, Gen switch may happen just in this time, but
-			 * we keep on accessing devices in unstable link status. Given
-			 * that LTSSM max timeout is 24ms per period, we can wait a bit
-			 * more for Gen switch.
-			 */
-			msleep(100);
-			dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n",
-				 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
+		for (retries = 0; retries < 100; retries++) {
+			if (dw_pcie_link_up(pci)) {
+				/*
+				 * We may be here in case of L0 in Gen1. But if EP is capable
+				 * of Gen2 or Gen3, Gen switch may happen just in this time, but
+				 * we keep on accessing devices in unstable link status. Given
+				 * that LTSSM max timeout is 24ms per period, we can wait a bit
+				 * more for Gen switch.
+				 */
+				msleep(50);
+				/* In case link drop after linkup, double check it */
+				if (dw_pcie_link_up(pci)) {
+					dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n",
+						rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
+					rk_pcie_debug_dump(rk_pcie);
+					return 0;
+				}
+			}
+
+			dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n",
+					rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
 			rk_pcie_debug_dump(rk_pcie);
-			return 0;
+			msleep(20);
 		}
 
-		dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n",
-				     rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
-		rk_pcie_debug_dump(rk_pcie);
-		msleep(1000);
+		/*
+		 * In response to the situation where PCIe peripherals cannot be
+		 * enumerated due tosignal abnormalities, reset PERST# and reset
+		 * the peripheral power supply, then restart the enumeration.
+		 */
+		ltssm = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS);
+		dev_err(pci->dev, "PCIe Link Fail, LTSSM is 0x%x, hw_retries=%d\n", ltssm, hw_retries);
+		if (ltssm >= 3 && !rk_pcie->is_signal_test) {
+			rk_pcie_disable_power(rk_pcie);
+			msleep(1000);
+			rk_pcie_enable_power(rk_pcie);
+		} else {
+			break;
+		}
 	}
-
-	dev_err(pci->dev, "PCIe Link Fail\n");
 
 	return rk_pcie->is_signal_test == true ? 0 : -EINVAL;
 }
 
+static bool rk_pcie_udma_enabled(struct rk_pcie *rk_pcie)
+{
+	return dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
+				 PCIE_DMA_CTRL_OFF);
+}
+
 static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie)
 {
+	if (!rk_pcie_udma_enabled(rk_pcie))
+		return 0;
+
 	rk_pcie->dma_obj = rk_pcie_dma_obj_probe(rk_pcie->pci->dev);
 	if (IS_ERR(rk_pcie->dma_obj)) {
 		dev_err(rk_pcie->pci->dev, "failed to prepare dma object\n");
 		return -EINVAL;
+	} else if (rk_pcie->dma_obj) {
+		goto out;
 	}
 
 	rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci->dev, true);
@@ -553,7 +871,7 @@
 		dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n");
 		return -EINVAL;
 	}
-
+out:
 	/* Enable client write and read interrupt */
 	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
 
@@ -566,6 +884,76 @@
 	return 0;
 }
 
+static int rk_pci_find_resbar_capability(struct rk_pcie *rk_pcie)
+{
+	u32 header;
+	int ttl;
+	int start = 0;
+	int pos = PCI_CFG_SPACE_SIZE;
+	int cap = PCI_EXT_CAP_ID_REBAR;
+
+	/* minimum 8 bytes per capability */
+	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+	header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
+
+	/*
+	 * If we have no capabilities, this is indicated by cap ID,
+	 * cap version and next pointer all being 0.
+	 */
+	if (header == 0)
+		return 0;
+
+	while (ttl-- > 0) {
+		if (PCI_EXT_CAP_ID(header) == cap && pos != start)
+			return pos;
+
+		pos = PCI_EXT_CAP_NEXT(header);
+		if (pos < PCI_CFG_SPACE_SIZE)
+			break;
+
+		header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
+		if (!header)
+			break;
+	}
+
+	return 0;
+}
+
+#ifdef MODULE
+void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
+{
+	int ret;
+
+	if (pci->ops && pci->ops->write_dbi2) {
+		pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
+		return;
+	}
+
+	ret = dw_pcie_write(pci->dbi_base2 + reg, size, val);
+	if (ret)
+		dev_err(pci->dev, "write DBI address failed\n");
+}
+#endif
+
+static int rk_pcie_ep_set_bar_flag(struct rk_pcie *rk_pcie, enum pci_barno barno, int flags)
+{
+	enum pci_barno bar = barno;
+	u32 reg;
+
+	reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+
+	/* Disabled the upper 32bits BAR to make a 64bits bar pair */
+	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
+		dw_pcie_writel_dbi2(rk_pcie->pci, reg + 4, 0);
+
+	dw_pcie_writel_dbi(rk_pcie->pci, reg, flags);
+	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
+		dw_pcie_writel_dbi(rk_pcie->pci, reg + 4, 0);
+
+	return 0;
+}
+
 static void rk_pcie_ep_setup(struct rk_pcie *rk_pcie)
 {
 	int ret;
@@ -573,6 +961,8 @@
 	u32 lanes;
 	struct device *dev = rk_pcie->pci->dev;
 	struct device_node *np = dev->of_node;
+	int resbar_base;
+	int bar;
 
 	/* Enable client write and read interrupt */
 	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
@@ -636,17 +1026,36 @@
 	/* Enable bus master and memory space */
 	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_TYPE0_STATUS_COMMAND_REG, 0x6);
 
-	/* Resize BAR0 to 4GB */
-	/* bit13-8 set to 6 means 64MB */
-	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_RESBAR_CTRL_REG0_REG, 0x600);
+	resbar_base = rk_pci_find_resbar_capability(rk_pcie);
+	if (!resbar_base) {
+		dev_warn(dev, "failed to find resbar_base\n");
+	} else {
+		/* Resize BAR0 to support 512GB, BAR1 to support 8M, BAR2~5 to support 64M */
+		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x4, 0xfffff0);
+		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x8, 0x13c0);
+		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0xc, 0xfffff0);
+		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x10, 0x3c0);
+		for (bar = 2; bar < 6; bar++) {
+			dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x4 + bar * 0x8, 0xfffff0);
+			dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x8 + bar * 0x8, 0x6c0);
+		}
 
-	/* Set shadow BAR0 according 64MB */
-	val = rk_pcie->mem_size - 1;
-	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_SB_BAR0_MASK_REG, val);
+		/* Set flags */
+		rk_pcie_ep_set_bar_flag(rk_pcie, BAR_0, PCI_BASE_ADDRESS_MEM_TYPE_32);
+		rk_pcie_ep_set_bar_flag(rk_pcie, BAR_1, PCI_BASE_ADDRESS_MEM_TYPE_32);
+		rk_pcie_ep_set_bar_flag(rk_pcie, BAR_2, PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64);
+		rk_pcie_ep_set_bar_flag(rk_pcie, BAR_4, PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64);
+	}
 
-	/* Set reserved memory address to BAR0 */
-	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_TYPE0_BAR0_REG,
-			   rk_pcie->mem_start);
+	/* Device id and class id needed for request bar address */
+	dw_pcie_writew_dbi(rk_pcie->pci, PCI_DEVICE_ID, 0x356a);
+	dw_pcie_writew_dbi(rk_pcie->pci, PCI_CLASS_DEVICE, 0x0580);
+
+	/* Set shadow BAR0 */
+	if (rk_pcie->is_rk1808) {
+		val = rk_pcie->mem_size - 1;
+		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_SB_BAR0_MASK_REG, val);
+	}
 }
 
 static int rk_pcie_ep_win_parse(struct rk_pcie *rk_pcie)
@@ -722,6 +1131,10 @@
 
 	dw_pcie_setup_rc(pp);
 
+	/* Disable BAR0 BAR1 */
+	dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0);
+	dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0);
+
 	ret = rk_pcie_establish_link(pci);
 
 	if (pp->msi_irq > 0)
@@ -754,9 +1167,6 @@
 	}
 
 	pp->ops = &rk_pcie_host_ops;
-
-	if (device_property_read_bool(dev, "msi-map"))
-		pp->msi_ext = 1;
 
 	ret = dw_pcie_host_init(pp);
 	if (ret) {
@@ -796,6 +1206,7 @@
 		return ret;
 	}
 
+	rk_pcie->pci->atu_base = rk_pcie->pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
 	rk_pcie->pci->iatu_unroll_enabled = rk_pcie_iatu_unroll_enabled(rk_pcie->pci);
 
 	ret = rk_pcie_ep_atu_init(rk_pcie);
@@ -812,52 +1223,24 @@
 		return ret;
 	}
 
-	return 0;
-}
+	if (!rk_pcie_udma_enabled(rk_pcie))
+		return 0;
 
-static void rk_pcie_clk_deinit(struct rk_pcie *rk_pcie)
-{
-	clk_bulk_disable(rk_pcie->clk_cnt, rk_pcie->clks);
-	clk_bulk_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
+	return 0;
 }
 
 static int rk_pcie_clk_init(struct rk_pcie *rk_pcie)
 {
 	struct device *dev = rk_pcie->pci->dev;
-	struct property *prop;
-	const char *name;
-	int i = 0, ret, count;
+	int ret;
 
-	count = of_property_count_strings(dev->of_node, "clock-names");
-	if (count < 1)
+	rk_pcie->clk_cnt = devm_clk_bulk_get_all(dev, &rk_pcie->clks);
+	if (rk_pcie->clk_cnt < 1)
 		return -ENODEV;
 
-	rk_pcie->clks = devm_kcalloc(dev, count,
-				     sizeof(struct clk_bulk_data),
-				     GFP_KERNEL);
-	if (!rk_pcie->clks)
-		return -ENOMEM;
-
-	rk_pcie->clk_cnt = count;
-
-	of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
-		rk_pcie->clks[i].id = name;
-		if (!rk_pcie->clks[i].id)
-			return -ENOMEM;
-		i++;
-	}
-
-	ret = devm_clk_bulk_get(dev, count, rk_pcie->clks);
-	if (ret)
-		return ret;
-
-	ret = clk_bulk_prepare(count, rk_pcie->clks);
-	if (ret)
-		return ret;
-
-	ret = clk_bulk_enable(count, rk_pcie->clks);
+	ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks);
 	if (ret) {
-		clk_bulk_unprepare(count, rk_pcie->clks);
+		dev_err(dev, "failed to prepare enable pcie bulk clks: %d\n", ret);
 		return ret;
 	}
 
@@ -882,6 +1265,7 @@
 		return PTR_ERR(rk_pcie->dbi_base);
 
 	rk_pcie->pci->dbi_base = rk_pcie->dbi_base;
+	rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET;
 
 	apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"pcie-apb");
@@ -908,6 +1292,10 @@
 		return PTR_ERR(rk_pcie->rst_gpio);
 	}
 
+	if (device_property_read_u32(&pdev->dev, "rockchip,perst-inactive-ms",
+				     &rk_pcie->perst_inactive_ms))
+		rk_pcie->perst_inactive_ms = 200;
+
 	rk_pcie->prsnt_gpio = devm_gpiod_get_optional(&pdev->dev, "prsnt", GPIOD_IN);
 	if (IS_ERR_OR_NULL(rk_pcie->prsnt_gpio))
 		dev_info(&pdev->dev, "invalid prsnt-gpios property in node\n");
@@ -920,7 +1308,7 @@
 	int ret;
 	struct device *dev = rk_pcie->pci->dev;
 
-	rk_pcie->phy = devm_phy_get(dev, "pcie-phy");
+	rk_pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
 	if (IS_ERR(rk_pcie->phy)) {
 		if (PTR_ERR(rk_pcie->phy) != -EPROBE_DEFER)
 			dev_info(dev, "missing phy\n");
@@ -929,23 +1317,27 @@
 
 	switch (rk_pcie->mode) {
 	case RK_PCIE_RC_TYPE:
-		rk_pcie->phy_mode = PHY_MODE_PCIE_RC;
+		rk_pcie->phy_mode = PHY_MODE_PCIE; /* make no sense */
+		rk_pcie->phy_sub_mode = PHY_MODE_PCIE_RC;
 		break;
 	case RK_PCIE_EP_TYPE:
-		rk_pcie->phy_mode = PHY_MODE_PCIE_EP;
+		rk_pcie->phy_mode = PHY_MODE_PCIE;
+		rk_pcie->phy_sub_mode = PHY_MODE_PCIE_EP;
 		break;
 	}
 
-	ret = phy_set_mode(rk_pcie->phy, rk_pcie->phy_mode);
+	ret = phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
+			       rk_pcie->phy_sub_mode);
 	if (ret) {
 		dev_err(dev, "fail to set phy to  mode %s, err %d\n",
-			(rk_pcie->phy_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
+			(rk_pcie->phy_sub_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
 			ret);
 		return ret;
 	}
 
 	if (rk_pcie->bifurcation)
-		ret = phy_set_mode(rk_pcie->phy, PHY_MODE_PCIE_BIFURCATION);
+		phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
+				 PHY_MODE_PCIE_BIFURCATION);
 
 	ret = phy_init(rk_pcie->phy);
 	if (ret < 0) {
@@ -954,53 +1346,6 @@
 	}
 
 	phy_power_on(rk_pcie->phy);
-
-	return 0;
-}
-
-static int rk_pcie_reset_control_release(struct rk_pcie *rk_pcie)
-{
-	struct device *dev = rk_pcie->pci->dev;
-	struct property *prop;
-	const char *name;
-	int ret, count, i = 0;
-
-	count = of_property_count_strings(dev->of_node, "reset-names");
-	if (count < 1)
-		return -ENODEV;
-
-	rk_pcie->rsts = devm_kcalloc(dev, count,
-				     sizeof(struct reset_bulk_data),
-				     GFP_KERNEL);
-	if (!rk_pcie->rsts)
-		return -ENOMEM;
-
-	of_property_for_each_string(dev->of_node, "reset-names",
-				    prop, name) {
-		rk_pcie->rsts[i].id = name;
-		if (!rk_pcie->rsts[i].id)
-			return -ENOMEM;
-		i++;
-	}
-
-	for (i = 0; i < count; i++) {
-		rk_pcie->rsts[i].rst = devm_reset_control_get_exclusive(dev,
-						rk_pcie->rsts[i].id);
-		if (IS_ERR_OR_NULL(rk_pcie->rsts[i].rst)) {
-			dev_err(dev, "failed to get %s\n",
-				rk_pcie->clks[i].id);
-			return -PTR_ERR(rk_pcie->rsts[i].rst);
-		}
-	}
-
-	for (i = 0; i < count; i++) {
-		ret = reset_control_deassert(rk_pcie->rsts[i].rst);
-		if (ret) {
-			dev_err(dev, "failed to release %s\n",
-				rk_pcie->rsts[i].id);
-			return ret;
-		}
-	}
 
 	return 0;
 }
@@ -1105,13 +1450,37 @@
 	table->start.chnl = table->chn;
 }
 
+static void rk_pcie_hot_rst_work(struct work_struct *work)
+{
+	struct rk_pcie *rk_pcie = container_of(work, struct rk_pcie, hot_rst_work);
+	u32 val, status;
+	int ret;
+
+	/* Setup command register */
+	val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND);
+	val &= 0xffff0000;
+	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+	dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val);
+
+	if (rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN) {
+		ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_LTSSM_STATUS,
+			 status, ((status & 0x3F) == 0), 100, RK_PCIE_HOTRESET_TMOUT_US);
+		if (ret)
+			dev_err(rk_pcie->pci->dev, "wait for detect quiet failed!\n");
+
+		rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL,
+			(PCIE_LTSSM_APP_DLY2_DONE) | ((PCIE_LTSSM_APP_DLY2_DONE) << 16));
+	}
+}
+
 static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg)
 {
 	struct rk_pcie *rk_pcie = arg;
 	u32 chn;
 	union int_status status;
 	union int_clear clears;
-	u32 reg, val;
+	u32 reg;
 
 	status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
 					   PCIE_DMA_WR_INT_STATUS);
@@ -1152,14 +1521,8 @@
 	}
 
 	reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC);
-	if (reg & BIT(2)) {
-		/* Setup command register */
-		val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND);
-		val &= 0xffff0000;
-		val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-		       PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
-		dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val);
-	}
+	if (reg & BIT(2))
+		queue_work(rk_pcie->hot_rst_wq, &rk_pcie->hot_rst_work);
 
 	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC, reg);
 
@@ -1215,11 +1578,23 @@
 		.data = &rk3528_pcie_rc_of_data,
 	},
 	{
+		.compatible = "rockchip,rk3562-pcie",
+		.data = &rk3528_pcie_rc_of_data,
+	},
+	{
 		.compatible = "rockchip,rk3568-pcie",
 		.data = &rk_pcie_rc_of_data,
 	},
 	{
 		.compatible = "rockchip,rk3568-pcie-ep",
+		.data = &rk_pcie_ep_of_data,
+	},
+	{
+		.compatible = "rockchip,rk3588-pcie",
+		.data = &rk_pcie_rc_of_data,
+	},
+	{
+		.compatible = "rockchip,rk3588-pcie-ep",
 		.data = &rk_pcie_ep_of_data,
 	},
 	{},
@@ -1229,7 +1604,6 @@
 
 static const struct dw_pcie_ops dw_pcie_ops = {
 	.start_link = rk_pcie_establish_link,
-	.link_up = rk_pcie_link_up,
 };
 
 static int rk1808_pcie_fixup(struct rk_pcie *rk_pcie, struct device_node *np)
@@ -1271,7 +1645,8 @@
 
 	/* LTSSM EN ctrl mode */
 	val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL);
-	val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
+	val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN)
+		| ((PCIE_LTSSM_APP_DLY2_EN | PCIE_LTSSM_ENABLE_ENHANCE) << 16);
 	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, val);
 }
 
@@ -1309,7 +1684,7 @@
 static int rk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 			    irq_hw_number_t hwirq)
 {
-	irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_simple_irq);
+	irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_level_irq);
 	irq_set_chip_data(irq, domain->host_data);
 
 	return 0;
@@ -1398,41 +1773,6 @@
 	return ret;
 }
 
-static int rk_pci_find_capability(struct rk_pcie *rk_pcie, int cap)
-{
-	u32 header;
-	int ttl;
-	int start = 0;
-	int pos = PCI_CFG_SPACE_SIZE;
-
-	/* minimum 8 bytes per capability */
-	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
-
-	header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
-
-	/*
-	 * If we have no capabilities, this is indicated by cap ID,
-	 * cap version and next pointer all being 0.
-	 */
-	if (header == 0)
-		return 0;
-
-	while (ttl-- > 0) {
-		if (PCI_EXT_CAP_ID(header) == cap && pos != start)
-			return pos;
-
-		pos = PCI_EXT_CAP_NEXT(header);
-		if (pos < PCI_CFG_SPACE_SIZE)
-			break;
-
-		header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
-		if (!header)
-			break;
-	}
-
-	return 0;
-}
-
 #define RAS_DES_EVENT(ss, v) \
 do { \
 	dw_pcie_writel_dbi(pcie->pci, cap_base + 8, v); \
@@ -1443,8 +1783,27 @@
 {
 	struct rk_pcie *pcie = s->private;
 	int cap_base;
+	u32 val = rk_pcie_readl_apb(pcie, PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN);
+	char *pm;
 
-	cap_base = rk_pci_find_capability(pcie, PCI_EXT_CAP_ID_VNDR);
+	if (val & BIT(6))
+		pm = "In training";
+	else if (val & BIT(5))
+		pm = "L1.2";
+	else if (val & BIT(4))
+		pm = "L1.1";
+	else if (val & BIT(3))
+		pm = "L1";
+	else if (val & BIT(2))
+		pm = "L0";
+	else if (val & 0x3)
+		pm = (val == 0x3) ? "L0s" : (val & BIT(1) ? "RX L0s" : "TX L0s");
+	else
+		pm = "Invalid";
+
+	seq_printf(s, "Common event signal status: 0x%s\n", pm);
+
+	cap_base = dw_pcie_find_ext_capability(pcie->pci, PCI_EXT_CAP_ID_VNDR);
 	if (!cap_base) {
 		dev_err(pcie->pci->dev, "Not able to find RASDES CAP!\n");
 		return 0;
@@ -1480,7 +1839,6 @@
 
 	return 0;
 }
-
 static int rockchip_pcie_rasdes_open(struct inode *inode, struct file *file)
 {
 	return single_open(file, rockchip_pcie_rasdes_show,
@@ -1499,7 +1857,7 @@
 	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
-	cap_base = rk_pci_find_capability(pcie, PCI_EXT_CAP_ID_VNDR);
+	cap_base = dw_pcie_find_ext_capability(pcie->pci, PCI_EXT_CAP_ID_VNDR);
 	if (!cap_base) {
 		dev_err(pcie->pci->dev, "Not able to find RASDES CAP!\n");
 		return 0;
@@ -1584,7 +1942,6 @@
 	const struct rk_pcie_of_data *data;
 	enum rk_pcie_device_mode mode;
 	struct device_node *np = pdev->dev.of_node;
-	struct platform_driver *drv = to_platform_driver(dev->driver);
 	u32 val = 0;
 	int irq;
 
@@ -1633,10 +1990,13 @@
 
 	if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) {
 		if (!gpiod_get_value(rk_pcie->prsnt_gpio)) {
+			dev_info(dev, "device isn't present\n");
 			ret = -ENODEV;
 			goto release_driver;
 		}
 	}
+
+	rk_pcie->supports_clkreq = device_property_read_bool(dev, "supports-clkreq");
 
 retry_regulator:
 	/* DON'T MOVE ME: must be enable before phy init */
@@ -1667,11 +2027,14 @@
 		goto disable_vpcie3v3;
 	}
 
-	ret = rk_pcie_reset_control_release(rk_pcie);
-	if (ret) {
-		dev_err(dev, "reset control init failed\n");
+	rk_pcie->rsts = devm_reset_control_array_get_exclusive(dev);
+	if (IS_ERR(rk_pcie->rsts)) {
+		ret = PTR_ERR(rk_pcie->rsts);
+		dev_err(dev, "failed to get reset lines\n");
 		goto disable_phy;
 	}
+
+	reset_control_deassert(rk_pcie->rsts);
 
 	ret = rk_pcie_request_sys_irq(rk_pcie, pdev);
 	if (ret) {
@@ -1723,17 +2086,39 @@
 		rk_pcie->is_signal_test = true;
 	}
 
-	/* Force into compliance mode */
-	if (device_property_read_bool(dev, "rockchip,compliance-mode")) {
-		val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS);
-		val |= BIT(4);
-		dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val);
+	/*
+	 * Force into compliance mode
+	 * comp_prst is a two dimensional array of which the first element
+	 * stands for speed mode, and the second one is preset value encoding:
+	 * [0] 0->SMA tool control the signal switch, 1/2/3 is for manual Gen setting
+	 * [1] transmitter setting for manual Gen setting, valid only if [0] isn't zero.
+	 */
+	if (!device_property_read_u32_array(dev, "rockchip,compliance-mode",
+					    rk_pcie->comp_prst, 2)) {
+		BUG_ON(rk_pcie->comp_prst[0] > 3 || rk_pcie->comp_prst[1] > 10);
+		if (!rk_pcie->comp_prst[0]) {
+			dev_info(dev, "Auto compliance mode for SMA tool.\n");
+		} else {
+			dev_info(dev, "compliance mode for soldered board Gen%d, P%d.\n",
+				 rk_pcie->comp_prst[0], rk_pcie->comp_prst[1]);
+			val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS);
+			val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12);
+			dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val);
+		}
 		rk_pcie->is_signal_test = true;
 	}
 
 	/* Skip waiting for training to pass in system PM routine */
 	if (device_property_read_bool(dev, "rockchip,skip-scan-in-resume"))
 		rk_pcie->skip_scan_in_resume = true;
+
+	rk_pcie->hot_rst_wq = create_singlethread_workqueue("rk_pcie_hot_rst_wq");
+	if (!rk_pcie->hot_rst_wq) {
+		dev_err(dev, "failed to create hot_rst workqueue\n");
+		ret = -ENOMEM;
+		goto remove_irq_domain;
+	}
+	INIT_WORK(&rk_pcie->hot_rst_work, rk_pcie_hot_rst_work);
 
 	switch (rk_pcie->mode) {
 	case RK_PCIE_RC_TYPE:
@@ -1748,12 +2133,12 @@
 		return 0;
 
 	if (ret)
-		goto remove_irq_domain;
+		goto remove_rst_wq;
 
 	ret = rk_pcie_init_dma_trx(rk_pcie);
 	if (ret) {
 		dev_err(dev, "failed to add dma extension\n");
-		return ret;
+		goto remove_rst_wq;
 	}
 
 	if (rk_pcie->dma_obj) {
@@ -1765,13 +2150,15 @@
 		/* hold link reset grant after link-up */
 		ret = rk_pcie_reset_grant_ctrl(rk_pcie, false);
 		if (ret)
-			goto remove_irq_domain;
+			goto remove_rst_wq;
 	}
 
 	dw_pcie_dbi_ro_wr_dis(pci);
 
 	device_init_wakeup(dev, true);
-	drv->driver.pm = &rockchip_dw_pcie_pm_ops;
+
+	/* Enable async system PM for multiports SoC */
+	device_enable_async_suspend(dev);
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		ret = rockchip_pcie_debugfs_init(rk_pcie);
@@ -1779,7 +2166,7 @@
 			dev_err(dev, "failed to setup debugfs: %d\n", ret);
 
 		/* Enable RASDES Error event by default */
-		val = rk_pci_find_capability(rk_pcie, PCI_EXT_CAP_ID_VNDR);
+		val = dw_pcie_find_ext_capability(rk_pcie->pci, PCI_EXT_CAP_ID_VNDR);
 		if (!val) {
 			dev_err(dev, "Not able to find RASDES CAP!\n");
 			return 0;
@@ -1791,6 +2178,8 @@
 
 	return 0;
 
+remove_rst_wq:
+	destroy_workqueue(rk_pcie->hot_rst_wq);
 remove_irq_domain:
 	if (rk_pcie->irq_domain)
 		irq_domain_remove(rk_pcie->irq_domain);
@@ -1798,10 +2187,9 @@
 	phy_power_off(rk_pcie->phy);
 	phy_exit(rk_pcie->phy);
 deinit_clk:
-	rk_pcie_clk_deinit(rk_pcie);
+	clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
 disable_vpcie3v3:
 	rk_pcie_disable_power(rk_pcie);
-
 release_driver:
 	if (IS_ENABLED(CONFIG_PCIE_RK_THREADED_INIT))
 		device_release_driver(dev);
@@ -1826,13 +2214,154 @@
 	return rk_pcie_really_probe(pdev);
 }
 
+#ifdef CONFIG_PCIEASPM
+static void rk_pcie_downstream_dev_to_d0(struct rk_pcie *rk_pcie, bool enable)
+{
+	struct pcie_port *pp = &rk_pcie->pci->pp;
+	struct pci_bus *child, *root_bus = NULL;
+	struct pci_dev *pdev, *bridge;
+	u32 val;
+
+	list_for_each_entry(child, &pp->bridge->bus->children, node) {
+		/* Bring downstream devices to D3 if they are not already in */
+		if (child->parent == pp->bridge->bus) {
+			root_bus = child;
+			bridge = root_bus->self;
+			break;
+		}
+	}
+
+	if (!root_bus) {
+		dev_err(rk_pcie->pci->dev, "Failed to find downstream devices\n");
+		return;
+	}
+
+	/* Save and restore root bus ASPM */
+	if (enable) {
+		if (rk_pcie->l1ss_ctl1)
+			dw_pcie_writel_dbi(rk_pcie->pci, bridge->l1ss + PCI_L1SS_CTL1, rk_pcie->l1ss_ctl1);
+
+		/* rk_pcie->aspm woule be saved in advance when enable is false */
+		dw_pcie_writel_dbi(rk_pcie->pci, bridge->pcie_cap + PCI_EXP_LNKCTL, rk_pcie->aspm);
+	} else {
+		val = dw_pcie_readl_dbi(rk_pcie->pci, bridge->l1ss + PCI_L1SS_CTL1);
+		if (val & PCI_L1SS_CTL1_L1SS_MASK)
+			rk_pcie->l1ss_ctl1 = val;
+		else
+			rk_pcie->l1ss_ctl1 = 0;
+
+		val = dw_pcie_readl_dbi(rk_pcie->pci, bridge->pcie_cap + PCI_EXP_LNKCTL);
+		rk_pcie->aspm = val & PCI_EXP_LNKCTL_ASPMC;
+		val &= ~(PCI_EXP_LNKCAP_ASPM_L1 | PCI_EXP_LNKCAP_ASPM_L0S);
+		dw_pcie_writel_dbi(rk_pcie->pci, bridge->pcie_cap + PCI_EXP_LNKCTL, val);
+	}
+
+	list_for_each_entry(pdev, &root_bus->devices, bus_list) {
+		if (PCI_SLOT(pdev->devfn) == 0) {
+			if (pci_set_power_state(pdev, PCI_D0))
+				dev_err(rk_pcie->pci->dev,
+					"Failed to transition %s to D3hot state\n",
+					dev_name(&pdev->dev));
+			if (enable) {
+				if (rk_pcie->l1ss_ctl1) {
+					pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, &val);
+					val &= ~PCI_L1SS_CTL1_L1SS_MASK;
+					val |= (rk_pcie->l1ss_ctl1 & PCI_L1SS_CTL1_L1SS_MASK);
+					pci_write_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, val);
+				}
+
+				pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_ASPMC, rk_pcie->aspm);
+			} else {
+				pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+			}
+		}
+	}
+}
+#endif
+
 static int __maybe_unused rockchip_dw_pcie_suspend(struct device *dev)
 {
 	struct rk_pcie *rk_pcie = dev_get_drvdata(dev);
-	int ret;
+	int ret = 0, power;
+	struct dw_pcie *pci = rk_pcie->pci;
+	u32 status;
+
+	/*
+	 * This is as per PCI Express Base r5.0 r1.0 May 22-2019,
+	 * 5.2 Link State Power Management (Page #440).
+	 *
+	 * L2/L3 Ready entry negotiations happen while in the L0 state.
+	 * L2/L3 Ready are entered only after the negotiation completes.
+	 *
+	 * The following example sequence illustrates the multi-step Link state
+	 * transition process leading up to entering a system sleep state:
+	 * 1. System software directs all Functions of a Downstream component to D3Hot.
+	 * 2. The Downstream component then initiates the transition of the Link to L1
+	 *    as required.
+	 * 3. System software then causes the Root Complex to broadcast the PME_Turn_Off
+	 *    Message in preparation for removing the main power source.
+	 * 4. This Message causes the subject Link to transition back to L0 in order to
+	 *    send it and to enable the Downstream component to respond with PME_TO_Ack.
+	 * 5. After sending the PME_TO_Ack, the Downstream component initiates the L2/L3
+	 *    Ready transition protocol.
+	 */
+
+	/* 1. All sub-devices are in D3hot by PCIe stack */
+	dw_pcie_dbi_ro_wr_dis(rk_pcie->pci);
 
 	rk_pcie_link_status_clear(rk_pcie);
+
+	/*
+	 * Wlan devices will be shutdown from function driver now, so doing L2 here
+	 * must fail. Skip L2 routine.
+	 */
+	if (rk_pcie->skip_scan_in_resume) {
+		rfkill_get_wifi_power_state(&power);
+		if (!power)
+			goto no_l2;
+	}
+
+	/* 2. Broadcast PME_Turn_Off Message */
+	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_MSG_GEN, PME_TURN_OFF);
+	ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_MSG_GEN,
+				 status, !(status & BIT(4)), 20, RK_PCIE_L2_TMOUT_US);
+	if (ret) {
+		dev_err(dev, "Failed to send PME_Turn_Off\n");
+		goto no_l2;
+	}
+
+	/* 3. Wait for PME_TO_Ack */
+	ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_INTR_STATUS_MSG_RX,
+				 status, status & BIT(9), 20, RK_PCIE_L2_TMOUT_US);
+	if (ret) {
+		dev_err(dev, "Failed to receive PME_TO_Ack\n");
+		goto no_l2;
+	}
+
+	/* 4. Clear PME_TO_Ack and Wait for ready to enter L23 message */
+	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MSG_RX, PME_TO_ACK);
+	ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_POWER,
+				 status, status & READY_ENTER_L23, 20, RK_PCIE_L2_TMOUT_US);
+	if (ret) {
+		dev_err(dev, "Failed to ready to enter L23\n");
+		goto no_l2;
+	}
+
+	/* 5. Check we are in L2 */
+	ret = readl_poll_timeout(rk_pcie->apb_base + PCIE_CLIENT_LTSSM_STATUS,
+				 status, ((status & S_MAX) == S_L2_IDLE), 20, RK_PCIE_L2_TMOUT_US);
+	if (ret)
+		dev_err(pci->dev, "Link isn't in L2 idle!\n");
+
+no_l2:
 	rk_pcie_disable_ltssm(rk_pcie);
+
+	ret = phy_validate(rk_pcie->phy, PHY_TYPE_PCIE, 0, NULL);
+	if (ret && ret != -EOPNOTSUPP) {
+		dev_err(dev, "PHY is reused by other controller, check the dts!\n");
+		return ret;
+	}
 
 	/* make sure assert phy success */
 	usleep_range(200, 300);
@@ -1840,7 +2369,9 @@
 	phy_power_off(rk_pcie->phy);
 	phy_exit(rk_pcie->phy);
 
-	clk_bulk_disable(rk_pcie->clk_cnt, rk_pcie->clks);
+	rk_pcie->intx = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY);
+
+	clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
 
 	rk_pcie->in_suspend = true;
 
@@ -1856,20 +2387,25 @@
 	bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj;
 	int ret;
 
+	reset_control_assert(rk_pcie->rsts);
+	udelay(10);
+	reset_control_deassert(rk_pcie->rsts);
+
 	ret = rk_pcie_enable_power(rk_pcie);
 	if (ret)
 		return ret;
 
-	ret = clk_bulk_enable(rk_pcie->clk_cnt, rk_pcie->clks);
+	ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks);
 	if (ret) {
-		clk_bulk_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
+		dev_err(dev, "failed to prepare enable pcie bulk clks: %d\n", ret);
 		return ret;
 	}
 
-	ret = phy_set_mode(rk_pcie->phy, rk_pcie->phy_mode);
+	ret = phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
+			       rk_pcie->phy_sub_mode);
 	if (ret) {
 		dev_err(dev, "fail to set phy to mode %s, err %d\n",
-			(rk_pcie->phy_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
+			(rk_pcie->phy_sub_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
 			ret);
 		return ret;
 	}
@@ -1898,6 +2434,9 @@
 
 	if (std_rc)
 		dw_pcie_setup_rc(&rk_pcie->pci->pp);
+
+	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
+			   rk_pcie->intx | 0xffff0000);
 
 	ret = rk_pcie_establish_link(rk_pcie->pci);
 	if (ret) {
@@ -1937,7 +2476,33 @@
 	return ret;
 }
 
+#ifdef CONFIG_PCIEASPM
+static int rockchip_dw_pcie_prepare(struct device *dev)
+{
+	struct rk_pcie *rk_pcie = dev_get_drvdata(dev);
+
+	dw_pcie_dbi_ro_wr_en(rk_pcie->pci);
+	rk_pcie_downstream_dev_to_d0(rk_pcie, false);
+	dw_pcie_dbi_ro_wr_dis(rk_pcie->pci);
+
+	return 0;
+}
+
+static void rockchip_dw_pcie_complete(struct device *dev)
+{
+	struct rk_pcie *rk_pcie = dev_get_drvdata(dev);
+
+	dw_pcie_dbi_ro_wr_en(rk_pcie->pci);
+	rk_pcie_downstream_dev_to_d0(rk_pcie, true);
+	dw_pcie_dbi_ro_wr_dis(rk_pcie->pci);
+}
+#endif
+
 static const struct dev_pm_ops rockchip_dw_pcie_pm_ops = {
+#ifdef CONFIG_PCIEASPM
+	.prepare = rockchip_dw_pcie_prepare,
+	.complete = rockchip_dw_pcie_complete,
+#endif
 	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_dw_pcie_suspend,
 				      rockchip_dw_pcie_resume)
 };
@@ -1947,10 +2512,12 @@
 		.name	= "rk-pcie",
 		.of_match_table = rk_pcie_of_match,
 		.suppress_bind_attrs = true,
+		.pm = &rockchip_dw_pcie_pm_ops,
 	},
+	.probe = rk_pcie_probe,
 };
 
-module_platform_driver_probe(rk_plat_pcie_driver, rk_pcie_probe);
+module_platform_driver(rk_plat_pcie_driver);
 
 MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com>");
 MODULE_DESCRIPTION("RockChip PCIe Controller driver");

--
Gitblit v1.6.2