]>
Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
979934da YY |
2 | /* |
3 | * Interrupt handing routines for NEC VR4100 series. | |
4 | * | |
ada8e951 | 5 | * Copyright (C) 2005-2007 Yoichi Yuasa <yuasa@linux-mips.org> |
979934da | 6 | */ |
26dd3e4f | 7 | #include <linux/export.h> |
979934da | 8 | #include <linux/interrupt.h> |
ca4d3e67 | 9 | #include <linux/irq.h> |
979934da YY |
10 | |
11 | #include <asm/irq_cpu.h> | |
66151bbd | 12 | #include <asm/vr41xx/irq.h> |
979934da YY |
13 | |
14 | typedef struct irq_cascade { | |
937a8015 | 15 | int (*get_irq)(unsigned int); |
979934da YY |
16 | } irq_cascade_t; |
17 | ||
18 | static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; | |
19 | ||
937a8015 | 20 | int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)) |
979934da YY |
21 | { |
22 | int retval = 0; | |
23 | ||
24 | if (irq >= NR_IRQS) | |
25 | return -EINVAL; | |
26 | ||
27 | if (irq_cascade[irq].get_irq != NULL) | |
28 | free_irq(irq, NULL); | |
29 | ||
30 | irq_cascade[irq].get_irq = get_irq; | |
31 | ||
32 | if (get_irq != NULL) { | |
ac8fd122 | 33 | retval = request_irq(irq, no_action, IRQF_NO_THREAD, |
34 | "cascade", NULL); | |
979934da YY |
35 | if (retval < 0) |
36 | irq_cascade[irq].get_irq = NULL; | |
37 | } | |
38 | ||
39 | return retval; | |
40 | } | |
41 | ||
42 | EXPORT_SYMBOL_GPL(cascade_irq); | |
43 | ||
937a8015 | 44 | static void irq_dispatch(unsigned int irq) |
979934da YY |
45 | { |
46 | irq_cascade_t *cascade; | |
979934da YY |
47 | |
48 | if (irq >= NR_IRQS) { | |
49 | atomic_inc(&irq_err_count); | |
50 | return; | |
51 | } | |
52 | ||
53 | cascade = irq_cascade + irq; | |
54 | if (cascade->get_irq != NULL) { | |
fbaa4e2a TG |
55 | struct irq_desc *desc = irq_to_desc(irq); |
56 | struct irq_data *idata = irq_desc_get_irq_data(desc); | |
57 | struct irq_chip *chip = irq_desc_get_chip(desc); | |
a8347954 | 58 | int ret; |
fbaa4e2a TG |
59 | |
60 | if (chip->irq_mask_ack) | |
61 | chip->irq_mask_ack(idata); | |
364ca8a8 | 62 | else { |
fbaa4e2a TG |
63 | chip->irq_mask(idata); |
64 | chip->irq_ack(idata); | |
364ca8a8 | 65 | } |
a8347954 | 66 | ret = cascade->get_irq(irq); |
67 | irq = ret; | |
68 | if (ret < 0) | |
979934da YY |
69 | atomic_inc(&irq_err_count); |
70 | else | |
937a8015 | 71 | irq_dispatch(irq); |
1d5f821c | 72 | if (!irqd_irq_disabled(idata) && chip->irq_unmask) |
fbaa4e2a | 73 | chip->irq_unmask(idata); |
979934da | 74 | } else |
937a8015 | 75 | do_IRQ(irq); |
979934da YY |
76 | } |
77 | ||
937a8015 | 78 | asmlinkage void plat_irq_dispatch(void) |
e4ac58af RB |
79 | { |
80 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | |
81 | ||
82 | if (pending & CAUSEF_IP7) | |
24d55728 | 83 | do_IRQ(TIMER_IRQ); |
e4ac58af RB |
84 | else if (pending & 0x7800) { |
85 | if (pending & CAUSEF_IP3) | |
24d55728 | 86 | irq_dispatch(INT1_IRQ); |
e4ac58af | 87 | else if (pending & CAUSEF_IP4) |
24d55728 | 88 | irq_dispatch(INT2_IRQ); |
e4ac58af | 89 | else if (pending & CAUSEF_IP5) |
24d55728 | 90 | irq_dispatch(INT3_IRQ); |
e4ac58af | 91 | else if (pending & CAUSEF_IP6) |
24d55728 | 92 | irq_dispatch(INT4_IRQ); |
e4ac58af | 93 | } else if (pending & CAUSEF_IP2) |
24d55728 | 94 | irq_dispatch(INT0_IRQ); |
e4ac58af | 95 | else if (pending & CAUSEF_IP0) |
24d55728 | 96 | do_IRQ(MIPS_SOFTINT0_IRQ); |
e4ac58af | 97 | else if (pending & CAUSEF_IP1) |
24d55728 | 98 | do_IRQ(MIPS_SOFTINT1_IRQ); |
e4ac58af | 99 | else |
937a8015 | 100 | spurious_interrupt(); |
e4ac58af | 101 | } |
979934da YY |
102 | |
103 | void __init arch_init_irq(void) | |
104 | { | |
97dcb82d | 105 | mips_cpu_irq_init(); |
979934da | 106 | } |