Re: [PATCH 1/4] PCI: imx6: Add pci host wakeup support on imx platforms.

From: Lucas Stach
Date: Fri Dec 08 2023 - 05:17:00 EST


Am Freitag, dem 08.12.2023 um 17:13 +0800 schrieb Sherry Sun:
> Add pci host wakeup feature for imx platforms.
> Example of configuring the corresponding dts property under the PCI
> node:
> host-wake-gpio = <&gpio5 21 GPIO_ACTIVE_LOW>;
>
> Signed-off-by: Sherry Sun <sherry.sun@xxxxxxx>
> Reviewed-by: Richard Zhu <hongxing.zhu@xxxxxxx>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 69 +++++++++++++++++++++++++++
> 1 file changed, 69 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 74703362aeec..050c9140f4a3 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,46 @@ 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;
> +
> + dev_dbg(dev, "%s: host wakeup by pcie", __func__);
> +
Not sure how much value this debug print carries. If you want to keep
it, drop the __func__. There is no other place in this driver handling
the wakeup, so the function name in the print is pure noise.

> + /* 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 +1286,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 +1494,32 @@ 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, "host-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) {
> + dev_err(dev, "Failed to request host_wake_irq %d (%d)\n",
> + imx6_pcie->host_wake_irq, ret);
> + imx6_pcie->host_wake_irq = -1;

What's the point of resetting host_wake_irq to -1 in those error paths?
Nobody is going to access this member anymore after the error. Just
drop this.

You could simplify all those error paths to
if (err)
return dev_err_probe(...);

> + return ret;
> + }
> +
> + if (device_init_wakeup(dev, true)) {
> + dev_err(dev, "fail to init host_wake_irq\n");
> + imx6_pcie->host_wake_irq = -1;
> + return ret;
> + }
> + }
> }
>
> return 0;
> @@ -1466,6 +1529,12 @@ 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);
> + imx6_pcie->host_wake_irq = -1;
> + }
> +
> /* bring down link, so bootloader gets clean state in case of reboot */
> imx6_pcie_assert_core_reset(imx6_pcie);
> }