]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Handle interrupts from the SRM, assuming no additional weirdness. | |
3 | */ | |
4 | ||
5 | #include <linux/init.h> | |
6 | #include <linux/sched.h> | |
7 | #include <linux/irq.h> | |
8 | ||
9 | #include "proto.h" | |
10 | #include "irq_impl.h" | |
11 | ||
12 | ||
13 | /* | |
14 | * Is the palcode SMP safe? In other words: can we call cserve_ena/dis | |
15 | * at the same time in multiple CPUs? To be safe I added a spinlock | |
16 | * but it can be removed trivially if the palcode is robust against smp. | |
17 | */ | |
18 | DEFINE_SPINLOCK(srm_irq_lock); | |
19 | ||
20 | static inline void | |
21 | srm_enable_irq(unsigned int irq) | |
22 | { | |
23 | spin_lock(&srm_irq_lock); | |
24 | cserve_ena(irq - 16); | |
25 | spin_unlock(&srm_irq_lock); | |
26 | } | |
27 | ||
28 | static void | |
29 | srm_disable_irq(unsigned int irq) | |
30 | { | |
31 | spin_lock(&srm_irq_lock); | |
32 | cserve_dis(irq - 16); | |
33 | spin_unlock(&srm_irq_lock); | |
34 | } | |
35 | ||
36 | static unsigned int | |
37 | srm_startup_irq(unsigned int irq) | |
38 | { | |
39 | srm_enable_irq(irq); | |
40 | return 0; | |
41 | } | |
42 | ||
43 | static void | |
44 | srm_end_irq(unsigned int irq) | |
45 | { | |
46 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | |
47 | srm_enable_irq(irq); | |
48 | } | |
49 | ||
50 | /* Handle interrupts from the SRM, assuming no additional weirdness. */ | |
51 | static struct hw_interrupt_type srm_irq_type = { | |
52 | .typename = "SRM", | |
53 | .startup = srm_startup_irq, | |
54 | .shutdown = srm_disable_irq, | |
55 | .enable = srm_enable_irq, | |
56 | .disable = srm_disable_irq, | |
57 | .ack = srm_disable_irq, | |
58 | .end = srm_end_irq, | |
59 | }; | |
60 | ||
61 | void __init | |
62 | init_srm_irqs(long max, unsigned long ignore_mask) | |
63 | { | |
64 | long i; | |
65 | ||
66 | for (i = 16; i < max; ++i) { | |
67 | if (i < 64 && ((ignore_mask >> i) & 1)) | |
68 | continue; | |
69 | irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; | |
70 | irq_desc[i].handler = &srm_irq_type; | |
71 | } | |
72 | } | |
73 | ||
74 | void | |
75 | srm_device_interrupt(unsigned long vector, struct pt_regs * regs) | |
76 | { | |
77 | int irq = (vector - 0x800) >> 4; | |
78 | handle_irq(irq, regs); | |
79 | } |