diff mbox

[PATCHv2,05/16] gpio: mvebu: add suspend/resume support

Message ID 1415978496-9334-6-git-send-email-thomas.petazzoni@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thomas Petazzoni Nov. 14, 2014, 3:21 p.m. UTC
This commit adds the implementation of ->suspend() and ->resume()
platform_driver hooks in order to save and restore the state of the
GPIO configuration. In order to achieve that, additional fields are
added to the mvebu_gpio_chip structure.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: linux-gpio@vger.kernel.org
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 drivers/gpio/gpio-mvebu.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

Comments

Linus Walleij Nov. 27, 2014, 1:29 p.m. UTC | #1
On Fri, Nov 14, 2014 at 4:21 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:

> This commit adds the implementation of ->suspend() and ->resume()
> platform_driver hooks in order to save and restore the state of the
> GPIO configuration. In order to achieve that, additional fields are
> added to the mvebu_gpio_chip structure.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Alexandre Courbot <gnurou@gmail.com>
> Cc: linux-gpio@vger.kernel.org
> Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Do you want me to merge the patch or is it dependent on other patches?

Yours,
Linus Walleij
Jason Cooper Nov. 27, 2014, 5:53 p.m. UTC | #2
On Thu, Nov 27, 2014 at 02:29:47PM +0100, Linus Walleij wrote:
> On Fri, Nov 14, 2014 at 4:21 PM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com> wrote:
> 
> > This commit adds the implementation of ->suspend() and ->resume()
> > platform_driver hooks in order to save and restore the state of the
> > GPIO configuration. In order to achieve that, additional fields are
> > added to the mvebu_gpio_chip structure.
> >
> > Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Alexandre Courbot <gnurou@gmail.com>
> > Cc: linux-gpio@vger.kernel.org
> > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> > Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Do you want me to merge the patch or is it dependent on other patches?

I have a separate branch for this series, mvebu/soc-suspend which
contains everything.  I've been a bit wrapped around the axle this
cycle, and didn't want the series to suffer for lack of testing.  So
when I had a moment, I put the whole thing into mvebu/for-next.  It's
been there for a while.

If you don't mind, I can just send a pull request to arm-soc for the
branch as is.

I can break it up also, but I can't guarantee my availability for the
next week or two.  So there a risk of the arch changes not making it in.

thx,

Jason.
Thomas Petazzoni Nov. 27, 2014, 6:44 p.m. UTC | #3
Dear Linus Walleij,

On Thu, 27 Nov 2014 14:29:47 +0100, Linus Walleij wrote:
> On Fri, Nov 14, 2014 at 4:21 PM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com> wrote:
> 
> > This commit adds the implementation of ->suspend() and ->resume()
> > platform_driver hooks in order to save and restore the state of the
> > GPIO configuration. In order to achieve that, additional fields are
> > added to the mvebu_gpio_chip structure.
> >
> > Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Alexandre Courbot <gnurou@gmail.com>
> > Cc: linux-gpio@vger.kernel.org
> > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> > Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Do you want me to merge the patch or is it dependent on other patches?

This patch has already been merged by you, and is already in
linux-next. See
https://git.kernel.org/cgit/linux/kernel/git/linusw/linux-gpio.git/commit/?h=for-next&id=b5b7b487431b01619f2947d91dadd7c7a233692e.

Best regards,

Thomas
Linus Walleij Nov. 28, 2014, 3:42 p.m. UTC | #4
On Thu, Nov 27, 2014 at 7:44 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> Dear Linus Walleij,

>> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>>
>> Do you want me to merge the patch or is it dependent on other patches?
>
> This patch has already been merged by you, and is already in
> linux-next. See
> https://git.kernel.org/cgit/linux/kernel/git/linusw/linux-gpio.git/commit/?h=for-next&id=b5b7b487431b01619f2947d91dadd7c7a233692e.

Argh, haha yeah it was the resending that confused me... too many
patches floating around. Well then, it lands upstream.

Yours,
Linus Walleij
Jason Cooper Nov. 30, 2014, 4:49 p.m. UTC | #5
Linus, Stephen,

On Fri, Nov 28, 2014 at 04:42:14PM +0100, Linus Walleij wrote:
> On Thu, Nov 27, 2014 at 7:44 PM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com> wrote:
> > Dear Linus Walleij,
> 
> >> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> >>
> >> Do you want me to merge the patch or is it dependent on other patches?
> >
> > This patch has already been merged by you, and is already in
> > linux-next. See
> > https://git.kernel.org/cgit/linux/kernel/git/linusw/linux-gpio.git/commit/?h=for-next&id=b5b7b487431b01619f2947d91dadd7c7a233692e.
> 
> Argh, haha yeah it was the resending that confused me... too many
> patches floating around. Well then, it lands upstream.

Odd.  I've had the same patch in mvebu/for-next since the 22nd of
November...  You'd think it would have caused a merge conflict.

At any rate, I've dropped it from the mvebu/soc-suspend branch and
updated mvebu/for-next.

thx,

Jason.
Jason Cooper Nov. 30, 2014, 5:01 p.m. UTC | #6
Linus, Stephen,

Sorry for the double send.  Forgot to add Stehpen. :(

On Fri, Nov 28, 2014 at 04:42:14PM +0100, Linus Walleij wrote:
> On Thu, Nov 27, 2014 at 7:44 PM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com> wrote:
> > Dear Linus Walleij,
> 
> >> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> >>
> >> Do you want me to merge the patch or is it dependent on other patches?
> >
> > This patch has already been merged by you, and is already in
> > linux-next. See
> > https://git.kernel.org/cgit/linux/kernel/git/linusw/linux-gpio.git/commit/?h=for-next&id=b5b7b487431b01619f2947d91dadd7c7a233692e.
> 
> Argh, haha yeah it was the resending that confused me... too many
> patches floating around. Well then, it lands upstream.

Odd.  I've had the same patch in mvebu/for-next since the 22nd of
November...  You'd think it would have caused a merge conflict.

At any rate, I've dropped it from the mvebu/soc-suspend branch and
updated mvebu/for-next.

thx,

Jason.
diff mbox

Patch

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 418e386..dd5545c 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -83,6 +83,14 @@  struct mvebu_gpio_chip {
 	int		   irqbase;
 	struct irq_domain *domain;
 	int                soc_variant;
+
+	/* Used to preserve GPIO registers accross suspend/resume */
+	u32                out_reg;
+	u32                io_conf_reg;
+	u32                blink_en_reg;
+	u32                in_pol_reg;
+	u32                edge_mask_regs[4];
+	u32                level_mask_regs[4];
 };
 
 /*
@@ -554,6 +562,93 @@  static const struct of_device_id mvebu_gpio_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
 
+static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
+	int i;
+
+	mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip));
+	mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip));
+	mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip));
+	mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip));
+
+	switch (mvchip->soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+		mvchip->edge_mask_regs[0] =
+			readl(mvchip->membase + GPIO_EDGE_MASK_OFF);
+		mvchip->level_mask_regs[0] =
+			readl(mvchip->membase + GPIO_LEVEL_MASK_OFF);
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		for (i = 0; i < 2; i++) {
+			mvchip->edge_mask_regs[i] =
+				readl(mvchip->membase +
+				      GPIO_EDGE_MASK_MV78200_OFF(i));
+			mvchip->level_mask_regs[i] =
+				readl(mvchip->membase +
+				      GPIO_LEVEL_MASK_MV78200_OFF(i));
+		}
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		for (i = 0; i < 4; i++) {
+			mvchip->edge_mask_regs[i] =
+				readl(mvchip->membase +
+				      GPIO_EDGE_MASK_ARMADAXP_OFF(i));
+			mvchip->level_mask_regs[i] =
+				readl(mvchip->membase +
+				      GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int mvebu_gpio_resume(struct platform_device *pdev)
+{
+	struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
+	int i;
+
+	writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip));
+	writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip));
+	writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip));
+	writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip));
+
+	switch (mvchip->soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+		writel(mvchip->edge_mask_regs[0],
+		       mvchip->membase + GPIO_EDGE_MASK_OFF);
+		writel(mvchip->level_mask_regs[0],
+		       mvchip->membase + GPIO_LEVEL_MASK_OFF);
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		for (i = 0; i < 2; i++) {
+			writel(mvchip->edge_mask_regs[i],
+			       mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i));
+			writel(mvchip->level_mask_regs[i],
+			       mvchip->membase +
+			       GPIO_LEVEL_MASK_MV78200_OFF(i));
+		}
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		for (i = 0; i < 4; i++) {
+			writel(mvchip->edge_mask_regs[i],
+			       mvchip->membase +
+			       GPIO_EDGE_MASK_ARMADAXP_OFF(i));
+			writel(mvchip->level_mask_regs[i],
+			       mvchip->membase +
+			       GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
 static int mvebu_gpio_probe(struct platform_device *pdev)
 {
 	struct mvebu_gpio_chip *mvchip;
@@ -577,6 +672,8 @@  static int mvebu_gpio_probe(struct platform_device *pdev)
 	if (!mvchip)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, mvchip);
+
 	if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
 		dev_err(&pdev->dev, "Missing ngpios OF property\n");
 		return -ENODEV;
@@ -735,5 +832,7 @@  static struct platform_driver mvebu_gpio_driver = {
 		.of_match_table = mvebu_gpio_of_match,
 	},
 	.probe		= mvebu_gpio_probe,
+	.suspend        = mvebu_gpio_suspend,
+	.resume         = mvebu_gpio_resume,
 };
 module_platform_driver(mvebu_gpio_driver);