All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peng Fan <peng.fan@nxp.com>
To: Shenwei Wang <shenwei.wang@nxp.com>
Cc: Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Shawn Guo <shawnguo@kernel.org>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	Linus Walleij <linus.walleij@linaro.org>,
	Bartosz Golaszewski <brgl@bgdev.pl>,
	Dong Aisheng <aisheng.dong@nxp.com>, Jacky Bai <ping.bai@nxp.com>,
	Pengutronix Kernel Team <kernel@pengutronix.de>,
	Fabio Estevam <festevam@gmail.com>,
	NXP Linux Team <linux-imx@nxp.com>,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev
Subject: Re: [PATCH v3 5/5] gpio: mxc: enable pad wakeup on i.MX8x platforms
Date: Wed, 26 Oct 2022 14:20:11 +0800	[thread overview]
Message-ID: <20221026062011.GA18160@linux-1xn6> (raw)
In-Reply-To: <20221025183244.615318-6-shenwei.wang@nxp.com>

On Tue, Oct 25, 2022 at 01:32:44PM -0500, Shenwei Wang wrote:
>On i.MX8QM/QXP/DXL SoCs, even a GPIO is selected as the wakeup source,
>the GPIO block will be powered off when system enters into suspend
>state. This can greatly reduce the power consumption of suspend state
>because the whole partition can be shutdown. This is called PAD wakeup
>feature on i.MX8x platform.
>
>This patch adds the noirq suspend/resume hooks and uses the pad wakeup
>feature as the default wakeup method for GPIO modules on
>i.MX8QM/QXP/DXL platforms.
>
>Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
>---
> drivers/gpio/gpio-mxc.c | 91 ++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 90 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
>index c871602fc5ba..a6fe5ed3d320 100644
>--- a/drivers/gpio/gpio-mxc.c
>+++ b/drivers/gpio/gpio-mxc.c
>@@ -24,6 +24,12 @@
> #include <linux/of_device.h>
> #include <linux/bug.h>
> 
>+#define IMX_SCU_WAKEUP_OFF		0
>+#define IMX_SCU_WAKEUP_LOW_LVL		4
>+#define IMX_SCU_WAKEUP_FALL_EDGE	5
>+#define IMX_SCU_WAKEUP_RISE_EDGE	6
>+#define IMX_SCU_WAKEUP_HIGH_LVL		7
>+
> /* device type dependent stuff */
> struct mxc_gpio_hwdata {
> 	unsigned dr_reg;
>@@ -61,6 +67,9 @@ struct mxc_gpio_port {
> 	u32 both_edges;
> 	struct mxc_gpio_reg_saved gpio_saved_reg;
> 	bool power_off;
>+	u32 wakeup_pads;
>+	bool is_pad_wakeup;
>+	u32 pad_type[32];
> 	const struct mxc_gpio_hwdata *hwdata;
> };
> 
>@@ -130,6 +139,9 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
> 	{ .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
> 	{ .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
> 	{ .compatible = "fsl,imx7d-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
> 	{ /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, mxc_gpio_dt_ids);
>@@ -203,6 +215,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
> 	}
> 
> 	writel(1 << gpio_idx, port->base + GPIO_ISR);
>+	port->pad_type[gpio_idx] = type;
> 
> 	return 0;
> }
>@@ -254,6 +267,9 @@ static void mx3_gpio_irq_handler(struct irq_desc *desc)
> 	struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
> 	struct irq_chip *chip = irq_desc_get_chip(desc);
> 
>+	if (port->is_pad_wakeup)
>+		return;
>+
> 	chained_irq_enter(chip, desc);
> 
> 	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
>@@ -306,11 +322,13 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
> 			ret = enable_irq_wake(port->irq_high);
> 		else
> 			ret = enable_irq_wake(port->irq);
>+		port->wakeup_pads |= (1<<gpio_idx);

"1 << gpio_idx"

> 	} else {
> 		if (port->irq_high && (gpio_idx >= 16))
> 			ret = disable_irq_wake(port->irq_high);
> 		else
> 			ret = disable_irq_wake(port->irq);
>+		port->wakeup_pads &= ~(1<<gpio_idx);

"1 << gpio_idx"

> 	}
> 
> 	return ret;
>@@ -365,7 +383,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> 		return -ENOMEM;
> 
> 	port->dev = &pdev->dev;
>-
> 	port->hwdata = device_get_match_data(&pdev->dev);
> 
> 	port->base = devm_platform_ioremap_resource(pdev, 0);
>@@ -498,6 +515,77 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
> 	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
> }
> 
>+static int mxc_gpio_generic_config(struct mxc_gpio_port *port,
>+		unsigned int offset, unsigned long config)
>+{
>+	struct device_node *np = port->dev->of_node;
>+
>+	if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
>+		of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
>+		of_device_is_compatible(np, "fsl,imx8qm-gpio"))
>+		return gpiochip_generic_config(&port->gc, offset, config);

