kernel: update 3.14 to 3.14.18
[openwrt/openwrt.git] / target / linux / sunxi / patches-3.14 / 136-1-irqchip-sun4i-fixes.patch
index 5a8c83c5e1e51e87c8c0db51ba316bfd620d2dec..4345d3e0dde4bcda0b2d5d4a5d6ae8089dc22780 100644 (file)
@@ -17,8 +17,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  kernel/irq/manage.c    |  2 +-
  4 files changed, 45 insertions(+), 9 deletions(-)
 
-diff --git a/include/linux/irq.h b/include/linux/irq.h
-index 7dc1003..0f036fb 100644
 --- a/include/linux/irq.h
 +++ b/include/linux/irq.h
 @@ -349,6 +349,8 @@ struct irq_chip {
@@ -38,8 +36,6 @@ index 7dc1003..0f036fb 100644
  };
  
  /* This include will go away once we isolated irq_desc usage to core code */
-diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
-index dc04c16..6397df2 100644
 --- a/kernel/irq/chip.c
 +++ b/kernel/irq/chip.c
 @@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
@@ -62,7 +58,7 @@ index dc04c16..6397df2 100644
  /*
   *    handle_nested_irq - Handle a nested irq from a irq thread
   *    @irq:   the interrupt number
-@@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc)
+@@ -435,6 +448,27 @@ static inline void preflow_handler(struc
  static inline void preflow_handler(struct irq_desc *desc) { }
  #endif
  
@@ -90,7 +86,7 @@ index dc04c16..6397df2 100644
  /**
   *    handle_fasteoi_irq - irq handler for transparent controllers
   *    @irq:   the interrupt number
-@@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { }
+@@ -448,6 +482,8 @@ static inline void preflow_handler(struc
  void
  handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
  {
@@ -99,7 +95,7 @@ index dc04c16..6397df2 100644
        raw_spin_lock(&desc->lock);
  
        if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
-@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
+@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, str
        preflow_handler(desc);
        handle_irq_event(desc);
  
@@ -122,11 +118,9 @@ index dc04c16..6397df2 100644
  }
  
  /**
-diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
-index 001fa5b..e98bb56 100644
 --- a/kernel/irq/internals.h
 +++ b/kernel/irq/internals.h
-@@ -73,6 +73,7 @@ extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
+@@ -73,6 +73,7 @@ extern void irq_percpu_enable(struct irq
  extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
  extern void mask_irq(struct irq_desc *desc);
  extern void unmask_irq(struct irq_desc *desc);
@@ -134,11 +128,9 @@ index 001fa5b..e98bb56 100644
  
  extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
  
-diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
-index d3bf660..7593958 100644
 --- a/kernel/irq/manage.c
 +++ b/kernel/irq/manage.c
-@@ -718,7 +718,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc,
+@@ -713,7 +713,7 @@ again:
  
        if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
            irqd_irq_masked(&desc->irq_data))
@@ -147,35 +139,56 @@ index d3bf660..7593958 100644
  
  out_unlock:
        raw_spin_unlock_irq(&desc->lock);
--- 
-2.0.3
-
-From d000f9a5348e6d6c8b620a9c2d0b97c69d6d6153 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 11 Mar 2014 16:47:46 +0100
-Subject: [PATCH] irqchip: sun4i: Fix irq 0 not working
-
-SUN4I_IRQ_VECTOR_REG containing 0 can mean one of 3 things:
-1) no more irqs pending
-2) irq 0 pending
-3) spurious irq
-
-So if we immediately get a reading of 0, check the irq-pending reg
-to differentiate between 2 and 3. We only do this once to avoid
-the extra check in the common case of 1) hapening after having
-read the vector-reg once.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- drivers/irqchip/irq-sun4i.c | 18 ++++++++++++++++--
- 1 file changed, 16 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
-index a5438d8..5c25048 100644
 --- a/drivers/irqchip/irq-sun4i.c
 +++ b/drivers/irqchip/irq-sun4i.c
-@@ -140,10 +140,24 @@ static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *re
+@@ -41,13 +41,11 @@ static asmlinkage void __exception_irq_e
+ static void sun4i_irq_ack(struct irq_data *irqd)
+ {
+       unsigned int irq = irqd_to_hwirq(irqd);
+-      unsigned int irq_off = irq % 32;
+-      int reg = irq / 32;
+-      u32 val;
+-      val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
+-      writel(val | (1 << irq_off),
+-             sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
++      if (irq != 0)
++              return; /* Only IRQ 0 / the ENMI needs to be acked */
++
++      writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
+ }
+ static void sun4i_irq_mask(struct irq_data *irqd)
+@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_
+ static struct irq_chip sun4i_irq_chip = {
+       .name           = "sun4i_irq",
+-      .irq_ack        = sun4i_irq_ack,
++      .irq_eoi        = sun4i_irq_ack,
+       .irq_mask       = sun4i_irq_mask,
+       .irq_unmask     = sun4i_irq_unmask,
++      .flags          = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
+ };
+ static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
+                        irq_hw_number_t hw)
+ {
+-      irq_set_chip_and_handler(virq, &sun4i_irq_chip,
+-                               handle_level_irq);
++      irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       return 0;
+@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct d
+       writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
+       writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
+-      /* Mask all the interrupts */
++      /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
+       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
+       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
+       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
+@@ -140,10 +138,24 @@ static asmlinkage void __exception_irq_e
  {
        u32 irq, hwirq;
  
@@ -202,214 +215,3 @@ index a5438d8..5c25048 100644
 -      }
 +      } while (hwirq != 0);
  }
