9fa768ca9bd15947cecf58958fc9da393d2241a7
[openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0007-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch
1 From e3e8c56abfe6a036025f75908b63ae69d8eaed11 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
3 Date: Fri, 23 Oct 2015 16:26:55 +0200
4 Subject: [PATCH 007/127] irqchip: irq-bcm2835: Add 2836 FIQ support
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
10 ---
11  drivers/irqchip/irq-bcm2835.c | 42 ++++++++++++++++++++++++++++++++++++++++--
12  1 file changed, 40 insertions(+), 2 deletions(-)
13
14 --- a/drivers/irqchip/irq-bcm2835.c
15 +++ b/drivers/irqchip/irq-bcm2835.c
16 @@ -50,6 +50,8 @@
17  #include <linux/of_irq.h>
18  #include <linux/irqchip.h>
19  #include <linux/irqdomain.h>
20 +#include <linux/mfd/syscon.h>
21 +#include <linux/regmap.h>
22  
23  #include <asm/exception.h>
24  #include <asm/mach/irq.h>
25 @@ -70,6 +72,9 @@
26  #define BANK0_VALID_MASK       (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \
27                                         | SHORTCUT1_MASK | SHORTCUT2_MASK)
28  
29 +#undef ARM_LOCAL_GPU_INT_ROUTING
30 +#define ARM_LOCAL_GPU_INT_ROUTING 0x0c
31 +
32  #define REG_FIQ_CONTROL                0x0c
33  #define REG_FIQ_ENABLE         0x80
34  #define REG_FIQ_DISABLE                0
35 @@ -95,6 +100,7 @@ struct armctrl_ic {
36         void __iomem *enable[NR_BANKS];
37         void __iomem *disable[NR_BANKS];
38         struct irq_domain *domain;
39 +       struct regmap *local_regmap;
40  };
41  
42  static struct armctrl_ic intc __read_mostly;
43 @@ -128,12 +134,35 @@ static void armctrl_mask_irq(struct irq_
44  
45  static void armctrl_unmask_irq(struct irq_data *d)
46  {
47 -       if (d->hwirq >= NUMBER_IRQS)
48 +       if (d->hwirq >= NUMBER_IRQS) {
49 +               if (num_online_cpus() > 1) {
50 +                       unsigned int data;
51 +                       int ret;
52 +
53 +                       if (!intc.local_regmap) {
54 +                               pr_err("FIQ is disabled due to missing regmap\n");
55 +                               return;
56 +                       }
57 +
58 +                       ret = regmap_read(intc.local_regmap,
59 +                                         ARM_LOCAL_GPU_INT_ROUTING, &data);
60 +                       if (ret) {
61 +                               pr_err("Failed to read int routing %d\n", ret);
62 +                               return;
63 +                       }
64 +
65 +                       data &= ~0xc;
66 +                       data |= (1 << 2);
67 +                       regmap_write(intc.local_regmap,
68 +                                    ARM_LOCAL_GPU_INT_ROUTING, data);
69 +               }
70 +
71                 writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
72                                intc.base + REG_FIQ_CONTROL);
73 -       else
74 +       } else {
75                 writel_relaxed(HWIRQ_BIT(d->hwirq),
76                                intc.enable[HWIRQ_BANK(d->hwirq)]);
77 +       }
78  }
79  
80  static struct irq_chip armctrl_chip = {
81 @@ -211,6 +240,15 @@ static int __init armctrl_of_init(struct
82                 set_handle_irq(bcm2835_handle_irq);
83         }
84  
85 +       if (is_2836) {
86 +               intc.local_regmap =
87 +                       syscon_regmap_lookup_by_compatible("brcm,bcm2836-arm-local");
88 +               if (IS_ERR(intc.local_regmap)) {
89 +                       pr_err("Failed to get local register map. FIQ is disabled for cpus > 1\n");
90 +                       intc.local_regmap = NULL;
91 +               }
92 +       }
93 +
94         /* Make a duplicate irq range which is used to enable FIQ */
95         for (b = 0; b < NR_BANKS; b++) {
96                 for (i = 0; i < bank_irqs[b]; i++) {