1 --- a/arch/mips/ath79/gpio.c
2 +++ b/arch/mips/ath79/gpio.c
5 #include <linux/ioport.h>
6 #include <linux/gpio.h>
7 +#include <linux/irq.h>
8 +#include <linux/interrupt.h>
10 +#include <linux/of.h>
12 #include <asm/mach-ath79/ar71xx_regs.h>
13 #include <asm/mach-ath79/ath79.h>
14 +#include <asm/mach-ath79/irq.h>
17 void __iomem *ath79_gpio_base;
18 @@ -31,6 +36,13 @@ EXPORT_SYMBOL_GPL(ath79_gpio_base);
19 static unsigned long ath79_gpio_count;
20 static DEFINE_SPINLOCK(ath79_gpio_lock);
23 + * gpio_both_edge is a bitmask of which gpio pins need to have
24 + * the detect priority flipped from the interrupt handler to
25 + * emulate IRQ_TYPE_EDGE_BOTH.
27 +static unsigned long gpio_both_edge = 0;
29 static void __ath79_gpio_set_value(unsigned gpio, int value)
31 void __iomem *base = ath79_gpio_base;
32 @@ -233,6 +245,132 @@ void __init ath79_gpio_output_select(uns
33 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
36 +static int ath79_gpio_irq_type(struct irq_data *d, unsigned type)
38 + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
39 + void __iomem *base = ath79_gpio_base;
40 + unsigned long flags;
41 + unsigned long int_type;
42 + unsigned long int_polarity;
43 + unsigned long bit = (1 << offset);
45 + spin_lock_irqsave(&ath79_gpio_lock, flags);
47 + int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE);
48 + int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY);
50 + gpio_both_edge &= ~bit;
53 + case IRQ_TYPE_EDGE_RISING:
55 + int_polarity |= bit;
58 + case IRQ_TYPE_EDGE_FALLING:
60 + int_polarity &= ~bit;
63 + case IRQ_TYPE_LEVEL_HIGH:
65 + int_polarity |= bit;
68 + case IRQ_TYPE_LEVEL_LOW:
70 + int_polarity &= ~bit;
73 + case IRQ_TYPE_EDGE_BOTH:
75 + /* set polarity based on current value */
76 + if (gpio_get_value(offset)) {
77 + int_polarity &= ~bit;
79 + int_polarity |= bit;
81 + /* flip this gpio in the interrupt handler */
82 + gpio_both_edge |= bit;
86 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
90 + __raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE);
91 + __raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY);
93 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << offset),
94 + base + AR71XX_GPIO_REG_INT_MODE);
96 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
97 + base + AR71XX_GPIO_REG_INT_ENABLE);
99 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
103 +static void ath79_gpio_irq_enable(struct irq_data *d)
105 + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
106 + void __iomem *base = ath79_gpio_base;
108 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << offset),
109 + base + AR71XX_GPIO_REG_INT_ENABLE);
112 +static void ath79_gpio_irq_disable(struct irq_data *d)
114 + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
115 + void __iomem *base = ath79_gpio_base;
117 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
118 + base + AR71XX_GPIO_REG_INT_ENABLE);
121 +static struct irq_chip ath79_gpio_irqchip = {
123 + .irq_enable = ath79_gpio_irq_enable,
124 + .irq_disable = ath79_gpio_irq_disable,
125 + .irq_set_type = ath79_gpio_irq_type,
128 +static irqreturn_t ath79_gpio_irq(int irq, void *dev)
130 + void __iomem *base = ath79_gpio_base;
131 + unsigned long stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING);
134 + for_each_set_bit(bit_num, &stat, sizeof(stat) * BITS_PER_BYTE) {
135 + unsigned long bit = BIT(bit_num);
137 + if (bit & gpio_both_edge) {
138 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY) ^ bit,
139 + base + AR71XX_GPIO_REG_INT_POLARITY);
142 + generic_handle_irq(ATH79_GPIO_IRQ(bit_num));
145 + return IRQ_HANDLED;
148 +static int __init ath79_gpio_irq_init(struct gpio_chip *chip)
151 + int irq_base = ATH79_GPIO_IRQ_BASE;
153 + for (irq = irq_base; irq < irq_base + chip->ngpio; irq++) {
154 + irq_set_chip_data(irq, chip);
155 + irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, handle_simple_irq);
156 + irq_set_noprobe(irq);
162 void __init ath79_gpio_init(void)
165 @@ -269,6 +407,10 @@ void __init ath79_gpio_init(void)
166 err = gpiochip_add(&ath79_gpio_chip);
168 panic("cannot add AR71xx GPIO chip, error=%d", err);
170 + ath79_gpio_irq_init(&ath79_gpio_chip);
172 + request_irq(ATH79_MISC_IRQ(2), ath79_gpio_irq, 0, "ath79-gpio", NULL);
175 int gpio_get_value(unsigned gpio)
176 @@ -291,14 +433,22 @@ EXPORT_SYMBOL(gpio_set_value);
178 int gpio_to_irq(unsigned gpio)
182 + if (gpio > ath79_gpio_count) {
186 + return ATH79_GPIO_IRQ_BASE + gpio;
188 EXPORT_SYMBOL(gpio_to_irq);
190 int irq_to_gpio(unsigned irq)
194 + unsigned gpio = irq - ATH79_GPIO_IRQ_BASE;
196 + if (gpio > ath79_gpio_count) {
202 EXPORT_SYMBOL(irq_to_gpio);
203 --- a/arch/mips/include/asm/mach-ath79/irq.h
204 +++ b/arch/mips/include/asm/mach-ath79/irq.h
206 #define __ASM_MACH_ATH79_IRQ_H
208 #define MIPS_CPU_IRQ_BASE 0
212 #define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x))
215 #define ATH79_IP3_IRQ_COUNT 3
216 #define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x))
218 +#define ATH79_GPIO_IRQ_BASE (ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT)
219 +#define ATH79_GPIO_IRQ_COUNT 32
220 +#define ATH79_GPIO_IRQ(_x) (ATH79_GPIO_IRQ_BASE + (_x))
222 #include_next <irq.h>
224 #endif /* __ASM_MACH_ATH79_IRQ_H */