aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-10-24 07:59:19 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-11-03 08:28:03 -0500
commitb5b7b487431b01619f2947d91dadd7c7a233692e (patch)
treebc1bc9164747b69410948f154610530aa17d68e4
parent5bb5428956d3eecb428e72e7f521ff6ac767384b (diff)
gpio: mvebu: add suspend/resume support
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> Acked-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpio-mvebu.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 418e38650363..dd5545c293d4 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -83,6 +83,14 @@ struct mvebu_gpio_chip {
83 int irqbase; 83 int irqbase;
84 struct irq_domain *domain; 84 struct irq_domain *domain;
85 int soc_variant; 85 int soc_variant;
86
87 /* Used to preserve GPIO registers accross suspend/resume */
88 u32 out_reg;
89 u32 io_conf_reg;
90 u32 blink_en_reg;
91 u32 in_pol_reg;
92 u32 edge_mask_regs[4];
93 u32 level_mask_regs[4];
86}; 94};
87 95
88/* 96/*
@@ -554,6 +562,93 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
554}; 562};
555MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); 563MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
556 564
565static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
566{
567 struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
568 int i;
569
570 mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip));
571 mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip));
572 mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip));
573 mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip));
574
575 switch (mvchip->soc_variant) {
576 case MVEBU_GPIO_SOC_VARIANT_ORION:
577 mvchip->edge_mask_regs[0] =
578 readl(mvchip->membase + GPIO_EDGE_MASK_OFF);
579 mvchip->level_mask_regs[0] =
580 readl(mvchip->membase + GPIO_LEVEL_MASK_OFF);
581 break;
582 case MVEBU_GPIO_SOC_VARIANT_MV78200:
583 for (i = 0; i < 2; i++) {
584 mvchip->edge_mask_regs[i] =
585 readl(mvchip->membase +
586 GPIO_EDGE_MASK_MV78200_OFF(i));
587 mvchip->level_mask_regs[i] =
588 readl(mvchip->membase +
589 GPIO_LEVEL_MASK_MV78200_OFF(i));
590 }
591 break;
592 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
593 for (i = 0; i < 4; i++) {
594 mvchip->edge_mask_regs[i] =
595 readl(mvchip->membase +
596 GPIO_EDGE_MASK_ARMADAXP_OFF(i));
597 mvchip->level_mask_regs[i] =
598 readl(mvchip->membase +
599 GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
600 }
601 break;
602 default:
603 BUG();
604 }
605
606 return 0;
607}
608
609static int mvebu_gpio_resume(struct platform_device *pdev)
610{
611 struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
612 int i;
613
614 writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip));
615 writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip));
616 writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip));
617 writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip));
618
619 switch (mvchip->soc_variant) {
620 case MVEBU_GPIO_SOC_VARIANT_ORION:
621 writel(mvchip->edge_mask_regs[0],
622 mvchip->membase + GPIO_EDGE_MASK_OFF);
623 writel(mvchip->level_mask_regs[0],
624 mvchip->membase + GPIO_LEVEL_MASK_OFF);
625 break;
626 case MVEBU_GPIO_SOC_VARIANT_MV78200:
627 for (i = 0; i < 2; i++) {
628 writel(mvchip->edge_mask_regs[i],
629 mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i));
630 writel(mvchip->level_mask_regs[i],
631 mvchip->membase +
632 GPIO_LEVEL_MASK_MV78200_OFF(i));
633 }
634 break;
635 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
636 for (i = 0; i < 4; i++) {
637 writel(mvchip->edge_mask_regs[i],
638 mvchip->membase +
639 GPIO_EDGE_MASK_ARMADAXP_OFF(i));
640 writel(mvchip->level_mask_regs[i],
641 mvchip->membase +
642 GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
643 }
644 break;
645 default:
646 BUG();
647 }
648
649 return 0;
650}
651
557static int mvebu_gpio_probe(struct platform_device *pdev) 652static int mvebu_gpio_probe(struct platform_device *pdev)
558{ 653{
559 struct mvebu_gpio_chip *mvchip; 654 struct mvebu_gpio_chip *mvchip;
@@ -577,6 +672,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
577 if (!mvchip) 672 if (!mvchip)
578 return -ENOMEM; 673 return -ENOMEM;
579 674
675 platform_set_drvdata(pdev, mvchip);
676
580 if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { 677 if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
581 dev_err(&pdev->dev, "Missing ngpios OF property\n"); 678 dev_err(&pdev->dev, "Missing ngpios OF property\n");
582 return -ENODEV; 679 return -ENODEV;
@@ -735,5 +832,7 @@ static struct platform_driver mvebu_gpio_driver = {
735 .of_match_table = mvebu_gpio_of_match, 832 .of_match_table = mvebu_gpio_of_match,
736 }, 833 },
737 .probe = mvebu_gpio_probe, 834 .probe = mvebu_gpio_probe,
835 .suspend = mvebu_gpio_suspend,
836 .resume = mvebu_gpio_resume,
738}; 837};
739module_platform_driver(mvebu_gpio_driver); 838module_platform_driver(mvebu_gpio_driver);