Commit ba9e7f27 authored by Alexandre Belloni's avatar Alexandre Belloni Committed by Linus Walleij
Browse files

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: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 8d5e7c5d
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -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;
}