aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch')
-rw-r--r--target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch304
1 files changed, 53 insertions, 251 deletions
diff --git a/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch b/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
index 5a8c83c5e1..4345d3e0dd 100644
--- a/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
+++ b/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
@@ -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
-