xref: /linux/arch/powerpc/sysdev/ipic.c (revision 185000fc556372b7fb7f26516c325f212030dbd3)
1 /*
2  * arch/powerpc/sysdev/ipic.c
3  *
4  * IPIC routines implementations.
5  *
6  * Copyright 2005 Freescale Semiconductor, Inc.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/reboot.h>
17 #include <linux/slab.h>
18 #include <linux/stddef.h>
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/sysdev.h>
22 #include <linux/device.h>
23 #include <linux/bootmem.h>
24 #include <linux/spinlock.h>
25 #include <asm/irq.h>
26 #include <asm/io.h>
27 #include <asm/prom.h>
28 #include <asm/ipic.h>
29 
30 #include "ipic.h"
31 
32 static struct ipic * primary_ipic;
33 static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
34 static DEFINE_SPINLOCK(ipic_lock);
35 
36 static struct ipic_info ipic_info[] = {
37 	[1] = {
38 		.mask	= IPIC_SIMSR_H,
39 		.prio	= IPIC_SIPRR_C,
40 		.force	= IPIC_SIFCR_H,
41 		.bit	= 16,
42 		.prio_mask = 0,
43 	},
44 	[2] = {
45 		.mask	= IPIC_SIMSR_H,
46 		.prio	= IPIC_SIPRR_C,
47 		.force	= IPIC_SIFCR_H,
48 		.bit	= 17,
49 		.prio_mask = 1,
50 	},
51 	[3] = {
52 		.mask	= IPIC_SIMSR_H,
53 		.prio	= IPIC_SIPRR_C,
54 		.force	= IPIC_SIFCR_H,
55 		.bit	= 18,
56 		.prio_mask = 2,
57 	},
58 	[4] = {
59 		.mask	= IPIC_SIMSR_H,
60 		.prio	= IPIC_SIPRR_C,
61 		.force	= IPIC_SIFCR_H,
62 		.bit	= 19,
63 		.prio_mask = 3,
64 	},
65 	[5] = {
66 		.mask	= IPIC_SIMSR_H,
67 		.prio	= IPIC_SIPRR_C,
68 		.force	= IPIC_SIFCR_H,
69 		.bit	= 20,
70 		.prio_mask = 4,
71 	},
72 	[6] = {
73 		.mask	= IPIC_SIMSR_H,
74 		.prio	= IPIC_SIPRR_C,
75 		.force	= IPIC_SIFCR_H,
76 		.bit	= 21,
77 		.prio_mask = 5,
78 	},
79 	[7] = {
80 		.mask	= IPIC_SIMSR_H,
81 		.prio	= IPIC_SIPRR_C,
82 		.force	= IPIC_SIFCR_H,
83 		.bit	= 22,
84 		.prio_mask = 6,
85 	},
86 	[8] = {
87 		.mask	= IPIC_SIMSR_H,
88 		.prio	= IPIC_SIPRR_C,
89 		.force	= IPIC_SIFCR_H,
90 		.bit	= 23,
91 		.prio_mask = 7,
92 	},
93 	[9] = {
94 		.mask	= IPIC_SIMSR_H,
95 		.prio	= IPIC_SIPRR_D,
96 		.force	= IPIC_SIFCR_H,
97 		.bit	= 24,
98 		.prio_mask = 0,
99 	},
100 	[10] = {
101 		.mask	= IPIC_SIMSR_H,
102 		.prio	= IPIC_SIPRR_D,
103 		.force	= IPIC_SIFCR_H,
104 		.bit	= 25,
105 		.prio_mask = 1,
106 	},
107 	[11] = {
108 		.mask	= IPIC_SIMSR_H,
109 		.prio	= IPIC_SIPRR_D,
110 		.force	= IPIC_SIFCR_H,
111 		.bit	= 26,
112 		.prio_mask = 2,
113 	},
114 	[12] = {
115 		.mask	= IPIC_SIMSR_H,
116 		.prio	= IPIC_SIPRR_D,
117 		.force	= IPIC_SIFCR_H,
118 		.bit	= 27,
119 		.prio_mask = 3,
120 	},
121 	[13] = {
122 		.mask	= IPIC_SIMSR_H,
123 		.prio	= IPIC_SIPRR_D,
124 		.force	= IPIC_SIFCR_H,
125 		.bit	= 28,
126 		.prio_mask = 4,
127 	},
128 	[14] = {
129 		.mask	= IPIC_SIMSR_H,
130 		.prio	= IPIC_SIPRR_D,
131 		.force	= IPIC_SIFCR_H,
132 		.bit	= 29,
133 		.prio_mask = 5,
134 	},
135 	[15] = {
136 		.mask	= IPIC_SIMSR_H,
137 		.prio	= IPIC_SIPRR_D,
138 		.force	= IPIC_SIFCR_H,
139 		.bit	= 30,
140 		.prio_mask = 6,
141 	},
142 	[16] = {
143 		.mask	= IPIC_SIMSR_H,
144 		.prio	= IPIC_SIPRR_D,
145 		.force	= IPIC_SIFCR_H,
146 		.bit	= 31,
147 		.prio_mask = 7,
148 	},
149 	[17] = {
150 		.ack	= IPIC_SEPNR,
151 		.mask	= IPIC_SEMSR,
152 		.prio	= IPIC_SMPRR_A,
153 		.force	= IPIC_SEFCR,
154 		.bit	= 1,
155 		.prio_mask = 5,
156 	},
157 	[18] = {
158 		.ack	= IPIC_SEPNR,
159 		.mask	= IPIC_SEMSR,
160 		.prio	= IPIC_SMPRR_A,
161 		.force	= IPIC_SEFCR,
162 		.bit	= 2,
163 		.prio_mask = 6,
164 	},
165 	[19] = {
166 		.ack	= IPIC_SEPNR,
167 		.mask	= IPIC_SEMSR,
168 		.prio	= IPIC_SMPRR_A,
169 		.force	= IPIC_SEFCR,
170 		.bit	= 3,
171 		.prio_mask = 7,
172 	},
173 	[20] = {
174 		.ack	= IPIC_SEPNR,
175 		.mask	= IPIC_SEMSR,
176 		.prio	= IPIC_SMPRR_B,
177 		.force	= IPIC_SEFCR,
178 		.bit	= 4,
179 		.prio_mask = 4,
180 	},
181 	[21] = {
182 		.ack	= IPIC_SEPNR,
183 		.mask	= IPIC_SEMSR,
184 		.prio	= IPIC_SMPRR_B,
185 		.force	= IPIC_SEFCR,
186 		.bit	= 5,
187 		.prio_mask = 5,
188 	},
189 	[22] = {
190 		.ack	= IPIC_SEPNR,
191 		.mask	= IPIC_SEMSR,
192 		.prio	= IPIC_SMPRR_B,
193 		.force	= IPIC_SEFCR,
194 		.bit	= 6,
195 		.prio_mask = 6,
196 	},
197 	[23] = {
198 		.ack	= IPIC_SEPNR,
199 		.mask	= IPIC_SEMSR,
200 		.prio	= IPIC_SMPRR_B,
201 		.force	= IPIC_SEFCR,
202 		.bit	= 7,
203 		.prio_mask = 7,
204 	},
205 	[32] = {
206 		.mask	= IPIC_SIMSR_H,
207 		.prio	= IPIC_SIPRR_A,
208 		.force	= IPIC_SIFCR_H,
209 		.bit	= 0,
210 		.prio_mask = 0,
211 	},
212 	[33] = {
213 		.mask	= IPIC_SIMSR_H,
214 		.prio	= IPIC_SIPRR_A,
215 		.force	= IPIC_SIFCR_H,
216 		.bit	= 1,
217 		.prio_mask = 1,
218 	},
219 	[34] = {
220 		.mask	= IPIC_SIMSR_H,
221 		.prio	= IPIC_SIPRR_A,
222 		.force	= IPIC_SIFCR_H,
223 		.bit	= 2,
224 		.prio_mask = 2,
225 	},
226 	[35] = {
227 		.mask	= IPIC_SIMSR_H,
228 		.prio	= IPIC_SIPRR_A,
229 		.force	= IPIC_SIFCR_H,
230 		.bit	= 3,
231 		.prio_mask = 3,
232 	},
233 	[36] = {
234 		.mask	= IPIC_SIMSR_H,
235 		.prio	= IPIC_SIPRR_A,
236 		.force	= IPIC_SIFCR_H,
237 		.bit	= 4,
238 		.prio_mask = 4,
239 	},
240 	[37] = {
241 		.mask	= IPIC_SIMSR_H,
242 		.prio	= IPIC_SIPRR_A,
243 		.force	= IPIC_SIFCR_H,
244 		.bit	= 5,
245 		.prio_mask = 5,
246 	},
247 	[38] = {
248 		.mask	= IPIC_SIMSR_H,
249 		.prio	= IPIC_SIPRR_A,
250 		.force	= IPIC_SIFCR_H,
251 		.bit	= 6,
252 		.prio_mask = 6,
253 	},
254 	[39] = {
255 		.mask	= IPIC_SIMSR_H,
256 		.prio	= IPIC_SIPRR_A,
257 		.force	= IPIC_SIFCR_H,
258 		.bit	= 7,
259 		.prio_mask = 7,
260 	},
261 	[40] = {
262 		.mask	= IPIC_SIMSR_H,
263 		.prio	= IPIC_SIPRR_B,
264 		.force	= IPIC_SIFCR_H,
265 		.bit	= 8,
266 		.prio_mask = 0,
267 	},
268 	[41] = {
269 		.mask	= IPIC_SIMSR_H,
270 		.prio	= IPIC_SIPRR_B,
271 		.force	= IPIC_SIFCR_H,
272 		.bit	= 9,
273 		.prio_mask = 1,
274 	},
275 	[42] = {
276 		.mask	= IPIC_SIMSR_H,
277 		.prio	= IPIC_SIPRR_B,
278 		.force	= IPIC_SIFCR_H,
279 		.bit	= 10,
280 		.prio_mask = 2,
281 	},
282 	[43] = {
283 		.mask	= IPIC_SIMSR_H,
284 		.prio	= IPIC_SIPRR_B,
285 		.force	= IPIC_SIFCR_H,
286 		.bit	= 11,
287 		.prio_mask = 3,
288 	},
289 	[44] = {
290 		.mask	= IPIC_SIMSR_H,
291 		.prio	= IPIC_SIPRR_B,
292 		.force	= IPIC_SIFCR_H,
293 		.bit	= 12,
294 		.prio_mask = 4,
295 	},
296 	[45] = {
297 		.mask	= IPIC_SIMSR_H,
298 		.prio	= IPIC_SIPRR_B,
299 		.force	= IPIC_SIFCR_H,
300 		.bit	= 13,
301 		.prio_mask = 5,
302 	},
303 	[46] = {
304 		.mask	= IPIC_SIMSR_H,
305 		.prio	= IPIC_SIPRR_B,
306 		.force	= IPIC_SIFCR_H,
307 		.bit	= 14,
308 		.prio_mask = 6,
309 	},
310 	[47] = {
311 		.mask	= IPIC_SIMSR_H,
312 		.prio	= IPIC_SIPRR_B,
313 		.force	= IPIC_SIFCR_H,
314 		.bit	= 15,
315 		.prio_mask = 7,
316 	},
317 	[48] = {
318 		.mask	= IPIC_SEMSR,
319 		.prio	= IPIC_SMPRR_A,
320 		.force	= IPIC_SEFCR,
321 		.bit	= 0,
322 		.prio_mask = 4,
323 	},
324 	[64] = {
325 		.mask	= IPIC_SIMSR_L,
326 		.prio	= IPIC_SMPRR_A,
327 		.force	= IPIC_SIFCR_L,
328 		.bit	= 0,
329 		.prio_mask = 0,
330 	},
331 	[65] = {
332 		.mask	= IPIC_SIMSR_L,
333 		.prio	= IPIC_SMPRR_A,
334 		.force	= IPIC_SIFCR_L,
335 		.bit	= 1,
336 		.prio_mask = 1,
337 	},
338 	[66] = {
339 		.mask	= IPIC_SIMSR_L,
340 		.prio	= IPIC_SMPRR_A,
341 		.force	= IPIC_SIFCR_L,
342 		.bit	= 2,
343 		.prio_mask = 2,
344 	},
345 	[67] = {
346 		.mask	= IPIC_SIMSR_L,
347 		.prio	= IPIC_SMPRR_A,
348 		.force	= IPIC_SIFCR_L,
349 		.bit	= 3,
350 		.prio_mask = 3,
351 	},
352 	[68] = {
353 		.mask	= IPIC_SIMSR_L,
354 		.prio	= IPIC_SMPRR_B,
355 		.force	= IPIC_SIFCR_L,
356 		.bit	= 4,
357 		.prio_mask = 0,
358 	},
359 	[69] = {
360 		.mask	= IPIC_SIMSR_L,
361 		.prio	= IPIC_SMPRR_B,
362 		.force	= IPIC_SIFCR_L,
363 		.bit	= 5,
364 		.prio_mask = 1,
365 	},
366 	[70] = {
367 		.mask	= IPIC_SIMSR_L,
368 		.prio	= IPIC_SMPRR_B,
369 		.force	= IPIC_SIFCR_L,
370 		.bit	= 6,
371 		.prio_mask = 2,
372 	},
373 	[71] = {
374 		.mask	= IPIC_SIMSR_L,
375 		.prio	= IPIC_SMPRR_B,
376 		.force	= IPIC_SIFCR_L,
377 		.bit	= 7,
378 		.prio_mask = 3,
379 	},
380 	[72] = {
381 		.mask	= IPIC_SIMSR_L,
382 		.prio	= 0,
383 		.force	= IPIC_SIFCR_L,
384 		.bit	= 8,
385 	},
386 	[73] = {
387 		.mask	= IPIC_SIMSR_L,
388 		.prio	= 0,
389 		.force	= IPIC_SIFCR_L,
390 		.bit	= 9,
391 	},
392 	[74] = {
393 		.mask	= IPIC_SIMSR_L,
394 		.prio	= 0,
395 		.force	= IPIC_SIFCR_L,
396 		.bit	= 10,
397 	},
398 	[75] = {
399 		.mask	= IPIC_SIMSR_L,
400 		.prio	= 0,
401 		.force	= IPIC_SIFCR_L,
402 		.bit	= 11,
403 	},
404 	[76] = {
405 		.mask	= IPIC_SIMSR_L,
406 		.prio	= 0,
407 		.force	= IPIC_SIFCR_L,
408 		.bit	= 12,
409 	},
410 	[77] = {
411 		.mask	= IPIC_SIMSR_L,
412 		.prio	= 0,
413 		.force	= IPIC_SIFCR_L,
414 		.bit	= 13,
415 	},
416 	[78] = {
417 		.mask	= IPIC_SIMSR_L,
418 		.prio	= 0,
419 		.force	= IPIC_SIFCR_L,
420 		.bit	= 14,
421 	},
422 	[79] = {
423 		.mask	= IPIC_SIMSR_L,
424 		.prio	= 0,
425 		.force	= IPIC_SIFCR_L,
426 		.bit	= 15,
427 	},
428 	[80] = {
429 		.mask	= IPIC_SIMSR_L,
430 		.prio	= 0,
431 		.force	= IPIC_SIFCR_L,
432 		.bit	= 16,
433 	},
434 	[81] = {
435 		.mask	= IPIC_SIMSR_L,
436 		.prio	= 0,
437 		.force	= IPIC_SIFCR_L,
438 		.bit	= 17,
439 	},
440 	[82] = {
441 		.mask	= IPIC_SIMSR_L,
442 		.prio	= 0,
443 		.force	= IPIC_SIFCR_L,
444 		.bit	= 18,
445 	},
446 	[83] = {
447 		.mask	= IPIC_SIMSR_L,
448 		.prio	= 0,
449 		.force	= IPIC_SIFCR_L,
450 		.bit	= 19,
451 	},
452 	[84] = {
453 		.mask	= IPIC_SIMSR_L,
454 		.prio	= 0,
455 		.force	= IPIC_SIFCR_L,
456 		.bit	= 20,
457 	},
458 	[85] = {
459 		.mask	= IPIC_SIMSR_L,
460 		.prio	= 0,
461 		.force	= IPIC_SIFCR_L,
462 		.bit	= 21,
463 	},
464 	[86] = {
465 		.mask	= IPIC_SIMSR_L,
466 		.prio	= 0,
467 		.force	= IPIC_SIFCR_L,
468 		.bit	= 22,
469 	},
470 	[87] = {
471 		.mask	= IPIC_SIMSR_L,
472 		.prio	= 0,
473 		.force	= IPIC_SIFCR_L,
474 		.bit	= 23,
475 	},
476 	[88] = {
477 		.mask	= IPIC_SIMSR_L,
478 		.prio	= 0,
479 		.force	= IPIC_SIFCR_L,
480 		.bit	= 24,
481 	},
482 	[89] = {
483 		.mask	= IPIC_SIMSR_L,
484 		.prio	= 0,
485 		.force	= IPIC_SIFCR_L,
486 		.bit	= 25,
487 	},
488 	[90] = {
489 		.mask	= IPIC_SIMSR_L,
490 		.prio	= 0,
491 		.force	= IPIC_SIFCR_L,
492 		.bit	= 26,
493 	},
494 	[91] = {
495 		.mask	= IPIC_SIMSR_L,
496 		.prio	= 0,
497 		.force	= IPIC_SIFCR_L,
498 		.bit	= 27,
499 	},
500 	[94] = {
501 		.mask	= IPIC_SIMSR_L,
502 		.prio	= 0,
503 		.force	= IPIC_SIFCR_L,
504 		.bit	= 30,
505 	},
506 };
507 
508 static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
509 {
510 	return in_be32(base + (reg >> 2));
511 }
512 
513 static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
514 {
515 	out_be32(base + (reg >> 2), value);
516 }
517 
518 static inline struct ipic * ipic_from_irq(unsigned int virq)
519 {
520 	return primary_ipic;
521 }
522 
523 #define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
524 
525 static void ipic_unmask_irq(unsigned int virq)
526 {
527 	struct ipic *ipic = ipic_from_irq(virq);
528 	unsigned int src = ipic_irq_to_hw(virq);
529 	unsigned long flags;
530 	u32 temp;
531 
532 	spin_lock_irqsave(&ipic_lock, flags);
533 
534 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
535 	temp |= (1 << (31 - ipic_info[src].bit));
536 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
537 
538 	spin_unlock_irqrestore(&ipic_lock, flags);
539 }
540 
541 static void ipic_mask_irq(unsigned int virq)
542 {
543 	struct ipic *ipic = ipic_from_irq(virq);
544 	unsigned int src = ipic_irq_to_hw(virq);
545 	unsigned long flags;
546 	u32 temp;
547 
548 	spin_lock_irqsave(&ipic_lock, flags);
549 
550 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
551 	temp &= ~(1 << (31 - ipic_info[src].bit));
552 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
553 
554 	/* mb() can't guarantee that masking is finished.  But it does finish
555 	 * for nearly all cases. */
556 	mb();
557 
558 	spin_unlock_irqrestore(&ipic_lock, flags);
559 }
560 
561 static void ipic_ack_irq(unsigned int virq)
562 {
563 	struct ipic *ipic = ipic_from_irq(virq);
564 	unsigned int src = ipic_irq_to_hw(virq);
565 	unsigned long flags;
566 	u32 temp;
567 
568 	spin_lock_irqsave(&ipic_lock, flags);
569 
570 	temp = ipic_read(ipic->regs, ipic_info[src].ack);
571 	temp |= (1 << (31 - ipic_info[src].bit));
572 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
573 
574 	/* mb() can't guarantee that ack is finished.  But it does finish
575 	 * for nearly all cases. */
576 	mb();
577 
578 	spin_unlock_irqrestore(&ipic_lock, flags);
579 }
580 
581 static void ipic_mask_irq_and_ack(unsigned int virq)
582 {
583 	struct ipic *ipic = ipic_from_irq(virq);
584 	unsigned int src = ipic_irq_to_hw(virq);
585 	unsigned long flags;
586 	u32 temp;
587 
588 	spin_lock_irqsave(&ipic_lock, flags);
589 
590 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
591 	temp &= ~(1 << (31 - ipic_info[src].bit));
592 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
593 
594 	temp = ipic_read(ipic->regs, ipic_info[src].ack);
595 	temp |= (1 << (31 - ipic_info[src].bit));
596 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
597 
598 	/* mb() can't guarantee that ack is finished.  But it does finish
599 	 * for nearly all cases. */
600 	mb();
601 
602 	spin_unlock_irqrestore(&ipic_lock, flags);
603 }
604 
605 static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
606 {
607 	struct ipic *ipic = ipic_from_irq(virq);
608 	unsigned int src = ipic_irq_to_hw(virq);
609 	struct irq_desc *desc = get_irq_desc(virq);
610 	unsigned int vold, vnew, edibit;
611 
612 	if (flow_type == IRQ_TYPE_NONE)
613 		flow_type = IRQ_TYPE_LEVEL_LOW;
614 
615 	/* ipic supports only low assertion and high-to-low change senses
616 	 */
617 	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
618 		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
619 			flow_type);
620 		return -EINVAL;
621 	}
622 	/* ipic supports only edge mode on external interrupts */
623 	if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
624 		printk(KERN_ERR "ipic: edge sense not supported on internal "
625 				"interrupts\n");
626 		return -EINVAL;
627 	}
628 
629 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
630 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
631 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
632 		desc->status |= IRQ_LEVEL;
633 		desc->handle_irq = handle_level_irq;
634 		desc->chip = &ipic_level_irq_chip;
635 	} else {
636 		desc->handle_irq = handle_edge_irq;
637 		desc->chip = &ipic_edge_irq_chip;
638 	}
639 
640 	/* only EXT IRQ senses are programmable on ipic
641 	 * internal IRQ senses are LEVEL_LOW
642 	 */
643 	if (src == IPIC_IRQ_EXT0)
644 		edibit = 15;
645 	else
646 		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
647 			edibit = (14 - (src - IPIC_IRQ_EXT1));
648 		else
649 			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
650 
651 	vold = ipic_read(ipic->regs, IPIC_SECNR);
652 	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
653 		vnew = vold | (1 << edibit);
654 	} else {
655 		vnew = vold & ~(1 << edibit);
656 	}
657 	if (vold != vnew)
658 		ipic_write(ipic->regs, IPIC_SECNR, vnew);
659 	return 0;
660 }
661 
662 /* level interrupts and edge interrupts have different ack operations */
663 static struct irq_chip ipic_level_irq_chip = {
664 	.typename	= " IPIC  ",
665 	.unmask		= ipic_unmask_irq,
666 	.mask		= ipic_mask_irq,
667 	.mask_ack	= ipic_mask_irq,
668 	.set_type	= ipic_set_irq_type,
669 };
670 
671 static struct irq_chip ipic_edge_irq_chip = {
672 	.typename	= " IPIC  ",
673 	.unmask		= ipic_unmask_irq,
674 	.mask		= ipic_mask_irq,
675 	.mask_ack	= ipic_mask_irq_and_ack,
676 	.ack		= ipic_ack_irq,
677 	.set_type	= ipic_set_irq_type,
678 };
679 
680 static int ipic_host_match(struct irq_host *h, struct device_node *node)
681 {
682 	/* Exact match, unless ipic node is NULL */
683 	return h->of_node == NULL || h->of_node == node;
684 }
685 
686 static int ipic_host_map(struct irq_host *h, unsigned int virq,
687 			 irq_hw_number_t hw)
688 {
689 	struct ipic *ipic = h->host_data;
690 
691 	set_irq_chip_data(virq, ipic);
692 	set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
693 
694 	/* Set default irq type */
695 	set_irq_type(virq, IRQ_TYPE_NONE);
696 
697 	return 0;
698 }
699 
700 static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
701 			   u32 *intspec, unsigned int intsize,
702 			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
703 
704 {
705 	/* interrupt sense values coming from the device tree equal either
706 	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
707 	 */
708 	*out_hwirq = intspec[0];
709 	if (intsize > 1)
710 		*out_flags = intspec[1];
711 	else
712 		*out_flags = IRQ_TYPE_NONE;
713 	return 0;
714 }
715 
716 static struct irq_host_ops ipic_host_ops = {
717 	.match	= ipic_host_match,
718 	.map	= ipic_host_map,
719 	.xlate	= ipic_host_xlate,
720 };
721 
722 struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
723 {
724 	struct ipic	*ipic;
725 	struct resource res;
726 	u32 temp = 0, ret;
727 
728 	ret = of_address_to_resource(node, 0, &res);
729 	if (ret)
730 		return NULL;
731 
732 	ipic = alloc_bootmem(sizeof(struct ipic));
733 	if (ipic == NULL)
734 		return NULL;
735 
736 	memset(ipic, 0, sizeof(struct ipic));
737 
738 	ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
739 				       NR_IPIC_INTS,
740 				       &ipic_host_ops, 0);
741 	if (ipic->irqhost == NULL)
742 		return NULL;
743 
744 	ipic->regs = ioremap(res.start, res.end - res.start + 1);
745 
746 	ipic->irqhost->host_data = ipic;
747 
748 	/* init hw */
749 	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
750 
751 	/* default priority scheme is grouped. If spread mode is required
752 	 * configure SICFR accordingly */
753 	if (flags & IPIC_SPREADMODE_GRP_A)
754 		temp |= SICFR_IPSA;
755 	if (flags & IPIC_SPREADMODE_GRP_B)
756 		temp |= SICFR_IPSB;
757 	if (flags & IPIC_SPREADMODE_GRP_C)
758 		temp |= SICFR_IPSC;
759 	if (flags & IPIC_SPREADMODE_GRP_D)
760 		temp |= SICFR_IPSD;
761 	if (flags & IPIC_SPREADMODE_MIX_A)
762 		temp |= SICFR_MPSA;
763 	if (flags & IPIC_SPREADMODE_MIX_B)
764 		temp |= SICFR_MPSB;
765 
766 	ipic_write(ipic->regs, IPIC_SICFR, temp);
767 
768 	/* handle MCP route */
769 	temp = 0;
770 	if (flags & IPIC_DISABLE_MCP_OUT)
771 		temp = SERCR_MCPR;
772 	ipic_write(ipic->regs, IPIC_SERCR, temp);
773 
774 	/* handle routing of IRQ0 to MCP */
775 	temp = ipic_read(ipic->regs, IPIC_SEMSR);
776 
777 	if (flags & IPIC_IRQ0_MCP)
778 		temp |= SEMSR_SIRQ0;
779 	else
780 		temp &= ~SEMSR_SIRQ0;
781 
782 	ipic_write(ipic->regs, IPIC_SEMSR, temp);
783 
784 	primary_ipic = ipic;
785 	irq_set_default_host(primary_ipic->irqhost);
786 
787 	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
788 			primary_ipic->regs);
789 
790 	return ipic;
791 }
792 
793 int ipic_set_priority(unsigned int virq, unsigned int priority)
794 {
795 	struct ipic *ipic = ipic_from_irq(virq);
796 	unsigned int src = ipic_irq_to_hw(virq);
797 	u32 temp;
798 
799 	if (priority > 7)
800 		return -EINVAL;
801 	if (src > 127)
802 		return -EINVAL;
803 	if (ipic_info[src].prio == 0)
804 		return -EINVAL;
805 
806 	temp = ipic_read(ipic->regs, ipic_info[src].prio);
807 
808 	if (priority < 4) {
809 		temp &= ~(0x7 << (20 + (3 - priority) * 3));
810 		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
811 	} else {
812 		temp &= ~(0x7 << (4 + (7 - priority) * 3));
813 		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
814 	}
815 
816 	ipic_write(ipic->regs, ipic_info[src].prio, temp);
817 
818 	return 0;
819 }
820 
821 void ipic_set_highest_priority(unsigned int virq)
822 {
823 	struct ipic *ipic = ipic_from_irq(virq);
824 	unsigned int src = ipic_irq_to_hw(virq);
825 	u32 temp;
826 
827 	temp = ipic_read(ipic->regs, IPIC_SICFR);
828 
829 	/* clear and set HPI */
830 	temp &= 0x7f000000;
831 	temp |= (src & 0x7f) << 24;
832 
833 	ipic_write(ipic->regs, IPIC_SICFR, temp);
834 }
835 
836 void ipic_set_default_priority(void)
837 {
838 	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
839 	ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
840 	ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
841 	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
842 	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
843 	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
844 }
845 
846 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
847 {
848 	struct ipic *ipic = primary_ipic;
849 	u32 temp;
850 
851 	temp = ipic_read(ipic->regs, IPIC_SERMR);
852 	temp |= (1 << (31 - mcp_irq));
853 	ipic_write(ipic->regs, IPIC_SERMR, temp);
854 }
855 
856 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
857 {
858 	struct ipic *ipic = primary_ipic;
859 	u32 temp;
860 
861 	temp = ipic_read(ipic->regs, IPIC_SERMR);
862 	temp &= (1 << (31 - mcp_irq));
863 	ipic_write(ipic->regs, IPIC_SERMR, temp);
864 }
865 
866 u32 ipic_get_mcp_status(void)
867 {
868 	return ipic_read(primary_ipic->regs, IPIC_SERMR);
869 }
870 
871 void ipic_clear_mcp_status(u32 mask)
872 {
873 	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
874 }
875 
876 /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
877 unsigned int ipic_get_irq(void)
878 {
879 	int irq;
880 
881 	BUG_ON(primary_ipic == NULL);
882 
883 #define IPIC_SIVCR_VECTOR_MASK	0x7f
884 	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
885 
886 	if (irq == 0)    /* 0 --> no irq is pending */
887 		return NO_IRQ;
888 
889 	return irq_linear_revmap(primary_ipic->irqhost, irq);
890 }
891 
892 static struct sysdev_class ipic_sysclass = {
893 	.name = "ipic",
894 };
895 
896 static struct sys_device device_ipic = {
897 	.id		= 0,
898 	.cls		= &ipic_sysclass,
899 };
900 
901 static int __init init_ipic_sysfs(void)
902 {
903 	int rc;
904 
905 	if (!primary_ipic || !primary_ipic->regs)
906 		return -ENODEV;
907 	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
908 
909 	rc = sysdev_class_register(&ipic_sysclass);
910 	if (rc) {
911 		printk(KERN_ERR "Failed registering ipic sys class\n");
912 		return -ENODEV;
913 	}
914 	rc = sysdev_register(&device_ipic);
915 	if (rc) {
916 		printk(KERN_ERR "Failed registering ipic sys device\n");
917 		return -ENODEV;
918 	}
919 	return 0;
920 }
921 
922 subsys_initcall(init_ipic_sysfs);
923