Commit 647f8d94 authored by Ludovic Desroches's avatar Ludovic Desroches Committed by Nicolas Ferre
Browse files

ARM: at91: add gpio suspend/resume support when using pinctrl



gpio suspend/resume and wakeup sources where not managed when using pinctrl so
it was impossible to wake up the system with a gpio.

Signed-off-by: default avatarLudovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: default avatarJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
parent 7f06472f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -209,6 +209,14 @@ extern int at91_get_gpio_value(unsigned pin);
extern void at91_gpio_suspend(void);
extern void at91_gpio_resume(void);

#ifdef CONFIG_PINCTRL_AT91
extern void at91_pinctrl_gpio_suspend(void);
extern void at91_pinctrl_gpio_resume(void);
#else
static inline void at91_pinctrl_gpio_suspend(void) {}
static inline void at91_pinctrl_gpio_resume(void) {}
#endif

#endif	/* __ASSEMBLY__ */

#endif
+8 −2
Original line number Diff line number Diff line
@@ -201,6 +201,9 @@ extern u32 at91_slow_clock_sz;

static int at91_pm_enter(suspend_state_t state)
{
	if (of_have_populated_dt())
		at91_pinctrl_gpio_suspend();
	else
		at91_gpio_suspend();
	at91_irq_suspend();

@@ -286,6 +289,9 @@ static int at91_pm_enter(suspend_state_t state)
error:
	target_state = PM_SUSPEND_ON;
	at91_irq_resume();
	if (of_have_populated_dt())
		at91_pinctrl_gpio_resume();
	else
		at91_gpio_resume();
	return 0;
}
+60 −1
Original line number Diff line number Diff line
@@ -1277,21 +1277,80 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
}

#ifdef CONFIG_PM

static u32 wakeups[MAX_GPIO_BANKS];
static u32 backups[MAX_GPIO_BANKS];

static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
{
	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
	unsigned	bank = at91_gpio->pioc_idx;
	unsigned mask = 1 << d->hwirq;

	if (unlikely(bank >= MAX_GPIO_BANKS))
		return -EINVAL;

	if (state)
		wakeups[bank] |= mask;
	else
		wakeups[bank] &= ~mask;

	irq_set_irq_wake(at91_gpio->pioc_virq, state);

	return 0;
}

void at91_pinctrl_gpio_suspend(void)
{
	int i;

	for (i = 0; i < gpio_banks; i++) {
		void __iomem  *pio;

		if (!gpio_chips[i])
			continue;

		pio = gpio_chips[i]->regbase;

		backups[i] = __raw_readl(pio + PIO_IMR);
		__raw_writel(backups[i], pio + PIO_IDR);
		__raw_writel(wakeups[i], pio + PIO_IER);

		if (!wakeups[i]) {
			clk_unprepare(gpio_chips[i]->clock);
			clk_disable(gpio_chips[i]->clock);
		} else {
			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n",
			       'A'+i, wakeups[i]);
		}
	}
}

void at91_pinctrl_gpio_resume(void)
{
	int i;

	for (i = 0; i < gpio_banks; i++) {
		void __iomem  *pio;

		if (!gpio_chips[i])
			continue;

		pio = gpio_chips[i]->regbase;

		if (!wakeups[i]) {
			if (clk_prepare(gpio_chips[i]->clock) == 0)
				clk_enable(gpio_chips[i]->clock);
		}

		__raw_writel(wakeups[i], pio + PIO_IDR);
		__raw_writel(backups[i], pio + PIO_IER);
	}
}

#else
#define gpio_irq_set_wake	NULL
#endif
#endif /* CONFIG_PM */

static struct irq_chip gpio_irqchip = {
	.name		= "GPIO",