56
56
#include "irqchip.h"
57
57
58
58
/* Put the bank and irq (32 bits) into the hwirq */
59
- #define MAKE_HWIRQ (b , n ) ((b << 5) | (n))
59
+ #define MAKE_HWIRQ (b , n ) (((b) << 5) | (n))
60
60
#define HWIRQ_BANK (i ) (i >> 5)
61
61
#define HWIRQ_BIT (i ) BIT(i & 0x1f)
62
62
72
72
| SHORTCUT1_MASK | SHORTCUT2_MASK)
73
73
74
74
#define REG_FIQ_CONTROL 0x0c
75
+ #define REG_FIQ_ENABLE 0x80
76
+ #define REG_FIQ_DISABLE 0
75
77
76
78
#define NR_BANKS 3
77
79
#define IRQS_PER_BANK 32
80
+ #define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0)
81
+ #define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0))
78
82
79
83
static int reg_pending [] __initconst = { 0x00 , 0x04 , 0x08 };
80
84
static int reg_enable [] __initconst = { 0x18 , 0x10 , 0x14 };
@@ -98,14 +102,38 @@ static struct armctrl_ic intc __read_mostly;
98
102
static void __exception_irq_entry bcm2835_handle_irq (
99
103
struct pt_regs * regs );
100
104
105
+ static inline unsigned int hwirq_to_fiq (unsigned long hwirq )
106
+ {
107
+ hwirq -= NUMBER_IRQS ;
108
+ /*
109
+ * The hwirq numbering used in this driver is:
110
+ * BASE (0-7) GPU1 (32-63) GPU2 (64-95).
111
+ * This differ from the one used in the FIQ register:
112
+ * GPU1 (0-31) GPU2 (32-63) BASE (64-71)
113
+ */
114
+ if (hwirq >= 32 )
115
+ return hwirq - 32 ;
116
+
117
+ return hwirq + 64 ;
118
+ }
119
+
101
120
static void armctrl_mask_irq (struct irq_data * d )
102
121
{
103
- writel_relaxed (HWIRQ_BIT (d -> hwirq ), intc .disable [HWIRQ_BANK (d -> hwirq )]);
122
+ if (d -> hwirq >= NUMBER_IRQS )
123
+ writel_relaxed (REG_FIQ_DISABLE , intc .base + REG_FIQ_CONTROL );
124
+ else
125
+ writel_relaxed (HWIRQ_BIT (d -> hwirq ),
126
+ intc .disable [HWIRQ_BANK (d -> hwirq )]);
104
127
}
105
128
106
129
static void armctrl_unmask_irq (struct irq_data * d )
107
130
{
108
- writel_relaxed (HWIRQ_BIT (d -> hwirq ), intc .enable [HWIRQ_BANK (d -> hwirq )]);
131
+ if (d -> hwirq >= NUMBER_IRQS )
132
+ writel_relaxed (REG_FIQ_ENABLE | hwirq_to_fiq (d -> hwirq ),
133
+ intc .base + REG_FIQ_CONTROL );
134
+ else
135
+ writel_relaxed (HWIRQ_BIT (d -> hwirq ),
136
+ intc .enable [HWIRQ_BANK (d -> hwirq )]);
109
137
}
110
138
111
139
static struct irq_chip armctrl_chip = {
@@ -150,8 +178,9 @@ static int __init armctrl_of_init(struct device_node *node,
150
178
panic ("%s: unable to map IC registers\n" ,
151
179
node -> full_name );
152
180
153
- intc .domain = irq_domain_add_linear (node , MAKE_HWIRQ (NR_BANKS , 0 ),
154
- & armctrl_ops , NULL );
181
+ intc .base = base ;
182
+ intc .domain = irq_domain_add_linear (node , NUMBER_IRQS * 2 ,
183
+ & armctrl_ops , NULL );
155
184
if (!intc .domain )
156
185
panic ("%s: unable to create IRQ domain\n" , node -> full_name );
157
186
@@ -168,8 +197,20 @@ static int __init armctrl_of_init(struct device_node *node,
168
197
set_irq_flags (irq , IRQF_VALID | IRQF_PROBE );
169
198
}
170
199
}
171
-
172
200
set_handle_irq (bcm2835_handle_irq );
201
+
202
+ /* Make a duplicate irq range which is used to enable FIQ */
203
+ for (b = 0 ; b < NR_BANKS ; b ++ ) {
204
+ for (i = 0 ; i < bank_irqs [b ]; i ++ ) {
205
+ irq = irq_create_mapping (intc .domain ,
206
+ MAKE_HWIRQ (b , i ) + NUMBER_IRQS );
207
+ BUG_ON (irq <= 0 );
208
+ irq_set_chip (irq , & armctrl_chip );
209
+ set_irq_flags (irq , IRQF_VALID | IRQF_PROBE );
210
+ }
211
+ }
212
+ init_FIQ (FIQ_START );
213
+
173
214
return 0 ;
174
215
}
175
216
0 commit comments