diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha/kernel/irq_pyxis.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/alpha/kernel/irq_pyxis.c')
-rw-r--r-- | arch/alpha/kernel/irq_pyxis.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c new file mode 100644 index 000000000000..146a20b9e3d5 --- /dev/null +++ b/arch/alpha/kernel/irq_pyxis.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * linux/arch/alpha/kernel/irq_pyxis.c | ||
3 | * | ||
4 | * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). | ||
5 | * | ||
6 | * IRQ Code common to all PYXIS core logic chips. | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/irq.h> | ||
12 | |||
13 | #include <asm/io.h> | ||
14 | #include <asm/core_cia.h> | ||
15 | |||
16 | #include "proto.h" | ||
17 | #include "irq_impl.h" | ||
18 | |||
19 | |||
20 | /* Note mask bit is true for ENABLED irqs. */ | ||
21 | static unsigned long cached_irq_mask; | ||
22 | |||
23 | static inline void | ||
24 | pyxis_update_irq_hw(unsigned long mask) | ||
25 | { | ||
26 | *(vulp)PYXIS_INT_MASK = mask; | ||
27 | mb(); | ||
28 | *(vulp)PYXIS_INT_MASK; | ||
29 | } | ||
30 | |||
31 | static inline void | ||
32 | pyxis_enable_irq(unsigned int irq) | ||
33 | { | ||
34 | pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16)); | ||
35 | } | ||
36 | |||
37 | static void | ||
38 | pyxis_disable_irq(unsigned int irq) | ||
39 | { | ||
40 | pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16))); | ||
41 | } | ||
42 | |||
43 | static unsigned int | ||
44 | pyxis_startup_irq(unsigned int irq) | ||
45 | { | ||
46 | pyxis_enable_irq(irq); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static void | ||
51 | pyxis_end_irq(unsigned int irq) | ||
52 | { | ||
53 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
54 | pyxis_enable_irq(irq); | ||
55 | } | ||
56 | |||
57 | static void | ||
58 | pyxis_mask_and_ack_irq(unsigned int irq) | ||
59 | { | ||
60 | unsigned long bit = 1UL << (irq - 16); | ||
61 | unsigned long mask = cached_irq_mask &= ~bit; | ||
62 | |||
63 | /* Disable the interrupt. */ | ||
64 | *(vulp)PYXIS_INT_MASK = mask; | ||
65 | wmb(); | ||
66 | /* Ack PYXIS PCI interrupt. */ | ||
67 | *(vulp)PYXIS_INT_REQ = bit; | ||
68 | mb(); | ||
69 | /* Re-read to force both writes. */ | ||
70 | *(vulp)PYXIS_INT_MASK; | ||
71 | } | ||
72 | |||
73 | static struct hw_interrupt_type pyxis_irq_type = { | ||
74 | .typename = "PYXIS", | ||
75 | .startup = pyxis_startup_irq, | ||
76 | .shutdown = pyxis_disable_irq, | ||
77 | .enable = pyxis_enable_irq, | ||
78 | .disable = pyxis_disable_irq, | ||
79 | .ack = pyxis_mask_and_ack_irq, | ||
80 | .end = pyxis_end_irq, | ||
81 | }; | ||
82 | |||
83 | void | ||
84 | pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs) | ||
85 | { | ||
86 | unsigned long pld; | ||
87 | unsigned int i; | ||
88 | |||
89 | /* Read the interrupt summary register of PYXIS */ | ||
90 | pld = *(vulp)PYXIS_INT_REQ; | ||
91 | pld &= cached_irq_mask; | ||
92 | |||
93 | /* | ||
94 | * Now for every possible bit set, work through them and call | ||
95 | * the appropriate interrupt handler. | ||
96 | */ | ||
97 | while (pld) { | ||
98 | i = ffz(~pld); | ||
99 | pld &= pld - 1; /* clear least bit set */ | ||
100 | if (i == 7) | ||
101 | isa_device_interrupt(vector, regs); | ||
102 | else | ||
103 | handle_irq(16+i, regs); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | void __init | ||
108 | init_pyxis_irqs(unsigned long ignore_mask) | ||
109 | { | ||
110 | long i; | ||
111 | |||
112 | *(vulp)PYXIS_INT_MASK = 0; /* disable all */ | ||
113 | *(vulp)PYXIS_INT_REQ = -1; /* flush all */ | ||
114 | mb(); | ||
115 | |||
116 | /* Send -INTA pulses to clear any pending interrupts ...*/ | ||
117 | *(vuip) CIA_IACK_SC; | ||
118 | |||
119 | for (i = 16; i < 48; ++i) { | ||
120 | if ((ignore_mask >> i) & 1) | ||
121 | continue; | ||
122 | irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; | ||
123 | irq_desc[i].handler = &pyxis_irq_type; | ||
124 | } | ||
125 | |||
126 | setup_irq(16+7, &isa_cascade_irqaction); | ||
127 | } | ||