openvswitch: Fix FLOW_BUFSIZE definition.
[deliverable/linux.git] / arch / mips / cavium-octeon / octeon-irq.c
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2004-2012 Cavium, Inc.
7 */
8
9 #include <linux/interrupt.h>
10 #include <linux/irqdomain.h>
11 #include <linux/bitops.h>
12 #include <linux/percpu.h>
13 #include <linux/slab.h>
14 #include <linux/irq.h>
15 #include <linux/smp.h>
16 #include <linux/of.h>
17
18 #include <asm/octeon/octeon.h>
19
20 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock);
21 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock);
22
23 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror);
24 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror);
25
26 static __read_mostly u8 octeon_irq_ciu_to_irq[8][64];
27
28 union octeon_ciu_chip_data {
29 void *p;
30 unsigned long l;
31 struct {
32 unsigned int line:6;
33 unsigned int bit:6;
34 } s;
35 };
36
37 struct octeon_core_chip_data {
38 struct mutex core_irq_mutex;
39 bool current_en;
40 bool desired_en;
41 u8 bit;
42 };
43
44 #define MIPS_CORE_IRQ_LINES 8
45
46 static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
47
48 static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
49 struct irq_chip *chip,
50 irq_flow_handler_t handler)
51 {
52 union octeon_ciu_chip_data cd;
53
54 irq_set_chip_and_handler(irq, chip, handler);
55
56 cd.l = 0;
57 cd.s.line = line;
58 cd.s.bit = bit;
59
60 irq_set_chip_data(irq, cd.p);
61 octeon_irq_ciu_to_irq[line][bit] = irq;
62 }
63
64 static int octeon_coreid_for_cpu(int cpu)
65 {
66 #ifdef CONFIG_SMP
67 return cpu_logical_map(cpu);
68 #else
69 return cvmx_get_core_num();
70 #endif
71 }
72
73 static int octeon_cpu_for_coreid(int coreid)
74 {
75 #ifdef CONFIG_SMP
76 return cpu_number_map(coreid);
77 #else
78 return smp_processor_id();
79 #endif
80 }
81
82 static void octeon_irq_core_ack(struct irq_data *data)
83 {
84 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
85 unsigned int bit = cd->bit;
86
87 /*
88 * We don't need to disable IRQs to make these atomic since
89 * they are already disabled earlier in the low level
90 * interrupt code.
91 */
92 clear_c0_status(0x100 << bit);
93 /* The two user interrupts must be cleared manually. */
94 if (bit < 2)
95 clear_c0_cause(0x100 << bit);
96 }
97
98 static void octeon_irq_core_eoi(struct irq_data *data)
99 {
100 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
101
102 /*
103 * We don't need to disable IRQs to make these atomic since
104 * they are already disabled earlier in the low level
105 * interrupt code.
106 */
107 set_c0_status(0x100 << cd->bit);
108 }
109
110 static void octeon_irq_core_set_enable_local(void *arg)
111 {
112 struct irq_data *data = arg;
113 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
114 unsigned int mask = 0x100 << cd->bit;
115
116 /*
117 * Interrupts are already disabled, so these are atomic.
118 */
119 if (cd->desired_en)
120 set_c0_status(mask);
121 else
122 clear_c0_status(mask);
123
124 }
125
126 static void octeon_irq_core_disable(struct irq_data *data)
127 {
128 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
129 cd->desired_en = false;
130 }
131
132 static void octeon_irq_core_enable(struct irq_data *data)
133 {
134 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
135 cd->desired_en = true;
136 }
137
138 static void octeon_irq_core_bus_lock(struct irq_data *data)
139 {
140 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
141
142 mutex_lock(&cd->core_irq_mutex);
143 }
144
145 static void octeon_irq_core_bus_sync_unlock(struct irq_data *data)
146 {
147 struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
148
149 if (cd->desired_en != cd->current_en) {
150 on_each_cpu(octeon_irq_core_set_enable_local, data, 1);
151
152 cd->current_en = cd->desired_en;
153 }
154
155 mutex_unlock(&cd->core_irq_mutex);
156 }
157
158 static struct irq_chip octeon_irq_chip_core = {
159 .name = "Core",
160 .irq_enable = octeon_irq_core_enable,
161 .irq_disable = octeon_irq_core_disable,
162 .irq_ack = octeon_irq_core_ack,
163 .irq_eoi = octeon_irq_core_eoi,
164 .irq_bus_lock = octeon_irq_core_bus_lock,
165 .irq_bus_sync_unlock = octeon_irq_core_bus_sync_unlock,
166
167 .irq_cpu_online = octeon_irq_core_eoi,
168 .irq_cpu_offline = octeon_irq_core_ack,
169 .flags = IRQCHIP_ONOFFLINE_ENABLED,
170 };
171
172 static void __init octeon_irq_init_core(void)
173 {
174 int i;
175 int irq;
176 struct octeon_core_chip_data *cd;
177
178 for (i = 0; i < MIPS_CORE_IRQ_LINES; i++) {
179 cd = &octeon_irq_core_chip_data[i];
180 cd->current_en = false;
181 cd->desired_en = false;
182 cd->bit = i;
183 mutex_init(&cd->core_irq_mutex);
184
185 irq = OCTEON_IRQ_SW0 + i;
186 switch (irq) {
187 case OCTEON_IRQ_TIMER:
188 case OCTEON_IRQ_SW0:
189 case OCTEON_IRQ_SW1:
190 case OCTEON_IRQ_5:
191 case OCTEON_IRQ_PERF:
192 irq_set_chip_data(irq, cd);
193 irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
194 handle_percpu_irq);
195 break;
196 default:
197 break;
198 }
199 }
200 }
201
202 static int next_cpu_for_irq(struct irq_data *data)
203 {
204
205 #ifdef CONFIG_SMP
206 int cpu;
207 int weight = cpumask_weight(data->affinity);
208
209 if (weight > 1) {
210 cpu = smp_processor_id();
211 for (;;) {
212 cpu = cpumask_next(cpu, data->affinity);
213 if (cpu >= nr_cpu_ids) {
214 cpu = -1;
215 continue;
216 } else if (cpumask_test_cpu(cpu, cpu_online_mask)) {
217 break;
218 }
219 }
220 } else if (weight == 1) {
221 cpu = cpumask_first(data->affinity);
222 } else {
223 cpu = smp_processor_id();
224 }
225 return cpu;
226 #else
227 return smp_processor_id();
228 #endif
229 }
230
231 static void octeon_irq_ciu_enable(struct irq_data *data)
232 {
233 int cpu = next_cpu_for_irq(data);
234 int coreid = octeon_coreid_for_cpu(cpu);
235 unsigned long *pen;
236 unsigned long flags;
237 union octeon_ciu_chip_data cd;
238
239 cd.p = irq_data_get_irq_chip_data(data);
240
241 if (cd.s.line == 0) {
242 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
243 pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
244 set_bit(cd.s.bit, pen);
245 cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
246 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
247 } else {
248 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
249 pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
250 set_bit(cd.s.bit, pen);
251 cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
252 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
253 }
254 }
255
256 static void octeon_irq_ciu_enable_local(struct irq_data *data)
257 {
258 unsigned long *pen;
259 unsigned long flags;
260 union octeon_ciu_chip_data cd;
261
262 cd.p = irq_data_get_irq_chip_data(data);
263
264 if (cd.s.line == 0) {
265 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
266 pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
267 set_bit(cd.s.bit, pen);
268 cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
269 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
270 } else {
271 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
272 pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
273 set_bit(cd.s.bit, pen);
274 cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
275 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
276 }
277 }
278
279 static void octeon_irq_ciu_disable_local(struct irq_data *data)
280 {
281 unsigned long *pen;
282 unsigned long flags;
283 union octeon_ciu_chip_data cd;
284
285 cd.p = irq_data_get_irq_chip_data(data);
286
287 if (cd.s.line == 0) {
288 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
289 pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
290 clear_bit(cd.s.bit, pen);
291 cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
292 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
293 } else {
294 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
295 pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
296 clear_bit(cd.s.bit, pen);
297 cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
298 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
299 }
300 }
301
302 static void octeon_irq_ciu_disable_all(struct irq_data *data)
303 {
304 unsigned long flags;
305 unsigned long *pen;
306 int cpu;
307 union octeon_ciu_chip_data cd;
308
309 wmb(); /* Make sure flag changes arrive before register updates. */
310
311 cd.p = irq_data_get_irq_chip_data(data);
312
313 if (cd.s.line == 0) {
314 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
315 for_each_online_cpu(cpu) {
316 int coreid = octeon_coreid_for_cpu(cpu);
317 pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
318 clear_bit(cd.s.bit, pen);
319 cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
320 }
321 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
322 } else {
323 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
324 for_each_online_cpu(cpu) {
325 int coreid = octeon_coreid_for_cpu(cpu);
326 pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
327 clear_bit(cd.s.bit, pen);
328 cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
329 }
330 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
331 }
332 }
333
334 static void octeon_irq_ciu_enable_all(struct irq_data *data)
335 {
336 unsigned long flags;
337 unsigned long *pen;
338 int cpu;
339 union octeon_ciu_chip_data cd;
340
341 cd.p = irq_data_get_irq_chip_data(data);
342
343 if (cd.s.line == 0) {
344 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
345 for_each_online_cpu(cpu) {
346 int coreid = octeon_coreid_for_cpu(cpu);
347 pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
348 set_bit(cd.s.bit, pen);
349 cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
350 }
351 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
352 } else {
353 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
354 for_each_online_cpu(cpu) {
355 int coreid = octeon_coreid_for_cpu(cpu);
356 pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
357 set_bit(cd.s.bit, pen);
358 cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
359 }
360 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
361 }
362 }
363
364 /*
365 * Enable the irq on the next core in the affinity set for chips that
366 * have the EN*_W1{S,C} registers.
367 */
368 static void octeon_irq_ciu_enable_v2(struct irq_data *data)
369 {
370 u64 mask;
371 int cpu = next_cpu_for_irq(data);
372 union octeon_ciu_chip_data cd;
373
374 cd.p = irq_data_get_irq_chip_data(data);
375 mask = 1ull << (cd.s.bit);
376
377 /*
378 * Called under the desc lock, so these should never get out
379 * of sync.
380 */
381 if (cd.s.line == 0) {
382 int index = octeon_coreid_for_cpu(cpu) * 2;
383 set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
384 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
385 } else {
386 int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
387 set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
388 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
389 }
390 }
391
392 /*
393 * Enable the irq on the current CPU for chips that
394 * have the EN*_W1{S,C} registers.
395 */
396 static void octeon_irq_ciu_enable_local_v2(struct irq_data *data)
397 {
398 u64 mask;
399 union octeon_ciu_chip_data cd;
400
401 cd.p = irq_data_get_irq_chip_data(data);
402 mask = 1ull << (cd.s.bit);
403
404 if (cd.s.line == 0) {
405 int index = cvmx_get_core_num() * 2;
406 set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
407 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
408 } else {
409 int index = cvmx_get_core_num() * 2 + 1;
410 set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
411 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
412 }
413 }
414
415 static void octeon_irq_ciu_disable_local_v2(struct irq_data *data)
416 {
417 u64 mask;
418 union octeon_ciu_chip_data cd;
419
420 cd.p = irq_data_get_irq_chip_data(data);
421 mask = 1ull << (cd.s.bit);
422
423 if (cd.s.line == 0) {
424 int index = cvmx_get_core_num() * 2;
425 clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
426 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
427 } else {
428 int index = cvmx_get_core_num() * 2 + 1;
429 clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
430 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
431 }
432 }
433
434 /*
435 * Write to the W1C bit in CVMX_CIU_INTX_SUM0 to clear the irq.
436 */
437 static void octeon_irq_ciu_ack(struct irq_data *data)
438 {
439 u64 mask;
440 union octeon_ciu_chip_data cd;
441
442 cd.p = data->chip_data;
443 mask = 1ull << (cd.s.bit);
444
445 if (cd.s.line == 0) {
446 int index = cvmx_get_core_num() * 2;
447 cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
448 } else {
449 cvmx_write_csr(CVMX_CIU_INT_SUM1, mask);
450 }
451 }
452
453 /*
454 * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
455 * registers.
456 */
457 static void octeon_irq_ciu_disable_all_v2(struct irq_data *data)
458 {
459 int cpu;
460 u64 mask;
461 union octeon_ciu_chip_data cd;
462
463 wmb(); /* Make sure flag changes arrive before register updates. */
464
465 cd.p = data->chip_data;
466 mask = 1ull << (cd.s.bit);
467
468 if (cd.s.line == 0) {
469 for_each_online_cpu(cpu) {
470 int index = octeon_coreid_for_cpu(cpu) * 2;
471 clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
472 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
473 }
474 } else {
475 for_each_online_cpu(cpu) {
476 int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
477 clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
478 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
479 }
480 }
481 }
482
483 /*
484 * Enable the irq on the all cores for chips that have the EN*_W1{S,C}
485 * registers.
486 */
487 static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
488 {
489 int cpu;
490 u64 mask;
491 union octeon_ciu_chip_data cd;
492
493 cd.p = data->chip_data;
494 mask = 1ull << (cd.s.bit);
495
496 if (cd.s.line == 0) {
497 for_each_online_cpu(cpu) {
498 int index = octeon_coreid_for_cpu(cpu) * 2;
499 set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
500 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
501 }
502 } else {
503 for_each_online_cpu(cpu) {
504 int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
505 set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
506 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
507 }
508 }
509 }
510
511 static void octeon_irq_gpio_setup(struct irq_data *data)
512 {
513 union cvmx_gpio_bit_cfgx cfg;
514 union octeon_ciu_chip_data cd;
515 u32 t = irqd_get_trigger_type(data);
516
517 cd.p = irq_data_get_irq_chip_data(data);
518
519 cfg.u64 = 0;
520 cfg.s.int_en = 1;
521 cfg.s.int_type = (t & IRQ_TYPE_EDGE_BOTH) != 0;
522 cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0;
523
524 /* 140 nS glitch filter*/
525 cfg.s.fil_cnt = 7;
526 cfg.s.fil_sel = 3;
527
528 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64);
529 }
530
531 static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data)
532 {
533 octeon_irq_gpio_setup(data);
534 octeon_irq_ciu_enable_v2(data);
535 }
536
537 static void octeon_irq_ciu_enable_gpio(struct irq_data *data)
538 {
539 octeon_irq_gpio_setup(data);
540 octeon_irq_ciu_enable(data);
541 }
542
543 static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
544 {
545 irqd_set_trigger_type(data, t);
546 octeon_irq_gpio_setup(data);
547
548 return IRQ_SET_MASK_OK;
549 }
550
551 static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data)
552 {
553 union octeon_ciu_chip_data cd;
554
555 cd.p = irq_data_get_irq_chip_data(data);
556 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0);
557
558 octeon_irq_ciu_disable_all_v2(data);
559 }
560
561 static void octeon_irq_ciu_disable_gpio(struct irq_data *data)
562 {
563 union octeon_ciu_chip_data cd;
564
565 cd.p = irq_data_get_irq_chip_data(data);
566 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0);
567
568 octeon_irq_ciu_disable_all(data);
569 }
570
571 static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
572 {
573 union octeon_ciu_chip_data cd;
574 u64 mask;
575
576 cd.p = irq_data_get_irq_chip_data(data);
577 mask = 1ull << (cd.s.bit - 16);
578
579 cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
580 }
581
582 static void octeon_irq_handle_gpio(unsigned int irq, struct irq_desc *desc)
583 {
584 if (irqd_get_trigger_type(irq_desc_get_irq_data(desc)) & IRQ_TYPE_EDGE_BOTH)
585 handle_edge_irq(irq, desc);
586 else
587 handle_level_irq(irq, desc);
588 }
589
590 #ifdef CONFIG_SMP
591
592 static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
593 {
594 int cpu = smp_processor_id();
595 cpumask_t new_affinity;
596
597 if (!cpumask_test_cpu(cpu, data->affinity))
598 return;
599
600 if (cpumask_weight(data->affinity) > 1) {
601 /*
602 * It has multi CPU affinity, just remove this CPU
603 * from the affinity set.
604 */
605 cpumask_copy(&new_affinity, data->affinity);
606 cpumask_clear_cpu(cpu, &new_affinity);
607 } else {
608 /* Otherwise, put it on lowest numbered online CPU. */
609 cpumask_clear(&new_affinity);
610 cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
611 }
612 __irq_set_affinity_locked(data, &new_affinity);
613 }
614
615 static int octeon_irq_ciu_set_affinity(struct irq_data *data,
616 const struct cpumask *dest, bool force)
617 {
618 int cpu;
619 bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
620 unsigned long flags;
621 union octeon_ciu_chip_data cd;
622
623 cd.p = data->chip_data;
624
625 /*
626 * For non-v2 CIU, we will allow only single CPU affinity.
627 * This removes the need to do locking in the .ack/.eoi
628 * functions.
629 */
630 if (cpumask_weight(dest) != 1)
631 return -EINVAL;
632
633 if (!enable_one)
634 return 0;
635
636 if (cd.s.line == 0) {
637 raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
638 for_each_online_cpu(cpu) {
639 int coreid = octeon_coreid_for_cpu(cpu);
640 unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
641
642 if (cpumask_test_cpu(cpu, dest) && enable_one) {
643 enable_one = false;
644 set_bit(cd.s.bit, pen);
645 } else {
646 clear_bit(cd.s.bit, pen);
647 }
648 cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
649 }
650 raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
651 } else {
652 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
653 for_each_online_cpu(cpu) {
654 int coreid = octeon_coreid_for_cpu(cpu);
655 unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
656
657 if (cpumask_test_cpu(cpu, dest) && enable_one) {
658 enable_one = false;
659 set_bit(cd.s.bit, pen);
660 } else {
661 clear_bit(cd.s.bit, pen);
662 }
663 cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
664 }
665 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
666 }
667 return 0;
668 }
669
670 /*
671 * Set affinity for the irq for chips that have the EN*_W1{S,C}
672 * registers.
673 */
674 static int octeon_irq_ciu_set_affinity_v2(struct irq_data *data,
675 const struct cpumask *dest,
676 bool force)
677 {
678 int cpu;
679 bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
680 u64 mask;
681 union octeon_ciu_chip_data cd;
682
683 if (!enable_one)
684 return 0;
685
686 cd.p = data->chip_data;
687 mask = 1ull << cd.s.bit;
688
689 if (cd.s.line == 0) {
690 for_each_online_cpu(cpu) {
691 unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
692 int index = octeon_coreid_for_cpu(cpu) * 2;
693 if (cpumask_test_cpu(cpu, dest) && enable_one) {
694 enable_one = false;
695 set_bit(cd.s.bit, pen);
696 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
697 } else {
698 clear_bit(cd.s.bit, pen);
699 cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
700 }
701 }
702 } else {
703 for_each_online_cpu(cpu) {
704 unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
705 int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
706 if (cpumask_test_cpu(cpu, dest) && enable_one) {
707 enable_one = false;
708 set_bit(cd.s.bit, pen);
709 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
710 } else {
711 clear_bit(cd.s.bit, pen);
712 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
713 }
714 }
715 }
716 return 0;
717 }
718 #endif
719
720 /*
721 * The v1 CIU code already masks things, so supply a dummy version to
722 * the core chip code.
723 */
724 static void octeon_irq_dummy_mask(struct irq_data *data)
725 {
726 }
727
728 /*
729 * Newer octeon chips have support for lockless CIU operation.
730 */
731 static struct irq_chip octeon_irq_chip_ciu_v2 = {
732 .name = "CIU",
733 .irq_enable = octeon_irq_ciu_enable_v2,
734 .irq_disable = octeon_irq_ciu_disable_all_v2,
735 .irq_ack = octeon_irq_ciu_ack,
736 .irq_mask = octeon_irq_ciu_disable_local_v2,
737 .irq_unmask = octeon_irq_ciu_enable_v2,
738 #ifdef CONFIG_SMP
739 .irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
740 .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
741 #endif
742 };
743
744 static struct irq_chip octeon_irq_chip_ciu = {
745 .name = "CIU",
746 .irq_enable = octeon_irq_ciu_enable,
747 .irq_disable = octeon_irq_ciu_disable_all,
748 .irq_ack = octeon_irq_ciu_ack,
749 .irq_mask = octeon_irq_dummy_mask,
750 #ifdef CONFIG_SMP
751 .irq_set_affinity = octeon_irq_ciu_set_affinity,
752 .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
753 #endif
754 };
755
756 /* The mbox versions don't do any affinity or round-robin. */
757 static struct irq_chip octeon_irq_chip_ciu_mbox_v2 = {
758 .name = "CIU-M",
759 .irq_enable = octeon_irq_ciu_enable_all_v2,
760 .irq_disable = octeon_irq_ciu_disable_all_v2,
761 .irq_ack = octeon_irq_ciu_disable_local_v2,
762 .irq_eoi = octeon_irq_ciu_enable_local_v2,
763
764 .irq_cpu_online = octeon_irq_ciu_enable_local_v2,
765 .irq_cpu_offline = octeon_irq_ciu_disable_local_v2,
766 .flags = IRQCHIP_ONOFFLINE_ENABLED,
767 };
768
769 static struct irq_chip octeon_irq_chip_ciu_mbox = {
770 .name = "CIU-M",
771 .irq_enable = octeon_irq_ciu_enable_all,
772 .irq_disable = octeon_irq_ciu_disable_all,
773
774 .irq_cpu_online = octeon_irq_ciu_enable_local,
775 .irq_cpu_offline = octeon_irq_ciu_disable_local,
776 .flags = IRQCHIP_ONOFFLINE_ENABLED,
777 };
778
779 static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = {
780 .name = "CIU-GPIO",
781 .irq_enable = octeon_irq_ciu_enable_gpio_v2,
782 .irq_disable = octeon_irq_ciu_disable_gpio_v2,
783 .irq_ack = octeon_irq_ciu_gpio_ack,
784 .irq_mask = octeon_irq_ciu_disable_local_v2,
785 .irq_unmask = octeon_irq_ciu_enable_v2,
786 .irq_set_type = octeon_irq_ciu_gpio_set_type,
787 #ifdef CONFIG_SMP
788 .irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
789 #endif
790 .flags = IRQCHIP_SET_TYPE_MASKED,
791 };
792
793 static struct irq_chip octeon_irq_chip_ciu_gpio = {
794 .name = "CIU-GPIO",
795 .irq_enable = octeon_irq_ciu_enable_gpio,
796 .irq_disable = octeon_irq_ciu_disable_gpio,
797 .irq_mask = octeon_irq_dummy_mask,
798 .irq_ack = octeon_irq_ciu_gpio_ack,
799 .irq_set_type = octeon_irq_ciu_gpio_set_type,
800 #ifdef CONFIG_SMP
801 .irq_set_affinity = octeon_irq_ciu_set_affinity,
802 #endif
803 .flags = IRQCHIP_SET_TYPE_MASKED,
804 };
805
806 /*
807 * Watchdog interrupts are special. They are associated with a single
808 * core, so we hardwire the affinity to that core.
809 */
810 static void octeon_irq_ciu_wd_enable(struct irq_data *data)
811 {
812 unsigned long flags;
813 unsigned long *pen;
814 int coreid = data->irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
815 int cpu = octeon_cpu_for_coreid(coreid);
816
817 raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
818 pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
819 set_bit(coreid, pen);
820 cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
821 raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
822 }
823
824 /*
825 * Watchdog interrupts are special. They are associated with a single
826 * core, so we hardwire the affinity to that core.
827 */
828 static void octeon_irq_ciu1_wd_enable_v2(struct irq_data *data)
829 {
830 int coreid = data->irq - OCTEON_IRQ_WDOG0;
831 int cpu = octeon_cpu_for_coreid(coreid);
832
833 set_bit(coreid, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
834 cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(coreid * 2 + 1), 1ull << coreid);
835 }
836
837
838 static struct irq_chip octeon_irq_chip_ciu_wd_v2 = {
839 .name = "CIU-W",
840 .irq_enable = octeon_irq_ciu1_wd_enable_v2,
841 .irq_disable = octeon_irq_ciu_disable_all_v2,
842 .irq_mask = octeon_irq_ciu_disable_local_v2,
843 .irq_unmask = octeon_irq_ciu_enable_local_v2,
844 };
845
846 static struct irq_chip octeon_irq_chip_ciu_wd = {
847 .name = "CIU-W",
848 .irq_enable = octeon_irq_ciu_wd_enable,
849 .irq_disable = octeon_irq_ciu_disable_all,
850 .irq_mask = octeon_irq_dummy_mask,
851 };
852
853 static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
854 {
855 bool edge = false;
856
857 if (line == 0)
858 switch (bit) {
859 case 48 ... 49: /* GMX DRP */
860 case 50: /* IPD_DRP */
861 case 52 ... 55: /* Timers */
862 case 58: /* MPI */
863 edge = true;
864 break;
865 default:
866 break;
867 }
868 else /* line == 1 */
869 switch (bit) {
870 case 47: /* PTP */
871 edge = true;
872 break;
873 default:
874 break;
875 }
876 return edge;
877 }
878
879 struct octeon_irq_gpio_domain_data {
880 unsigned int base_hwirq;
881 };
882
883 static int octeon_irq_gpio_xlat(struct irq_domain *d,
884 struct device_node *node,
885 const u32 *intspec,
886 unsigned int intsize,
887 unsigned long *out_hwirq,
888 unsigned int *out_type)
889 {
890 unsigned int type;
891 unsigned int pin;
892 unsigned int trigger;
893 struct octeon_irq_gpio_domain_data *gpiod;
894
895 if (d->of_node != node)
896 return -EINVAL;
897
898 if (intsize < 2)
899 return -EINVAL;
900
901 pin = intspec[0];
902 if (pin >= 16)
903 return -EINVAL;
904
905 trigger = intspec[1];
906
907 switch (trigger) {
908 case 1:
909 type = IRQ_TYPE_EDGE_RISING;
910 break;
911 case 2:
912 type = IRQ_TYPE_EDGE_FALLING;
913 break;
914 case 4:
915 type = IRQ_TYPE_LEVEL_HIGH;
916 break;
917 case 8:
918 type = IRQ_TYPE_LEVEL_LOW;
919 break;
920 default:
921 pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
922 node->name,
923 trigger);
924 type = IRQ_TYPE_LEVEL_LOW;
925 break;
926 }
927 *out_type = type;
928 gpiod = d->host_data;
929 *out_hwirq = gpiod->base_hwirq + pin;
930
931 return 0;
932 }
933
934 static int octeon_irq_ciu_xlat(struct irq_domain *d,
935 struct device_node *node,
936 const u32 *intspec,
937 unsigned int intsize,
938 unsigned long *out_hwirq,
939 unsigned int *out_type)
940 {
941 unsigned int ciu, bit;
942
943 ciu = intspec[0];
944 bit = intspec[1];
945
946 if (ciu > 1 || bit > 63)
947 return -EINVAL;
948
949 /* These are the GPIO lines */
950 if (ciu == 0 && bit >= 16 && bit < 32)
951 return -EINVAL;
952
953 *out_hwirq = (ciu << 6) | bit;
954 *out_type = 0;
955
956 return 0;
957 }
958
959 static struct irq_chip *octeon_irq_ciu_chip;
960 static struct irq_chip *octeon_irq_gpio_chip;
961
962 static bool octeon_irq_virq_in_range(unsigned int virq)
963 {
964 /* We cannot let it overflow the mapping array. */
965 if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0])))
966 return true;
967
968 WARN_ONCE(true, "virq out of range %u.\n", virq);
969 return false;
970 }
971
972 static int octeon_irq_ciu_map(struct irq_domain *d,
973 unsigned int virq, irq_hw_number_t hw)
974 {
975 unsigned int line = hw >> 6;
976 unsigned int bit = hw & 63;
977
978 if (!octeon_irq_virq_in_range(virq))
979 return -EINVAL;
980
981 if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
982 return -EINVAL;
983
984 if (octeon_irq_ciu_is_edge(line, bit))
985 octeon_irq_set_ciu_mapping(virq, line, bit,
986 octeon_irq_ciu_chip,
987 handle_edge_irq);
988 else
989 octeon_irq_set_ciu_mapping(virq, line, bit,
990 octeon_irq_ciu_chip,
991 handle_level_irq);
992
993 return 0;
994 }
995
996 static int octeon_irq_gpio_map(struct irq_domain *d,
997 unsigned int virq, irq_hw_number_t hw)
998 {
999 unsigned int line = hw >> 6;
1000 unsigned int bit = hw & 63;
1001
1002 if (!octeon_irq_virq_in_range(virq))
1003 return -EINVAL;
1004
1005 if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
1006 return -EINVAL;
1007
1008 octeon_irq_set_ciu_mapping(virq, line, bit,
1009 octeon_irq_gpio_chip,
1010 octeon_irq_handle_gpio);
1011
1012 return 0;
1013 }
1014
1015 static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
1016 .map = octeon_irq_ciu_map,
1017 .xlate = octeon_irq_ciu_xlat,
1018 };
1019
1020 static struct irq_domain_ops octeon_irq_domain_gpio_ops = {
1021 .map = octeon_irq_gpio_map,
1022 .xlate = octeon_irq_gpio_xlat,
1023 };
1024
1025 static void octeon_irq_ip2_v1(void)
1026 {
1027 const unsigned long core_id = cvmx_get_core_num();
1028 u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
1029
1030 ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
1031 clear_c0_status(STATUSF_IP2);
1032 if (likely(ciu_sum)) {
1033 int bit = fls64(ciu_sum) - 1;
1034 int irq = octeon_irq_ciu_to_irq[0][bit];
1035 if (likely(irq))
1036 do_IRQ(irq);
1037 else
1038 spurious_interrupt();
1039 } else {
1040 spurious_interrupt();
1041 }
1042 set_c0_status(STATUSF_IP2);
1043 }
1044
1045 static void octeon_irq_ip2_v2(void)
1046 {
1047 const unsigned long core_id = cvmx_get_core_num();
1048 u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
1049
1050 ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
1051 if (likely(ciu_sum)) {
1052 int bit = fls64(ciu_sum) - 1;
1053 int irq = octeon_irq_ciu_to_irq[0][bit];
1054 if (likely(irq))
1055 do_IRQ(irq);
1056 else
1057 spurious_interrupt();
1058 } else {
1059 spurious_interrupt();
1060 }
1061 }
1062 static void octeon_irq_ip3_v1(void)
1063 {
1064 u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
1065
1066 ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
1067 clear_c0_status(STATUSF_IP3);
1068 if (likely(ciu_sum)) {
1069 int bit = fls64(ciu_sum) - 1;
1070 int irq = octeon_irq_ciu_to_irq[1][bit];
1071 if (likely(irq))
1072 do_IRQ(irq);
1073 else
1074 spurious_interrupt();
1075 } else {
1076 spurious_interrupt();
1077 }
1078 set_c0_status(STATUSF_IP3);
1079 }
1080
1081 static void octeon_irq_ip3_v2(void)
1082 {
1083 u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
1084
1085 ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
1086 if (likely(ciu_sum)) {
1087 int bit = fls64(ciu_sum) - 1;
1088 int irq = octeon_irq_ciu_to_irq[1][bit];
1089 if (likely(irq))
1090 do_IRQ(irq);
1091 else
1092 spurious_interrupt();
1093 } else {
1094 spurious_interrupt();
1095 }
1096 }
1097
1098 static void octeon_irq_ip4_mask(void)
1099 {
1100 clear_c0_status(STATUSF_IP4);
1101 spurious_interrupt();
1102 }
1103
1104 static void (*octeon_irq_ip2)(void);
1105 static void (*octeon_irq_ip3)(void);
1106 static void (*octeon_irq_ip4)(void);
1107
1108 void __cpuinitdata (*octeon_irq_setup_secondary)(void);
1109
1110 static void __cpuinit octeon_irq_percpu_enable(void)
1111 {
1112 irq_cpu_online();
1113 }
1114
1115 static void __cpuinit octeon_irq_init_ciu_percpu(void)
1116 {
1117 int coreid = cvmx_get_core_num();
1118 /*
1119 * Disable All CIU Interrupts. The ones we need will be
1120 * enabled later. Read the SUM register so we know the write
1121 * completed.
1122 */
1123 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
1124 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
1125 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
1126 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
1127 cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
1128 }
1129
1130 static void __cpuinit octeon_irq_setup_secondary_ciu(void)
1131 {
1132
1133 __get_cpu_var(octeon_irq_ciu0_en_mirror) = 0;
1134 __get_cpu_var(octeon_irq_ciu1_en_mirror) = 0;
1135
1136 octeon_irq_init_ciu_percpu();
1137 octeon_irq_percpu_enable();
1138
1139 /* Enable the CIU lines */
1140 set_c0_status(STATUSF_IP3 | STATUSF_IP2);
1141 clear_c0_status(STATUSF_IP4);
1142 }
1143
1144 static void __init octeon_irq_init_ciu(void)
1145 {
1146 unsigned int i;
1147 struct irq_chip *chip;
1148 struct irq_chip *chip_mbox;
1149 struct irq_chip *chip_wd;
1150 struct device_node *gpio_node;
1151 struct device_node *ciu_node;
1152
1153 octeon_irq_init_ciu_percpu();
1154 octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
1155
1156 if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
1157 OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
1158 OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) ||
1159 OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
1160 octeon_irq_ip2 = octeon_irq_ip2_v2;
1161 octeon_irq_ip3 = octeon_irq_ip3_v2;
1162 chip = &octeon_irq_chip_ciu_v2;
1163 chip_mbox = &octeon_irq_chip_ciu_mbox_v2;
1164 chip_wd = &octeon_irq_chip_ciu_wd_v2;
1165 octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio_v2;
1166 } else {
1167 octeon_irq_ip2 = octeon_irq_ip2_v1;
1168 octeon_irq_ip3 = octeon_irq_ip3_v1;
1169 chip = &octeon_irq_chip_ciu;
1170 chip_mbox = &octeon_irq_chip_ciu_mbox;
1171 chip_wd = &octeon_irq_chip_ciu_wd;
1172 octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio;
1173 }
1174 octeon_irq_ciu_chip = chip;
1175 octeon_irq_ip4 = octeon_irq_ip4_mask;
1176
1177 /* Mips internal */
1178 octeon_irq_init_core();
1179
1180 /* CIU_0 */
1181 for (i = 0; i < 16; i++)
1182 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
1183
1184 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
1185 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
1186
1187 for (i = 0; i < 4; i++)
1188 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
1189 for (i = 0; i < 4; i++)
1190 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
1191
1192 octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
1193 for (i = 0; i < 4; i++)
1194 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
1195
1196 octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
1197 octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
1198
1199 /* CIU_1 */
1200 for (i = 0; i < 16; i++)
1201 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
1202
1203 octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
1204
1205 gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
1206 if (gpio_node) {
1207 struct octeon_irq_gpio_domain_data *gpiod;
1208
1209 gpiod = kzalloc(sizeof(*gpiod), GFP_KERNEL);
1210 if (gpiod) {
1211 /* gpio domain host_data is the base hwirq number. */
1212 gpiod->base_hwirq = 16;
1213 irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, gpiod);
1214 of_node_put(gpio_node);
1215 } else
1216 pr_warn("Cannot allocate memory for GPIO irq_domain.\n");
1217 } else
1218 pr_warn("Cannot find device node for cavium,octeon-3860-gpio.\n");
1219
1220 ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
1221 if (ciu_node) {
1222 irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
1223 of_node_put(ciu_node);
1224 } else
1225 pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n");
1226
1227 /* Enable the CIU lines */
1228 set_c0_status(STATUSF_IP3 | STATUSF_IP2);
1229 clear_c0_status(STATUSF_IP4);
1230 }
1231
1232 void __init arch_init_irq(void)
1233 {
1234 #ifdef CONFIG_SMP
1235 /* Set the default affinity to the boot cpu. */
1236 cpumask_clear(irq_default_affinity);
1237 cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
1238 #endif
1239 octeon_irq_init_ciu();
1240 }
1241
1242 asmlinkage void plat_irq_dispatch(void)
1243 {
1244 unsigned long cop0_cause;
1245 unsigned long cop0_status;
1246
1247 while (1) {
1248 cop0_cause = read_c0_cause();
1249 cop0_status = read_c0_status();
1250 cop0_cause &= cop0_status;
1251 cop0_cause &= ST0_IM;
1252
1253 if (unlikely(cop0_cause & STATUSF_IP2))
1254 octeon_irq_ip2();
1255 else if (unlikely(cop0_cause & STATUSF_IP3))
1256 octeon_irq_ip3();
1257 else if (unlikely(cop0_cause & STATUSF_IP4))
1258 octeon_irq_ip4();
1259 else if (likely(cop0_cause))
1260 do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE);
1261 else
1262 break;
1263 }
1264 }
1265
1266 #ifdef CONFIG_HOTPLUG_CPU
1267
1268 void fixup_irqs(void)
1269 {
1270 irq_cpu_offline();
1271 }
1272
1273 #endif /* CONFIG_HOTPLUG_CPU */
This page took 0.057388 seconds and 5 git commands to generate.