From 2d2af22d23af0a7e51a34cbaac1fcd53d563aae0 Mon Sep 17 00:00:00 2001
From: "shangavelan.m" <shangavelan.m@adlinktech.com>
Date: Mon, 3 Nov 2025 16:09:00 +0530
Subject: [PATCH 8/9] LECMTKI1200: Added PCIe compliance

Signed-off-by: shangavelan.m <shangavelan.m@adlinktech.com>
---
 drivers/pci/controller/pcie-mediatek-gen3.c | 55 ++++++++++++++++++---
 1 file changed, 48 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index bbd9e14ccfe9..ccc308d5d86b 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -22,6 +22,13 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
+#include <linux/string.h>
+ 
+#ifdef CONFIG_ARCH_ADLINKTECH
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#endif
 
 #include "../pci.h"
 
@@ -142,6 +149,7 @@ struct mtk_pcie_port {
 	struct phy *phy;
 	struct clk_bulk_data *clks;
 	int num_clks;
+	int compliance_test_enable;
 
 	int irq;
 	u32 saved_irq_state;
@@ -311,16 +319,25 @@ static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
 	val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
 	writel_relaxed(val, port->base + PCIE_RST_CTRL_REG);
 
+	/* Wait 10ms after PCIE_BRG_RSTB is set */
+	usleep_range(10 * 1000, 15 * 1000);
+
+	/* De-assert reset signals */
+	val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB);
+	writel_relaxed(val, port->base + PCIE_RST_CTRL_REG);
+
+
+
 	/*
 	 * Described in PCIe CEM specification setctions 2.2 (PERST# Signal)
 	 * and 2.2.1 (Initial Power-Up (G3 to S0)).
 	 * The deassertion of PERST# should be delayed 100ms (TPVPERL)
 	 * for the power and clock to become stable.
 	 */
-	msleep(100);
+	msleep(90);
 
 	/* De-assert reset signals */
-	val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB);
+	val &= ~PCIE_PE_RSTB;
 	writel_relaxed(val, port->base + PCIE_RST_CTRL_REG);
 
 	/* Check if the link is up or not */
@@ -601,8 +618,7 @@ static int mtk_pcie_init_irq_domains(struct mtk_pcie_port *port)
 						  &intx_domain_ops, port);
 	if (!port->intx_domain) {
 		dev_err(dev, "failed to create INTx IRQ domain\n");
-		ret = -ENODEV;
-		goto out_put_node;
+		return -ENODEV;
 	}
 
 	/* Setup MSI */
@@ -625,7 +641,6 @@ static int mtk_pcie_init_irq_domains(struct mtk_pcie_port *port)
 		goto err_msi_domain;
 	}
 
-	of_node_put(intc_node);
 	return 0;
 
 err_msi_domain:
@@ -633,8 +648,6 @@ static int mtk_pcie_init_irq_domains(struct mtk_pcie_port *port)
 err_msi_bottom_domain:
 	irq_domain_remove(port->intx_domain);
 
-out_put_node:
-	of_node_put(intc_node);
 	return ret;
 }
 
@@ -726,6 +739,7 @@ static int mtk_pcie_parse_port(struct mtk_pcie_port *port)
 	struct device *dev = port->dev;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *regs;
+	const char *tmp;
 	int ret;
 
 	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-mac");
@@ -771,6 +785,14 @@ static int mtk_pcie_parse_port(struct mtk_pcie_port *port)
 		dev_err(dev, "failed to get clocks\n");
 		return port->num_clks;
 	}
+	
+	port->compliance_test_enable = false;
+        if (!of_property_read_string(dev->of_node, "compliance-test", &tmp) || strstr(boot_command_line, "pcie_compliance_test")) {
+                if (!strcmp(tmp, "enabled") || strstr(boot_command_line, "pcie_compliance_test")) {
+			port->compliance_test_enable = true;
+			dev_info(dev, "Compliance test mode enabled\n");
+		}
+	}	
 
 	return 0;
 }
@@ -824,6 +846,9 @@ static int mtk_pcie_power_up(struct mtk_pcie_port *port)
 
 static void mtk_pcie_power_down(struct mtk_pcie_port *port)
 {
+	if (port->compliance_test_enable == true)
+		return;
+
 	clk_bulk_disable_unprepare(port->num_clks, port->clks);
 
 	pm_runtime_put_sync(port->dev);
@@ -860,6 +885,8 @@ static int mtk_pcie_setup(struct mtk_pcie_port *port)
 	return 0;
 
 err_setup:
+	if (port->compliance_test_enable == true)
+		return 0;
 	mtk_pcie_power_down(port);
 
 	return err;
@@ -871,6 +898,10 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	struct mtk_pcie_port *port;
 	struct pci_host_bridge *host;
 	int err;
+#ifdef CONFIG_ARCH_ADLINKTECH
+	struct device_node *np = pdev->dev.of_node;
+	int pd_gpio;
+#endif
 
 	host = devm_pci_alloc_host_bridge(dev, sizeof(*port));
 	if (!host)
@@ -881,6 +912,16 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	port->dev = dev;
 	platform_set_drvdata(pdev, port);
 
+#ifdef CONFIG_ARCH_ADLINKTECH
+	pd_gpio = of_get_named_gpio(np, "pd-gpios", 0);
+       /* GPIO request and configuration */
+
+        err = devm_gpio_request_one(&pdev->dev, pd_gpio,GPIOF_OUT_INIT_HIGH, "WIFI PD");
+        if (err)
+                printk("%s: [Adlink] Failed to request wifi pd pin\n",__func__);
+        else
+                printk("%s: [Adlink] Success to request wifi pd pin\n", __func__);
+#endif
 	err = mtk_pcie_setup(port);
 	if (err)
 		return err;
-- 
2.43.0

