diff options
Diffstat (limited to 'arch/mips/kernel/irq_cpu.c')
-rw-r--r-- | arch/mips/kernel/irq_cpu.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index e498f2b3646a..590c2c980fd3 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/irq_cpu.h> | 36 | #include <asm/irq_cpu.h> |
37 | #include <asm/mipsregs.h> | 37 | #include <asm/mipsregs.h> |
38 | #include <asm/mipsmtregs.h> | 38 | #include <asm/mipsmtregs.h> |
39 | #include <asm/setup.h> | ||
39 | 40 | ||
40 | static inline void unmask_mips_irq(struct irq_data *d) | 41 | static inline void unmask_mips_irq(struct irq_data *d) |
41 | { | 42 | { |
@@ -94,28 +95,24 @@ static struct irq_chip mips_mt_cpu_irq_controller = { | |||
94 | .irq_eoi = unmask_mips_irq, | 95 | .irq_eoi = unmask_mips_irq, |
95 | }; | 96 | }; |
96 | 97 | ||
97 | void __init mips_cpu_irq_init(void) | 98 | asmlinkage void __weak plat_irq_dispatch(void) |
98 | { | 99 | { |
99 | int irq_base = MIPS_CPU_IRQ_BASE; | 100 | unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM; |
100 | int i; | 101 | int irq; |
101 | 102 | ||
102 | /* Mask interrupts. */ | 103 | if (!pending) { |
103 | clear_c0_status(ST0_IM); | 104 | spurious_interrupt(); |
104 | clear_c0_cause(CAUSEF_IP); | 105 | return; |
105 | 106 | } | |
106 | /* Software interrupts are used for MT/CMT IPI */ | ||
107 | for (i = irq_base; i < irq_base + 2; i++) | ||
108 | irq_set_chip_and_handler(i, cpu_has_mipsmt ? | ||
109 | &mips_mt_cpu_irq_controller : | ||
110 | &mips_cpu_irq_controller, | ||
111 | handle_percpu_irq); | ||
112 | 107 | ||
113 | for (i = irq_base + 2; i < irq_base + 8; i++) | 108 | pending >>= CAUSEB_IP; |
114 | irq_set_chip_and_handler(i, &mips_cpu_irq_controller, | 109 | while (pending) { |
115 | handle_percpu_irq); | 110 | irq = fls(pending) - 1; |
111 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
112 | pending &= ~BIT(irq); | ||
113 | } | ||
116 | } | 114 | } |
117 | 115 | ||
118 | #ifdef CONFIG_IRQ_DOMAIN | ||
119 | static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, | 116 | static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, |
120 | irq_hw_number_t hw) | 117 | irq_hw_number_t hw) |
121 | { | 118 | { |
@@ -128,6 +125,9 @@ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, | |||
128 | chip = &mips_cpu_irq_controller; | 125 | chip = &mips_cpu_irq_controller; |
129 | } | 126 | } |
130 | 127 | ||
128 | if (cpu_has_vint) | ||
129 | set_vi_handler(hw, plat_irq_dispatch); | ||
130 | |||
131 | irq_set_chip_and_handler(irq, chip, handle_percpu_irq); | 131 | irq_set_chip_and_handler(irq, chip, handle_percpu_irq); |
132 | 132 | ||
133 | return 0; | 133 | return 0; |
@@ -138,8 +138,7 @@ static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = { | |||
138 | .xlate = irq_domain_xlate_onecell, | 138 | .xlate = irq_domain_xlate_onecell, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | int __init mips_cpu_intc_init(struct device_node *of_node, | 141 | static void __init __mips_cpu_irq_init(struct device_node *of_node) |
142 | struct device_node *parent) | ||
143 | { | 142 | { |
144 | struct irq_domain *domain; | 143 | struct irq_domain *domain; |
145 | 144 | ||
@@ -151,7 +150,16 @@ int __init mips_cpu_intc_init(struct device_node *of_node, | |||
151 | &mips_cpu_intc_irq_domain_ops, NULL); | 150 | &mips_cpu_intc_irq_domain_ops, NULL); |
152 | if (!domain) | 151 | if (!domain) |
153 | panic("Failed to add irqdomain for MIPS CPU"); | 152 | panic("Failed to add irqdomain for MIPS CPU"); |
153 | } | ||
154 | 154 | ||
155 | void __init mips_cpu_irq_init(void) | ||
156 | { | ||
157 | __mips_cpu_irq_init(NULL); | ||
158 | } | ||
159 | |||
160 | int __init mips_cpu_irq_of_init(struct device_node *of_node, | ||
161 | struct device_node *parent) | ||
162 | { | ||
163 | __mips_cpu_irq_init(of_node); | ||
155 | return 0; | 164 | return 0; |
156 | } | 165 | } |
157 | #endif /* CONFIG_IRQ_DOMAIN */ | ||