checkpatch should report warning.

>+
>+	return 0;
>+}
>+
>+static void mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
>+{
>+	unsigned long config;
>+	int i, type;
>+
>+	static const u32 pad_type_map[] = {
>+		IMX_SCU_WAKEUP_OFF,		/* 0 */
>+		IMX_SCU_WAKEUP_RISE_EDGE,	/* IRQ_TYPE_EDGE_RISING */
>+		IMX_SCU_WAKEUP_FALL_EDGE,	/* IRQ_TYPE_EDGE_FALLING */
>+		IMX_SCU_WAKEUP_FALL_EDGE,	/* IRQ_TYPE_EDGE_BOTH */
>+		IMX_SCU_WAKEUP_HIGH_LVL,	/* IRQ_TYPE_LEVEL_HIGH */
>+		IMX_SCU_WAKEUP_OFF,		/* 5 */
>+		IMX_SCU_WAKEUP_OFF,		/* 6 */
>+		IMX_SCU_WAKEUP_OFF,		/* 7 */
>+		IMX_SCU_WAKEUP_LOW_LVL,		/* IRQ_TYPE_LEVEL_LOW */
>+	};
>+
>+	for (i = 0; i < 32; i++) {
>+		if ((port->wakeup_pads & (1<<i))) {
>+			type = port->pad_type[i];
>+			if (enable)
>+				config = pad_type_map[type];
>+			else
>+				config = IMX_SCU_WAKEUP_OFF;
>+			mxc_gpio_generic_config(port, i, config);
>+		}
>+	}
>+}
>+
>+static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
>+{
>+	struct platform_device *pdev = to_platform_device(dev);
>+	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
>+
>+	if (port->wakeup_pads > 0) {
>+		mxc_gpio_set_pad_wakeup(port, true);
>+		port->is_pad_wakeup = true;
>+	}
>+
>+	return 0;
>+}
>+
>+static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
>+{
>+	struct platform_device *pdev = to_platform_device(dev);
>+	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
>+
>+	if (port->wakeup_pads > 0)
>+		mxc_gpio_set_pad_wakeup(port, false);
>+	port->is_pad_wakeup = false;
>+
>+	return 0;
>+}
>+
>+static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
>+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume)
>+};
>+
> static int mxc_gpio_syscore_suspend(void)
> {
> 	struct mxc_gpio_port *port;
>@@ -537,6 +625,7 @@ static struct platform_driver mxc_gpio_driver = {
> 		.name	= "gpio-mxc",
> 		.of_match_table = mxc_gpio_dt_ids,
> 		.suppress_bind_attrs = true,
>+		.pm = &mxc_gpio_dev_pm_ops,
> 	},
> 	.probe		= mxc_gpio_probe,
> };


Except the format issue, patch looks good to me.

Regards,
Peng.

>-- 
>2.34.1
>

-- 

WARNING: multiple messages have this Message-ID (diff)
From: Peng Fan <peng.fan@nxp.com>
To: Shenwei Wang <shenwei.wang@nxp.com>
Cc: Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Shawn Guo <shawnguo@kernel.org>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	Linus Walleij <linus.walleij@linaro.org>,
	Bartosz Golaszewski <brgl@bgdev.pl>,
	Dong Aisheng <aisheng.dong@nxp.com>, Jacky Bai <ping.bai@nxp.com>,
	Pengutronix Kernel Team <kernel@pengutronix.de>,
	Fabio Estevam <festevam@gmail.com>,
	NXP Linux Team <linux-imx@nxp.com>,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev
Subject: Re: [PATCH v3 5/5] gpio: mxc: enable pad wakeup on i.MX8x platforms
Date: Wed, 26 Oct 2022 14:20:11 +0800	[thread overview]
Message-ID: <20221026062011.GA18160@linux-1xn6> (raw)
In-Reply-To: <20221025183244.615318-6-shenwei.wang@nxp.com>

