1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/linkage.h>
21#include <linux/interrupt.h>
22#include <linux/spinlock.h>
23#include <linux/smp.h>
24#include <linux/mm.h>
25#include <linux/kernel_stat.h>
26
27#include <asm/errno.h>
28#include <asm/signal.h>
29#include <asm/time.h>
30#include <asm/io.h>
31
32#include <asm/sibyte/sb1250_regs.h>
33#include <asm/sibyte/sb1250_int.h>
34#include <asm/sibyte/sb1250_uart.h>
35#include <asm/sibyte/sb1250_scd.h>
36#include <asm/sibyte/sb1250.h>
37
38
39
40
41
42
43
44
45#ifdef CONFIG_SIBYTE_HAS_LDT
46extern unsigned long ldt_eoi_space;
47#endif
48
49
50int sb1250_irq_owner[SB1250_NR_IRQS];
51
52static DEFINE_RAW_SPINLOCK(sb1250_imr_lock);
53
54void sb1250_mask_irq(int cpu, int irq)
55{
56 unsigned long flags;
57 u64 cur_ints;
58
59 raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
60 cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
61 R_IMR_INTERRUPT_MASK));
62 cur_ints |= (((u64) 1) << irq);
63 ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
64 R_IMR_INTERRUPT_MASK));
65 raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
66}
67
68void sb1250_unmask_irq(int cpu, int irq)
69{
70 unsigned long flags;
71 u64 cur_ints;
72
73 raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
74 cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
75 R_IMR_INTERRUPT_MASK));
76 cur_ints &= ~(((u64) 1) << irq);
77 ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
78 R_IMR_INTERRUPT_MASK));
79 raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
80}
81
82#ifdef CONFIG_SMP
83static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
84 bool force)
85{
86 int i = 0, old_cpu, cpu, int_on;
87 unsigned int irq = d->irq;
88 u64 cur_ints;
89 unsigned long flags;
90
91 i = cpumask_first_and(mask, cpu_online_mask);
92
93
94 cpu = cpu_logical_map(i);
95
96
97 raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
98
99
100 old_cpu = sb1250_irq_owner[irq];
101 cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
102 R_IMR_INTERRUPT_MASK));
103 int_on = !(cur_ints & (((u64) 1) << irq));
104 if (int_on) {
105
106 cur_ints |= (((u64) 1) << irq);
107 ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
108 R_IMR_INTERRUPT_MASK));
109 }
110 sb1250_irq_owner[irq] = cpu;
111 if (int_on) {
112
113 cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
114 R_IMR_INTERRUPT_MASK));
115 cur_ints &= ~(((u64) 1) << irq);
116 ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
117 R_IMR_INTERRUPT_MASK));
118 }
119 raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
120
121 return 0;
122}
123#endif
124
125static void disable_sb1250_irq(struct irq_data *d)
126{
127 unsigned int irq = d->irq;
128
129 sb1250_mask_irq(sb1250_irq_owner[irq], irq);
130}
131
132static void enable_sb1250_irq(struct irq_data *d)
133{
134 unsigned int irq = d->irq;
135
136 sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
137}
138
139
140static void ack_sb1250_irq(struct irq_data *d)
141{
142 unsigned int irq = d->irq;
143#ifdef CONFIG_SIBYTE_HAS_LDT
144 u64 pending;
145
146
147
148
149
150
151
152 pending = __raw_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
153 R_IMR_LDT_INTERRUPT)));
154 pending &= ((u64)1 << (irq));
155 if (pending) {
156 int i;
157 for (i=0; i<NR_CPUS; i++) {
158 int cpu;
159#ifdef CONFIG_SMP
160 cpu = cpu_logical_map(i);
161#else
162 cpu = i;
163#endif
164
165
166
167
168 __raw_writeq(pending,
169 IOADDR(A_IMR_REGISTER(cpu,
170 R_IMR_LDT_INTERRUPT_CLR)));
171 }
172
173
174
175
176
177
178
179 *(uint32_t *)(ldt_eoi_space+(irq<<16)+(7<<2)) = 0;
180 }
181#endif
182 sb1250_mask_irq(sb1250_irq_owner[irq], irq);
183}
184
185static struct irq_chip sb1250_irq_type = {
186 .name = "SB1250-IMR",
187 .irq_mask_ack = ack_sb1250_irq,
188 .irq_unmask = enable_sb1250_irq,
189 .irq_mask = disable_sb1250_irq,
190#ifdef CONFIG_SMP
191 .irq_set_affinity = sb1250_set_affinity
192#endif
193};
194
195void __init init_sb1250_irqs(void)
196{
197 int i;
198
199 for (i = 0; i < SB1250_NR_IRQS; i++) {
200 irq_set_chip_and_handler(i, &sb1250_irq_type,
201 handle_level_irq);
202 sb1250_irq_owner[i] = 0;
203 }
204}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227#define IMR_IP2_VAL K_INT_MAP_I0
228#define IMR_IP3_VAL K_INT_MAP_I1
229#define IMR_IP4_VAL K_INT_MAP_I2
230#define IMR_IP5_VAL K_INT_MAP_I3
231#define IMR_IP6_VAL K_INT_MAP_I4
232
233void __init arch_init_irq(void)
234{
235
236 unsigned int i;
237 u64 tmp;
238 unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
239 STATUSF_IP1 | STATUSF_IP0;
240
241
242 for (i = 0; i < SB1250_NR_IRQS; i++) {
243 __raw_writeq(IMR_IP2_VAL,
244 IOADDR(A_IMR_REGISTER(0,
245 R_IMR_INTERRUPT_MAP_BASE) +
246 (i << 3)));
247 __raw_writeq(IMR_IP2_VAL,
248 IOADDR(A_IMR_REGISTER(1,
249 R_IMR_INTERRUPT_MAP_BASE) +
250 (i << 3)));
251 }
252
253 init_sb1250_irqs();
254
255
256
257
258
259
260 __raw_writeq(IMR_IP3_VAL,
261 IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
262 (K_INT_MBOX_0 << 3)));
263 __raw_writeq(IMR_IP3_VAL,
264 IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
265 (K_INT_MBOX_0 << 3)));
266
267
268 __raw_writeq(0xffffffffffffffffULL,
269 IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
270 __raw_writeq(0xffffffffffffffffULL,
271 IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
272
273
274 tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0);
275 __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
276 __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
277
278
279
280
281
282
283
284
285 change_c0_status(ST0_IM, imask);
286}
287
288extern void sb1250_mailbox_interrupt(void);
289
290static inline void dispatch_ip2(void)
291{
292 unsigned int cpu = smp_processor_id();
293 unsigned long long mask;
294
295
296
297
298
299
300 mask = __raw_readq(IOADDR(A_IMR_REGISTER(cpu,
301 R_IMR_INTERRUPT_STATUS_BASE)));
302 if (mask)
303 do_IRQ(fls64(mask) - 1);
304}
305
306asmlinkage void plat_irq_dispatch(void)
307{
308 unsigned int cpu = smp_processor_id();
309 unsigned int pending;
310
311
312
313
314
315
316
317
318
319
320
321 pending = read_c0_cause() & read_c0_status() & ST0_IM;
322
323 if (pending & CAUSEF_IP7)
324 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
325 else if (pending & CAUSEF_IP4)
326 do_IRQ(K_INT_TIMER_0 + cpu);
327
328#ifdef CONFIG_SMP
329 else if (pending & CAUSEF_IP3)
330 sb1250_mailbox_interrupt();
331#endif
332
333 else if (pending & CAUSEF_IP2)
334 dispatch_ip2();
335 else
336 spurious_interrupt();
337}
338