28ba48b34c3f12542e0db6067d7dd03306408262
[openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0006-irqchip-bcm2835-Add-FIQ-support.patch
1 From 44b5e890373665231d9a5876966ef3a670b9efd7 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
3 Date: Fri, 12 Jun 2015 19:01:05 +0200
4 Subject: [PATCH 006/127] irqchip: bcm2835: Add FIQ support
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Add a duplicate irq range with an offset on the hwirq's so the
10 driver can detect that enable_fiq() is used.
11 Tested with downstream dwc_otg USB controller driver.
12
13 Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
14 Reviewed-by: Eric Anholt <eric@anholt.net>
15 Acked-by: Stephen Warren <swarren@wwwdotorg.org>
16 ---
17  arch/arm/mach-bcm/Kconfig     |  1 +
18  drivers/irqchip/irq-bcm2835.c | 51 ++++++++++++++++++++++++++++++++++++++-----
19  2 files changed, 47 insertions(+), 5 deletions(-)
20
21 --- a/arch/arm/mach-bcm/Kconfig
22 +++ b/arch/arm/mach-bcm/Kconfig
23 @@ -128,6 +128,7 @@ config ARCH_BCM2835
24         select ARM_ERRATA_411920
25         select ARM_TIMER_SP804
26         select CLKSRC_OF
27 +       select FIQ
28         select PINCTRL
29         select PINCTRL_BCM2835
30         help
31 --- a/drivers/irqchip/irq-bcm2835.c
32 +++ b/drivers/irqchip/irq-bcm2835.c
33 @@ -55,7 +55,7 @@
34  #include <asm/mach/irq.h>
35  
36  /* Put the bank and irq (32 bits) into the hwirq */
37 -#define MAKE_HWIRQ(b, n)       ((b << 5) | (n))
38 +#define MAKE_HWIRQ(b, n)       (((b) << 5) | (n))
39  #define HWIRQ_BANK(i)          (i >> 5)
40  #define HWIRQ_BIT(i)           BIT(i & 0x1f)
41  
42 @@ -71,9 +71,13 @@
43                                         | SHORTCUT1_MASK | SHORTCUT2_MASK)
44  
45  #define REG_FIQ_CONTROL                0x0c
46 +#define REG_FIQ_ENABLE         0x80
47 +#define REG_FIQ_DISABLE                0
48  
49  #define NR_BANKS               3
50  #define IRQS_PER_BANK          32
51 +#define NUMBER_IRQS            MAKE_HWIRQ(NR_BANKS, 0)
52 +#define FIQ_START              (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0))
53  
54  static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
55  static const int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
56 @@ -98,14 +102,38 @@ static void __exception_irq_entry bcm283
57         struct pt_regs *regs);
58  static void bcm2836_chained_handle_irq(struct irq_desc *desc);
59  
60 +static inline unsigned int hwirq_to_fiq(unsigned long hwirq)
61 +{
62 +       hwirq -= NUMBER_IRQS;
63 +       /*
64 +        * The hwirq numbering used in this driver is:
65 +        *   BASE (0-7) GPU1 (32-63) GPU2 (64-95).
66 +        * This differ from the one used in the FIQ register:
67 +        *   GPU1 (0-31) GPU2 (32-63) BASE (64-71)
68 +        */
69 +       if (hwirq >= 32)
70 +               return hwirq - 32;
71 +
72 +       return hwirq + 64;
73 +}
74 +
75  static void armctrl_mask_irq(struct irq_data *d)
76  {
77 -       writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]);
78 +       if (d->hwirq >= NUMBER_IRQS)
79 +               writel_relaxed(REG_FIQ_DISABLE, intc.base + REG_FIQ_CONTROL);
80 +       else
81 +               writel_relaxed(HWIRQ_BIT(d->hwirq),
82 +                              intc.disable[HWIRQ_BANK(d->hwirq)]);
83  }
84  
85  static void armctrl_unmask_irq(struct irq_data *d)
86  {
87 -       writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]);
88 +       if (d->hwirq >= NUMBER_IRQS)
89 +               writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
90 +                              intc.base + REG_FIQ_CONTROL);
91 +       else
92 +               writel_relaxed(HWIRQ_BIT(d->hwirq),
93 +                              intc.enable[HWIRQ_BANK(d->hwirq)]);
94  }
95  
96  static struct irq_chip armctrl_chip = {
97 @@ -151,8 +179,9 @@ static int __init armctrl_of_init(struct
98                 panic("%s: unable to map IC registers\n",
99                         node->full_name);
100  
101 -       intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
102 -                       &armctrl_ops, NULL);
103 +       intc.base = base;
104 +       intc.domain = irq_domain_add_linear(node, NUMBER_IRQS * 2,
105 +                                           &armctrl_ops, NULL);
106         if (!intc.domain)
107                 panic("%s: unable to create IRQ domain\n", node->full_name);
108  
109 @@ -182,6 +211,18 @@ static int __init armctrl_of_init(struct
110                 set_handle_irq(bcm2835_handle_irq);
111         }
112  
113 +       /* Make a duplicate irq range which is used to enable FIQ */
114 +       for (b = 0; b < NR_BANKS; b++) {
115 +               for (i = 0; i < bank_irqs[b]; i++) {
116 +                       irq = irq_create_mapping(intc.domain,
117 +                                       MAKE_HWIRQ(b, i) + NUMBER_IRQS);
118 +                       BUG_ON(irq <= 0);
119 +                       irq_set_chip(irq, &armctrl_chip);
120 +                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
121 +               }
122 +       }
123 +       init_FIQ(FIQ_START);
124 +
125         return 0;
126  }
127