diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2017-04-06 16:36:23 +0300 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-04-07 15:32:51 +0300 |
commit | ba9e7f2794d8158c93aacd279830a6f1f98b19b0 (patch) | |
tree | 68d98fa179f3d28fa50406f9aa163e7ff048ee0a /drivers/pinctrl/pinctrl-at91-pio4.c | |
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>
Diffstat (limited to 'drivers/pinctrl/pinctrl-at91-pio4.c')
-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 { struct irq_domain *irq_domain; int *irqs; unsigned *pm_wakeup_sources; - unsigned *pm_suspend_backup; + struct { + u32 imr; + u32 odsr; + u32 cfgr[ATMEL_PIO_NPINS_PER_BANK]; + } *pm_suspend_backup; struct device *dev; struct device_node *node; }; @@ -830,17 +834,26 @@ static int __maybe_unused atmel_pctrl_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); - int i; + int i, j; /* * For each bank, save IMR to restore it later and disable all GPIO * interrupts excepting the ones marked as wakeup sources. */ for (i = 0; i < atmel_pioctrl->nbanks; i++) { - atmel_pioctrl->pm_suspend_backup[i] = + atmel_pioctrl->pm_suspend_backup[i].imr = atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR); atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR, ~atmel_pioctrl->pm_wakeup_sources[i]); + atmel_pioctrl->pm_suspend_backup[i].odsr = + atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_ODSR); + for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { + atmel_gpio_write(atmel_pioctrl, i, + ATMEL_PIO_MSKR, BIT(j)); + atmel_pioctrl->pm_suspend_backup[i].cfgr[j] = + atmel_gpio_read(atmel_pioctrl, i, + ATMEL_PIO_CFGR); + } } return 0; @@ -850,11 +863,20 @@ static int __maybe_unused atmel_pctrl_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); - int i; + int i, j; - for (i = 0; i < atmel_pioctrl->nbanks; i++) + for (i = 0; i < atmel_pioctrl->nbanks; i++) { atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER, - atmel_pioctrl->pm_suspend_backup[i]); + atmel_pioctrl->pm_suspend_backup[i].imr); + atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_SODR, + atmel_pioctrl->pm_suspend_backup[i].odsr); + for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { + atmel_gpio_write(atmel_pioctrl, i, + ATMEL_PIO_MSKR, BIT(j)); + atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_CFGR, + atmel_pioctrl->pm_suspend_backup[i].cfgr[j]); + } + } return 0; } |