gpio: mxc: add power management support

Message ID 1531208921-23342-1-git-send-email-Anson.Huang@nxp.com
State New
Headers show
Series
  • gpio: mxc: add power management support
Related show

Commit Message

Anson Huang July 10, 2018, 7:48 a.m.
GPIO registers could lose context on some i.MX SoCs,
like on i.MX7D, when enter LPSR mode, the whole SoC
will be powered off except LPSR domain, GPIO banks
will lose context in this case, need to restore
the context after resume from LPSR mode.

This patch adds GPIO save/restore for those necessary
registers, and put the save/restore operations in noirq
suspend/resume phase, since GPIO is fundamental module
which could be used by other peripherals' resume phase.

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

Comments

Linus Walleij July 13, 2018, 7:11 a.m. | #1
On Tue, Jul 10, 2018 at 9:53 AM Anson Huang <Anson.Huang@nxp.com> wrote:

> GPIO registers could lose context on some i.MX SoCs,
> like on i.MX7D, when enter LPSR mode, the whole SoC
> will be powered off except LPSR domain, GPIO banks
> will lose context in this case, need to restore
> the context after resume from LPSR mode.
>
> This patch adds GPIO save/restore for those necessary
> registers, and put the save/restore operations in noirq
> suspend/resume phase, since GPIO is fundamental module
> which could be used by other peripherals' resume phase.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>

Hoping for some review on this before applying...
Fabio? Bartosz?

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski July 13, 2018, 7:19 a.m. | #2
2018-07-13 9:11 GMT+02:00 Linus Walleij <linus.walleij@linaro.org>:
> On Tue, Jul 10, 2018 at 9:53 AM Anson Huang <Anson.Huang@nxp.com> wrote:
>
>> GPIO registers could lose context on some i.MX SoCs,
>> like on i.MX7D, when enter LPSR mode, the whole SoC
>> will be powered off except LPSR domain, GPIO banks
>> will lose context in this case, need to restore
>> the context after resume from LPSR mode.
>>
>> This patch adds GPIO save/restore for those necessary
>> registers, and put the save/restore operations in noirq
>> suspend/resume phase, since GPIO is fundamental module
>> which could be used by other peripherals' resume phase.
>>
>> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
>
> Hoping for some review on this before applying...
> Fabio? Bartosz?
>
> Yours,
> Linus Walleij

I'm not familiar with these SoCs but the code looks good and clean to me.

Reviewed-by: Bartosz Golaszewski <brgl@bgdev.pl>
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Fabio Estevam July 13, 2018, 5:57 p.m. | #3
On Fri, Jul 13, 2018 at 4:11 AM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Jul 10, 2018 at 9:53 AM Anson Huang <Anson.Huang@nxp.com> wrote:
>
>> GPIO registers could lose context on some i.MX SoCs,
>> like on i.MX7D, when enter LPSR mode, the whole SoC
>> will be powered off except LPSR domain, GPIO banks
>> will lose context in this case, need to restore
>> the context after resume from LPSR mode.
>>
>> This patch adds GPIO save/restore for those necessary
>> registers, and put the save/restore operations in noirq
>> suspend/resume phase, since GPIO is fundamental module
>> which could be used by other peripherals' resume phase.
>>
>> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
>
> Hoping for some review on this before applying...
> Fabio? Bartosz?

Now I could find the patch on my Gmail Inbox :-)

It looks good to me:

Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Fabio Estevam July 13, 2018, 6:33 p.m. | #4
Hi Anson,

On Tue, Jul 10, 2018 at 4:48 AM, Anson Huang <Anson.Huang@nxp.com> wrote:
> GPIO registers could lose context on some i.MX SoCs,
> like on i.MX7D, when enter LPSR mode, the whole SoC

After further reviewing this patchI have a question: here you say that
i.MX7D needs to save some registers.

