Hi, minor nitpick inline
On 07/07/2015 14:58, Günther Kelleter wrote: > Signed-off-by: Günther Kelleter <guenther.kelle...@devolo.de> > --- > .../739-MIPS-ath79-add-gpio-irq-support.patch | 225 > +++++++++++++++++++++ > 1 file changed, 225 insertions(+) > create mode 100644 > target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch > > diff --git > a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch > b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch > new file mode 100644 > index 0000000..2b90df0 > --- /dev/null > +++ > b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch > @@ -0,0 +1,225 @@ > +--- a/arch/mips/ath79/gpio.c > ++++ b/arch/mips/ath79/gpio.c > +@@ -20,9 +20,14 @@ > + #include <linux/io.h> > + #include <linux/ioport.h> > + #include <linux/gpio.h> > ++#include <linux/irq.h> > ++#include <linux/interrupt.h> > ++ > ++#include <linux/of.h> > + > + #include <asm/mach-ath79/ar71xx_regs.h> > + #include <asm/mach-ath79/ath79.h> > ++#include <asm/mach-ath79/irq.h> > + #include "common.h" > + > + void __iomem *ath79_gpio_base; > +@@ -31,6 +36,13 @@ EXPORT_SYMBOL_GPL(ath79_gpio_base); > + static unsigned long ath79_gpio_count; > + static DEFINE_SPINLOCK(ath79_gpio_lock); > + > ++/* > ++ * gpio_both_edge is a bitmask of which gpio pins need to have > ++ * the detect priority flipped from the interrupt handler to > ++ * emulate IRQ_TYPE_EDGE_BOTH. > ++ */ > ++static unsigned long gpio_both_edge = 0; > ++ > + static void __ath79_gpio_set_value(unsigned gpio, int value) > + { > + void __iomem *base = ath79_gpio_base; > +@@ -209,6 +221,133 @@ void __init ath79_gpio_output_select(uns > + spin_unlock_irqrestore(&ath79_gpio_lock, flags); > + } > + > ++static int ath79_gpio_irq_type(struct irq_data *d, unsigned type) > ++{ > ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; > ++ void __iomem *base = ath79_gpio_base; > ++ unsigned long flags; > ++ unsigned long int_type; > ++ unsigned long int_polarity; > ++ unsigned long bit = (1 << offset); > ++ > ++ spin_lock_irqsave(&ath79_gpio_lock, flags); > ++ > ++ int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE); > ++ int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY); > ++ > ++ gpio_both_edge &= ~bit; > ++ > ++ switch (type) { > ++ case IRQ_TYPE_EDGE_RISING: > ++ int_type &= ~bit; > ++ int_polarity |= bit; > ++ break; > ++ > ++ case IRQ_TYPE_EDGE_FALLING: > ++ int_type &= ~bit; > ++ int_polarity &= ~bit; > ++ break; > ++ > ++ case IRQ_TYPE_LEVEL_HIGH: > ++ int_type |= bit; > ++ int_polarity |= bit; > ++ break; > ++ > ++ case IRQ_TYPE_LEVEL_LOW: > ++ int_type |= bit; > ++ int_polarity &= ~bit; > ++ break; > ++ > ++ case IRQ_TYPE_EDGE_BOTH: > ++ int_type |= bit; > ++ /* set polarity based on current value */ > ++ if (gpio_get_value(offset)) { > ++ int_polarity &= ~bit; > ++ } else { > ++ int_polarity |= bit; > ++ } > ++ /* flip this gpio in the interrupt handler */ > ++ gpio_both_edge |= bit; > ++ break; > ++ > ++ default: > ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags); > ++ return -EINVAL; > ++ } > ++ > ++ __raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE); > ++ __raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY); > ++ > ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << > offset), > ++ base + AR71XX_GPIO_REG_INT_MODE); > ++ > ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << > offset), > ++ base + AR71XX_GPIO_REG_INT_ENABLE); > ++ > ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags); > ++ return 0; > ++} > ++ > ++static void ath79_gpio_irq_enable(struct irq_data *d) > ++{ > ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; > ++ void __iomem *base = ath79_gpio_base; > ++ > ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << > offset), > ++ base + AR71XX_GPIO_REG_INT_ENABLE); > ++} > ++ > ++static void ath79_gpio_irq_disable(struct irq_data *d) > ++{ > ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE; > ++ void __iomem *base = ath79_gpio_base; > ++ > ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << > offset), > ++ base + AR71XX_GPIO_REG_INT_ENABLE); > ++} > ++ > ++static struct irq_chip ath79_gpio_irqchip = { > ++ .name = "GPIO", > ++ .irq_enable = ath79_gpio_irq_enable, > ++ .irq_disable = ath79_gpio_irq_disable, > ++ .irq_set_type = ath79_gpio_irq_type, > ++}; > ++ > ++static irqreturn_t ath79_gpio_irq(int irq, void *dev) > ++{ > ++ void __iomem *base = ath79_gpio_base; > ++ unsigned int stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING); > ++ > ++ while (stat) { make use of the for_each_set_bit() macro please John > ++ int bit_num = __ffs(stat); > ++ unsigned long bit = (1<<bit_num); > ++ > ++ if (bit & gpio_both_edge) { > ++ __raw_writel(__raw_readl(base + > AR71XX_GPIO_REG_INT_POLARITY) ^ bit, > ++ base + AR71XX_GPIO_REG_INT_POLARITY); > ++ } > ++ > ++ generic_handle_irq(ATH79_GPIO_IRQ(bit_num)); > ++ stat &= ~bit; > ++ } > ++ > ++ return IRQ_HANDLED; > ++} > ++ > ++static int __init ath79_gpio_irq_init(struct gpio_chip *chip) > ++{ > ++ int irq; > ++ int irq_base = ATH79_GPIO_IRQ_BASE; > ++ > ++ for (irq = irq_base; irq < irq_base + chip->ngpio; irq++) { > ++ irq_set_chip_data(irq, chip); > ++ irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, > handle_simple_irq); > ++ irq_set_noprobe(irq); > ++ } > ++ > ++ return 0; > ++} > ++ > + void __init ath79_gpio_init(void) > + { > + int err; > +@@ -245,6 +384,10 @@ void __init ath79_gpio_init(void) > + err = gpiochip_add(&ath79_gpio_chip); > + if (err) > + panic("cannot add AR71xx GPIO chip, error=%d", err); > ++ > ++ ath79_gpio_irq_init(&ath79_gpio_chip); > ++ > ++ request_irq(ATH79_MISC_IRQ(2), ath79_gpio_irq, 0, "ath79-gpio", NULL); > + } > + > + int gpio_get_value(unsigned gpio) > +@@ -267,14 +410,22 @@ EXPORT_SYMBOL(gpio_set_value); > + > + int gpio_to_irq(unsigned gpio) > + { > +- /* FIXME */ > +- return -EINVAL; > ++ if (gpio > ath79_gpio_count) { > ++ return -EINVAL; > ++ } > ++ > ++ return ATH79_GPIO_IRQ_BASE + gpio; > + } > + EXPORT_SYMBOL(gpio_to_irq); > + > + int irq_to_gpio(unsigned irq) > + { > +- /* FIXME */ > +- return -EINVAL; > ++ unsigned gpio = irq - ATH79_GPIO_IRQ_BASE; > ++ > ++ if (gpio > ath79_gpio_count) { > ++ return -EINVAL; > ++ } > ++ > ++ return gpio; > + } > + EXPORT_SYMBOL(irq_to_gpio); > +--- a/arch/mips/include/asm/mach-ath79/irq.h > ++++ b/arch/mips/include/asm/mach-ath79/irq.h > +@@ -10,7 +10,7 @@ > + #define __ASM_MACH_ATH79_IRQ_H > + > + #define MIPS_CPU_IRQ_BASE 0 > +-#define NR_IRQS 51 > ++#define NR_IRQS 83 > + > + #define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x)) > + > +@@ -30,6 +30,10 @@ > + #define ATH79_IP3_IRQ_COUNT 3 > + #define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x)) > + > ++#define ATH79_GPIO_IRQ_BASE (ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT) > ++#define ATH79_GPIO_IRQ_COUNT 32 > ++#define ATH79_GPIO_IRQ(_x) (ATH79_GPIO_IRQ_BASE + (_x)) > ++ > + #include_next <irq.h> > + > + #endif /* __ASM_MACH_ATH79_IRQ_H */ > _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel