aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2007-12-04 06:01:40 -0500
committerKumar Gala <galak@kernel.crashing.org>2007-12-12 02:53:07 -0500
commit77d4309e19b1a7ab3286cd741e924894fc329986 (patch)
treebc6626e5acb07c77df9c06e238873f12f24bb6e9
parentea082fa94eab6c2d8ad81c8a46b680cf4c2a3bb3 (diff)
[POWERPC] ipic: ack only for edge interrupts
Only external interrupts in edge detect mode support ack operation. Therefore, in most cases ack is not needed. The patch makes ipic ack only when it's needed. This could boost over all system performance. Signed-off-by: Li Yang <leoli@freescale.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r--arch/powerpc/sysdev/ipic.c113
-rw-r--r--arch/powerpc/sysdev/ipic.h6
2 files changed, 45 insertions, 74 deletions
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 7168b0349792..7274750fd9c6 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -30,11 +30,11 @@
30#include "ipic.h" 30#include "ipic.h"
31 31
32static struct ipic * primary_ipic; 32static struct ipic * primary_ipic;
33static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
33static DEFINE_SPINLOCK(ipic_lock); 34static DEFINE_SPINLOCK(ipic_lock);
34 35
35static struct ipic_info ipic_info[] = { 36static struct ipic_info ipic_info[] = {
36 [1] = { 37 [1] = {
37 .pend = IPIC_SIPNR_H,
38 .mask = IPIC_SIMSR_H, 38 .mask = IPIC_SIMSR_H,
39 .prio = IPIC_SIPRR_C, 39 .prio = IPIC_SIPRR_C,
40 .force = IPIC_SIFCR_H, 40 .force = IPIC_SIFCR_H,
@@ -42,7 +42,6 @@ static struct ipic_info ipic_info[] = {
42 .prio_mask = 0, 42 .prio_mask = 0,
43 }, 43 },
44 [2] = { 44 [2] = {
45 .pend = IPIC_SIPNR_H,
46 .mask = IPIC_SIMSR_H, 45 .mask = IPIC_SIMSR_H,
47 .prio = IPIC_SIPRR_C, 46 .prio = IPIC_SIPRR_C,
48 .force = IPIC_SIFCR_H, 47 .force = IPIC_SIFCR_H,
@@ -50,7 +49,6 @@ static struct ipic_info ipic_info[] = {
50 .prio_mask = 1, 49 .prio_mask = 1,
51 }, 50 },
52 [4] = { 51 [4] = {
53 .pend = IPIC_SIPNR_H,
54 .mask = IPIC_SIMSR_H, 52 .mask = IPIC_SIMSR_H,
55 .prio = IPIC_SIPRR_C, 53 .prio = IPIC_SIPRR_C,
56 .force = IPIC_SIFCR_H, 54 .force = IPIC_SIFCR_H,
@@ -58,7 +56,6 @@ static struct ipic_info ipic_info[] = {
58 .prio_mask = 3, 56 .prio_mask = 3,
59 }, 57 },
60 [9] = { 58 [9] = {
61 .pend = IPIC_SIPNR_H,
62 .mask = IPIC_SIMSR_H, 59 .mask = IPIC_SIMSR_H,
63 .prio = IPIC_SIPRR_D, 60 .prio = IPIC_SIPRR_D,
64 .force = IPIC_SIFCR_H, 61 .force = IPIC_SIFCR_H,
@@ -66,7 +63,6 @@ static struct ipic_info ipic_info[] = {
66 .prio_mask = 0, 63 .prio_mask = 0,
67 }, 64 },
68 [10] = { 65 [10] = {
69 .pend = IPIC_SIPNR_H,
70 .mask = IPIC_SIMSR_H, 66 .mask = IPIC_SIMSR_H,
71 .prio = IPIC_SIPRR_D, 67 .prio = IPIC_SIPRR_D,
72 .force = IPIC_SIFCR_H, 68 .force = IPIC_SIFCR_H,
@@ -74,7 +70,6 @@ static struct ipic_info ipic_info[] = {
74 .prio_mask = 1, 70 .prio_mask = 1,
75 }, 71 },
76 [11] = { 72 [11] = {
77 .pend = IPIC_SIPNR_H,
78 .mask = IPIC_SIMSR_H, 73 .mask = IPIC_SIMSR_H,
79 .prio = IPIC_SIPRR_D, 74 .prio = IPIC_SIPRR_D,
80 .force = IPIC_SIFCR_H, 75 .force = IPIC_SIFCR_H,
@@ -82,7 +77,6 @@ static struct ipic_info ipic_info[] = {
82 .prio_mask = 2, 77 .prio_mask = 2,
83 }, 78 },
84 [12] = { 79 [12] = {
85 .pend = IPIC_SIPNR_H,
86 .mask = IPIC_SIMSR_H, 80 .mask = IPIC_SIMSR_H,
87 .prio = IPIC_SIPRR_D, 81 .prio = IPIC_SIPRR_D,
88 .force = IPIC_SIFCR_H, 82 .force = IPIC_SIFCR_H,
@@ -90,7 +84,6 @@ static struct ipic_info ipic_info[] = {
90 .prio_mask = 3, 84 .prio_mask = 3,
91 }, 85 },
92 [13] = { 86 [13] = {
93 .pend = IPIC_SIPNR_H,
94 .mask = IPIC_SIMSR_H, 87 .mask = IPIC_SIMSR_H,
95 .prio = IPIC_SIPRR_D, 88 .prio = IPIC_SIPRR_D,
96 .force = IPIC_SIFCR_H, 89 .force = IPIC_SIFCR_H,
@@ -98,7 +91,6 @@ static struct ipic_info ipic_info[] = {
98 .prio_mask = 4, 91 .prio_mask = 4,
99 }, 92 },
100 [14] = { 93 [14] = {
101 .pend = IPIC_SIPNR_H,
102 .mask = IPIC_SIMSR_H, 94 .mask = IPIC_SIMSR_H,
103 .prio = IPIC_SIPRR_D, 95 .prio = IPIC_SIPRR_D,
104 .force = IPIC_SIFCR_H, 96 .force = IPIC_SIFCR_H,
@@ -106,7 +98,6 @@ static struct ipic_info ipic_info[] = {
106 .prio_mask = 5, 98 .prio_mask = 5,
107 }, 99 },
108 [15] = { 100 [15] = {
109 .pend = IPIC_SIPNR_H,
110 .mask = IPIC_SIMSR_H, 101 .mask = IPIC_SIMSR_H,
111 .prio = IPIC_SIPRR_D, 102 .prio = IPIC_SIPRR_D,
112 .force = IPIC_SIFCR_H, 103 .force = IPIC_SIFCR_H,
@@ -114,7 +105,6 @@ static struct ipic_info ipic_info[] = {
114 .prio_mask = 6, 105 .prio_mask = 6,
115 }, 106 },
116 [16] = { 107 [16] = {
117 .pend = IPIC_SIPNR_H,
118 .mask = IPIC_SIMSR_H, 108 .mask = IPIC_SIMSR_H,
119 .prio = IPIC_SIPRR_D, 109 .prio = IPIC_SIPRR_D,
120 .force = IPIC_SIFCR_H, 110 .force = IPIC_SIFCR_H,
@@ -122,7 +112,7 @@ static struct ipic_info ipic_info[] = {
122 .prio_mask = 7, 112 .prio_mask = 7,
123 }, 113 },
124 [17] = { 114 [17] = {
125 .pend = IPIC_SEPNR, 115 .ack = IPIC_SEPNR,
126 .mask = IPIC_SEMSR, 116 .mask = IPIC_SEMSR,
127 .prio = IPIC_SMPRR_A, 117 .prio = IPIC_SMPRR_A,
128 .force = IPIC_SEFCR, 118 .force = IPIC_SEFCR,
@@ -130,7 +120,7 @@ static struct ipic_info ipic_info[] = {
130 .prio_mask = 5, 120 .prio_mask = 5,
131 }, 121 },
132 [18] = { 122 [18] = {
133 .pend = IPIC_SEPNR, 123 .ack = IPIC_SEPNR,
134 .mask = IPIC_SEMSR, 124 .mask = IPIC_SEMSR,
135 .prio = IPIC_SMPRR_A, 125 .prio = IPIC_SMPRR_A,
136 .force = IPIC_SEFCR, 126 .force = IPIC_SEFCR,
@@ -138,7 +128,7 @@ static struct ipic_info ipic_info[] = {
138 .prio_mask = 6, 128 .prio_mask = 6,
139 }, 129 },
140 [19] = { 130 [19] = {
141 .pend = IPIC_SEPNR, 131 .ack = IPIC_SEPNR,
142 .mask = IPIC_SEMSR, 132 .mask = IPIC_SEMSR,
143 .prio = IPIC_SMPRR_A, 133 .prio = IPIC_SMPRR_A,
144 .force = IPIC_SEFCR, 134 .force = IPIC_SEFCR,
@@ -146,7 +136,7 @@ static struct ipic_info ipic_info[] = {
146 .prio_mask = 7, 136 .prio_mask = 7,
147 }, 137 },
148 [20] = { 138 [20] = {
149 .pend = IPIC_SEPNR, 139 .ack = IPIC_SEPNR,
150 .mask = IPIC_SEMSR, 140 .mask = IPIC_SEMSR,
151 .prio = IPIC_SMPRR_B, 141 .prio = IPIC_SMPRR_B,
152 .force = IPIC_SEFCR, 142 .force = IPIC_SEFCR,
@@ -154,7 +144,7 @@ static struct ipic_info ipic_info[] = {
154 .prio_mask = 4, 144 .prio_mask = 4,
155 }, 145 },
156 [21] = { 146 [21] = {
157 .pend = IPIC_SEPNR, 147 .ack = IPIC_SEPNR,
158 .mask = IPIC_SEMSR, 148 .mask = IPIC_SEMSR,
159 .prio = IPIC_SMPRR_B, 149 .prio = IPIC_SMPRR_B,
160 .force = IPIC_SEFCR, 150 .force = IPIC_SEFCR,
@@ -162,7 +152,7 @@ static struct ipic_info ipic_info[] = {
162 .prio_mask = 5, 152 .prio_mask = 5,
163 }, 153 },
164 [22] = { 154 [22] = {
165 .pend = IPIC_SEPNR, 155 .ack = IPIC_SEPNR,
166 .mask = IPIC_SEMSR, 156 .mask = IPIC_SEMSR,
167 .prio = IPIC_SMPRR_B, 157 .prio = IPIC_SMPRR_B,
168 .force = IPIC_SEFCR, 158 .force = IPIC_SEFCR,
@@ -170,7 +160,7 @@ static struct ipic_info ipic_info[] = {
170 .prio_mask = 6, 160 .prio_mask = 6,
171 }, 161 },
172 [23] = { 162 [23] = {
173 .pend = IPIC_SEPNR, 163 .ack = IPIC_SEPNR,
174 .mask = IPIC_SEMSR, 164 .mask = IPIC_SEMSR,
175 .prio = IPIC_SMPRR_B, 165 .prio = IPIC_SMPRR_B,
176 .force = IPIC_SEFCR, 166 .force = IPIC_SEFCR,
@@ -178,7 +168,6 @@ static struct ipic_info ipic_info[] = {
178 .prio_mask = 7, 168 .prio_mask = 7,
179 }, 169 },
180 [32] = { 170 [32] = {
181 .pend = IPIC_SIPNR_H,
182 .mask = IPIC_SIMSR_H, 171 .mask = IPIC_SIMSR_H,
183 .prio = IPIC_SIPRR_A, 172 .prio = IPIC_SIPRR_A,
184 .force = IPIC_SIFCR_H, 173 .force = IPIC_SIFCR_H,
@@ -186,7 +175,6 @@ static struct ipic_info ipic_info[] = {
186 .prio_mask = 0, 175 .prio_mask = 0,
187 }, 176 },
188 [33] = { 177 [33] = {
189 .pend = IPIC_SIPNR_H,
190 .mask = IPIC_SIMSR_H, 178 .mask = IPIC_SIMSR_H,
191 .prio = IPIC_SIPRR_A, 179 .prio = IPIC_SIPRR_A,
192 .force = IPIC_SIFCR_H, 180 .force = IPIC_SIFCR_H,
@@ -194,7 +182,6 @@ static struct ipic_info ipic_info[] = {
194 .prio_mask = 1, 182 .prio_mask = 1,
195 }, 183 },
196 [34] = { 184 [34] = {
197 .pend = IPIC_SIPNR_H,
198 .mask = IPIC_SIMSR_H, 185 .mask = IPIC_SIMSR_H,
199 .prio = IPIC_SIPRR_A, 186 .prio = IPIC_SIPRR_A,
200 .force = IPIC_SIFCR_H, 187 .force = IPIC_SIFCR_H,
@@ -202,7 +189,6 @@ static struct ipic_info ipic_info[] = {
202 .prio_mask = 2, 189 .prio_mask = 2,
203 }, 190 },
204 [35] = { 191 [35] = {
205 .pend = IPIC_SIPNR_H,
206 .mask = IPIC_SIMSR_H, 192 .mask = IPIC_SIMSR_H,
207 .prio = IPIC_SIPRR_A, 193 .prio = IPIC_SIPRR_A,
208 .force = IPIC_SIFCR_H, 194 .force = IPIC_SIFCR_H,
@@ -210,7 +196,6 @@ static struct ipic_info ipic_info[] = {
210 .prio_mask = 3, 196 .prio_mask = 3,
211 }, 197 },
212 [36] = { 198 [36] = {
213 .pend = IPIC_SIPNR_H,
214 .mask = IPIC_SIMSR_H, 199 .mask = IPIC_SIMSR_H,
215 .prio = IPIC_SIPRR_A, 200 .prio = IPIC_SIPRR_A,
216 .force = IPIC_SIFCR_H, 201 .force = IPIC_SIFCR_H,
@@ -218,7 +203,6 @@ static struct ipic_info ipic_info[] = {
218 .prio_mask = 4, 203 .prio_mask = 4,
219 }, 204 },
220 [37] = { 205 [37] = {
221 .pend = IPIC_SIPNR_H,
222 .mask = IPIC_SIMSR_H, 206 .mask = IPIC_SIMSR_H,
223 .prio = IPIC_SIPRR_A, 207 .prio = IPIC_SIPRR_A,
224 .force = IPIC_SIFCR_H, 208 .force = IPIC_SIFCR_H,
@@ -226,7 +210,6 @@ static struct ipic_info ipic_info[] = {
226 .prio_mask = 5, 210 .prio_mask = 5,
227 }, 211 },
228 [38] = { 212 [38] = {
229 .pend = IPIC_SIPNR_H,
230 .mask = IPIC_SIMSR_H, 213 .mask = IPIC_SIMSR_H,
231 .prio = IPIC_SIPRR_A, 214 .prio = IPIC_SIPRR_A,
232 .force = IPIC_SIFCR_H, 215 .force = IPIC_SIFCR_H,
@@ -234,7 +217,6 @@ static struct ipic_info ipic_info[] = {
234 .prio_mask = 6, 217 .prio_mask = 6,
235 }, 218 },
236 [39] = { 219 [39] = {
237 .pend = IPIC_SIPNR_H,
238 .mask = IPIC_SIMSR_H, 220 .mask = IPIC_SIMSR_H,
239 .prio = IPIC_SIPRR_A, 221 .prio = IPIC_SIPRR_A,
240 .force = IPIC_SIFCR_H, 222 .force = IPIC_SIFCR_H,
@@ -242,7 +224,6 @@ static struct ipic_info ipic_info[] = {
242 .prio_mask = 7, 224 .prio_mask = 7,
243 }, 225 },
244 [42] = { 226 [42] = {
245 .pend = IPIC_SIPNR_H,
246 .mask = IPIC_SIMSR_H, 227 .mask = IPIC_SIMSR_H,
247 .prio = IPIC_SIPRR_B, 228 .prio = IPIC_SIPRR_B,
248 .force = IPIC_SIFCR_H, 229 .force = IPIC_SIFCR_H,
@@ -250,7 +231,6 @@ static struct ipic_info ipic_info[] = {
250 .prio_mask = 2, 231 .prio_mask = 2,
251 }, 232 },
252 [44] = { 233 [44] = {
253 .pend = IPIC_SIPNR_H,
254 .mask = IPIC_SIMSR_H, 234 .mask = IPIC_SIMSR_H,
255 .prio = IPIC_SIPRR_B, 235 .prio = IPIC_SIPRR_B,
256 .force = IPIC_SIFCR_H, 236 .force = IPIC_SIFCR_H,
@@ -258,7 +238,6 @@ static struct ipic_info ipic_info[] = {
258 .prio_mask = 4, 238 .prio_mask = 4,
259 }, 239 },
260 [45] = { 240 [45] = {
261 .pend = IPIC_SIPNR_H,
262 .mask = IPIC_SIMSR_H, 241 .mask = IPIC_SIMSR_H,
263 .prio = IPIC_SIPRR_B, 242 .prio = IPIC_SIPRR_B,
264 .force = IPIC_SIFCR_H, 243 .force = IPIC_SIFCR_H,
@@ -266,7 +245,6 @@ static struct ipic_info ipic_info[] = {
266 .prio_mask = 5, 245 .prio_mask = 5,
267 }, 246 },
268 [46] = { 247 [46] = {
269 .pend = IPIC_SIPNR_H,
270 .mask = IPIC_SIMSR_H, 248 .mask = IPIC_SIMSR_H,
271 .prio = IPIC_SIPRR_B, 249 .prio = IPIC_SIPRR_B,
272 .force = IPIC_SIFCR_H, 250 .force = IPIC_SIFCR_H,
@@ -274,7 +252,6 @@ static struct ipic_info ipic_info[] = {
274 .prio_mask = 6, 252 .prio_mask = 6,
275 }, 253 },
276 [47] = { 254 [47] = {
277 .pend = IPIC_SIPNR_H,
278 .mask = IPIC_SIMSR_H, 255 .mask = IPIC_SIMSR_H,
279 .prio = IPIC_SIPRR_B, 256 .prio = IPIC_SIPRR_B,
280 .force = IPIC_SIFCR_H, 257 .force = IPIC_SIFCR_H,
@@ -282,7 +259,6 @@ static struct ipic_info ipic_info[] = {
282 .prio_mask = 7, 259 .prio_mask = 7,
283 }, 260 },
284 [48] = { 261 [48] = {
285 .pend = IPIC_SEPNR,
286 .mask = IPIC_SEMSR, 262 .mask = IPIC_SEMSR,
287 .prio = IPIC_SMPRR_A, 263 .prio = IPIC_SMPRR_A,
288 .force = IPIC_SEFCR, 264 .force = IPIC_SEFCR,
@@ -290,7 +266,6 @@ static struct ipic_info ipic_info[] = {
290 .prio_mask = 4, 266 .prio_mask = 4,
291 }, 267 },
292 [64] = { 268 [64] = {
293 .pend = IPIC_SIPNR_L,
294 .mask = IPIC_SIMSR_L, 269 .mask = IPIC_SIMSR_L,
295 .prio = IPIC_SMPRR_A, 270 .prio = IPIC_SMPRR_A,
296 .force = IPIC_SIFCR_L, 271 .force = IPIC_SIFCR_L,
@@ -298,7 +273,6 @@ static struct ipic_info ipic_info[] = {
298 .prio_mask = 0, 273 .prio_mask = 0,
299 }, 274 },
300 [65] = { 275 [65] = {
301 .pend = IPIC_SIPNR_L,
302 .mask = IPIC_SIMSR_L, 276 .mask = IPIC_SIMSR_L,
303 .prio = IPIC_SMPRR_A, 277 .prio = IPIC_SMPRR_A,
304 .force = IPIC_SIFCR_L, 278 .force = IPIC_SIFCR_L,
@@ -306,7 +280,6 @@ static struct ipic_info ipic_info[] = {
306 .prio_mask = 1, 280 .prio_mask = 1,
307 }, 281 },
308 [66] = { 282 [66] = {
309 .pend = IPIC_SIPNR_L,
310 .mask = IPIC_SIMSR_L, 283 .mask = IPIC_SIMSR_L,
311 .prio = IPIC_SMPRR_A, 284 .prio = IPIC_SMPRR_A,
312 .force = IPIC_SIFCR_L, 285 .force = IPIC_SIFCR_L,
@@ -314,7 +287,6 @@ static struct ipic_info ipic_info[] = {
314 .prio_mask = 2, 287 .prio_mask = 2,
315 }, 288 },
316 [67] = { 289 [67] = {
317 .pend = IPIC_SIPNR_L,
318 .mask = IPIC_SIMSR_L, 290 .mask = IPIC_SIMSR_L,
319 .prio = IPIC_SMPRR_A, 291 .prio = IPIC_SMPRR_A,
320 .force = IPIC_SIFCR_L, 292 .force = IPIC_SIFCR_L,
@@ -322,7 +294,6 @@ static struct ipic_info ipic_info[] = {
322 .prio_mask = 3, 294 .prio_mask = 3,
323 }, 295 },
324 [68] = { 296 [68] = {
325 .pend = IPIC_SIPNR_L,
326 .mask = IPIC_SIMSR_L, 297 .mask = IPIC_SIMSR_L,
327 .prio = IPIC_SMPRR_B, 298 .prio = IPIC_SMPRR_B,
328 .force = IPIC_SIFCR_L, 299 .force = IPIC_SIFCR_L,
@@ -330,7 +301,6 @@ static struct ipic_info ipic_info[] = {
330 .prio_mask = 0, 301 .prio_mask = 0,
331 }, 302 },
332 [69] = { 303 [69] = {
333 .pend = IPIC_SIPNR_L,
334 .mask = IPIC_SIMSR_L, 304 .mask = IPIC_SIMSR_L,
335 .prio = IPIC_SMPRR_B, 305 .prio = IPIC_SMPRR_B,
336 .force = IPIC_SIFCR_L, 306 .force = IPIC_SIFCR_L,
@@ -338,7 +308,6 @@ static struct ipic_info ipic_info[] = {
338 .prio_mask = 1, 308 .prio_mask = 1,
339 }, 309 },
340 [70] = { 310 [70] = {
341 .pend = IPIC_SIPNR_L,
342 .mask = IPIC_SIMSR_L, 311 .mask = IPIC_SIMSR_L,
343 .prio = IPIC_SMPRR_B, 312 .prio = IPIC_SMPRR_B,
344 .force = IPIC_SIFCR_L, 313 .force = IPIC_SIFCR_L,
@@ -346,7 +315,6 @@ static struct ipic_info ipic_info[] = {
346 .prio_mask = 2, 315 .prio_mask = 2,
347 }, 316 },
348 [71] = { 317 [71] = {
349 .pend = IPIC_SIPNR_L,
350 .mask = IPIC_SIMSR_L, 318 .mask = IPIC_SIMSR_L,
351 .prio = IPIC_SMPRR_B, 319 .prio = IPIC_SMPRR_B,
352 .force = IPIC_SIFCR_L, 320 .force = IPIC_SIFCR_L,
@@ -354,133 +322,114 @@ static struct ipic_info ipic_info[] = {
354 .prio_mask = 3, 322 .prio_mask = 3,
355 }, 323 },
356 [72] = { 324 [72] = {
357 .pend = IPIC_SIPNR_L,
358 .mask = IPIC_SIMSR_L, 325 .mask = IPIC_SIMSR_L,
359 .prio = 0, 326 .prio = 0,
360 .force = IPIC_SIFCR_L, 327 .force = IPIC_SIFCR_L,
361 .bit = 8, 328 .bit = 8,
362 }, 329 },
363 [73] = { 330 [73] = {
364 .pend = IPIC_SIPNR_L,
365 .mask = IPIC_SIMSR_L, 331 .mask = IPIC_SIMSR_L,
366 .prio = 0, 332 .prio = 0,
367 .force = IPIC_SIFCR_L, 333 .force = IPIC_SIFCR_L,
368 .bit = 9, 334 .bit = 9,
369 }, 335 },
370 [74] = { 336 [74] = {
371 .pend = IPIC_SIPNR_L,
372 .mask = IPIC_SIMSR_L, 337 .mask = IPIC_SIMSR_L,
373 .prio = 0, 338 .prio = 0,
374 .force = IPIC_SIFCR_L, 339 .force = IPIC_SIFCR_L,
375 .bit = 10, 340 .bit = 10,
376 }, 341 },
377 [75] = { 342 [75] = {
378 .pend = IPIC_SIPNR_L,
379 .mask = IPIC_SIMSR_L, 343 .mask = IPIC_SIMSR_L,
380 .prio = 0, 344 .prio = 0,
381 .force = IPIC_SIFCR_L, 345 .force = IPIC_SIFCR_L,
382 .bit = 11, 346 .bit = 11,
383 }, 347 },
384 [76] = { 348 [76] = {
385 .pend = IPIC_SIPNR_L,
386 .mask = IPIC_SIMSR_L, 349 .mask = IPIC_SIMSR_L,
387 .prio = 0, 350 .prio = 0,
388 .force = IPIC_SIFCR_L, 351 .force = IPIC_SIFCR_L,
389 .bit = 12, 352 .bit = 12,
390 }, 353 },
391 [77] = { 354 [77] = {
392 .pend = IPIC_SIPNR_L,
393 .mask = IPIC_SIMSR_L, 355 .mask = IPIC_SIMSR_L,
394 .prio = 0, 356 .prio = 0,
395 .force = IPIC_SIFCR_L, 357 .force = IPIC_SIFCR_L,
396 .bit = 13, 358 .bit = 13,
397 }, 359 },
398 [78] = { 360 [78] = {
399 .pend = IPIC_SIPNR_L,
400 .mask = IPIC_SIMSR_L, 361 .mask = IPIC_SIMSR_L,
401 .prio = 0, 362 .prio = 0,
402 .force = IPIC_SIFCR_L, 363 .force = IPIC_SIFCR_L,
403 .bit = 14, 364 .bit = 14,
404 }, 365 },
405 [79] = { 366 [79] = {
406 .pend = IPIC_SIPNR_L,
407 .mask = IPIC_SIMSR_L, 367 .mask = IPIC_SIMSR_L,
408 .prio = 0, 368 .prio = 0,
409 .force = IPIC_SIFCR_L, 369 .force = IPIC_SIFCR_L,
410 .bit = 15, 370 .bit = 15,
411 }, 371 },
412 [80] = { 372 [80] = {
413 .pend = IPIC_SIPNR_L,
414 .mask = IPIC_SIMSR_L, 373 .mask = IPIC_SIMSR_L,
415 .prio = 0, 374 .prio = 0,
416 .force = IPIC_SIFCR_L, 375 .force = IPIC_SIFCR_L,
417 .bit = 16, 376 .bit = 16,
418 }, 377 },
419 [81] = { 378 [81] = {
420 .pend = IPIC_SIPNR_L,
421 .mask = IPIC_SIMSR_L, 379 .mask = IPIC_SIMSR_L,
422 .prio = 0, 380 .prio = 0,
423 .force = IPIC_SIFCR_L, 381 .force = IPIC_SIFCR_L,
424 .bit = 17, 382 .bit = 17,
425 }, 383 },
426 [82] = { 384 [82] = {
427 .pend = IPIC_SIPNR_L,
428 .mask = IPIC_SIMSR_L, 385 .mask = IPIC_SIMSR_L,
429 .prio = 0, 386 .prio = 0,
430 .force = IPIC_SIFCR_L, 387 .force = IPIC_SIFCR_L,
431 .bit = 18, 388 .bit = 18,
432 }, 389 },
433 [84] = { 390 [84] = {
434 .pend = IPIC_SIPNR_L,
435 .mask = IPIC_SIMSR_L, 391 .mask = IPIC_SIMSR_L,
436 .prio = 0, 392 .prio = 0,
437 .force = IPIC_SIFCR_L, 393 .force = IPIC_SIFCR_L,
438 .bit = 20, 394 .bit = 20,
439 }, 395 },
440 [85] = { 396 [85] = {
441 .pend = IPIC_SIPNR_L,
442 .mask = IPIC_SIMSR_L, 397 .mask = IPIC_SIMSR_L,
443 .prio = 0, 398 .prio = 0,
444 .force = IPIC_SIFCR_L, 399 .force = IPIC_SIFCR_L,
445 .bit = 21, 400 .bit = 21,
446 }, 401 },
447 [86] = { 402 [86] = {
448 .pend = IPIC_SIPNR_L,
449 .mask = IPIC_SIMSR_L, 403 .mask = IPIC_SIMSR_L,
450 .prio = 0, 404 .prio = 0,
451 .force = IPIC_SIFCR_L, 405 .force = IPIC_SIFCR_L,
452 .bit = 22, 406 .bit = 22,
453 }, 407 },
454 [87] = { 408 [87] = {
455 .pend = IPIC_SIPNR_L,
456 .mask = IPIC_SIMSR_L, 409 .mask = IPIC_SIMSR_L,
457 .prio = 0, 410 .prio = 0,
458 .force = IPIC_SIFCR_L, 411 .force = IPIC_SIFCR_L,
459 .bit = 23, 412 .bit = 23,
460 }, 413 },
461 [88] = { 414 [88] = {
462 .pend = IPIC_SIPNR_L,
463 .mask = IPIC_SIMSR_L, 415 .mask = IPIC_SIMSR_L,
464 .prio = 0, 416 .prio = 0,
465 .force = IPIC_SIFCR_L, 417 .force = IPIC_SIFCR_L,
466 .bit = 24, 418 .bit = 24,
467 }, 419 },
468 [89] = { 420 [89] = {
469 .pend = IPIC_SIPNR_L,
470 .mask = IPIC_SIMSR_L, 421 .mask = IPIC_SIMSR_L,
471 .prio = 0, 422 .prio = 0,
472 .force = IPIC_SIFCR_L, 423 .force = IPIC_SIFCR_L,
473 .bit = 25, 424 .bit = 25,
474 }, 425 },
475 [90] = { 426 [90] = {
476 .pend = IPIC_SIPNR_L,
477 .mask = IPIC_SIMSR_L, 427 .mask = IPIC_SIMSR_L,
478 .prio = 0, 428 .prio = 0,
479 .force = IPIC_SIFCR_L, 429 .force = IPIC_SIFCR_L,
480 .bit = 26, 430 .bit = 26,
481 }, 431 },
482 [91] = { 432 [91] = {
483 .pend = IPIC_SIPNR_L,
484 .mask = IPIC_SIMSR_L, 433 .mask = IPIC_SIMSR_L,
485 .prio = 0, 434 .prio = 0,
486 .force = IPIC_SIFCR_L, 435 .force = IPIC_SIFCR_L,
@@ -534,6 +483,10 @@ static void ipic_mask_irq(unsigned int virq)
534 temp &= ~(1 << (31 - ipic_info[src].bit)); 483 temp &= ~(1 << (31 - ipic_info[src].bit));
535 ipic_write(ipic->regs, ipic_info[src].mask, temp); 484 ipic_write(ipic->regs, ipic_info[src].mask, temp);
536 485
486 /* mb() can't guarantee that masking is finished. But it does finish
487 * for nearly all cases. */
488 mb();
489
537 spin_unlock_irqrestore(&ipic_lock, flags); 490 spin_unlock_irqrestore(&ipic_lock, flags);
538} 491}
539 492
@@ -546,9 +499,13 @@ static void ipic_ack_irq(unsigned int virq)
546 499
547 spin_lock_irqsave(&ipic_lock, flags); 500 spin_lock_irqsave(&ipic_lock, flags);
548 501
549 temp = ipic_read(ipic->regs, ipic_info[src].pend); 502 temp = ipic_read(ipic->regs, ipic_info[src].ack);
550 temp |= (1 << (31 - ipic_info[src].bit)); 503 temp |= (1 << (31 - ipic_info[src].bit));
551 ipic_write(ipic->regs, ipic_info[src].pend, temp); 504 ipic_write(ipic->regs, ipic_info[src].ack, temp);
505
506 /* mb() can't guarantee that ack is finished. But it does finish
507 * for nearly all cases. */
508 mb();
552 509
553 spin_unlock_irqrestore(&ipic_lock, flags); 510 spin_unlock_irqrestore(&ipic_lock, flags);
554} 511}
@@ -566,9 +523,13 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
566 temp &= ~(1 << (31 - ipic_info[src].bit)); 523 temp &= ~(1 << (31 - ipic_info[src].bit));
567 ipic_write(ipic->regs, ipic_info[src].mask, temp); 524 ipic_write(ipic->regs, ipic_info[src].mask, temp);
568 525
569 temp = ipic_read(ipic->regs, ipic_info[src].pend); 526 temp = ipic_read(ipic->regs, ipic_info[src].ack);
570 temp |= (1 << (31 - ipic_info[src].bit)); 527 temp |= (1 << (31 - ipic_info[src].bit));
571 ipic_write(ipic->regs, ipic_info[src].pend, temp); 528 ipic_write(ipic->regs, ipic_info[src].ack, temp);
529
530 /* mb() can't guarantee that ack is finished. But it does finish
531 * for nearly all cases. */
532 mb();
572 533
573 spin_unlock_irqrestore(&ipic_lock, flags); 534 spin_unlock_irqrestore(&ipic_lock, flags);
574} 535}
@@ -590,14 +551,22 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
590 flow_type); 551 flow_type);
591 return -EINVAL; 552 return -EINVAL;
592 } 553 }
554 /* ipic supports only edge mode on external interrupts */
555 if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
556 printk(KERN_ERR "ipic: edge sense not supported on internal "
557 "interrupts\n");
558 return -EINVAL;
559 }
593 560
594 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 561 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
595 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 562 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
596 if (flow_type & IRQ_TYPE_LEVEL_LOW) { 563 if (flow_type & IRQ_TYPE_LEVEL_LOW) {
597 desc->status |= IRQ_LEVEL; 564 desc->status |= IRQ_LEVEL;
598 desc->handle_irq = handle_level_irq; 565 desc->handle_irq = handle_level_irq;
566 desc->chip = &ipic_level_irq_chip;
599 } else { 567 } else {
600 desc->handle_irq = handle_edge_irq; 568 desc->handle_irq = handle_edge_irq;
569 desc->chip = &ipic_edge_irq_chip;
601 } 570 }
602 571
603 /* only EXT IRQ senses are programmable on ipic 572 /* only EXT IRQ senses are programmable on ipic
@@ -622,7 +591,16 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
622 return 0; 591 return 0;
623} 592}
624 593
625static struct irq_chip ipic_irq_chip = { 594/* level interrupts and edge interrupts have different ack operations */
595static struct irq_chip ipic_level_irq_chip = {
596 .typename = " IPIC ",
597 .unmask = ipic_unmask_irq,
598 .mask = ipic_mask_irq,
599 .mask_ack = ipic_mask_irq,
600 .set_type = ipic_set_irq_type,
601};
602
603static struct irq_chip ipic_edge_irq_chip = {
626 .typename = " IPIC ", 604 .typename = " IPIC ",
627 .unmask = ipic_unmask_irq, 605 .unmask = ipic_unmask_irq,
628 .mask = ipic_mask_irq, 606 .mask = ipic_mask_irq,
@@ -641,13 +619,9 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq,
641 irq_hw_number_t hw) 619 irq_hw_number_t hw)
642{ 620{
643 struct ipic *ipic = h->host_data; 621 struct ipic *ipic = h->host_data;
644 struct irq_chip *chip;
645
646 /* Default chip */
647 chip = &ipic->hc_irq;
648 622
649 set_irq_chip_data(virq, ipic); 623 set_irq_chip_data(virq, ipic);
650 set_irq_chip_and_handler(virq, chip, handle_level_irq); 624 set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
651 625
652 /* Set default irq type */ 626 /* Set default irq type */
653 set_irq_type(virq, IRQ_TYPE_NONE); 627 set_irq_type(virq, IRQ_TYPE_NONE);
@@ -706,7 +680,6 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
706 ipic->regs = ioremap(res.start, res.end - res.start + 1); 680 ipic->regs = ioremap(res.start, res.end - res.start + 1);
707 681
708 ipic->irqhost->host_data = ipic; 682 ipic->irqhost->host_data = ipic;
709 ipic->hc_irq = ipic_irq_chip;
710 683
711 /* init hw */ 684 /* init hw */
712 ipic_write(ipic->regs, IPIC_SICNR, 0x0); 685 ipic_write(ipic->regs, IPIC_SICNR, 0x0);
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index 1158b8f5cb20..9391c57b0c51 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -44,13 +44,11 @@ struct ipic {
44 44
45 /* The remapper for this IPIC */ 45 /* The remapper for this IPIC */
46 struct irq_host *irqhost; 46 struct irq_host *irqhost;
47
48 /* The "linux" controller struct */
49 struct irq_chip hc_irq;
50}; 47};
51 48
52struct ipic_info { 49struct ipic_info {
53 u8 pend; /* pending register offset from base */ 50 u8 ack; /* pending register offset from base if the irq
51 supports ack operation */
54 u8 mask; /* mask register offset from base */ 52 u8 mask; /* mask register offset from base */
55 u8 prio; /* priority register offset from base */ 53 u8 prio; /* priority register offset from base */
56 u8 force; /* force register offset from base */ 54 u8 force; /* force register offset from base */