Message ID | 1362755901-20279-1-git-send-email-ludovic.desroches@atmel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 03/08/2013 04:18 PM, ludovic.desroches@atmel.com : > From: Ludovic Desroches <ludovic.desroches@atmel.com> > > 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: Ludovic Desroches <ludovic.desroches@atmel.com> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Nice, I queue it for "fixes" in at91-3.9-fixes. Thanks, best regards, > --- > arch/arm/mach-at91/include/mach/gpio.h | 8 +++++ > arch/arm/mach-at91/pm.c | 10 ++++-- > drivers/pinctrl/pinctrl-at91.c | 61 +++++++++++++++++++++++++++++++++- > 3 files changed, 76 insertions(+), 3 deletions(-) > > diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h > index eed465a..5fc2377 100644 > --- a/arch/arm/mach-at91/include/mach/gpio.h > +++ b/arch/arm/mach-at91/include/mach/gpio.h > @@ -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 > diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c > index adb6db8..73f1f25 100644 > --- a/arch/arm/mach-at91/pm.c > +++ b/arch/arm/mach-at91/pm.c > @@ -201,7 +201,10 @@ extern u32 at91_slow_clock_sz; > > static int at91_pm_enter(suspend_state_t state) > { > - at91_gpio_suspend(); > + if (of_have_populated_dt()) > + at91_pinctrl_gpio_suspend(); > + else > + at91_gpio_suspend(); > at91_irq_suspend(); > > pr_debug("AT91: PM - wake mask %08x, pm state %d\n", > @@ -286,7 +289,10 @@ static int at91_pm_enter(suspend_state_t state) > error: > target_state = PM_SUSPEND_ON; > at91_irq_resume(); > - at91_gpio_resume(); > + if (of_have_populated_dt()) > + at91_pinctrl_gpio_resume(); > + else > + at91_gpio_resume(); > return 0; > } > > diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c > index 75933a6..efb7f10 100644 > --- a/drivers/pinctrl/pinctrl-at91.c > +++ b/drivers/pinctrl/pinctrl-at91.c > @@ -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", >
On Fri, Mar 8, 2013 at 4:18 PM, <ludovic.desroches@atmel.com> wrote: > From: Ludovic Desroches <ludovic.desroches@atmel.com> > > 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: Ludovic Desroches <ludovic.desroches@atmel.com> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> I saw that Nicolas is taking care of it... Yours, Linus Walleij
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index eed465a..5fc2377 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -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 diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index adb6db8..73f1f25 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -201,7 +201,10 @@ extern u32 at91_slow_clock_sz; static int at91_pm_enter(suspend_state_t state) { - at91_gpio_suspend(); + if (of_have_populated_dt()) + at91_pinctrl_gpio_suspend(); + else + at91_gpio_suspend(); at91_irq_suspend(); pr_debug("AT91: PM - wake mask %08x, pm state %d\n", @@ -286,7 +289,10 @@ static int at91_pm_enter(suspend_state_t state) error: target_state = PM_SUSPEND_ON; at91_irq_resume(); - at91_gpio_resume(); + if (of_have_populated_dt()) + at91_pinctrl_gpio_resume(); + else + at91_gpio_resume(); return 0; } diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 75933a6..efb7f10 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -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",