diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2017-04-06 09:36:23 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-04-07 08:32:51 -0400 |
commit | ba9e7f2794d8158c93aacd279830a6f1f98b19b0 (patch) | |
tree | 68d98fa179f3d28fa50406f9aa163e7ff048ee0a | |
parent | 8d5e7c5df0a6c442373628be5221321172b1badf (diff) |
pinctrl: at91-pio4: handle suspend to ram
When suspending to RAM, the power to the core is cut and the register
values are lost. Save and restore more registers than just IMR.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/pinctrl-at91-pio4.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 28bbc1bb9e6c..dc8591543dee 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c | |||
@@ -126,7 +126,11 @@ struct atmel_pioctrl { | |||
126 | struct irq_domain *irq_domain; | 126 | struct irq_domain *irq_domain; |
127 | int *irqs; | 127 | int *irqs; |
128 | unsigned *pm_wakeup_sources; | 128 | unsigned *pm_wakeup_sources; |
129 | unsigned *pm_suspend_backup; | 129 | struct { |
130 | u32 imr; | ||
131 | u32 odsr; | ||
132 | u32 cfgr[ATMEL_PIO_NPINS_PER_BANK]; | ||
133 | } *pm_suspend_backup; | ||
130 | struct device *dev; | 134 | struct device *dev; |
131 | struct device_node *node; | 135 | struct device_node *node; |
132 | }; | 136 | }; |
@@ -830,17 +834,26 @@ static int __maybe_unused atmel_pctrl_suspend(struct device *dev) | |||
830 | { | 834 | { |
831 | struct platform_device *pdev = to_platform_device(dev); | 835 | struct platform_device *pdev = to_platform_device(dev); |
832 | struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); | 836 | struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); |
833 | int i; | 837 | int i, j; |
834 | 838 | ||
835 | /* | 839 | /* |
836 | * For each bank, save IMR to restore it later and disable all GPIO | 840 | * For each bank, save IMR to restore it later and disable all GPIO |
837 | * interrupts excepting the ones marked as wakeup sources. | 841 | * interrupts excepting the ones marked as wakeup sources. |
838 | */ | 842 | */ |
839 | for (i = 0; i < atmel_pioctrl->nbanks; i++) { | 843 | for (i = 0; i < atmel_pioctrl->nbanks; i++) { |
840 | atmel_pioctrl->pm_suspend_backup[i] = | 844 | atmel_pioctrl->pm_suspend_backup[i].imr = |
841 | atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR); | 845 | atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR); |
842 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR, | 846 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR, |
843 | ~atmel_pioctrl->pm_wakeup_sources[i]); | 847 | ~atmel_pioctrl->pm_wakeup_sources[i]); |
848 | atmel_pioctrl->pm_suspend_backup[i].odsr = | ||
849 | atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_ODSR); | ||
850 | for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { | ||
851 | atmel_gpio_write(atmel_pioctrl, i, | ||
852 | ATMEL_PIO_MSKR, BIT(j)); | ||
853 | atmel_pioctrl->pm_suspend_backup[i].cfgr[j] = | ||
854 | atmel_gpio_read(atmel_pioctrl, i, | ||
855 | ATMEL_PIO_CFGR); | ||
856 | } | ||
844 | } | 857 | } |
845 | 858 | ||
846 | return 0; | 859 | return 0; |
@@ -850,11 +863,20 @@ static int __maybe_unused atmel_pctrl_resume(struct device *dev) | |||
850 | { | 863 | { |
851 | struct platform_device *pdev = to_platform_device(dev); | 864 | struct platform_device *pdev = to_platform_device(dev); |
852 | struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); | 865 | struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); |
853 | int i; | 866 | int i, j; |
854 | 867 | ||
855 | for (i = 0; i < atmel_pioctrl->nbanks; i++) | 868 | for (i = 0; i < atmel_pioctrl->nbanks; i++) { |
856 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER, | 869 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER, |
857 | atmel_pioctrl->pm_suspend_backup[i]); | 870 | atmel_pioctrl->pm_suspend_backup[i].imr); |
871 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_SODR, | ||
872 | atmel_pioctrl->pm_suspend_backup[i].odsr); | ||
873 | for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { | ||
874 | atmel_gpio_write(atmel_pioctrl, i, | ||
875 | ATMEL_PIO_MSKR, BIT(j)); | ||
876 | atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_CFGR, | ||
877 | atmel_pioctrl->pm_suspend_backup[i].cfgr[j]); | ||
878 | } | ||
879 | } | ||
858 | 880 | ||
859 | return 0; | 881 | return 0; |
860 | } | 882 | } |