aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/irq_cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/irq_cpu.c')
-rw-r--r--arch/mips/kernel/irq_cpu.c91
1 files changed, 77 insertions, 14 deletions
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 2b936cf1ef70..5db67e31ec1a 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -3,6 +3,8 @@
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 * 4 *
5 * Copyright (C) 2001 Ralf Baechle 5 * Copyright (C) 2001 Ralf Baechle
6 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
7 * Author: Maciej W. Rozycki <macro@mips.com>
6 * 8 *
7 * This file define the irq handler for MIPS CPU interrupts. 9 * This file define the irq handler for MIPS CPU interrupts.
8 * 10 *
@@ -31,19 +33,21 @@
31 33
32#include <asm/irq_cpu.h> 34#include <asm/irq_cpu.h>
33#include <asm/mipsregs.h> 35#include <asm/mipsregs.h>
36#include <asm/mipsmtregs.h>
34#include <asm/system.h> 37#include <asm/system.h>
35 38
36static int mips_cpu_irq_base; 39static int mips_cpu_irq_base;
37 40
38static inline void unmask_mips_irq(unsigned int irq) 41static inline void unmask_mips_irq(unsigned int irq)
39{ 42{
40 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
41 set_c0_status(0x100 << (irq - mips_cpu_irq_base)); 43 set_c0_status(0x100 << (irq - mips_cpu_irq_base));
44 irq_enable_hazard();
42} 45}
43 46
44static inline void mask_mips_irq(unsigned int irq) 47static inline void mask_mips_irq(unsigned int irq)
45{ 48{
46 clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); 49 clear_c0_status(0x100 << (irq - mips_cpu_irq_base));
50 irq_disable_hazard();
47} 51}
48 52
49static inline void mips_cpu_irq_enable(unsigned int irq) 53static inline void mips_cpu_irq_enable(unsigned int irq)
@@ -52,6 +56,7 @@ static inline void mips_cpu_irq_enable(unsigned int irq)
52 56
53 local_irq_save(flags); 57 local_irq_save(flags);
54 unmask_mips_irq(irq); 58 unmask_mips_irq(irq);
59 back_to_back_c0_hazard();
55 local_irq_restore(flags); 60 local_irq_restore(flags);
56} 61}
57 62
@@ -61,6 +66,7 @@ static void mips_cpu_irq_disable(unsigned int irq)
61 66
62 local_irq_save(flags); 67 local_irq_save(flags);
63 mask_mips_irq(irq); 68 mask_mips_irq(irq);
69 back_to_back_c0_hazard();
64 local_irq_restore(flags); 70 local_irq_restore(flags);
65} 71}
66 72
@@ -71,7 +77,7 @@ static unsigned int mips_cpu_irq_startup(unsigned int irq)
71 return 0; 77 return 0;
72} 78}
73 79
74#define mips_cpu_irq_shutdown mips_cpu_irq_disable 80#define mips_cpu_irq_shutdown mips_cpu_irq_disable
75 81
76/* 82/*
77 * While we ack the interrupt interrupts are disabled and thus we don't need 83 * While we ack the interrupt interrupts are disabled and thus we don't need
@@ -79,9 +85,6 @@ static unsigned int mips_cpu_irq_startup(unsigned int irq)
79 */ 85 */
80static void mips_cpu_irq_ack(unsigned int irq) 86static void mips_cpu_irq_ack(unsigned int irq)
81{ 87{
82 /* Only necessary for soft interrupts */
83 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
84
85 mask_mips_irq(irq); 88 mask_mips_irq(irq);
86} 89}
87 90
@@ -92,22 +95,82 @@ static void mips_cpu_irq_end(unsigned int irq)
92} 95}
93 96
94static hw_irq_controller mips_cpu_irq_controller = { 97static hw_irq_controller mips_cpu_irq_controller = {
95 "MIPS", 98 .typename = "MIPS",
96 mips_cpu_irq_startup, 99 .startup = mips_cpu_irq_startup,
97 mips_cpu_irq_shutdown, 100 .shutdown = mips_cpu_irq_shutdown,
98 mips_cpu_irq_enable, 101 .enable = mips_cpu_irq_enable,
99 mips_cpu_irq_disable, 102 .disable = mips_cpu_irq_disable,
100 mips_cpu_irq_ack, 103 .ack = mips_cpu_irq_ack,
101 mips_cpu_irq_end, 104 .end = mips_cpu_irq_end,
102 NULL /* no affinity stuff for UP */
103}; 105};
104 106
107/*
108 * Basically the same as above but taking care of all the MT stuff
109 */
110
111#define unmask_mips_mt_irq unmask_mips_irq
112#define mask_mips_mt_irq mask_mips_irq
113#define mips_mt_cpu_irq_enable mips_cpu_irq_enable
114#define mips_mt_cpu_irq_disable mips_cpu_irq_disable
115
116static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
117{
118 unsigned int vpflags = dvpe();
119
120 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
121 evpe(vpflags);
122 mips_mt_cpu_irq_enable(irq);
123
124 return 0;
125}
126
127#define mips_mt_cpu_irq_shutdown mips_mt_cpu_irq_disable
128
129/*
130 * While we ack the interrupt interrupts are disabled and thus we don't need
131 * to deal with concurrency issues. Same for mips_cpu_irq_end.
132 */
133static void mips_mt_cpu_irq_ack(unsigned int irq)
134{
135 unsigned int vpflags = dvpe();
136 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
137 evpe(vpflags);
138 mask_mips_mt_irq(irq);
139}
140
141#define mips_mt_cpu_irq_end mips_cpu_irq_end
142
143static hw_irq_controller mips_mt_cpu_irq_controller = {
144 .typename = "MIPS",
145 .startup = mips_mt_cpu_irq_startup,
146 .shutdown = mips_mt_cpu_irq_shutdown,
147 .enable = mips_mt_cpu_irq_enable,
148 .disable = mips_mt_cpu_irq_disable,
149 .ack = mips_mt_cpu_irq_ack,
150 .end = mips_mt_cpu_irq_end,
151};
105 152
106void __init mips_cpu_irq_init(int irq_base) 153void __init mips_cpu_irq_init(int irq_base)
107{ 154{
108 int i; 155 int i;
109 156
110 for (i = irq_base; i < irq_base + 8; i++) { 157 /* Mask interrupts. */
158 clear_c0_status(ST0_IM);
159 clear_c0_cause(CAUSEF_IP);
160
161 /*
162 * Only MT is using the software interrupts currently, so we just
163 * leave them uninitialized for other processors.
164 */
165 if (cpu_has_mipsmt)
166 for (i = irq_base; i < irq_base + 2; i++) {
167 irq_desc[i].status = IRQ_DISABLED;
168 irq_desc[i].action = NULL;
169 irq_desc[i].depth = 1;
170 irq_desc[i].handler = &mips_mt_cpu_irq_controller;
171 }
172
173 for (i = irq_base + 2; i < irq_base + 8; i++) {
111 irq_desc[i].status = IRQ_DISABLED; 174 irq_desc[i].status = IRQ_DISABLED;
112 irq_desc[i].action = NULL; 175 irq_desc[i].action = NULL;
113 irq_desc[i].depth = 1; 176 irq_desc[i].depth = 1;