[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20231213092850.1706042-2-sherry.sun@nxp.com>
Date: Wed, 13 Dec 2023 17:28:47 +0800
From: Sherry Sun <sherry.sun@....com>
To: hongxing.zhu@....com, l.stach@...gutronix.de,
lpieralisi@...nel.org, kw@...ux.com, robh@...nel.org,
bhelgaas@...gle.com, krzysztof.kozlowski+dt@...aro.org,
conor+dt@...nel.org, shawnguo@...nel.org, s.hauer@...gutronix.de,
kernel@...gutronix.de, festevam@...il.com
Cc: linux-imx@....com, linux-pci@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH V2 1/4] PCI: imx6: Add pci host wakeup support on imx platforms.
Add pci host wakeup feature for imx platforms.
Example of configuring the corresponding dts property under the PCI
node:
wake-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
Signed-off-by: Sherry Sun <sherry.sun@....com>
Reviewed-by: Richard Zhu <hongxing.zhu@....com>
---
drivers/pci/controller/dwc/pci-imx6.c | 60 +++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 74703362aeec..0cf7f21adff8 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -72,6 +72,7 @@ struct imx6_pcie_drvdata {
struct imx6_pcie {
struct dw_pcie *pci;
int reset_gpio;
+ int host_wake_irq;
bool gpio_active_high;
bool link_is_up;
struct clk *pcie_bus;
@@ -1237,11 +1238,44 @@ static int imx6_pcie_resume_noirq(struct device *dev)
return 0;
}
+static int imx6_pcie_suspend(struct device *dev)
+{
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+
+ if (imx6_pcie->host_wake_irq >= 0)
+ enable_irq_wake(imx6_pcie->host_wake_irq);
+
+ return 0;
+}
+
+static int imx6_pcie_resume(struct device *dev)
+{
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+
+ if (imx6_pcie->host_wake_irq >= 0)
+ disable_irq_wake(imx6_pcie->host_wake_irq);
+
+ return 0;
+}
+
static const struct dev_pm_ops imx6_pcie_pm_ops = {
NOIRQ_SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend_noirq,
imx6_pcie_resume_noirq)
+ SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend, imx6_pcie_resume)
};
+irqreturn_t host_wake_irq_handler(int irq, void *priv)
+{
+ struct imx6_pcie *imx6_pcie = priv;
+ struct device *dev = imx6_pcie->pci->dev;
+
+ /* Notify PM core we are wakeup source */
+ pm_wakeup_event(dev, 0);
+ pm_system_wakeup();
+
+ return IRQ_HANDLED;
+}
+
static int imx6_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1250,6 +1284,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
struct device_node *np;
struct resource *dbi_base;
struct device_node *node = dev->of_node;
+ struct gpio_desc *host_wake_gpio;
int ret;
u16 val;
@@ -1457,6 +1492,26 @@ static int imx6_pcie_probe(struct platform_device *pdev)
val |= PCI_MSI_FLAGS_ENABLE;
dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
}
+
+ /* host wakeup support */
+ imx6_pcie->host_wake_irq = -1;
+ host_wake_gpio = devm_gpiod_get_optional(dev, "wake", GPIOD_IN);
+ if (IS_ERR(host_wake_gpio))
+ return PTR_ERR(host_wake_gpio);
+
+ if (host_wake_gpio != NULL) {
+ imx6_pcie->host_wake_irq = gpiod_to_irq(host_wake_gpio);
+ ret = devm_request_threaded_irq(dev, imx6_pcie->host_wake_irq, NULL,
+ host_wake_irq_handler,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ "host_wake", imx6_pcie);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request host_wake_irq\n");
+
+ ret = device_init_wakeup(dev, true);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to init host_wake_irq\n");
+ }
}
return 0;
@@ -1466,6 +1521,11 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
{
struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
+ if (imx6_pcie->host_wake_irq >= 0) {
+ device_init_wakeup(&pdev->dev, false);
+ disable_irq(imx6_pcie->host_wake_irq);
+ }
+
/* bring down link, so bootloader gets clean state in case of reboot */
imx6_pcie_assert_core_reset(imx6_pcie);
}
--
2.34.1
Powered by blists - more mailing lists