On Tue, Oct 25, 2022 at 01:32:44PM -0500, Shenwei Wang wrote:
>On i.MX8QM/QXP/DXL SoCs, even a GPIO is selected as the wakeup source,
>the GPIO block will be powered off when system enters into suspend
>state. This can greatly reduce the power consumption of suspend state
>because the whole partition can be shutdown. This is called PAD wakeup
>feature on i.MX8x platform.
>
>This patch adds the noirq suspend/resume hooks and uses the pad wakeup
>feature as the default wakeup method for GPIO modules on
>i.MX8QM/QXP/DXL platforms.
>
>Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
>---
> drivers/gpio/gpio-mxc.c | 91 ++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 90 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
>index c871602fc5ba..a6fe5ed3d320 100644
>--- a/drivers/gpio/gpio-mxc.c
>+++ b/drivers/gpio/gpio-mxc.c
>@@ -24,6 +24,12 @@
> #include <linux/of_device.h>
> #include <linux/bug.h>
> 
>+#define IMX_SCU_WAKEUP_OFF		0
>+#define IMX_SCU_WAKEUP_LOW_LVL		4
>+#define IMX_SCU_WAKEUP_FALL_EDGE	5
>+#define IMX_SCU_WAKEUP_RISE_EDGE	6
>+#define IMX_SCU_WAKEUP_HIGH_LVL		7
>+
> /* device type dependent stuff */
> struct mxc_gpio_hwdata {
> 	unsigned dr_reg;
>@@ -61,6 +67,9 @@ struct mxc_gpio_port {
> 	u32 both_edges;
> 	struct mxc_gpio_reg_saved gpio_saved_reg;
> 	bool power_off;
>+	u32 wakeup_pads;
>+	bool is_pad_wakeup;
>+	u32 pad_type[32];
> 	const struct mxc_gpio_hwdata *hwdata;
> };
> 
>@@ -130,6 +139,9 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
> 	{ .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
> 	{ .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
> 	{ .compatible = "fsl,imx7d-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
>+	{ .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
> 	{ /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, mxc_gpio_dt_ids);
>@@ -203,6 +215,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
> 	}
> 
> 	writel(1 << gpio_idx, port->base + GPIO_ISR);
>+	port->pad_type[gpio_idx] = type;
> 
> 	return 0;
> }
>@@ -254,6 +267,9 @@ static void mx3_gpio_irq_handler(struct irq_desc *desc)
> 	struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
> 	struct irq_chip *chip = irq_desc_get_chip(desc);
> 
>+	if (port->is_pad_wakeup)
>+		return;
>+
> 	chained_irq_enter(chip, desc);
> 
> 	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
>@@ -306,11 +322,13 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
> 			ret = enable_irq_wake(port->irq_high);
> 		else
> 			ret = enable_irq_wake(port->irq);
>+		port->wakeup_pads |= (1<<gpio_idx);

"1 << gpio_idx"

> 	} else {
> 		if (port->irq_high && (gpio_idx >= 16))
> 			ret = disable_irq_wake(port->irq_high);
> 		else
> 			ret = disable_irq_wake(port->irq);
>+		port->wakeup_pads &= ~(1<<gpio_idx);

"1 << gpio_idx"

> 	}
> 
> 	return ret;
>@@ -365,7 +383,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> 		return -ENOMEM;
> 
> 	port->dev = &pdev->dev;
>-
> 	port->hwdata = device_get_match_data(&pdev->dev);
> 
> 	port->base = devm_platform_ioremap_resource(pdev, 0);
>@@ -498,6 +515,77 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
> 	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
> }
> 
>+static int mxc_gpio_generic_config(struct mxc_gpio_port *port,
>+		unsigned int offset, unsigned long config)
>+{
>+	struct device_node *np = port->dev->of_node;
>+
>+	if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
>+		of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
>+		of_device_is_compatible(np, "fsl,imx8qm-gpio"))
>+		return gpiochip_generic_config(&port->gc, offset, config);

checkpatch should report warning.

>+
>+	return 0;
>+}
>+
>+static void mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
>+{
>+	unsigned long config;
>+	int i, type;
>+
>+	static const u32 pad_type_map[] = {
>+		IMX_SCU_WAKEUP_OFF,		/* 0 */
>+		IMX_SCU_WAKEUP_RISE_EDGE,	/* IRQ_TYPE_EDGE_RISING */
>+		IMX_SCU_WAKEUP_FALL_EDGE,	/* IRQ_TYPE_EDGE_FALLING */
>+		IMX_SCU_WAKEUP_FALL_EDGE,	/* IRQ_TYPE_EDGE_BOTH */
>+		IMX_SCU_WAKEUP_HIGH_LVL,	/* IRQ_TYPE_LEVEL_HIGH */
>+		IMX_SCU_WAKEUP_OFF,		/* 5 */
>+		IMX_SCU_WAKEUP_OFF,		/* 6 */
>+		IMX_SCU_WAKEUP_OFF,		/* 7 */
>+		IMX_SCU_WAKEUP_LOW_LVL,		/* IRQ_TYPE_LEVEL_LOW */
>+	};
>+
>+	for (i = 0; i < 32; i++) {
>+		if ((port->wakeup_pads & (1<<i))) {
>+			type = port->pad_type[i];
>+			if (enable)
>+				config = pad_type_map[type];
>+			else
>+				config = IMX_SCU_WAKEUP_OFF;
>+			mxc_gpio_generic_config(port, i, config);
>+		}
>+	}
>+}
>+
>+static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
>+{
>+	struct platform_device *pdev = to_platform_device(dev);
>+	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
>+
>+	if (port->wakeup_pads > 0) {
>+		mxc_gpio_set_pad_wakeup(port, true);
>+		port->is_pad_wakeup = true;
>+	}
>+
>+	return 0;
>+}
>+
>+static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
>+{
>+	struct platform_device *pdev = to_platform_device(dev);
>+	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
>+
>+	if (port->wakeup_pads > 0)
>+		mxc_gpio_set_pad_wakeup(port, false);
>+	port->is_pad_wakeup = false;
>+
>+	return 0;
>+}
>+
>+static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
>+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume)
>+};
>+
> static int mxc_gpio_syscore_suspend(void)
> {
> 	struct mxc_gpio_port *port;
>@@ -537,6 +625,7 @@ static struct platform_driver mxc_gpio_driver = {
> 		.name	= "gpio-mxc",
> 		.of_match_table = mxc_gpio_dt_ids,
> 		.suppress_bind_attrs = true,
>+		.pm = &mxc_gpio_dev_pm_ops,
> 	},
> 	.probe		= mxc_gpio_probe,
> };


