ar71xx: remove linux 3.18 support
[openwrt.git] / 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
deleted file mode 100644 (file)
index 90bc963..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
---- 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,132 @@ 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 long stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING);
-+      int bit_num;
-+
-+      for_each_set_bit(bit_num, &stat, sizeof(stat) * BITS_PER_BYTE) {
-+              unsigned long bit = BIT(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));
-+      }
-+
-+      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 +383,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 +409,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 */