diff options
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/mvebu/pinctrl-mvebu.c | 2 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-at91.c | 64 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 3 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 2 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-sirf.c | 2 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.c | 5 | ||||
-rw-r--r-- | drivers/pinctrl/spear/pinctrl-plgpio.c | 2 |
7 files changed, 71 insertions, 9 deletions
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 6114991..7f34a2b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -620,7 +620,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) /* special soc specific control */ if (ctrl->mpp_get || ctrl->mpp_set) { - if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) { + if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) { dev_err(&pdev->dev, "wrong soc control info\n"); return -EINVAL; } diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index e50fa5f..49bdc44 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/pinctrl/machine.h> @@ -27,8 +28,6 @@ /* Since we request GPIOs from ourself */ #include <linux/pinctrl/consumer.h> -#include <asm/mach/irq.h> - #include <mach/hardware.h> #include <mach/at91_pio.h> @@ -1277,21 +1276,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", diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 538b9dd..7265e55 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -23,13 +23,12 @@ #include <linux/interrupt.h> #include <linux/irqdomain.h> #include <linux/irq.h> +#include <linux/irqchip/chained_irq.h> #include <linux/of_irq.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/err.h> -#include <asm/mach/irq.h> - #include "pinctrl-samsung.h" #include "pinctrl-exynos.h" diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 2328baa..3fc8b99 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> #include <linux/slab.h> #include <linux/of_device.h> #include <linux/of_address.h> @@ -33,7 +34,6 @@ /* Since we request GPIOs from ourself */ #include <linux/pinctrl/consumer.h> #include <linux/platform_data/pinctrl-nomadik.h> -#include <asm/mach/irq.h> #include "pinctrl-nomadik.h" #include "core.h" diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 0990a721..08582fe 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -14,6 +14,7 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/consumer.h> @@ -25,7 +26,6 @@ #include <linux/bitops.h> #include <linux/gpio.h> #include <linux/of_gpio.h> -#include <asm/mach/irq.h> #define DRIVER_NAME "pinmux-sirf" diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 1a00658..bd83c8b 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -194,6 +194,11 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, } if (!gpio_range) { + /* + * A pin should not be freed more times than allocated. + */ + if (WARN_ON(!desc->mux_usecount)) + return NULL; desc->mux_usecount--; if (desc->mux_usecount) return NULL; diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c index 295b349..a4908ec 100644 --- a/drivers/pinctrl/spear/pinctrl-plgpio.c +++ b/drivers/pinctrl/spear/pinctrl-plgpio.c @@ -15,12 +15,12 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> #include <linux/module.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/spinlock.h> -#include <asm/mach/irq.h> #define MAX_GPIO_PER_REG 32 #define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG) |