diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2014-10-24 07:59:19 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-11-03 08:28:03 -0500 |
commit | b5b7b487431b01619f2947d91dadd7c7a233692e (patch) | |
tree | bc1bc9164747b69410948f154610530aa17d68e4 | |
parent | 5bb5428956d3eecb428e72e7f521ff6ac767384b (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.c | 99 |
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 | }; |
555 | MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); | 563 | MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); |
556 | 564 | ||
565 | static 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 | |||
609 | static 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 | |||
557 | static int mvebu_gpio_probe(struct platform_device *pdev) | 652 | static 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 | }; |
739 | module_platform_driver(mvebu_gpio_driver); | 838 | module_platform_driver(mvebu_gpio_driver); |