--- 
-2.0.3
-
-From b37587009473582d9fc080e8b8b99b67b0077a90 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 11 Mar 2014 16:53:23 +0100
-Subject: [PATCH] irqchip: sun4i: Fix a comment about mask register
- initialization
-
-The comment was claiming that we were masking all irqs, while the code actually
-*un*masks all of them.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- drivers/irqchip/irq-sun4i.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
-index 5c25048..8a2fbee 100644
---- a/drivers/irqchip/irq-sun4i.c
-+++ b/drivers/irqchip/irq-sun4i.c
-@@ -109,7 +109,7 @@ static int __init sun4i_of_init(struct device_node *node,
-       writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
-       writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
--      /* Mask all the interrupts */
-+      /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
-       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
-       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
-       writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
--- 
-2.0.3
-
-From c8865ee82b74b2d95339370972a0d9bfdbac09cf Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 12 Mar 2014 17:43:45 +0100
-Subject: [PATCH] irqchip: sun4i: Don't ack IRQs != 0, fix acking of IRQ 0
-
-All IRQs except for IRQ 0 seem to not need acking, so drop acking for them.
-
-The ENMI needs to have the ack done *after* clearing the interrupt source,
-otherwise we will get a spurious interrupt for each real interrupt.
-
-So use the new IRQCHIP_EOI_THREADED flag for this in combination with
-handle_fasteoi_irq. This uses a separate irq_chip struct for IRQ 0,
-since we only want this behavior for IRQ 0.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/irqchip/irq-sun4i.c | 19 ++++++++++++++++---
- 1 file changed, 16 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
-index 8a2fbee..a0ed1ea 100644
---- a/drivers/irqchip/irq-sun4i.c
-+++ b/drivers/irqchip/irq-sun4i.c
-@@ -76,16 +76,29 @@ static void sun4i_irq_unmask(struct irq_data *irqd)
- static struct irq_chip sun4i_irq_chip = {
-       .name           = "sun4i_irq",
--      .irq_ack        = sun4i_irq_ack,
-       .irq_mask       = sun4i_irq_mask,
-       .irq_unmask     = sun4i_irq_unmask,
- };
-+/* IRQ 0 / the ENMI needs a late eoi call */
-+static struct irq_chip sun4i_irq_chip_enmi = {
-+      .name           = "sun4i_irq",
-+      .irq_eoi        = sun4i_irq_ack,
-+      .irq_mask       = sun4i_irq_mask,
-+      .irq_unmask     = sun4i_irq_unmask,
-+      .flags          = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
-+};
-+
- static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
-                        irq_hw_number_t hw)
- {
--      irq_set_chip_and_handler(virq, &sun4i_irq_chip,
--                               handle_level_irq);
-+      if (hw == 0)
-+              irq_set_chip_and_handler(virq, &sun4i_irq_chip_enmi,
-+                                       handle_fasteoi_irq);
-+      else
-+              irq_set_chip_and_handler(virq, &sun4i_irq_chip,
-+                                       handle_level_irq);
-+
-       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-       return 0;
--- 
-2.0.3
-
-From f8b4347aa12d7a30aa1d3e5bfcdccece52d17af3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 13 Mar 2014 19:38:26 +0100
-Subject: [PATCH] irqchip: sun4i: Use handle_fasteoi_irq for all interrupts
-
-Since the sun4i irq chip does not require any action and clears the interrupt
-when the level goes back to inactive, we don't need to mask / unmask for
-non oneshot IRQs, to achieve this we make sun4i_irq_ack a nop for all irqs
-except irq 0 and use handle_fasteoi_irq for all interrupts.
-
-Now there might be a case when the device reactivates the interrupt
-before the RETI. But that does not matter as we run the primary
-interrupt handlers with interrupts disabled.
-
-This also allows us to get rid of needing to use 2 irq_chip structs, this
-means that the IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED will now influence
-all interrupts rather then just irq 0, but that does not matter as the eoi
-is now a nop anyways for all interrupts but irq 0.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- drivers/irqchip/irq-sun4i.c | 18 ++++--------------
- 1 file changed, 4 insertions(+), 14 deletions(-)
-
-diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
-index a0ed1ea..6a8c88d 100644
---- a/drivers/irqchip/irq-sun4i.c
-+++ b/drivers/irqchip/irq-sun4i.c
-@@ -45,6 +45,9 @@ static void sun4i_irq_ack(struct irq_data *irqd)
-       int reg = irq / 32;
-       u32 val;
-+      if (irq != 0)
-+              return; /* Only IRQ 0 / the ENMI needs to be acked */
-+
-       val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-       writel(val | (1 << irq_off),
-              sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-@@ -76,13 +79,6 @@ static void sun4i_irq_unmask(struct irq_data *irqd)
- static struct irq_chip sun4i_irq_chip = {
-       .name           = "sun4i_irq",
--      .irq_mask       = sun4i_irq_mask,
--      .irq_unmask     = sun4i_irq_unmask,
--};
--
--/* IRQ 0 / the ENMI needs a late eoi call */
--static struct irq_chip sun4i_irq_chip_enmi = {
--      .name           = "sun4i_irq",
-       .irq_eoi        = sun4i_irq_ack,
-       .irq_mask       = sun4i_irq_mask,
-       .irq_unmask     = sun4i_irq_unmask,
-@@ -92,13 +88,7 @@ static struct irq_chip sun4i_irq_chip_enmi = {
- static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
-                        irq_hw_number_t hw)
- {
--      if (hw == 0)
--              irq_set_chip_and_handler(virq, &sun4i_irq_chip_enmi,
--                                       handle_fasteoi_irq);
--      else
--              irq_set_chip_and_handler(virq, &sun4i_irq_chip,
--                                       handle_level_irq);
--
-+      irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
-       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-       return 0;
--- 
-2.0.3
-
-From de39bc31eaa554bd044e6adefacd3da6da5bf6e3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 13 Mar 2014 20:41:20 +0100
-Subject: [PATCH] irqchip: sun4i: simplify sun4i_irq_ack
-
-Now that we only ack irq 0 the code can be simplified a lot.
-
-Also switch from read / modify / write to a simple write clear:
-1) This is what the android code does (it has a hack for acking irq 0
-  in its unmask code doing this)
-2) read / modify / write simply does not make sense for an irq status
-  register like this, if the other bits are writeable (and the data sheet says
-  they are not) they should be write 1 to clear, since otherwise a read /
-  modify / write can race with a device raising an interrupt and then clear
-  the pending bit unintentionally
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- drivers/irqchip/irq-sun4i.c | 7 +------
- 1 file changed, 1 insertion(+), 6 deletions(-)
-
-diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
-index 6a8c88d..75615b5 100644
---- a/drivers/irqchip/irq-sun4i.c
-+++ b/drivers/irqchip/irq-sun4i.c
-@@ -41,16 +41,11 @@ static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *re
- static void sun4i_irq_ack(struct irq_data *irqd)
- {
-       unsigned int irq = irqd_to_hwirq(irqd);
--      unsigned int irq_off = irq % 32;
--      int reg = irq / 32;
--      u32 val;
-       if (irq != 0)
-               return; /* Only IRQ 0 / the ENMI needs to be acked */
--      val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
--      writel(val | (1 << irq_off),
--             sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-+      writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
- }
- static void sun4i_irq_mask(struct irq_data *irqd)
--- 
-2.0.3
-