> will be powered off except LPSR domain, GPIO banks
> will lose context in this case, need to restore
> the context after resume from LPSR mode.
>
> This patch adds GPIO save/restore for those necessary
> registers, and put the save/restore operations in noirq
> suspend/resume phase, since GPIO is fundamental module
> which could be used by other peripherals' resume phase.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
> ---
>  drivers/gpio/gpio-mxc.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 68 insertions(+)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 2f28299..0fc52d8 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -45,6 +45,15 @@ struct mxc_gpio_hwdata {
>         unsigned fall_edge;
>  };
>
> +struct mxc_gpio_reg_saved {
> +       u32 icr1;
> +       u32 icr2;
> +       u32 imr;
> +       u32 gdir;
> +       u32 edge_sel;
> +       u32 dr;
> +};
> +
>  struct mxc_gpio_port {
>         struct list_head node;
>         void __iomem *base;
> @@ -55,6 +64,7 @@ struct mxc_gpio_port {
>         struct gpio_chip gc;
>         struct device *dev;
>         u32 both_edges;
> +       struct mxc_gpio_reg_saved gpio_saved_reg;
>  };
>
>  static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
> @@ -497,6 +507,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
>         list_add_tail(&port->node, &mxc_gpio_ports);
>
> +       platform_set_drvdata(pdev, port);
> +
>         return 0;
>
>  out_irqdomain_remove:
> @@ -507,11 +519,67 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>         return err;
>  }
>
> +static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
> +{
> +       if (mxc_gpio_hwtype == IMX21_GPIO)
> +               return;

but here you only block IMX21_GPIO.

This means that mx31/mx35/mx51/mx53/mx6 will execute this code too
now. Is this always safe?

Shouldn't it this save/restore be executed only on mx7d?

Please clarify.
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anson Huang July 14, 2018, 1:53 a.m. | #5
Hi, Fabio

Anson Huang
Best Regards!


> -----Original Message-----
> From: Fabio Estevam [mailto:festevam@gmail.com]
> Sent: Saturday, July 14, 2018 2:34 AM
> To: Anson Huang <anson.huang@nxp.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>; open list:GPIO SUBSYSTEM
> <linux-gpio@vger.kernel.org>; linux-kernel <linux-kernel@vger.kernel.org>;
> dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH] gpio: mxc: add power management support
> 
> Hi Anson,
> 
> On Tue, Jul 10, 2018 at 4:48 AM, Anson Huang <Anson.Huang@nxp.com>
> wrote:
> > GPIO registers could lose context on some i.MX SoCs, like on i.MX7D,
> > when enter LPSR mode, the whole SoC
> 
> After further reviewing this patchI have a question: here you say that i.MX7D
> needs to save some registers.
> 
> > will be powered off except LPSR domain, GPIO banks will lose context
> > in this case, need to restore the context after resume from LPSR mode.
> >
> > This patch adds GPIO save/restore for those necessary registers, and
> > put the save/restore operations in noirq suspend/resume phase, since
> > GPIO is fundamental module which could be used by other peripherals'
> > resume phase.
> >
> > Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
> > ---
> >  drivers/gpio/gpio-mxc.c | 68
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 68 insertions(+)
> >
> > diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index
> > 2f28299..0fc52d8 100644
> > --- a/drivers/gpio/gpio-mxc.c
> > +++ b/drivers/gpio/gpio-mxc.c
> > @@ -45,6 +45,15 @@ struct mxc_gpio_hwdata {
> >         unsigned fall_edge;
> >  };
> >
> > +struct mxc_gpio_reg_saved {
> > +       u32 icr1;
> > +       u32 icr2;
> > +       u32 imr;
> > +       u32 gdir;
> > +       u32 edge_sel;
> > +       u32 dr;
> > +};
> > +
> >  struct mxc_gpio_port {
> >         struct list_head node;
> >         void __iomem *base;
> > @@ -55,6 +64,7 @@ struct mxc_gpio_port {
> >         struct gpio_chip gc;
> >         struct device *dev;
> >         u32 both_edges;
> > +       struct mxc_gpio_reg_saved gpio_saved_reg;
> >  };
> >
> >  static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { @@ -497,6
> > +507,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> >
> >         list_add_tail(&port->node, &mxc_gpio_ports);
> >
> > +       platform_set_drvdata(pdev, port);
> > +
> >         return 0;
> >
> >  out_irqdomain_remove:
> > @@ -507,11 +519,67 @@ static int mxc_gpio_probe(struct platform_device
> *pdev)
> >         return err;
> >  }
> >
> > +static void mxc_gpio_save_regs(struct mxc_gpio_port *port) {
> > +       if (mxc_gpio_hwtype == IMX21_GPIO)
> > +               return;
> 
> but here you only block IMX21_GPIO.
> 
> This means that mx31/mx35/mx51/mx53/mx6 will execute this code too now.
> Is this always safe?
> 
> Shouldn't it this save/restore be executed only on mx7d?
> 
> Please clarify.
Here are the details, i.MX7D LPSR mode and i.MX8QM/8QXP etc.' suspend/resume
may cause GPIO bank lose power, so need to save/restore, for other i.MX SoCs,
although no need to do save/restore, but doing it is NOT harmful, so do you think
we should add SoC type check here?

Anson.
Fabio Estevam July 14, 2018, 4:13 p.m. | #6
Hi Anson,

On Fri, Jul 13, 2018 at 10:53 PM, Anson Huang <anson.huang@nxp.com> wrote:

> Here are the details, i.MX7D LPSR mode and i.MX8QM/8QXP etc.' suspend/resume
> may cause GPIO bank lose power, so need to save/restore, for other i.MX SoCs,
> although no need to do save/restore, but doing it is NOT harmful, so do you think
> we should add SoC type check here?

I think it would be safer to restrict the save/restore operations to mx7/mx8.

You can add a fsl,imx7d-gpio compatible entry in the driver.

Thanks
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anson Huang July 16, 2018, 6:14 a.m. | #7
SGksIEZhYmlvDQoNCkFuc29uIEh1YW5nDQpCZXN0IFJlZ2FyZHMhDQoNCg0KPiAtLS0tLU9yaWdp
bmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBGYWJpbyBFc3RldmFtIFttYWlsdG86ZmVzdGV2YW1A
Z21haWwuY29tXQ0KPiBTZW50OiBTdW5kYXksIEp1bHkgMTUsIDIwMTggMTI6MTMgQU0NCj4gVG86
IEFuc29uIEh1YW5nIDxhbnNvbi5odWFuZ0BueHAuY29tPg0KPiBDYzogTGludXMgV2FsbGVpaiA8
bGludXMud2FsbGVpakBsaW5hcm8ub3JnPjsgb3BlbiBsaXN0OkdQSU8gU1VCU1lTVEVNDQo+IDxs
aW51eC1ncGlvQHZnZXIua2VybmVsLm9yZz47IGxpbnV4LWtlcm5lbCA8bGludXgta2VybmVsQHZn
ZXIua2VybmVsLm9yZz47DQo+IGRsLWxpbnV4LWlteCA8bGludXgtaW14QG54cC5jb20+DQo+IFN1
YmplY3Q6IFJlOiBbUEFUQ0hdIGdwaW86IG14YzogYWRkIHBvd2VyIG1hbmFnZW1lbnQgc3VwcG9y
dA0KPiANCj4gSGkgQW5zb24sDQo+IA0KPiBPbiBGcmksIEp1bCAxMywgMjAxOCBhdCAxMDo1MyBQ
TSwgQW5zb24gSHVhbmcgPGFuc29uLmh1YW5nQG54cC5jb20+DQo+IHdyb3RlOg0KPiANCj4gPiBI
ZXJlIGFyZSB0aGUgZGV0YWlscywgaS5NWDdEIExQU1IgbW9kZSBhbmQgaS5NWDhRTS84UVhQIGV0
Yy4nDQo+ID4gc3VzcGVuZC9yZXN1bWUgbWF5IGNhdXNlIEdQSU8gYmFuayBsb3NlIHBvd2VyLCBz
byBuZWVkIHRvDQo+ID4gc2F2ZS9yZXN0b3JlLCBmb3Igb3RoZXIgaS5NWCBTb0NzLCBhbHRob3Vn
aCBubyBuZWVkIHRvIGRvDQo+ID4gc2F2ZS9yZXN0b3JlLCBidXQgZG9pbmcgaXQgaXMgTk9UIGhh
cm1mdWwsIHNvIGRvIHlvdSB0aGluayB3ZSBzaG91bGQgYWRkIFNvQw0KPiB0eXBlIGNoZWNrIGhl
cmU/DQo+IA0KPiBJIHRoaW5rIGl0IHdvdWxkIGJlIHNhZmVyIHRvIHJlc3RyaWN0IHRoZSBzYXZl
L3Jlc3RvcmUgb3BlcmF0aW9ucyB0byBteDcvbXg4Lg0KPiANCj4gWW91IGNhbiBhZGQgYSBmc2ws
aW14N2QtZ3BpbyBjb21wYXRpYmxlIGVudHJ5IGluIHRoZSBkcml2ZXIuDQo+IA0KPiBUaGFua3MN
Ck9LLCBzaW5jZSBpLk1YN0QgaGFzIHNhbWUgR1BJTyB0eXBlIGFzIGkuTVgzNSwgdG8gbWFrZSBp
dCBzaW1wbGUsIEkganVzdCBhZGRlZA0KYSBmbGFnIHRvIGluZGljYXRlIHdoZXRoZXIgaXQgc3Vw
cG9ydHMgc2F2ZS9yZXN0b3JlLCBvbmx5IGkuTVg3RCBlbmFibGVzDQp0aGUgZmxhZyBub3csIHNp
bmNlIG90aGVyIGkuTVg4IFNvQ3MnIGR0cyBpcyBOT1QgdXBzdHJlYW1lZCB5ZXQsIHNvIEkgZGlk
IE5PVCBhZGQNCnN1cHBvcnQgZm9yIGkuTVg4IFNvQ3MsIHBsZWFzZSBoZWxwIHJldmlldyBWMiBw
YXRjaCwgdGhhbmtzLg0KDQpBbnNvbi4gDQoNCg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Fabio Estevam July 17, 2018, 1:43 p.m. | #8
Hi Anson,

On Mon, Jul 16, 2018 at 3:14 AM, Anson Huang <anson.huang@nxp.com> wrote:

> OK, since i.MX7D has same GPIO type as i.MX35, to make it simple, I just added
> a flag to indicate whether it supports save/restore, only i.MX7D enables

In imx7s.dtsi the gpio nodes have:

compatible = "fsl,imx7d-gpio", "fsl,imx35-gpio";

If you add fsl,imx7d-gpio entry in the gpio driver, then the match
will be done against "fsl,imx7d-gpio" since it is more specific.

Then in the mx8 dts you can add:

compatible = "fsl,imx8m-gpio", "fsl,imx7d-gpio";

and it will also match the more generic "fsl,imx7d-gpio" compatible.

> the flag now, since other i.MX8 SoCs' dts is NOT upstreamed yet, so I did NOT add
> support for i.MX8 SoCs, please help review V2 patch, thanks.

I did not see the v2. Did you put me on Cc?
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 2f28299..0fc52d8 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -45,6 +45,15 @@  struct mxc_gpio_hwdata {
 	unsigned fall_edge;
 };
 
+struct mxc_gpio_reg_saved {
+	u32 icr1;
+	u32 icr2;
+	u32 imr;
+	u32 gdir;
+	u32 edge_sel;
+	u32 dr;
+};
+
 struct mxc_gpio_port {
 	struct list_head node;
 	void __iomem *base;
@@ -55,6 +64,7 @@  struct mxc_gpio_port {
 	struct gpio_chip gc;
 	struct device *dev;
 	u32 both_edges;
+	struct mxc_gpio_reg_saved gpio_saved_reg;
 };
 
 static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
@@ -497,6 +507,8 @@  static int mxc_gpio_probe(struct platform_device *pdev)
 
 	list_add_tail(&port->node, &mxc_gpio_ports);
 
+	platform_set_drvdata(pdev, port);
+
 	return 0;
 
 out_irqdomain_remove:
@@ -507,11 +519,67 @@  static int mxc_gpio_probe(struct platform_device *pdev)
 	return err;
 }
 
+static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
+{
+	if (mxc_gpio_hwtype == IMX21_GPIO)
+		return;
+
+	port->gpio_saved_reg.icr1 = readl(port->base + GPIO_ICR1);
+	port->gpio_saved_reg.icr2 = readl(port->base + GPIO_ICR2);
+	port->gpio_saved_reg.imr = readl(port->base + GPIO_IMR);
+	port->gpio_saved_reg.gdir = readl(port->base + GPIO_GDIR);
+	port->gpio_saved_reg.edge_sel = readl(port->base + GPIO_EDGE_SEL);
+	port->gpio_saved_reg.dr = readl(port->base + GPIO_DR);
+}
+
+static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
+{
+	if (mxc_gpio_hwtype == IMX21_GPIO)
+		return;
+
+	writel(port->gpio_saved_reg.icr1, port->base + GPIO_ICR1);
+	writel(port->gpio_saved_reg.icr2, port->base + GPIO_ICR2);
+	writel(port->gpio_saved_reg.imr, port->base + GPIO_IMR);
+	writel(port->gpio_saved_reg.gdir, port->base + GPIO_GDIR);
+	writel(port->gpio_saved_reg.edge_sel, port->base + GPIO_EDGE_SEL);
+	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
+}
+
+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);
+
+	mxc_gpio_save_regs(port);
+	clk_disable_unprepare(port->clk);
+
+	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);
+	int ret;
+
+	ret = clk_prepare_enable(port->clk);
+	if (ret)
+		return ret;
+	mxc_gpio_restore_regs(port);
+
+	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 struct platform_driver mxc_gpio_driver = {
 	.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,