kernel/0109-feat-PCIe-Controller-support-low-power.patch
2024-12-19 16:34:44 -05:00

156 lines
4.3 KiB
Diff

From e1d231baadd650e3ef488d8256670c02a650fcd5 Mon Sep 17 00:00:00 2001
From: huzhixuan <huzhixuan@eswincomputing.com>
Date: Thu, 18 Jul 2024 19:22:23 +0800
Subject: [PATCH 109/219] feat:PCIe Controller support low power.
Changelogs:
1.PCIe Controller support low power.
Signed-off-by: huzhixuan <huzhixuan@eswincomputing.com>
---
drivers/pci/controller/dwc/pcie-eswin.c | 73 ++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-eswin.c b/drivers/pci/controller/dwc/pcie-eswin.c
index ab1f4b421eab..498a26304aea 100644
--- a/drivers/pci/controller/dwc/pcie-eswin.c
+++ b/drivers/pci/controller/dwc/pcie-eswin.c
@@ -39,6 +39,7 @@
#include <linux/gpio/consumer.h>
#include <linux/property.h>
#include "pcie-designware.h"
+#include <linux/pm_runtime.h>
struct eswin_pcie {
struct dw_pcie pci;
@@ -269,7 +270,7 @@ static int eswin_pcie_host_init(struct dw_pcie_rp *pp)
/* config eswin vendor id and win2030 device id */
dw_pcie_writel_dbi(pci, PCIE_TYPE_DEV_VEND_ID, 0x20301fe1);
-
+
/* lane fix config, real driver NOT need, default x4 */
val = dw_pcie_readl_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL);
val &= 0xffffff80;
@@ -310,6 +311,9 @@ static int __exit eswin_pcie_remove(struct platform_device *pdev)
dw_pcie_host_deinit(&pcie->pci.pp);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
win2030_tbu_power(&pdev->dev, false);
eswin_pcie_power_off(pcie);
eswin_pcie_clk_disable(pcie);
@@ -322,6 +326,7 @@ static int eswin_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct eswin_pcie *pcie;
+ int err;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -342,7 +347,7 @@ static int eswin_pcie_probe(struct platform_device *pdev)
dev_err(dev, "pcie_aux clock source missing or invalid\n");
return PTR_ERR(pcie->pcie_aux);
}
-
+
pcie->pcie_cfg = devm_clk_get(dev, "pcie_cfg_clk");
if (IS_ERR(pcie->pcie_cfg)) {
dev_err(dev, "pcie_cfg_clk clock source missing or invalid\n");
@@ -356,7 +361,7 @@ static int eswin_pcie_probe(struct platform_device *pdev)
}
pcie->pcie_aclk = devm_clk_get(dev, "pcie_aclk");
-
+
if (IS_ERR(pcie->pcie_aclk)) {
dev_err(dev, "pcie_aclk clock source missing or invalid\n");
return PTR_ERR(pcie->pcie_aclk);
@@ -380,7 +385,20 @@ static int eswin_pcie_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pcie);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ err = pm_runtime_get_sync(dev);
+ if (err < 0) {
+ dev_err(dev, "pm_runtime_get_sync failed: %d\n", err);
+ goto pm_runtime_put;
+ }
+
return dw_pcie_host_init(&pci->pp);
+
+pm_runtime_put:
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ return err;
}
static const struct of_device_id eswin_pcie_of_match[] = {
@@ -388,11 +406,60 @@ static const struct of_device_id eswin_pcie_of_match[] = {
{},
};
+static int eswin_pcie_suspend(struct device *dev)
+{
+ struct eswin_pcie *pcie = dev_get_drvdata(dev);
+ int err = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (!pm_runtime_status_suspended(dev)) {
+ err = eswin_pcie_clk_disable(pcie);
+ }
+
+ return err;
+}
+
+static int eswin_pcie_resume(struct device *dev)
+{
+ struct eswin_pcie *pcie = dev_get_drvdata(dev);
+ int err = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (!pm_runtime_status_suspended(dev)) {
+ err = eswin_pcie_clk_enable(pcie);
+ }
+
+ return err;
+}
+
+static int eswin_pcie_runtime_suspend(struct device *dev)
+{
+ struct eswin_pcie *pcie = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+ return eswin_pcie_clk_disable(pcie);
+}
+
+static int eswin_pcie_runtime_resume(struct device *dev)
+{
+ struct eswin_pcie *pcie = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+ return eswin_pcie_clk_enable(pcie);
+
+}
+
+static const struct dev_pm_ops eswin_pcie_pm_ops = {
+ RUNTIME_PM_OPS(eswin_pcie_runtime_suspend, eswin_pcie_runtime_resume, NULL)
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(eswin_pcie_suspend, eswin_pcie_resume)
+};
+
static struct platform_driver eswin_pcie_driver = {
.driver = {
.name = "eswin-pcie",
.of_match_table = eswin_pcie_of_match,
.suppress_bind_attrs = true,
+ .pm = &eswin_pcie_pm_ops,
},
.probe = eswin_pcie_probe,
.remove = __exit_p(eswin_pcie_remove),
--
2.47.0