All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase
@ 2018-11-09  4:56 Anson Huang
  2018-11-16 21:56 ` Linus Walleij
  0 siblings, 1 reply; 4+ messages in thread
From: Anson Huang @ 2018-11-09  4:56 UTC (permalink / raw)
  To: linus.walleij, bgolaszewski, linux-gpio, linux-kernel; +Cc: dl-linux-imx

During noirq suspend/resume phase, GPIO irq could arrive
and its registers like IMR will be changed by irq handle
process, to make the GPIO registers exactly when it is
powered ON after resume, move the GPIO noirq suspend/resume
callback to syscore suspend/resume phase, local irq is
disabled at this phase so GPIO registers are atomic.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
---
 drivers/gpio/gpio-mxc.c | 39 ++++++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 5c69516..2d1dfa1 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -17,6 +17,7 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/syscore_ops.h>
 #include <linux/gpio/driver.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -550,31 +551,38 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
 	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
 }
 
-static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
+static int mxc_gpio_syscore_suspend(void)
 {
-	struct mxc_gpio_port *port = dev_get_drvdata(dev);
+	struct mxc_gpio_port *port;
 
-	mxc_gpio_save_regs(port);
-	clk_disable_unprepare(port->clk);
+	/* walk through all ports */
+	list_for_each_entry(port, &mxc_gpio_ports, node) {
+		mxc_gpio_save_regs(port);
+		clk_disable_unprepare(port->clk);
+	}
 
 	return 0;
 }
 
-static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
+static void mxc_gpio_syscore_resume(void)
 {
-	struct mxc_gpio_port *port = dev_get_drvdata(dev);
+	struct mxc_gpio_port *port;
 	int ret;
 
-	ret = clk_prepare_enable(port->clk);
-	if (ret)
-		return ret;
-	mxc_gpio_restore_regs(port);
-
-	return 0;
+	/* walk through all ports */
+	list_for_each_entry(port, &mxc_gpio_ports, node) {
+		ret = clk_prepare_enable(port->clk);
+		if (ret) {
+			pr_err("mxc: failed to enable gpio clock %d\n", ret);
+			return;
+		}
+		mxc_gpio_restore_regs(port);
+	}
 }
 
-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 struct syscore_ops mxc_gpio_syscore_ops = {
+	.suspend = mxc_gpio_syscore_suspend,
+	.resume = mxc_gpio_syscore_resume,
 };
 
 static struct platform_driver mxc_gpio_driver = {
@@ -582,7 +590,6 @@ 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,
 	.id_table	= mxc_gpio_devtype,
@@ -590,6 +597,8 @@ static struct platform_driver mxc_gpio_driver = {
 
 static int __init gpio_mxc_init(void)
 {
+	register_syscore_ops(&mxc_gpio_syscore_ops);
+
 	return platform_driver_register(&mxc_gpio_driver);
 }
 subsys_initcall(gpio_mxc_init);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase
  2018-11-09  4:56 [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase Anson Huang
@ 2018-11-16 21:56 ` Linus Walleij
  0 siblings, 0 replies; 4+ messages in thread
From: Linus Walleij @ 2018-11-16 21:56 UTC (permalink / raw)
  To: Anson Huang, Fabio Estevam
  Cc: Bartosz Golaszewski, open list:GPIO SUBSYSTEM, linux-kernel,
	NXP Linux Team

On Fri, Nov 9, 2018 at 5:56 AM Anson Huang <anson.huang@nxp.com> wrote:

> During noirq suspend/resume phase, GPIO irq could arrive
> and its registers like IMR will be changed by irq handle
> process, to make the GPIO registers exactly when it is
> powered ON after resume, move the GPIO noirq suspend/resume
> callback to syscore suspend/resume phase, local irq is
> disabled at this phase so GPIO registers are atomic.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>

Patch applied. Cc Fabio so he knows it happens.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase
  2019-02-17 22:05 Martin Hundebøll
