sunxi: update pcDuino3 profile to the new u-boot
[15.05/openwrt.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