sunxi: initial 3.14 patchset
[openwrt/svn-archive/archive.git] / target / linux / sunxi / patches-3.14 / 136-1-irqchip-sun4i-fixes.patch
1 From 843da234cfc0e7014f9e2da82786a485e0820665 Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Thu, 13 Mar 2014 15:32:05 +0100
4 Subject: [PATCH] irq: Add a new IRQCHIP_EOI_THREADED flag
5
6 This flag must be used in combination with handle_fasteoi_irq, when set
7 handle_fasteoi_irq will delay the calling of chip->irq_eoi until the threaded
8 handler has run.
9
10 Reviewed-by: Hans de Goede <hdegoede@redhat.com>
11 Tested-by: Hans de Goede <hdegoede@redhat.com>
12 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
13 ---
14 include/linux/irq.h | 3 +++
15 kernel/irq/chip.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
16 kernel/irq/internals.h | 1 +
17 kernel/irq/manage.c | 2 +-
18 4 files changed, 45 insertions(+), 9 deletions(-)
19
20 diff --git a/include/linux/irq.h b/include/linux/irq.h
21 index 7dc1003..0f036fb 100644
22 --- a/include/linux/irq.h
23 +++ b/include/linux/irq.h
24 @@ -349,6 +349,8 @@ struct irq_chip {
25 * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
26 * when irq enabled
27 * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
28 + * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
29 + * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
30 */
31 enum {
32 IRQCHIP_SET_TYPE_MASKED = (1 << 0),
33 @@ -357,6 +359,7 @@ enum {
34 IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
35 IRQCHIP_SKIP_SET_WAKE = (1 << 4),
36 IRQCHIP_ONESHOT_SAFE = (1 << 5),
37 + IRQCHIP_EOI_THREADED = (1 << 6),
38 };
39
40 /* This include will go away once we isolated irq_desc usage to core code */
41 diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
42 index dc04c16..6397df2 100644
43 --- a/kernel/irq/chip.c
44 +++ b/kernel/irq/chip.c
45 @@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
46 }
47 }
48
49 +void unmask_threaded_irq(struct irq_desc *desc)
50 +{
51 + struct irq_chip *chip = desc->irq_data.chip;
52 +
53 + if (chip->flags & IRQCHIP_EOI_THREADED)
54 + chip->irq_eoi(&desc->irq_data);
55 +
56 + if (chip->irq_unmask) {
57 + chip->irq_unmask(&desc->irq_data);
58 + irq_state_clr_masked(desc);
59 + }
60 +}
61 +
62 /*
63 * handle_nested_irq - Handle a nested irq from a irq thread
64 * @irq: the interrupt number
65 @@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc)
66 static inline void preflow_handler(struct irq_desc *desc) { }
67 #endif
68
69 +static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
70 +{
71 + if (!(desc->istate & IRQS_ONESHOT)) {
72 + chip->irq_eoi(&desc->irq_data);
73 + return;
74 + }
75 + /*
76 + * We need to unmask in the following cases:
77 + * - Oneshot irq which did not wake the thread (caused by a
78 + * spurious interrupt or a primary handler handling it
79 + * completely).
80 + */
81 + if (!irqd_irq_disabled(&desc->irq_data) &&
82 + irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
83 + chip->irq_eoi(&desc->irq_data);
84 + unmask_irq(desc);
85 + } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
86 + chip->irq_eoi(&desc->irq_data);
87 + }
88 +}
89 +
90 /**
91 * handle_fasteoi_irq - irq handler for transparent controllers
92 * @irq: the interrupt number
93 @@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { }
94 void
95 handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
96 {
97 + struct irq_chip *chip = desc->irq_data.chip;
98 +
99 raw_spin_lock(&desc->lock);
100
101 if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
102 @@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
103 preflow_handler(desc);
104 handle_irq_event(desc);
105
106 - if (desc->istate & IRQS_ONESHOT)
107 - cond_unmask_irq(desc);
108 + cond_unmask_eoi_irq(desc, chip);
109
110 -out_eoi:
111 - desc->irq_data.chip->irq_eoi(&desc->irq_data);
112 -out_unlock:
113 raw_spin_unlock(&desc->lock);
114 return;
115 out:
116 - if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
117 - goto out_eoi;
118 - goto out_unlock;
119 + if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
120 + chip->irq_eoi(&desc->irq_data);
121 + raw_spin_unlock(&desc->lock);
122 }
123
124 /**
125 diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
126 index 001fa5b..e98bb56 100644
127 --- a/kernel/irq/internals.h
128 +++ b/kernel/irq/internals.h
129 @@ -73,6 +73,7 @@ extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
130 extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
131 extern void mask_irq(struct irq_desc *desc);
132 extern void unmask_irq(struct irq_desc *desc);
133 +extern void unmask_threaded_irq(struct irq_desc *desc);
134
135 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
136
137 diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
138 index d3bf660..7593958 100644
139 --- a/kernel/irq/manage.c
140 +++ b/kernel/irq/manage.c
141 @@ -718,7 +718,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc,
142
143 if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
144 irqd_irq_masked(&desc->irq_data))
145 - unmask_irq(desc);
146 + unmask_threaded_irq(desc);
147
148 out_unlock:
149 raw_spin_unlock_irq(&desc->lock);
150 --
151 2.0.3
152
153 From d000f9a5348e6d6c8b620a9c2d0b97c69d6d6153 Mon Sep 17 00:00:00 2001
154 From: Hans de Goede <hdegoede@redhat.com>
155 Date: Tue, 11 Mar 2014 16:47:46 +0100
156 Subject: [PATCH] irqchip: sun4i: Fix irq 0 not working
157
158 SUN4I_IRQ_VECTOR_REG containing 0 can mean one of 3 things:
159 1) no more irqs pending
160 2) irq 0 pending
161 3) spurious irq
162
163 So if we immediately get a reading of 0, check the irq-pending reg
164 to differentiate between 2 and 3. We only do this once to avoid
165 the extra check in the common case of 1) hapening after having
166 read the vector-reg once.
167
168 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
169 Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
170 ---
171 drivers/irqchip/irq-sun4i.c | 18 ++++++++++++++++--
172 1 file changed, 16 insertions(+), 2 deletions(-)
173
174 diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
175 index a5438d8..5c25048 100644
176 --- a/drivers/irqchip/irq-sun4i.c
177 +++ b/drivers/irqchip/irq-sun4i.c
178 @@ -140,10 +140,24 @@ static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *re
179 {
180 u32 irq, hwirq;
181
182 + /*
183 + * hwirq == 0 can mean one of 3 things:
184 + * 1) no more irqs pending
185 + * 2) irq 0 pending
186 + * 3) spurious irq
187 + * So if we immediately get a reading of 0, check the irq-pending reg
188 + * to differentiate between 2 and 3. We only do this once to avoid
189 + * the extra check in the common case of 1 hapening after having
190 + * read the vector-reg once.
191 + */
192 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
193 - while (hwirq != 0) {
194 + if (hwirq == 0 &&
195 + !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
196 + return;
197 +
198 + do {
199 irq = irq_find_mapping(sun4i_irq_domain, hwirq);
200 handle_IRQ(irq, regs);
201 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
202 - }
203 + } while (hwirq != 0);
204 }
205 --
206 2.0.3
207
208 From b37587009473582d9fc080e8b8b99b67b0077a90 Mon Sep 17 00:00:00 2001
209 From: Hans de Goede <hdegoede@redhat.com>
210 Date: Tue, 11 Mar 2014 16:53:23 +0100
211 Subject: [PATCH] irqchip: sun4i: Fix a comment about mask register
212 initialization
213
214 The comment was claiming that we were masking all irqs, while the code actually
215 *un*masks all of them.
216
217 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
218 Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
219 ---
220 drivers/irqchip/irq-sun4i.c | 2 +-
221 1 file changed, 1 insertion(+), 1 deletion(-)
222
223 diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
224 index 5c25048..8a2fbee 100644
225 --- a/drivers/irqchip/irq-sun4i.c
226 +++ b/drivers/irqchip/irq-sun4i.c
227 @@ -109,7 +109,7 @@ static int __init sun4i_of_init(struct device_node *node,
228 writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
229 writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
230
231 - /* Mask all the interrupts */
232 + /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
233 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
234 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
235 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
236 --
237 2.0.3
238
239 From c8865ee82b74b2d95339370972a0d9bfdbac09cf Mon Sep 17 00:00:00 2001
240 From: Hans de Goede <hdegoede@redhat.com>
241 Date: Wed, 12 Mar 2014 17:43:45 +0100
242 Subject: [PATCH] irqchip: sun4i: Don't ack IRQs != 0, fix acking of IRQ 0
243
244 All IRQs except for IRQ 0 seem to not need acking, so drop acking for them.
245
246 The ENMI needs to have the ack done *after* clearing the interrupt source,
247 otherwise we will get a spurious interrupt for each real interrupt.
248
249 So use the new IRQCHIP_EOI_THREADED flag for this in combination with
250 handle_fasteoi_irq. This uses a separate irq_chip struct for IRQ 0,
251 since we only want this behavior for IRQ 0.
252
253 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
254 ---
255 drivers/irqchip/irq-sun4i.c | 19 ++++++++++++++++---
256 1 file changed, 16 insertions(+), 3 deletions(-)
257
258 diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
259 index 8a2fbee..a0ed1ea 100644
260 --- a/drivers/irqchip/irq-sun4i.c
261 +++ b/drivers/irqchip/irq-sun4i.c
262 @@ -76,16 +76,29 @@ static void sun4i_irq_unmask(struct irq_data *irqd)
263
264 static struct irq_chip sun4i_irq_chip = {
265 .name = "sun4i_irq",
266 - .irq_ack = sun4i_irq_ack,
267 .irq_mask = sun4i_irq_mask,
268 .irq_unmask = sun4i_irq_unmask,
269 };
270
271 +/* IRQ 0 / the ENMI needs a late eoi call */
272 +static struct irq_chip sun4i_irq_chip_enmi = {
273 + .name = "sun4i_irq",
274 + .irq_eoi = sun4i_irq_ack,
275 + .irq_mask = sun4i_irq_mask,
276 + .irq_unmask = sun4i_irq_unmask,
277 + .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
278 +};
279 +
280 static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
281 irq_hw_number_t hw)
282 {
283 - irq_set_chip_and_handler(virq, &sun4i_irq_chip,
284 - handle_level_irq);
285 + if (hw == 0)
286 + irq_set_chip_and_handler(virq, &sun4i_irq_chip_enmi,
287 + handle_fasteoi_irq);
288 + else
289 + irq_set_chip_and_handler(virq, &sun4i_irq_chip,
290 + handle_level_irq);
291 +
292 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
293
294 return 0;
295 --
296 2.0.3
297
298 From f8b4347aa12d7a30aa1d3e5bfcdccece52d17af3 Mon Sep 17 00:00:00 2001
299 From: Hans de Goede <hdegoede@redhat.com>
300 Date: Thu, 13 Mar 2014 19:38:26 +0100
301 Subject: [PATCH] irqchip: sun4i: Use handle_fasteoi_irq for all interrupts
302
303 Since the sun4i irq chip does not require any action and clears the interrupt
304 when the level goes back to inactive, we don't need to mask / unmask for
305 non oneshot IRQs, to achieve this we make sun4i_irq_ack a nop for all irqs
306 except irq 0 and use handle_fasteoi_irq for all interrupts.
307
308 Now there might be a case when the device reactivates the interrupt
309 before the RETI. But that does not matter as we run the primary
310 interrupt handlers with interrupts disabled.
311
312 This also allows us to get rid of needing to use 2 irq_chip structs, this
313 means that the IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED will now influence
314 all interrupts rather then just irq 0, but that does not matter as the eoi
315 is now a nop anyways for all interrupts but irq 0.
316
317 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
318 Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
319 ---
320 drivers/irqchip/irq-sun4i.c | 18 ++++--------------
321 1 file changed, 4 insertions(+), 14 deletions(-)
322
323 diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
324 index a0ed1ea..6a8c88d 100644
325 --- a/drivers/irqchip/irq-sun4i.c
326 +++ b/drivers/irqchip/irq-sun4i.c
327 @@ -45,6 +45,9 @@ static void sun4i_irq_ack(struct irq_data *irqd)
328 int reg = irq / 32;
329 u32 val;
330
331 + if (irq != 0)
332 + return; /* Only IRQ 0 / the ENMI needs to be acked */
333 +
334 val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
335 writel(val | (1 << irq_off),
336 sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
337 @@ -76,13 +79,6 @@ static void sun4i_irq_unmask(struct irq_data *irqd)
338
339 static struct irq_chip sun4i_irq_chip = {
340 .name = "sun4i_irq",
341 - .irq_mask = sun4i_irq_mask,
342 - .irq_unmask = sun4i_irq_unmask,
343 -};
344 -
345 -/* IRQ 0 / the ENMI needs a late eoi call */
346 -static struct irq_chip sun4i_irq_chip_enmi = {
347 - .name = "sun4i_irq",
348 .irq_eoi = sun4i_irq_ack,
349 .irq_mask = sun4i_irq_mask,
350 .irq_unmask = sun4i_irq_unmask,
351 @@ -92,13 +88,7 @@ static struct irq_chip sun4i_irq_chip_enmi = {
352 static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
353 irq_hw_number_t hw)
354 {
355 - if (hw == 0)
356 - irq_set_chip_and_handler(virq, &sun4i_irq_chip_enmi,
357 - handle_fasteoi_irq);
358 - else
359 - irq_set_chip_and_handler(virq, &sun4i_irq_chip,
360 - handle_level_irq);
361 -
362 + irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
363 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
364
365 return 0;
366 --
367 2.0.3
368
369 From de39bc31eaa554bd044e6adefacd3da6da5bf6e3 Mon Sep 17 00:00:00 2001
370 From: Hans de Goede <hdegoede@redhat.com>
371 Date: Thu, 13 Mar 2014 20:41:20 +0100
372 Subject: [PATCH] irqchip: sun4i: simplify sun4i_irq_ack
373
374 Now that we only ack irq 0 the code can be simplified a lot.
375
376 Also switch from read / modify / write to a simple write clear:
377 1) This is what the android code does (it has a hack for acking irq 0
378 in its unmask code doing this)
379 2) read / modify / write simply does not make sense for an irq status
380 register like this, if the other bits are writeable (and the data sheet says
381 they are not) they should be write 1 to clear, since otherwise a read /
382 modify / write can race with a device raising an interrupt and then clear
383 the pending bit unintentionally
384
385 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
386 Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
387 ---
388 drivers/irqchip/irq-sun4i.c | 7 +------
389 1 file changed, 1 insertion(+), 6 deletions(-)
390
391 diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
392 index 6a8c88d..75615b5 100644
393 --- a/drivers/irqchip/irq-sun4i.c
394 +++ b/drivers/irqchip/irq-sun4i.c
395 @@ -41,16 +41,11 @@ static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *re
396 static void sun4i_irq_ack(struct irq_data *irqd)
397 {
398 unsigned int irq = irqd_to_hwirq(irqd);
399 - unsigned int irq_off = irq % 32;
400 - int reg = irq / 32;
401 - u32 val;
402
403 if (irq != 0)
404 return; /* Only IRQ 0 / the ENMI needs to be acked */
405
406 - val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
407 - writel(val | (1 << irq_off),
408 - sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
409 + writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
410 }
411
412 static void sun4i_irq_mask(struct irq_data *irqd)
413 --
414 2.0.3
415