Except the format issue, patch looks good to me.

Regards,
Peng.

>-- 
>2.34.1
>

-- 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2022-10-26  5:34 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-25 18:32 [PATCH v3 0/5] add suspend/resume support for i.mx8x SoCs Shenwei Wang
2022-10-25 18:32 ` Shenwei Wang
2022-10-25 18:32 ` [PATCH v3 1/5] arm64: dts: imx8dxl-ss-lsio: add gpio-ranges property Shenwei Wang
2022-10-25 18:32   ` Shenwei Wang
2022-10-26  8:25   ` Peng Fan
2022-10-26  8:25     ` Peng Fan
2022-10-25 18:32 ` [PATCH v3 2/5] arm64: dts: imx8qm-ss-lsio: " Shenwei Wang
2022-10-25 18:32   ` Shenwei Wang
2022-10-26  8:26   ` Peng Fan
2022-10-26  8:26     ` Peng Fan
2022-10-25 18:32 ` [PATCH v3 3/5] arm64: dts: imx8qxp-ss-lsio: " Shenwei Wang
2022-10-25 18:32   ` Shenwei Wang
2022-10-26  8:27   ` Peng Fan
2022-10-26  8:27     ` Peng Fan
2022-10-25 18:32 ` [PATCH v3 4/5] pinctrl: freescale: add pad wakeup config Shenwei Wang
2022-10-25 18:32   ` Shenwei Wang
2022-10-26  3:56   ` kernel test robot
2022-10-26  8:21   ` Peng Fan
2022-10-26  8:21     ` Peng Fan
2022-10-25 18:32 ` [PATCH v3 5/5] gpio: mxc: enable pad wakeup on i.MX8x platforms Shenwei Wang
2022-10-25 18:32   ` Shenwei Wang
2022-10-26  6:20   ` Peng Fan [this message]
2022-10-26  6:20     ` Peng Fan
2022-10-27  2:27     ` Shenwei Wang
2022-10-27  2:27       ` Shenwei Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221026062011.GA18160@linux-1xn6 \
    --to=peng.fan@nxp.com \
    --cc=aisheng.dong@nxp.com \
    --cc=brgl@bgdev.pl \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=imx@lists.linux.dev \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ping.bai@nxp.com \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=shawnguo@kernel.org \
    --cc=shenwei.wang@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.