diff mbox series

[V2,5/7] PCI: host-generic: Add power domain based handling for PCIe controller

Message ID 1721067215-5832-6-git-send-email-quic_mrana@quicinc.com (mailing list archive)
State New
Delegated to: Manivannan Sadhasivam
Headers show
Series Add power domain and MSI functionality with PCIe host generic ECAM driver | expand

Commit Message

Mayank Rana July 15, 2024, 6:13 p.m. UTC
Add usage of power domain to control PCIe controller enumeration. This is
needed to allow interaction with firmware to vote/unvote system resources,
PCIe PHY and configuration of PCIe controller into ECAM mode. This feature
support system suspend and resume to put PCIe into D3 cold and D0.

Signed-off-by: Mayank Rana <quic_mrana@quicinc.com>
---
 drivers/pci/controller/pci-host-generic.c | 42 +++++++++++++++++++++++++++++--
 1 file changed, 40 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/pci/controller/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c
index 41cb6a0..c2c027f 100644
--- a/drivers/pci/controller/pci-host-generic.c
+++ b/drivers/pci/controller/pci-host-generic.c
@@ -13,6 +13,7 @@ 
 #include <linux/module.h>
 #include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
 	.bus_shift	= 16,
@@ -76,13 +77,50 @@  static const struct of_device_id gen_pci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, gen_pci_of_match);
 
+static int gen_pcie_ecam_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int ret = 0;
+
+	if (!IS_ERR_OR_NULL(dev->pm_domain)) {
+		ret = devm_pm_runtime_enable(dev);
+		if (ret)
+			return ret;
+
+		ret = pm_runtime_resume_and_get(dev);
+		if (ret < 0) {
+			dev_err(dev, "fail to enable pcie controller:%d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = pci_host_common_probe(pdev);
+	if (ret) {
+		dev_err(dev, "pci_host_common_probe() failed:%d\n", ret);
+		goto err;
+	}
+
+	return ret;
+err:
+	if (!IS_ERR_OR_NULL(dev->pm_domain))
+		pm_runtime_put_sync(dev);
+	return ret;
+}
+
+static void gen_pcie_ecam_remove(struct platform_device *pdev)
+{
+	pci_host_common_remove(pdev);
+	if (pdev->dev.pm_domain)
+		pm_runtime_put_sync(&pdev->dev);
+}
+
 static struct platform_driver gen_pci_driver = {
 	.driver = {
 		.name = "pci-host-generic",
 		.of_match_table = gen_pci_of_match,
 	},
-	.probe = pci_host_common_probe,
-	.remove_new = pci_host_common_remove,
+	.probe = gen_pcie_ecam_probe,
+	.remove_new = gen_pcie_ecam_remove,
 };
 module_platform_driver(gen_pci_driver);