@ 2019-02-18  1:38 ` Sasha Levin
  0 siblings, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2019-02-18  1:38 UTC (permalink / raw)
  To: Martin Hundebøll; +Cc: stable, Anson Huang, Linus Walleij

On Sun, Feb 17, 2019 at 11:05:33PM +0100, Martin Hundebøll wrote:
>From: Anson Huang <anson.huang@nxp.com>
>
>commit 1a5287a3dbc34cd0c02c8f64c9131bd23cdfe2bb upstream.
>
>During noirq suspend/resume phase, GPIO irq could arrive
>and its registers like IMR will be changed by irq handle
>process, to make the GPIO registers exactly when it is
>powered ON after resume, move the GPIO noirq suspend/resume
>callback to syscore suspend/resume phase, local irq is
>disabled at this phase so GPIO registers are atomic.
>
>Fixes: c19fdaeea0aa ("gpio: mxc: add power management support")
>Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
>Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>Signed-off-by: Martin Hundebøll <martin@geanix.com>
>Cc: <stable@vger.kernel.org> # 4.19.x+

Queued for 4.19 and 4.20, thank you.

--
Thanks,
Sasha

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase
@ 2019-02-17 22:05 Martin Hundebøll
  2019-02-18  1:38 ` Sasha Levin
  0 siblings, 1 reply; 4+ messages in thread
From: Martin Hundebøll @ 2019-02-17 22:05 UTC (permalink / raw)
  To: stable; +Cc: Anson Huang, Anson Huang, Linus Walleij, Martin Hundebøll

From: Anson Huang <anson.huang@nxp.com>

commit 1a5287a3dbc34cd0c02c8f64c9131bd23cdfe2bb upstream.

During noirq suspend/resume phase, GPIO irq could arrive
and its registers like IMR will be changed by irq handle
process, to make the GPIO registers exactly when it is
powered ON after resume, move the GPIO noirq suspend/resume
callback to syscore suspend/resume phase, local irq is
disabled at this phase so GPIO registers are atomic.

Fixes: c19fdaeea0aa ("gpio: mxc: add power management support")
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Martin Hundebøll <martin@geanix.com>
Cc: <stable@vger.kernel.org> # 4.19.x+
---

This patch fixes gpio wakeup from suspend on (at least) imx6ul and
imx6ull. The backport handles the conflict from commit 7f3f2b478cab
("gpio: gpio-mxc: simplify getting .driver_data").

 drivers/gpio/gpio-mxc.c | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 995cf0b9e0b1..2d1dfa1e0745 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -17,6 +17,7 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/syscore_ops.h>
 #include <linux/gpio/driver.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -550,33 +551,38 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
 	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
 }
 
-static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
+static int mxc_gpio_syscore_suspend(void)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+	struct mxc_gpio_port *port;
 
-	mxc_gpio_save_regs(port);
-	clk_disable_unprepare(port->clk);
+	/* walk through all ports */
+	list_for_each_entry(port, &mxc_gpio_ports, node) {
+		mxc_gpio_save_regs(port);
+		clk_disable_unprepare(port->clk);
+	}
 
 	return 0;
 }
 
-static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
+static void mxc_gpio_syscore_resume(void)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+	struct mxc_gpio_port *port;
 	int ret;
 
-	ret = clk_prepare_enable(port->clk);
-	if (ret)
-		return ret;
-	mxc_gpio_restore_regs(port);
-
-	return 0;
+	/* walk through all ports */
+	list_for_each_entry(port, &mxc_gpio_ports, node) {
+		ret = clk_prepare_enable(port->clk);
+		if (ret) {
+			pr_err("mxc: failed to enable gpio clock %d\n", ret);
+			return;
+		}
+		mxc_gpio_restore_regs(port);
+	}
 }
 
-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 struct syscore_ops mxc_gpio_syscore_ops = {
+	.suspend = mxc_gpio_syscore_suspend,
+	.resume = mxc_gpio_syscore_resume,
 };
 
 static struct platform_driver mxc_gpio_driver = {
@@ -584,7 +590,6 @@ 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,
 	.id_table	= mxc_gpio_devtype,
@@ -592,6 +597,8 @@ static struct platform_driver mxc_gpio_driver = {
 
 static int __init gpio_mxc_init(void)
 {
+	register_syscore_ops(&mxc_gpio_syscore_ops);
+
 	return platform_driver_register(&mxc_gpio_driver);
 }
 subsys_initcall(gpio_mxc_init);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-02-18  1:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-09  4:56 [PATCH] gpio: mxc: move gpio noirq suspend/resume to syscore phase Anson Huang
2018-11-16 21:56 ` Linus Walleij
2019-02-17 22:05 Martin Hundebøll
2019-02-18  1:38 ` Sasha Levin

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.