diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-11 21:04:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-11 21:04:51 -0500 |
commit | 8f042aa75afccc45c5b60517f51644bce3f52545 (patch) | |
tree | bfef56445b0f88e809586a38cb42b6ed4511a393 /arch | |
parent | e6f1227e8bc8a2ea2d76d09e19c89fa66c2f3a4c (diff) | |
parent | 2690e2148b730c53acb8797821468d0ea1673f25 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: (29 commits)
m68k/mac: Remove mac_irq_{en,dis}able() wrappers
m68k/irq: Remove obsolete support for user vector interrupt fixups
m68k/irq: Remove obsolete m68k irq framework
m68k/q40: Convert Q40/Q60 to genirq
m68k/sun3: Convert Sun3/3x to genirq
m68k/sun3: Use the kstat_irqs_cpu() wrapper
m68k/apollo: Convert Apollo to genirq
m68k/vme: Convert VME to genirq
m68k/hp300: Convert HP9000/300 and HP9000/400 to genirq
m68k/mac: Optimize interrupts using chain handlers
m68k/mac: Convert Mac to genirq
m68k/amiga: Optimize interrupts using chain handlers
m68k/amiga: Convert Amiga to genirq
m68k/amiga: Refactor amiints.c
m68k/atari: Remove code and comments about different irq types
m68k/atari: Convert Atari to genirq
m68k/irq: Add genirq support
m68k/irq: Remove obsolete IRQ_FLG_* users
m68k/irq: Rename {,__}m68k_handle_int()
m68k/irq: Add m68k_setup_irq_controller()
...
Diffstat (limited to 'arch')
-rw-r--r-- | arch/m68k/Kconfig | 4 | ||||
-rw-r--r-- | arch/m68k/Kconfig.bus | 9 | ||||
-rw-r--r-- | arch/m68k/Kconfig.devices | 31 | ||||
-rw-r--r-- | arch/m68k/amiga/amiints.c | 168 | ||||
-rw-r--r-- | arch/m68k/amiga/cia.c | 39 | ||||
-rw-r--r-- | arch/m68k/apollo/dn_ints.c | 35 | ||||
-rw-r--r-- | arch/m68k/atari/ataints.c | 274 | ||||
-rw-r--r-- | arch/m68k/bvme6000/config.c | 2 | ||||
-rw-r--r-- | arch/m68k/hp300/time.c | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/hardirq.h | 5 | ||||
-rw-r--r-- | arch/m68k/include/asm/irq.h | 69 | ||||
-rw-r--r-- | arch/m68k/include/asm/macintosh.h | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/q40ints.h | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/Makefile | 9 | ||||
-rw-r--r-- | arch/m68k/kernel/entry_mm.S | 7 | ||||
-rw-r--r-- | arch/m68k/kernel/ints.c | 323 | ||||
-rw-r--r-- | arch/m68k/mac/baboon.c | 21 | ||||
-rw-r--r-- | arch/m68k/mac/iop.c | 10 | ||||
-rw-r--r-- | arch/m68k/mac/macints.c | 24 | ||||
-rw-r--r-- | arch/m68k/mac/oss.c | 54 | ||||
-rw-r--r-- | arch/m68k/mac/psc.c | 49 | ||||
-rw-r--r-- | arch/m68k/mac/via.c | 74 | ||||
-rw-r--r-- | arch/m68k/mvme147/config.c | 5 | ||||
-rw-r--r-- | arch/m68k/mvme16x/config.c | 2 | ||||
-rw-r--r-- | arch/m68k/q40/q40ints.c | 60 | ||||
-rw-r--r-- | arch/m68k/sun3/sun3ints.c | 46 |
26 files changed, 390 insertions, 937 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6c28582fb98..361d54019bb 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -4,8 +4,8 @@ config M68K | |||
4 | select HAVE_IDE | 4 | select HAVE_IDE |
5 | select HAVE_AOUT if MMU | 5 | select HAVE_AOUT if MMU |
6 | select GENERIC_ATOMIC64 if MMU | 6 | select GENERIC_ATOMIC64 if MMU |
7 | select HAVE_GENERIC_HARDIRQS if !MMU | 7 | select HAVE_GENERIC_HARDIRQS |
8 | select GENERIC_IRQ_SHOW if !MMU | 8 | select GENERIC_IRQ_SHOW |
9 | select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS | 9 | select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS |
10 | 10 | ||
11 | config RWSEM_GENERIC_SPINLOCK | 11 | config RWSEM_GENERIC_SPINLOCK |
diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus index 8294f0c1785..3adb499584f 100644 --- a/arch/m68k/Kconfig.bus +++ b/arch/m68k/Kconfig.bus | |||
@@ -2,6 +2,15 @@ if MMU | |||
2 | 2 | ||
3 | comment "Bus Support" | 3 | comment "Bus Support" |
4 | 4 | ||
5 | config DIO | ||
6 | bool "DIO bus support" | ||
7 | depends on HP300 | ||
8 | default y | ||
9 | help | ||
10 | Say Y here to enable support for the "DIO" expansion bus used in | ||
11 | HP300 machines. If you are using such a system you almost certainly | ||
12 | want this. | ||
13 | |||
5 | config NUBUS | 14 | config NUBUS |
6 | bool | 15 | bool |
7 | depends on MAC | 16 | depends on MAC |
diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices index d214034be6a..6033f5d4e67 100644 --- a/arch/m68k/Kconfig.devices +++ b/arch/m68k/Kconfig.devices | |||
@@ -24,6 +24,37 @@ config PROC_HARDWARE | |||
24 | including the model, CPU, MMU, clock speed, BogoMIPS rating, | 24 | including the model, CPU, MMU, clock speed, BogoMIPS rating, |
25 | and memory size. | 25 | and memory size. |
26 | 26 | ||
27 | config NATFEAT | ||
28 | bool "ARAnyM emulator support" | ||
29 | depends on ATARI | ||
30 | help | ||
31 | This option enables support for ARAnyM native features, such as | ||
32 | access to a disk image as /dev/hda. | ||
33 | |||
34 | config NFBLOCK | ||
35 | tristate "NatFeat block device support" | ||
36 | depends on BLOCK && NATFEAT | ||
37 | help | ||
38 | Say Y to include support for the ARAnyM NatFeat block device | ||
39 | which allows direct access to the hard drives without using | ||
40 | the hardware emulation. | ||
41 | |||
42 | config NFCON | ||
43 | tristate "NatFeat console driver" | ||
44 | depends on NATFEAT | ||
45 | help | ||
46 | Say Y to include support for the ARAnyM NatFeat console driver | ||
47 | which allows the console output to be redirected to the stderr | ||
48 | output of ARAnyM. | ||
49 | |||
50 | config NFETH | ||
51 | tristate "NatFeat Ethernet support" | ||
52 | depends on ETHERNET && NATFEAT | ||
53 | help | ||
54 | Say Y to include support for the ARAnyM NatFeat network device | ||
55 | which will emulate a regular ethernet device while presenting an | ||
56 | ethertap device to the host system. | ||
57 | |||
27 | endmenu | 58 | endmenu |
28 | 59 | ||
29 | menu "Character devices" | 60 | menu "Character devices" |
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index c5b5212cc3f..47b5f90002a 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c | |||
@@ -1,43 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code | 2 | * Amiga Linux interrupt handling code |
3 | * | 3 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License. See the file COPYING in the main directory of this archive | 5 | * License. See the file COPYING in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | ||
8 | * 11/07/96: rewritten interrupt handling, irq lists are exists now only for | ||
9 | * this sources where it makes sense (VERTB/PORTS/EXTER) and you must | ||
10 | * be careful that dev_id for this sources is unique since this the | ||
11 | * only possibility to distinguish between different handlers for | ||
12 | * free_irq. irq lists also have different irq flags: | ||
13 | * - IRQ_FLG_FAST: handler is inserted at top of list (after other | ||
14 | * fast handlers) | ||
15 | * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before | ||
16 | * they're executed irq level is set to the previous | ||
17 | * one, but handlers don't need to be reentrant, if | ||
18 | * reentrance occurred, slow handlers will be just | ||
19 | * called again. | ||
20 | * The whole interrupt handling for CIAs is moved to cia.c | ||
21 | * /Roman Zippel | ||
22 | * | ||
23 | * 07/08/99: rewamp of the interrupt handling - we now have two types of | ||
24 | * interrupts, normal and fast handlers, fast handlers being | ||
25 | * marked with IRQF_DISABLED and runs with all other interrupts | ||
26 | * disabled. Normal interrupts disable their own source but | ||
27 | * run with all other interrupt sources enabled. | ||
28 | * PORTS and EXTER interrupts are always shared even if the | ||
29 | * drivers do not explicitly mark this when calling | ||
30 | * request_irq which they really should do. | ||
31 | * This is similar to the way interrupts are handled on all | ||
32 | * other architectures and makes a ton of sense besides | ||
33 | * having the advantage of making it easier to share | ||
34 | * drivers. | ||
35 | * /Jes | ||
36 | */ | 7 | */ |
37 | 8 | ||
38 | #include <linux/init.h> | 9 | #include <linux/init.h> |
39 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
40 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/irq.h> | ||
41 | 13 | ||
42 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
43 | #include <asm/traps.h> | 15 | #include <asm/traps.h> |
@@ -45,56 +17,6 @@ | |||
45 | #include <asm/amigaints.h> | 17 | #include <asm/amigaints.h> |
46 | #include <asm/amipcmcia.h> | 18 | #include <asm/amipcmcia.h> |
47 | 19 | ||
48 | static void amiga_enable_irq(unsigned int irq); | ||
49 | static void amiga_disable_irq(unsigned int irq); | ||
50 | static irqreturn_t ami_int1(int irq, void *dev_id); | ||
51 | static irqreturn_t ami_int3(int irq, void *dev_id); | ||
52 | static irqreturn_t ami_int4(int irq, void *dev_id); | ||
53 | static irqreturn_t ami_int5(int irq, void *dev_id); | ||
54 | |||
55 | static struct irq_controller amiga_irq_controller = { | ||
56 | .name = "amiga", | ||
57 | .lock = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock), | ||
58 | .enable = amiga_enable_irq, | ||
59 | .disable = amiga_disable_irq, | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * void amiga_init_IRQ(void) | ||
64 | * | ||
65 | * Parameters: None | ||
66 | * | ||
67 | * Returns: Nothing | ||
68 | * | ||
69 | * This function should be called during kernel startup to initialize | ||
70 | * the amiga IRQ handling routines. | ||
71 | */ | ||
72 | |||
73 | void __init amiga_init_IRQ(void) | ||
74 | { | ||
75 | if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL)) | ||
76 | pr_err("Couldn't register int%d\n", 1); | ||
77 | if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL)) | ||
78 | pr_err("Couldn't register int%d\n", 3); | ||
79 | if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL)) | ||
80 | pr_err("Couldn't register int%d\n", 4); | ||
81 | if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) | ||
82 | pr_err("Couldn't register int%d\n", 5); | ||
83 | |||
84 | m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS); | ||
85 | |||
86 | /* turn off PCMCIA interrupts */ | ||
87 | if (AMIGAHW_PRESENT(PCMCIA)) | ||
88 | gayle.inten = GAYLE_IRQ_IDE; | ||
89 | |||
90 | /* turn off all interrupts and enable the master interrupt bit */ | ||
91 | amiga_custom.intena = 0x7fff; | ||
92 | amiga_custom.intreq = 0x7fff; | ||
93 | amiga_custom.intena = IF_SETCLR | IF_INTEN; | ||
94 | |||
95 | cia_init_IRQ(&ciaa_base); | ||
96 | cia_init_IRQ(&ciab_base); | ||
97 | } | ||
98 | 20 | ||
99 | /* | 21 | /* |
100 | * Enable/disable a particular machine specific interrupt source. | 22 | * Enable/disable a particular machine specific interrupt source. |
@@ -103,112 +25,150 @@ void __init amiga_init_IRQ(void) | |||
103 | * internal data, that may not be changed by the interrupt at the same time. | 25 | * internal data, that may not be changed by the interrupt at the same time. |
104 | */ | 26 | */ |
105 | 27 | ||
106 | static void amiga_enable_irq(unsigned int irq) | 28 | static void amiga_irq_enable(struct irq_data *data) |
107 | { | 29 | { |
108 | amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER)); | 30 | amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER)); |
109 | } | 31 | } |
110 | 32 | ||
111 | static void amiga_disable_irq(unsigned int irq) | 33 | static void amiga_irq_disable(struct irq_data *data) |
112 | { | 34 | { |
113 | amiga_custom.intena = 1 << (irq - IRQ_USER); | 35 | amiga_custom.intena = 1 << (data->irq - IRQ_USER); |
114 | } | 36 | } |
115 | 37 | ||
38 | static struct irq_chip amiga_irq_chip = { | ||
39 | .name = "amiga", | ||
40 | .irq_enable = amiga_irq_enable, | ||
41 | .irq_disable = amiga_irq_disable, | ||
42 | }; | ||
43 | |||
44 | |||
116 | /* | 45 | /* |
117 | * The builtin Amiga hardware interrupt handlers. | 46 | * The builtin Amiga hardware interrupt handlers. |
118 | */ | 47 | */ |
119 | 48 | ||
120 | static irqreturn_t ami_int1(int irq, void *dev_id) | 49 | static void ami_int1(unsigned int irq, struct irq_desc *desc) |
121 | { | 50 | { |
122 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; | 51 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
123 | 52 | ||
124 | /* if serial transmit buffer empty, interrupt */ | 53 | /* if serial transmit buffer empty, interrupt */ |
125 | if (ints & IF_TBE) { | 54 | if (ints & IF_TBE) { |
126 | amiga_custom.intreq = IF_TBE; | 55 | amiga_custom.intreq = IF_TBE; |
127 | m68k_handle_int(IRQ_AMIGA_TBE); | 56 | generic_handle_irq(IRQ_AMIGA_TBE); |
128 | } | 57 | } |
129 | 58 | ||
130 | /* if floppy disk transfer complete, interrupt */ | 59 | /* if floppy disk transfer complete, interrupt */ |
131 | if (ints & IF_DSKBLK) { | 60 | if (ints & IF_DSKBLK) { |
132 | amiga_custom.intreq = IF_DSKBLK; | 61 | amiga_custom.intreq = IF_DSKBLK; |
133 | m68k_handle_int(IRQ_AMIGA_DSKBLK); | 62 | generic_handle_irq(IRQ_AMIGA_DSKBLK); |
134 | } | 63 | } |
135 | 64 | ||
136 | /* if software interrupt set, interrupt */ | 65 | /* if software interrupt set, interrupt */ |
137 | if (ints & IF_SOFT) { | 66 | if (ints & IF_SOFT) { |
138 | amiga_custom.intreq = IF_SOFT; | 67 | amiga_custom.intreq = IF_SOFT; |
139 | m68k_handle_int(IRQ_AMIGA_SOFT); | 68 | generic_handle_irq(IRQ_AMIGA_SOFT); |
140 | } | 69 | } |
141 | return IRQ_HANDLED; | ||
142 | } | 70 | } |
143 | 71 | ||
144 | static irqreturn_t ami_int3(int irq, void *dev_id) | 72 | static void ami_int3(unsigned int irq, struct irq_desc *desc) |
145 | { | 73 | { |
146 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; | 74 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
147 | 75 | ||
148 | /* if a blitter interrupt */ | 76 | /* if a blitter interrupt */ |
149 | if (ints & IF_BLIT) { | 77 | if (ints & IF_BLIT) { |
150 | amiga_custom.intreq = IF_BLIT; | 78 | amiga_custom.intreq = IF_BLIT; |
151 | m68k_handle_int(IRQ_AMIGA_BLIT); | 79 | generic_handle_irq(IRQ_AMIGA_BLIT); |
152 | } | 80 | } |
153 | 81 | ||
154 | /* if a copper interrupt */ | 82 | /* if a copper interrupt */ |
155 | if (ints & IF_COPER) { | 83 | if (ints & IF_COPER) { |
156 | amiga_custom.intreq = IF_COPER; | 84 | amiga_custom.intreq = IF_COPER; |
157 | m68k_handle_int(IRQ_AMIGA_COPPER); | 85 | generic_handle_irq(IRQ_AMIGA_COPPER); |
158 | } | 86 | } |
159 | 87 | ||
160 | /* if a vertical blank interrupt */ | 88 | /* if a vertical blank interrupt */ |
161 | if (ints & IF_VERTB) { | 89 | if (ints & IF_VERTB) { |
162 | amiga_custom.intreq = IF_VERTB; | 90 | amiga_custom.intreq = IF_VERTB; |
163 | m68k_handle_int(IRQ_AMIGA_VERTB); | 91 | generic_handle_irq(IRQ_AMIGA_VERTB); |
164 | } | 92 | } |
165 | return IRQ_HANDLED; | ||
166 | } | 93 | } |
167 | 94 | ||
168 | static irqreturn_t ami_int4(int irq, void *dev_id) | 95 | static void ami_int4(unsigned int irq, struct irq_desc *desc) |
169 | { | 96 | { |
170 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; | 97 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
171 | 98 | ||
172 | /* if audio 0 interrupt */ | 99 | /* if audio 0 interrupt */ |
173 | if (ints & IF_AUD0) { | 100 | if (ints & IF_AUD0) { |
174 | amiga_custom.intreq = IF_AUD0; | 101 | amiga_custom.intreq = IF_AUD0; |
175 | m68k_handle_int(IRQ_AMIGA_AUD0); | 102 | generic_handle_irq(IRQ_AMIGA_AUD0); |
176 | } | 103 | } |
177 | 104 | ||
178 | /* if audio 1 interrupt */ | 105 | /* if audio 1 interrupt */ |
179 | if (ints & IF_AUD1) { | 106 | if (ints & IF_AUD1) { |
180 | amiga_custom.intreq = IF_AUD1; | 107 | amiga_custom.intreq = IF_AUD1; |
181 | m68k_handle_int(IRQ_AMIGA_AUD1); | 108 | generic_handle_irq(IRQ_AMIGA_AUD1); |
182 | } | 109 | } |
183 | 110 | ||
184 | /* if audio 2 interrupt */ | 111 | /* if audio 2 interrupt */ |
185 | if (ints & IF_AUD2) { | 112 | if (ints & IF_AUD2) { |
186 | amiga_custom.intreq = IF_AUD2; | 113 | amiga_custom.intreq = IF_AUD2; |
187 | m68k_handle_int(IRQ_AMIGA_AUD2); | 114 | generic_handle_irq(IRQ_AMIGA_AUD2); |
188 | } | 115 | } |
189 | 116 | ||
190 | /* if audio 3 interrupt */ | 117 | /* if audio 3 interrupt */ |
191 | if (ints & IF_AUD3) { | 118 | if (ints & IF_AUD3) { |
192 | amiga_custom.intreq = IF_AUD3; | 119 | amiga_custom.intreq = IF_AUD3; |
193 | m68k_handle_int(IRQ_AMIGA_AUD3); | 120 | generic_handle_irq(IRQ_AMIGA_AUD3); |
194 | } | 121 | } |
195 | return IRQ_HANDLED; | ||
196 | } | 122 | } |
197 | 123 | ||
198 | static irqreturn_t ami_int5(int irq, void *dev_id) | 124 | static void ami_int5(unsigned int irq, struct irq_desc *desc) |
199 | { | 125 | { |
200 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; | 126 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
201 | 127 | ||
202 | /* if serial receive buffer full interrupt */ | 128 | /* if serial receive buffer full interrupt */ |
203 | if (ints & IF_RBF) { | 129 | if (ints & IF_RBF) { |
204 | /* acknowledge of IF_RBF must be done by the serial interrupt */ | 130 | /* acknowledge of IF_RBF must be done by the serial interrupt */ |
205 | m68k_handle_int(IRQ_AMIGA_RBF); | 131 | generic_handle_irq(IRQ_AMIGA_RBF); |
206 | } | 132 | } |
207 | 133 | ||
208 | /* if a disk sync interrupt */ | 134 | /* if a disk sync interrupt */ |
209 | if (ints & IF_DSKSYN) { | 135 | if (ints & IF_DSKSYN) { |
210 | amiga_custom.intreq = IF_DSKSYN; | 136 | amiga_custom.intreq = IF_DSKSYN; |
211 | m68k_handle_int(IRQ_AMIGA_DSKSYN); | 137 | generic_handle_irq(IRQ_AMIGA_DSKSYN); |
212 | } | 138 | } |
213 | return IRQ_HANDLED; | 139 | } |
140 | |||
141 | |||
142 | /* | ||
143 | * void amiga_init_IRQ(void) | ||
144 | * | ||
145 | * Parameters: None | ||
146 | * | ||
147 | * Returns: Nothing | ||
148 | * | ||
149 | * This function should be called during kernel startup to initialize | ||
150 | * the amiga IRQ handling routines. | ||
151 | */ | ||
152 | |||
153 | void __init amiga_init_IRQ(void) | ||
154 | { | ||
155 | m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, | ||
156 | AMI_STD_IRQS); | ||
157 | |||
158 | irq_set_chained_handler(IRQ_AUTO_1, ami_int1); | ||
159 | irq_set_chained_handler(IRQ_AUTO_3, ami_int3); | ||
160 | irq_set_chained_handler(IRQ_AUTO_4, ami_int4); | ||
161 | irq_set_chained_handler(IRQ_AUTO_5, ami_int5); | ||
162 | |||
163 | /* turn off PCMCIA interrupts */ | ||
164 | if (AMIGAHW_PRESENT(PCMCIA)) | ||
165 | gayle.inten = GAYLE_IRQ_IDE; | ||
166 | |||
167 | /* turn off all interrupts and enable the master interrupt bit */ | ||
168 | amiga_custom.intena = 0x7fff; | ||
169 | amiga_custom.intreq = 0x7fff; | ||
170 | amiga_custom.intena = IF_SETCLR | IF_INTEN; | ||
171 | |||
172 | cia_init_IRQ(&ciaa_base); | ||
173 | cia_init_IRQ(&ciab_base); | ||
214 | } | 174 | } |
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index ecd0f7ca6f0..18c0e29976e 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c | |||
@@ -93,13 +93,14 @@ static irqreturn_t cia_handler(int irq, void *dev_id) | |||
93 | amiga_custom.intreq = base->int_mask; | 93 | amiga_custom.intreq = base->int_mask; |
94 | for (; ints; mach_irq++, ints >>= 1) { | 94 | for (; ints; mach_irq++, ints >>= 1) { |
95 | if (ints & 1) | 95 | if (ints & 1) |
96 | m68k_handle_int(mach_irq); | 96 | generic_handle_irq(mach_irq); |
97 | } | 97 | } |
98 | return IRQ_HANDLED; | 98 | return IRQ_HANDLED; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void cia_enable_irq(unsigned int irq) | 101 | static void cia_irq_enable(struct irq_data *data) |
102 | { | 102 | { |
103 | unsigned int irq = data->irq; | ||
103 | unsigned char mask; | 104 | unsigned char mask; |
104 | 105 | ||
105 | if (irq >= IRQ_AMIGA_CIAB) { | 106 | if (irq >= IRQ_AMIGA_CIAB) { |
@@ -113,19 +114,20 @@ static void cia_enable_irq(unsigned int irq) | |||
113 | } | 114 | } |
114 | } | 115 | } |
115 | 116 | ||
116 | static void cia_disable_irq(unsigned int irq) | 117 | static void cia_irq_disable(struct irq_data *data) |
117 | { | 118 | { |
119 | unsigned int irq = data->irq; | ||
120 | |||
118 | if (irq >= IRQ_AMIGA_CIAB) | 121 | if (irq >= IRQ_AMIGA_CIAB) |
119 | cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); | 122 | cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); |
120 | else | 123 | else |
121 | cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); | 124 | cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); |
122 | } | 125 | } |
123 | 126 | ||
124 | static struct irq_controller cia_irq_controller = { | 127 | static struct irq_chip cia_irq_chip = { |
125 | .name = "cia", | 128 | .name = "cia", |
126 | .lock = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock), | 129 | .irq_enable = cia_irq_enable, |
127 | .enable = cia_enable_irq, | 130 | .irq_disable = cia_irq_disable, |
128 | .disable = cia_disable_irq, | ||
129 | }; | 131 | }; |
130 | 132 | ||
131 | /* | 133 | /* |
@@ -134,9 +136,9 @@ static struct irq_controller cia_irq_controller = { | |||
134 | * into this chain. | 136 | * into this chain. |
135 | */ | 137 | */ |
136 | 138 | ||
137 | static void auto_enable_irq(unsigned int irq) | 139 | static void auto_irq_enable(struct irq_data *data) |
138 | { | 140 | { |
139 | switch (irq) { | 141 | switch (data->irq) { |
140 | case IRQ_AUTO_2: | 142 | case IRQ_AUTO_2: |
141 | amiga_custom.intena = IF_SETCLR | IF_PORTS; | 143 | amiga_custom.intena = IF_SETCLR | IF_PORTS; |
142 | break; | 144 | break; |
@@ -146,9 +148,9 @@ static void auto_enable_irq(unsigned int irq) | |||
146 | } | 148 | } |
147 | } | 149 | } |
148 | 150 | ||
149 | static void auto_disable_irq(unsigned int irq) | 151 | static void auto_irq_disable(struct irq_data *data) |
150 | { | 152 | { |
151 | switch (irq) { | 153 | switch (data->irq) { |
152 | case IRQ_AUTO_2: | 154 | case IRQ_AUTO_2: |
153 | amiga_custom.intena = IF_PORTS; | 155 | amiga_custom.intena = IF_PORTS; |
154 | break; | 156 | break; |
@@ -158,24 +160,25 @@ static void auto_disable_irq(unsigned int irq) | |||
158 | } | 160 | } |
159 | } | 161 | } |
160 | 162 | ||
161 | static struct irq_controller auto_irq_controller = { | 163 | static struct irq_chip auto_irq_chip = { |
162 | .name = "auto", | 164 | .name = "auto", |
163 | .lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock), | 165 | .irq_enable = auto_irq_enable, |
164 | .enable = auto_enable_irq, | 166 | .irq_disable = auto_irq_disable, |
165 | .disable = auto_disable_irq, | ||
166 | }; | 167 | }; |
167 | 168 | ||
168 | void __init cia_init_IRQ(struct ciabase *base) | 169 | void __init cia_init_IRQ(struct ciabase *base) |
169 | { | 170 | { |
170 | m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS); | 171 | m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq, |
172 | base->cia_irq, CIA_IRQS); | ||
171 | 173 | ||
172 | /* clear any pending interrupt and turn off all interrupts */ | 174 | /* clear any pending interrupt and turn off all interrupts */ |
173 | cia_set_irq(base, CIA_ICR_ALL); | 175 | cia_set_irq(base, CIA_ICR_ALL); |
174 | cia_able_irq(base, CIA_ICR_ALL); | 176 | cia_able_irq(base, CIA_ICR_ALL); |
175 | 177 | ||
176 | /* override auto int and install CIA handler */ | 178 | /* override auto int and install CIA handler */ |
177 | m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); | 179 | m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq, |
178 | m68k_irq_startup(base->handler_irq); | 180 | base->handler_irq, 1); |
181 | m68k_irq_startup_irq(base->handler_irq); | ||
179 | if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED, | 182 | if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED, |
180 | base->name, base)) | 183 | base->name, base)) |
181 | pr_err("Couldn't register %s interrupt\n", base->name); | 184 | pr_err("Couldn't register %s interrupt\n", base->name); |
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index 5d47f3aa381..17be1e7e2df 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c | |||
@@ -1,19 +1,13 @@ | |||
1 | #include <linux/interrupt.h> | 1 | #include <linux/interrupt.h> |
2 | #include <linux/irq.h> | ||
2 | 3 | ||
3 | #include <asm/irq.h> | ||
4 | #include <asm/traps.h> | 4 | #include <asm/traps.h> |
5 | #include <asm/apollohw.h> | 5 | #include <asm/apollohw.h> |
6 | 6 | ||
7 | void dn_process_int(unsigned int irq, struct pt_regs *fp) | 7 | unsigned int apollo_irq_startup(struct irq_data *data) |
8 | { | 8 | { |
9 | __m68k_handle_int(irq, fp); | 9 | unsigned int irq = data->irq; |
10 | 10 | ||
11 | *(volatile unsigned char *)(pica)=0x20; | ||
12 | *(volatile unsigned char *)(picb)=0x20; | ||
13 | } | ||
14 | |||
15 | int apollo_irq_startup(unsigned int irq) | ||
16 | { | ||
17 | if (irq < 8) | 11 | if (irq < 8) |
18 | *(volatile unsigned char *)(pica+1) &= ~(1 << irq); | 12 | *(volatile unsigned char *)(pica+1) &= ~(1 << irq); |
19 | else | 13 | else |
@@ -21,24 +15,33 @@ int apollo_irq_startup(unsigned int irq) | |||
21 | return 0; | 15 | return 0; |
22 | } | 16 | } |
23 | 17 | ||
24 | void apollo_irq_shutdown(unsigned int irq) | 18 | void apollo_irq_shutdown(struct irq_data *data) |
25 | { | 19 | { |
20 | unsigned int irq = data->irq; | ||
21 | |||
26 | if (irq < 8) | 22 | if (irq < 8) |
27 | *(volatile unsigned char *)(pica+1) |= (1 << irq); | 23 | *(volatile unsigned char *)(pica+1) |= (1 << irq); |
28 | else | 24 | else |
29 | *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8)); | 25 | *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8)); |
30 | } | 26 | } |
31 | 27 | ||
32 | static struct irq_controller apollo_irq_controller = { | 28 | void apollo_irq_eoi(struct irq_data *data) |
29 | { | ||
30 | *(volatile unsigned char *)(pica) = 0x20; | ||
31 | *(volatile unsigned char *)(picb) = 0x20; | ||
32 | } | ||
33 | |||
34 | static struct irq_chip apollo_irq_chip = { | ||
33 | .name = "apollo", | 35 | .name = "apollo", |
34 | .lock = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock), | 36 | .irq_startup = apollo_irq_startup, |
35 | .startup = apollo_irq_startup, | 37 | .irq_shutdown = apollo_irq_shutdown, |
36 | .shutdown = apollo_irq_shutdown, | 38 | .irq_eoi = apollo_irq_eoi, |
37 | }; | 39 | }; |
38 | 40 | ||
39 | 41 | ||
40 | void __init dn_init_IRQ(void) | 42 | void __init dn_init_IRQ(void) |
41 | { | 43 | { |
42 | m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int); | 44 | m68k_setup_user_interrupt(VEC_USER + 96, 16); |
43 | m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16); | 45 | m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq, |
46 | IRQ_APOLLO, 16); | ||
44 | } | 47 | } |
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 26a804e67bc..6d196dadfdb 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c | |||
@@ -60,243 +60,7 @@ | |||
60 | * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP, | 60 | * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP, |
61 | * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can | 61 | * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can |
62 | * be allocated by atari_register_vme_int(). | 62 | * be allocated by atari_register_vme_int(). |
63 | * | ||
64 | * Each interrupt can be of three types: | ||
65 | * | ||
66 | * - SLOW: The handler runs with all interrupts enabled, except the one it | ||
67 | * was called by (to avoid reentering). This should be the usual method. | ||
68 | * But it is currently possible only for MFP ints, since only the MFP | ||
69 | * offers an easy way to mask interrupts. | ||
70 | * | ||
71 | * - FAST: The handler runs with all interrupts disabled. This should be used | ||
72 | * only for really fast handlers, that just do actions immediately | ||
73 | * necessary, and let the rest do a bottom half or task queue. | ||
74 | * | ||
75 | * - PRIORITIZED: The handler can be interrupted by higher-level ints | ||
76 | * (greater IPL, no MFP priorities!). This is the method of choice for ints | ||
77 | * which should be slow, but are not from a MFP. | ||
78 | * | ||
79 | * The feature of more than one handler for one int source is still there, but | ||
80 | * only applicable if all handers are of the same type. To not slow down | ||
81 | * processing of ints with only one handler by the chaining feature, the list | ||
82 | * calling function atari_call_irq_list() is only plugged in at the time the | ||
83 | * second handler is registered. | ||
84 | * | ||
85 | * Implementation notes: For fast-as-possible int handling, there are separate | ||
86 | * entry points for each type (slow/fast/prio). The assembler handler calls | ||
87 | * the irq directly in the usual case, no C wrapper is involved. In case of | ||
88 | * multiple handlers, atari_call_irq_list() is registered as handler and calls | ||
89 | * in turn the real irq's. To ease access from assembler level to the irq | ||
90 | * function pointer and accompanying data, these two are stored in a separate | ||
91 | * array, irq_handler[]. The rest of data (type, name) are put into a second | ||
92 | * array, irq_param, that is accessed from C only. For each slow interrupt (32 | ||
93 | * in all) there are separate handler functions, which makes it possible to | ||
94 | * hard-code the MFP register address and value, are necessary to mask the | ||
95 | * int. If there'd be only one generic function, lots of calculations would be | ||
96 | * needed to determine MFP register and int mask from the vector number :-( | ||
97 | * | ||
98 | * Furthermore, slow ints may not lower the IPL below its previous value | ||
99 | * (before the int happened). This is needed so that an int of class PRIO, on | ||
100 | * that this int may be stacked, cannot be reentered. This feature is | ||
101 | * implemented as follows: If the stack frame format is 1 (throwaway), the int | ||
102 | * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level | ||
103 | * 2, which still blocks the HSYNC, but no interrupts of interest. If the | ||
104 | * frame format is 0, the int is nested, and the old IPL value can be found in | ||
105 | * the sr copy in the frame. | ||
106 | */ | ||
107 | |||
108 | #if 0 | ||
109 | |||
110 | #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) | ||
111 | |||
112 | typedef void (*asm_irq_handler)(void); | ||
113 | |||
114 | struct irqhandler { | ||
115 | irqreturn_t (*handler)(int, void *, struct pt_regs *); | ||
116 | void *dev_id; | ||
117 | }; | ||
118 | |||
119 | struct irqparam { | ||
120 | unsigned long flags; | ||
121 | const char *devname; | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * Array with irq's and their parameter data. This array is accessed from low | ||
126 | * level assembler code, so an element size of 8 allows usage of index scaling | ||
127 | * addressing mode. | ||
128 | */ | 63 | */ |
129 | static struct irqhandler irq_handler[NUM_INT_SOURCES]; | ||
130 | |||
131 | /* | ||
132 | * This array hold the rest of parameters of int handlers: type | ||
133 | * (slow,fast,prio) and the name of the handler. These values are only | ||
134 | * accessed from C | ||
135 | */ | ||
136 | static struct irqparam irq_param[NUM_INT_SOURCES]; | ||
137 | |||
138 | /* check for valid int number (complex, sigh...) */ | ||
139 | #define IS_VALID_INTNO(n) \ | ||
140 | ((n) > 0 && \ | ||
141 | /* autovec and ST-MFP ok anyway */ \ | ||
142 | (((n) < TTMFP_SOURCE_BASE) || \ | ||
143 | /* TT-MFP ok if present */ \ | ||
144 | ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \ | ||
145 | ATARIHW_PRESENT(TT_MFP)) || \ | ||
146 | /* SCC ok if present and number even */ \ | ||
147 | ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \ | ||
148 | !((n) & 1) && ATARIHW_PRESENT(SCC)) || \ | ||
149 | /* greater numbers ok if they are registered VME vectors */ \ | ||
150 | ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \ | ||
151 | free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE))))) | ||
152 | |||
153 | |||
154 | /* | ||
155 | * Here start the assembler entry points for interrupts | ||
156 | */ | ||
157 | |||
158 | #define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void) | ||
159 | |||
160 | #define BUILD_SLOW_IRQ(n) \ | ||
161 | asmlinkage void IRQ_NAME(n); \ | ||
162 | /* Dummy function to allow asm with operands. */ \ | ||
163 | void atari_slow_irq_##n##_dummy (void) { \ | ||
164 | __asm__ (__ALIGN_STR "\n" \ | ||
165 | "atari_slow_irq_" #n "_handler:\t" \ | ||
166 | " addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \ | ||
167 | SAVE_ALL_INT "\n" \ | ||
168 | GET_CURRENT(%%d0) "\n" \ | ||
169 | " andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ | ||
170 | /* get old IPL from stack frame */ \ | ||
171 | " bfextu %%sp@(%c2){#5,#3},%%d0\n" \ | ||
172 | " movew %%sr,%%d1\n" \ | ||
173 | " bfins %%d0,%%d1{#21,#3}\n" \ | ||
174 | " movew %%d1,%%sr\n" /* set IPL = previous value */ \ | ||
175 | " addql #1,%a0\n" \ | ||
176 | " lea %a1,%%a0\n" \ | ||
177 | " pea %%sp@\n" /* push addr of frame */ \ | ||
178 | " movel %%a0@(4),%%sp@-\n" /* push handler data */ \ | ||
179 | " pea (%c3+8)\n" /* push int number */ \ | ||
180 | " movel %%a0@,%%a0\n" \ | ||
181 | " jbsr %%a0@\n" /* call the handler */ \ | ||
182 | " addql #8,%%sp\n" \ | ||
183 | " addql #4,%%sp\n" \ | ||
184 | " orw #0x0600,%%sr\n" \ | ||
185 | " andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \ | ||
186 | " orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \ | ||
187 | " jbra ret_from_interrupt\n" \ | ||
188 | : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \ | ||
189 | "n" (PT_OFF_SR), "n" (n), \ | ||
190 | "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a) \ | ||
191 | : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \ | ||
192 | "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \ | ||
193 | ); \ | ||
194 | for (;;); /* fake noreturn */ \ | ||
195 | } | ||
196 | |||
197 | BUILD_SLOW_IRQ(0); | ||
198 | BUILD_SLOW_IRQ(1); | ||
199 | BUILD_SLOW_IRQ(2); | ||
200 | BUILD_SLOW_IRQ(3); | ||
201 | BUILD_SLOW_IRQ(4); | ||
202 | BUILD_SLOW_IRQ(5); | ||
203 | BUILD_SLOW_IRQ(6); | ||
204 | BUILD_SLOW_IRQ(7); | ||
205 | BUILD_SLOW_IRQ(8); | ||
206 | BUILD_SLOW_IRQ(9); | ||
207 | BUILD_SLOW_IRQ(10); | ||
208 | BUILD_SLOW_IRQ(11); | ||
209 | BUILD_SLOW_IRQ(12); | ||
210 | BUILD_SLOW_IRQ(13); | ||
211 | BUILD_SLOW_IRQ(14); | ||
212 | BUILD_SLOW_IRQ(15); | ||
213 | BUILD_SLOW_IRQ(16); | ||
214 | BUILD_SLOW_IRQ(17); | ||
215 | BUILD_SLOW_IRQ(18); | ||
216 | BUILD_SLOW_IRQ(19); | ||
217 | BUILD_SLOW_IRQ(20); | ||
218 | BUILD_SLOW_IRQ(21); | ||
219 | BUILD_SLOW_IRQ(22); | ||
220 | BUILD_SLOW_IRQ(23); | ||
221 | BUILD_SLOW_IRQ(24); | ||
222 | BUILD_SLOW_IRQ(25); | ||
223 | BUILD_SLOW_IRQ(26); | ||
224 | BUILD_SLOW_IRQ(27); | ||
225 | BUILD_SLOW_IRQ(28); | ||
226 | BUILD_SLOW_IRQ(29); | ||
227 | BUILD_SLOW_IRQ(30); | ||
228 | BUILD_SLOW_IRQ(31); | ||
229 | |||
230 | asm_irq_handler slow_handlers[32] = { | ||
231 | [0] = atari_slow_irq_0_handler, | ||
232 | [1] = atari_slow_irq_1_handler, | ||
233 | [2] = atari_slow_irq_2_handler, | ||
234 | [3] = atari_slow_irq_3_handler, | ||
235 | [4] = atari_slow_irq_4_handler, | ||
236 | [5] = atari_slow_irq_5_handler, | ||
237 | [6] = atari_slow_irq_6_handler, | ||
238 | [7] = atari_slow_irq_7_handler, | ||
239 | [8] = atari_slow_irq_8_handler, | ||
240 | [9] = atari_slow_irq_9_handler, | ||
241 | [10] = atari_slow_irq_10_handler, | ||
242 | [11] = atari_slow_irq_11_handler, | ||
243 | [12] = atari_slow_irq_12_handler, | ||
244 | [13] = atari_slow_irq_13_handler, | ||
245 | [14] = atari_slow_irq_14_handler, | ||
246 | [15] = atari_slow_irq_15_handler, | ||
247 | [16] = atari_slow_irq_16_handler, | ||
248 | [17] = atari_slow_irq_17_handler, | ||
249 | [18] = atari_slow_irq_18_handler, | ||
250 | [19] = atari_slow_irq_19_handler, | ||
251 | [20] = atari_slow_irq_20_handler, | ||
252 | [21] = atari_slow_irq_21_handler, | ||
253 | [22] = atari_slow_irq_22_handler, | ||
254 | [23] = atari_slow_irq_23_handler, | ||
255 | [24] = atari_slow_irq_24_handler, | ||
256 | [25] = atari_slow_irq_25_handler, | ||
257 | [26] = atari_slow_irq_26_handler, | ||
258 | [27] = atari_slow_irq_27_handler, | ||
259 | [28] = atari_slow_irq_28_handler, | ||
260 | [29] = atari_slow_irq_29_handler, | ||
261 | [30] = atari_slow_irq_30_handler, | ||
262 | [31] = atari_slow_irq_31_handler | ||
263 | }; | ||
264 | |||
265 | asmlinkage void atari_fast_irq_handler( void ); | ||
266 | asmlinkage void atari_prio_irq_handler( void ); | ||
267 | |||
268 | /* Dummy function to allow asm with operands. */ | ||
269 | void atari_fast_prio_irq_dummy (void) { | ||
270 | __asm__ (__ALIGN_STR "\n" | ||
271 | "atari_fast_irq_handler:\n\t" | ||
272 | "orw #0x700,%%sr\n" /* disable all interrupts */ | ||
273 | "atari_prio_irq_handler:\n\t" | ||
274 | "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */ | ||
275 | SAVE_ALL_INT "\n\t" | ||
276 | GET_CURRENT(%%d0) "\n\t" | ||
277 | /* get vector number from stack frame and convert to source */ | ||
278 | "bfextu %%sp@(%c1){#4,#10},%%d0\n\t" | ||
279 | "subw #(0x40-8),%%d0\n\t" | ||
280 | "jpl 1f\n\t" | ||
281 | "addw #(0x40-8-0x18),%%d0\n" | ||
282 | "1:\tlea %a0,%%a0\n\t" | ||
283 | "addql #1,%%a0@(%%d0:l:4)\n\t" | ||
284 | "lea irq_handler,%%a0\n\t" | ||
285 | "lea %%a0@(%%d0:l:8),%%a0\n\t" | ||
286 | "pea %%sp@\n\t" /* push frame address */ | ||
287 | "movel %%a0@(4),%%sp@-\n\t" /* push handler data */ | ||
288 | "movel %%d0,%%sp@-\n\t" /* push int number */ | ||
289 | "movel %%a0@,%%a0\n\t" | ||
290 | "jsr %%a0@\n\t" /* and call the handler */ | ||
291 | "addql #8,%%sp\n\t" | ||
292 | "addql #4,%%sp\n\t" | ||
293 | "jbra ret_from_interrupt" | ||
294 | : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC), | ||
295 | "m" (preempt_count()), "di" (HARDIRQ_OFFSET) | ||
296 | ); | ||
297 | for (;;); | ||
298 | } | ||
299 | #endif | ||
300 | 64 | ||
301 | /* | 65 | /* |
302 | * Bitmap for free interrupt vector numbers | 66 | * Bitmap for free interrupt vector numbers |
@@ -320,31 +84,44 @@ extern void atari_microwire_cmd(int cmd); | |||
320 | 84 | ||
321 | extern int atari_SCC_reset_done; | 85 | extern int atari_SCC_reset_done; |
322 | 86 | ||
323 | static int atari_startup_irq(unsigned int irq) | 87 | static unsigned int atari_irq_startup(struct irq_data *data) |
324 | { | 88 | { |
325 | m68k_irq_startup(irq); | 89 | unsigned int irq = data->irq; |
90 | |||
91 | m68k_irq_startup(data); | ||
326 | atari_turnon_irq(irq); | 92 | atari_turnon_irq(irq); |
327 | atari_enable_irq(irq); | 93 | atari_enable_irq(irq); |
328 | return 0; | 94 | return 0; |
329 | } | 95 | } |
330 | 96 | ||
331 | static void atari_shutdown_irq(unsigned int irq) | 97 | static void atari_irq_shutdown(struct irq_data *data) |
332 | { | 98 | { |
99 | unsigned int irq = data->irq; | ||
100 | |||
333 | atari_disable_irq(irq); | 101 | atari_disable_irq(irq); |
334 | atari_turnoff_irq(irq); | 102 | atari_turnoff_irq(irq); |
335 | m68k_irq_shutdown(irq); | 103 | m68k_irq_shutdown(data); |
336 | 104 | ||
337 | if (irq == IRQ_AUTO_4) | 105 | if (irq == IRQ_AUTO_4) |
338 | vectors[VEC_INT4] = falcon_hblhandler; | 106 | vectors[VEC_INT4] = falcon_hblhandler; |
339 | } | 107 | } |
340 | 108 | ||
341 | static struct irq_controller atari_irq_controller = { | 109 | static void atari_irq_enable(struct irq_data *data) |
110 | { | ||
111 | atari_enable_irq(data->irq); | ||
112 | } | ||
113 | |||
114 | static void atari_irq_disable(struct irq_data *data) | ||
115 | { | ||
116 | atari_disable_irq(data->irq); | ||
117 | } | ||
118 | |||
119 | static struct irq_chip atari_irq_chip = { | ||
342 | .name = "atari", | 120 | .name = "atari", |
343 | .lock = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock), | 121 | .irq_startup = atari_irq_startup, |
344 | .startup = atari_startup_irq, | 122 | .irq_shutdown = atari_irq_shutdown, |
345 | .shutdown = atari_shutdown_irq, | 123 | .irq_enable = atari_irq_enable, |
346 | .enable = atari_enable_irq, | 124 | .irq_disable = atari_irq_disable, |
347 | .disable = atari_disable_irq, | ||
348 | }; | 125 | }; |
349 | 126 | ||
350 | /* | 127 | /* |
@@ -360,8 +137,9 @@ static struct irq_controller atari_irq_controller = { | |||
360 | 137 | ||
361 | void __init atari_init_IRQ(void) | 138 | void __init atari_init_IRQ(void) |
362 | { | 139 | { |
363 | m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL); | 140 | m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER); |
364 | m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1); | 141 | m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1, |
142 | NUM_ATARI_SOURCES - 1); | ||
365 | 143 | ||
366 | /* Initialize the MFP(s) */ | 144 | /* Initialize the MFP(s) */ |
367 | 145 | ||
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 1edd95095cb..81286476f74 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c | |||
@@ -86,7 +86,7 @@ static void bvme6000_get_model(char *model) | |||
86 | */ | 86 | */ |
87 | static void __init bvme6000_init_IRQ(void) | 87 | static void __init bvme6000_init_IRQ(void) |
88 | { | 88 | { |
89 | m68k_setup_user_interrupt(VEC_USER, 192, NULL); | 89 | m68k_setup_user_interrupt(VEC_USER, 192); |
90 | } | 90 | } |
91 | 91 | ||
92 | void __init config_bvme6000(void) | 92 | void __init config_bvme6000(void) |
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index f6312c7d872..c87fe69b072 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c | |||
@@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector) | |||
70 | 70 | ||
71 | asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); | 71 | asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); |
72 | 72 | ||
73 | if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector)) | 73 | if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector)) |
74 | pr_err("Couldn't register timer interrupt\n"); | 74 | pr_err("Couldn't register timer interrupt\n"); |
75 | 75 | ||
76 | out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ | 76 | out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ |
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h index 870e5347155..db30ed27687 100644 --- a/arch/m68k/include/asm/hardirq.h +++ b/arch/m68k/include/asm/hardirq.h | |||
@@ -18,6 +18,11 @@ | |||
18 | 18 | ||
19 | #ifdef CONFIG_MMU | 19 | #ifdef CONFIG_MMU |
20 | 20 | ||
21 | static inline void ack_bad_irq(unsigned int irq) | ||
22 | { | ||
23 | pr_crit("unexpected IRQ trap at vector %02x\n", irq); | ||
24 | } | ||
25 | |||
21 | /* entry.S is sensitive to the offsets of these fields */ | 26 | /* entry.S is sensitive to the offsets of these fields */ |
22 | typedef struct { | 27 | typedef struct { |
23 | unsigned int __softirq_pending; | 28 | unsigned int __softirq_pending; |
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 69ed0d74d53..6198df5ff24 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h | |||
@@ -27,11 +27,6 @@ | |||
27 | 27 | ||
28 | #ifdef CONFIG_MMU | 28 | #ifdef CONFIG_MMU |
29 | 29 | ||
30 | #include <linux/linkage.h> | ||
31 | #include <linux/hardirq.h> | ||
32 | #include <linux/irqreturn.h> | ||
33 | #include <linux/spinlock_types.h> | ||
34 | |||
35 | /* | 30 | /* |
36 | * Interrupt source definitions | 31 | * Interrupt source definitions |
37 | * General interrupt sources are the level 1-7. | 32 | * General interrupt sources are the level 1-7. |
@@ -54,10 +49,6 @@ | |||
54 | 49 | ||
55 | #define IRQ_USER 8 | 50 | #define IRQ_USER 8 |
56 | 51 | ||
57 | extern unsigned int irq_canonicalize(unsigned int irq); | ||
58 | |||
59 | struct pt_regs; | ||
60 | |||
61 | /* | 52 | /* |
62 | * various flags for request_irq() - the Amiga now uses the standard | 53 | * various flags for request_irq() - the Amiga now uses the standard |
63 | * mechanism like all other architectures - IRQF_DISABLED and | 54 | * mechanism like all other architectures - IRQF_DISABLED and |
@@ -71,57 +62,27 @@ struct pt_regs; | |||
71 | #define IRQ_FLG_STD (0x8000) /* internally used */ | 62 | #define IRQ_FLG_STD (0x8000) /* internally used */ |
72 | #endif | 63 | #endif |
73 | 64 | ||
74 | /* | 65 | struct irq_data; |
75 | * This structure is used to chain together the ISRs for a particular | 66 | struct irq_chip; |
76 | * interrupt source (if it supports chaining). | 67 | struct irq_desc; |
77 | */ | 68 | extern unsigned int m68k_irq_startup(struct irq_data *data); |
78 | typedef struct irq_node { | 69 | extern unsigned int m68k_irq_startup_irq(unsigned int irq); |
79 | irqreturn_t (*handler)(int, void *); | 70 | extern void m68k_irq_shutdown(struct irq_data *data); |
80 | void *dev_id; | 71 | extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, |
81 | struct irq_node *next; | 72 | struct pt_regs *)); |
82 | unsigned long flags; | 73 | extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt); |
83 | const char *devname; | 74 | extern void m68k_setup_irq_controller(struct irq_chip *, |
84 | } irq_node_t; | 75 | void (*handle)(unsigned int irq, |
85 | 76 | struct irq_desc *desc), | |
86 | /* | 77 | unsigned int irq, unsigned int cnt); |
87 | * This structure has only 4 elements for speed reasons | ||
88 | */ | ||
89 | struct irq_handler { | ||
90 | int (*handler)(int, void *); | ||
91 | unsigned long flags; | ||
92 | void *dev_id; | ||
93 | const char *devname; | ||
94 | }; | ||
95 | |||
96 | struct irq_controller { | ||
97 | const char *name; | ||
98 | spinlock_t lock; | ||
99 | int (*startup)(unsigned int irq); | ||
100 | void (*shutdown)(unsigned int irq); | ||
101 | void (*enable)(unsigned int irq); | ||
102 | void (*disable)(unsigned int irq); | ||
103 | }; | ||
104 | |||
105 | extern int m68k_irq_startup(unsigned int); | ||
106 | extern void m68k_irq_shutdown(unsigned int); | ||
107 | |||
108 | /* | ||
109 | * This function returns a new irq_node_t | ||
110 | */ | ||
111 | extern irq_node_t *new_irq_node(void); | ||
112 | 78 | ||
113 | extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); | 79 | extern unsigned int irq_canonicalize(unsigned int irq); |
114 | extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, | ||
115 | void (*handler)(unsigned int, struct pt_regs *)); | ||
116 | extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int); | ||
117 | |||
118 | asmlinkage void m68k_handle_int(unsigned int); | ||
119 | asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *); | ||
120 | 80 | ||
121 | #else | 81 | #else |
122 | #define irq_canonicalize(irq) (irq) | 82 | #define irq_canonicalize(irq) (irq) |
123 | #endif /* CONFIG_MMU */ | 83 | #endif /* CONFIG_MMU */ |
124 | 84 | ||
125 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); | 85 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); |
86 | extern atomic_t irq_err_count; | ||
126 | 87 | ||
127 | #endif /* _M68K_IRQ_H_ */ | 88 | #endif /* _M68K_IRQ_H_ */ |
diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index c2a1c5eac1a..12ebe43b008 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h | |||
@@ -12,6 +12,8 @@ extern void mac_reset(void); | |||
12 | extern void mac_poweroff(void); | 12 | extern void mac_poweroff(void); |
13 | extern void mac_init_IRQ(void); | 13 | extern void mac_init_IRQ(void); |
14 | extern int mac_irq_pending(unsigned int); | 14 | extern int mac_irq_pending(unsigned int); |
15 | extern void mac_irq_enable(struct irq_data *data); | ||
16 | extern void mac_irq_disable(struct irq_data *data); | ||
15 | 17 | ||
16 | /* | 18 | /* |
17 | * Floppy driver magic hook - probably shouldn't be here | 19 | * Floppy driver magic hook - probably shouldn't be here |
diff --git a/arch/m68k/include/asm/q40ints.h b/arch/m68k/include/asm/q40ints.h index 3d970afb708..22f12c9eb91 100644 --- a/arch/m68k/include/asm/q40ints.h +++ b/arch/m68k/include/asm/q40ints.h | |||
@@ -24,6 +24,3 @@ | |||
24 | #define Q40_IRQ10_MASK (1<<5) | 24 | #define Q40_IRQ10_MASK (1<<5) |
25 | #define Q40_IRQ14_MASK (1<<6) | 25 | #define Q40_IRQ14_MASK (1<<6) |
26 | #define Q40_IRQ15_MASK (1<<7) | 26 | #define Q40_IRQ15_MASK (1<<7) |
27 | |||
28 | extern unsigned long q40_probe_irq_on (void); | ||
29 | extern int q40_probe_irq_off (unsigned long irqs); | ||
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index e7f0f2e5ad4..c5696193281 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile | |||
@@ -6,16 +6,15 @@ extra-$(CONFIG_MMU) := head.o | |||
6 | extra-$(CONFIG_SUN3) := sun3-head.o | 6 | extra-$(CONFIG_SUN3) := sun3-head.o |
7 | extra-y += vmlinux.lds | 7 | extra-y += vmlinux.lds |
8 | 8 | ||
9 | obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ | 9 | obj-y := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \ |
10 | sys_m68k.o syscalltable.o time.o traps.o | 10 | signal.o sys_m68k.o syscalltable.o time.o traps.o |
11 | 11 | ||
12 | obj-$(CONFIG_MMU) += ints.o devres.o vectors.o | 12 | obj-$(CONFIG_MMU) += ints.o vectors.o |
13 | devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o | ||
14 | 13 | ||
15 | ifndef CONFIG_MMU_SUN3 | 14 | ifndef CONFIG_MMU_SUN3 |
16 | obj-y += dma.o | 15 | obj-y += dma.o |
17 | endif | 16 | endif |
18 | ifndef CONFIG_MMU | 17 | ifndef CONFIG_MMU |
19 | obj-y += init_task.o irq.o | 18 | obj-y += init_task.o |
20 | endif | 19 | endif |
21 | 20 | ||
diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S index bd0ec05263b..c713f514843 100644 --- a/arch/m68k/kernel/entry_mm.S +++ b/arch/m68k/kernel/entry_mm.S | |||
@@ -48,7 +48,7 @@ | |||
48 | .globl sys_fork, sys_clone, sys_vfork | 48 | .globl sys_fork, sys_clone, sys_vfork |
49 | .globl ret_from_interrupt, bad_interrupt | 49 | .globl ret_from_interrupt, bad_interrupt |
50 | .globl auto_irqhandler_fixup | 50 | .globl auto_irqhandler_fixup |
51 | .globl user_irqvec_fixup, user_irqhandler_fixup | 51 | .globl user_irqvec_fixup |
52 | 52 | ||
53 | .text | 53 | .text |
54 | ENTRY(buserr) | 54 | ENTRY(buserr) |
@@ -207,7 +207,7 @@ ENTRY(auto_inthandler) | |||
207 | movel %sp,%sp@- | 207 | movel %sp,%sp@- |
208 | movel %d0,%sp@- | put vector # on stack | 208 | movel %d0,%sp@- | put vector # on stack |
209 | auto_irqhandler_fixup = . + 2 | 209 | auto_irqhandler_fixup = . + 2 |
210 | jsr __m68k_handle_int | process the IRQ | 210 | jsr do_IRQ | process the IRQ |
211 | addql #8,%sp | pop parameters off stack | 211 | addql #8,%sp | pop parameters off stack |
212 | 212 | ||
213 | ret_from_interrupt: | 213 | ret_from_interrupt: |
@@ -240,8 +240,7 @@ user_irqvec_fixup = . + 2 | |||
240 | 240 | ||
241 | movel %sp,%sp@- | 241 | movel %sp,%sp@- |
242 | movel %d0,%sp@- | put vector # on stack | 242 | movel %d0,%sp@- | put vector # on stack |
243 | user_irqhandler_fixup = . + 2 | 243 | jsr do_IRQ | process the IRQ |
244 | jsr __m68k_handle_int | process the IRQ | ||
245 | addql #8,%sp | pop parameters off stack | 244 | addql #8,%sp | pop parameters off stack |
246 | 245 | ||
247 | subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) | 246 | subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) |
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 761ee0440c9..74fefac0089 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c | |||
@@ -4,25 +4,6 @@ | |||
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License. See the file COPYING in the main directory of this archive | 5 | * License. See the file COPYING in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | ||
8 | * 07/03/96: Timer initialization, and thus mach_sched_init(), | ||
9 | * removed from request_irq() and moved to init_time(). | ||
10 | * We should therefore consider renaming our add_isr() and | ||
11 | * remove_isr() to request_irq() and free_irq() | ||
12 | * respectively, so they are compliant with the other | ||
13 | * architectures. /Jes | ||
14 | * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. | ||
15 | * Removed irq list support, if any machine needs an irq server | ||
16 | * it must implement this itself (as it's already done), instead | ||
17 | * only default handler are used with mach_default_handler. | ||
18 | * request_irq got some flags different from other architectures: | ||
19 | * - IRQ_FLG_REPLACE : Replace an existing handler (the default one | ||
20 | * can be replaced without this flag) | ||
21 | * - IRQ_FLG_LOCK : handler can't be replaced | ||
22 | * There are other machine depending flags, see there | ||
23 | * If you want to replace a default handler you should know what | ||
24 | * you're doing, since it might handle different other irq sources | ||
25 | * which must be served /Roman Zippel | ||
26 | */ | 7 | */ |
27 | 8 | ||
28 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -47,33 +28,22 @@ | |||
47 | #endif | 28 | #endif |
48 | 29 | ||
49 | extern u32 auto_irqhandler_fixup[]; | 30 | extern u32 auto_irqhandler_fixup[]; |
50 | extern u32 user_irqhandler_fixup[]; | ||
51 | extern u16 user_irqvec_fixup[]; | 31 | extern u16 user_irqvec_fixup[]; |
52 | 32 | ||
53 | /* table for system interrupt handlers */ | ||
54 | static struct irq_node *irq_list[NR_IRQS]; | ||
55 | static struct irq_controller *irq_controller[NR_IRQS]; | ||
56 | static int irq_depth[NR_IRQS]; | ||
57 | |||
58 | static int m68k_first_user_vec; | 33 | static int m68k_first_user_vec; |
59 | 34 | ||
60 | static struct irq_controller auto_irq_controller = { | 35 | static struct irq_chip auto_irq_chip = { |
61 | .name = "auto", | 36 | .name = "auto", |
62 | .lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock), | 37 | .irq_startup = m68k_irq_startup, |
63 | .startup = m68k_irq_startup, | 38 | .irq_shutdown = m68k_irq_shutdown, |
64 | .shutdown = m68k_irq_shutdown, | ||
65 | }; | 39 | }; |
66 | 40 | ||
67 | static struct irq_controller user_irq_controller = { | 41 | static struct irq_chip user_irq_chip = { |
68 | .name = "user", | 42 | .name = "user", |
69 | .lock = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock), | 43 | .irq_startup = m68k_irq_startup, |
70 | .startup = m68k_irq_startup, | 44 | .irq_shutdown = m68k_irq_shutdown, |
71 | .shutdown = m68k_irq_shutdown, | ||
72 | }; | 45 | }; |
73 | 46 | ||
74 | #define NUM_IRQ_NODES 100 | ||
75 | static irq_node_t nodes[NUM_IRQ_NODES]; | ||
76 | |||
77 | /* | 47 | /* |
78 | * void init_IRQ(void) | 48 | * void init_IRQ(void) |
79 | * | 49 | * |
@@ -96,7 +66,7 @@ void __init init_IRQ(void) | |||
96 | } | 66 | } |
97 | 67 | ||
98 | for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) | 68 | for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) |
99 | irq_controller[i] = &auto_irq_controller; | 69 | irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq); |
100 | 70 | ||
101 | mach_init_IRQ(); | 71 | mach_init_IRQ(); |
102 | } | 72 | } |
@@ -106,7 +76,7 @@ void __init init_IRQ(void) | |||
106 | * @handler: called from auto vector interrupts | 76 | * @handler: called from auto vector interrupts |
107 | * | 77 | * |
108 | * setup the handler to be called from auto vector interrupts instead of the | 78 | * setup the handler to be called from auto vector interrupts instead of the |
109 | * standard __m68k_handle_int(), it will be called with irq numbers in the range | 79 | * standard do_IRQ(), it will be called with irq numbers in the range |
110 | * from IRQ_AUTO_1 - IRQ_AUTO_7. | 80 | * from IRQ_AUTO_1 - IRQ_AUTO_7. |
111 | */ | 81 | */ |
112 | void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) | 82 | void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) |
@@ -120,217 +90,49 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re | |||
120 | * m68k_setup_user_interrupt | 90 | * m68k_setup_user_interrupt |
121 | * @vec: first user vector interrupt to handle | 91 | * @vec: first user vector interrupt to handle |
122 | * @cnt: number of active user vector interrupts | 92 | * @cnt: number of active user vector interrupts |
123 | * @handler: called from user vector interrupts | ||
124 | * | 93 | * |
125 | * setup user vector interrupts, this includes activating the specified range | 94 | * setup user vector interrupts, this includes activating the specified range |
126 | * of interrupts, only then these interrupts can be requested (note: this is | 95 | * of interrupts, only then these interrupts can be requested (note: this is |
127 | * different from auto vector interrupts). An optional handler can be installed | 96 | * different from auto vector interrupts). |
128 | * to be called instead of the default __m68k_handle_int(), it will be called | ||
129 | * with irq numbers starting from IRQ_USER. | ||
130 | */ | 97 | */ |
131 | void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, | 98 | void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt) |
132 | void (*handler)(unsigned int, struct pt_regs *)) | ||
133 | { | 99 | { |
134 | int i; | 100 | int i; |
135 | 101 | ||
136 | BUG_ON(IRQ_USER + cnt > NR_IRQS); | 102 | BUG_ON(IRQ_USER + cnt > NR_IRQS); |
137 | m68k_first_user_vec = vec; | 103 | m68k_first_user_vec = vec; |
138 | for (i = 0; i < cnt; i++) | 104 | for (i = 0; i < cnt; i++) |
139 | irq_controller[IRQ_USER + i] = &user_irq_controller; | 105 | irq_set_chip(IRQ_USER + i, &user_irq_chip); |
140 | *user_irqvec_fixup = vec - IRQ_USER; | 106 | *user_irqvec_fixup = vec - IRQ_USER; |
141 | if (handler) | ||
142 | *user_irqhandler_fixup = (u32)handler; | ||
143 | flush_icache(); | 107 | flush_icache(); |
144 | } | 108 | } |
145 | 109 | ||
146 | /** | 110 | /** |
147 | * m68k_setup_irq_controller | 111 | * m68k_setup_irq_controller |
148 | * @contr: irq controller which controls specified irq | 112 | * @chip: irq chip which controls specified irq |
113 | * @handle: flow handler which handles specified irq | ||
149 | * @irq: first irq to be managed by the controller | 114 | * @irq: first irq to be managed by the controller |
115 | * @cnt: number of irqs to be managed by the controller | ||
150 | * | 116 | * |
151 | * Change the controller for the specified range of irq, which will be used to | 117 | * Change the controller for the specified range of irq, which will be used to |
152 | * manage these irq. auto/user irq already have a default controller, which can | 118 | * manage these irq. auto/user irq already have a default controller, which can |
153 | * be changed as well, but the controller probably should use m68k_irq_startup/ | 119 | * be changed as well, but the controller probably should use m68k_irq_startup/ |
154 | * m68k_irq_shutdown. | 120 | * m68k_irq_shutdown. |
155 | */ | 121 | */ |
156 | void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, | 122 | void m68k_setup_irq_controller(struct irq_chip *chip, |
123 | irq_flow_handler_t handle, unsigned int irq, | ||
157 | unsigned int cnt) | 124 | unsigned int cnt) |
158 | { | 125 | { |
159 | int i; | 126 | int i; |
160 | 127 | ||
161 | for (i = 0; i < cnt; i++) | 128 | for (i = 0; i < cnt; i++) { |
162 | irq_controller[irq + i] = contr; | 129 | irq_set_chip(irq + i, chip); |
163 | } | 130 | if (handle) |
164 | 131 | irq_set_handler(irq + i, handle); | |
165 | irq_node_t *new_irq_node(void) | ||
166 | { | ||
167 | irq_node_t *node; | ||
168 | short i; | ||
169 | |||
170 | for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { | ||
171 | if (!node->handler) { | ||
172 | memset(node, 0, sizeof(*node)); | ||
173 | return node; | ||
174 | } | ||
175 | } | 132 | } |
176 | |||
177 | printk ("new_irq_node: out of nodes\n"); | ||
178 | return NULL; | ||
179 | } | 133 | } |
180 | 134 | ||
181 | int setup_irq(unsigned int irq, struct irq_node *node) | 135 | unsigned int m68k_irq_startup_irq(unsigned int irq) |
182 | { | ||
183 | struct irq_controller *contr; | ||
184 | struct irq_node **prev; | ||
185 | unsigned long flags; | ||
186 | |||
187 | if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { | ||
188 | printk("%s: Incorrect IRQ %d from %s\n", | ||
189 | __func__, irq, node->devname); | ||
190 | return -ENXIO; | ||
191 | } | ||
192 | |||
193 | spin_lock_irqsave(&contr->lock, flags); | ||
194 | |||
195 | prev = irq_list + irq; | ||
196 | if (*prev) { | ||
197 | /* Can't share interrupts unless both agree to */ | ||
198 | if (!((*prev)->flags & node->flags & IRQF_SHARED)) { | ||
199 | spin_unlock_irqrestore(&contr->lock, flags); | ||
200 | return -EBUSY; | ||
201 | } | ||
202 | while (*prev) | ||
203 | prev = &(*prev)->next; | ||
204 | } | ||
205 | |||
206 | if (!irq_list[irq]) { | ||
207 | if (contr->startup) | ||
208 | contr->startup(irq); | ||
209 | else | ||
210 | contr->enable(irq); | ||
211 | } | ||
212 | node->next = NULL; | ||
213 | *prev = node; | ||
214 | |||
215 | spin_unlock_irqrestore(&contr->lock, flags); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | int request_irq(unsigned int irq, | ||
221 | irq_handler_t handler, | ||
222 | unsigned long flags, const char *devname, void *dev_id) | ||
223 | { | ||
224 | struct irq_node *node; | ||
225 | int res; | ||
226 | |||
227 | node = new_irq_node(); | ||
228 | if (!node) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | node->handler = handler; | ||
232 | node->flags = flags; | ||
233 | node->dev_id = dev_id; | ||
234 | node->devname = devname; | ||
235 | |||
236 | res = setup_irq(irq, node); | ||
237 | if (res) | ||
238 | node->handler = NULL; | ||
239 | |||
240 | return res; | ||
241 | } | ||
242 | |||
243 | EXPORT_SYMBOL(request_irq); | ||
244 | |||
245 | void free_irq(unsigned int irq, void *dev_id) | ||
246 | { | ||
247 | struct irq_controller *contr; | ||
248 | struct irq_node **p, *node; | ||
249 | unsigned long flags; | ||
250 | |||
251 | if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { | ||
252 | printk("%s: Incorrect IRQ %d\n", __func__, irq); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | spin_lock_irqsave(&contr->lock, flags); | ||
257 | |||
258 | p = irq_list + irq; | ||
259 | while ((node = *p)) { | ||
260 | if (node->dev_id == dev_id) | ||
261 | break; | ||
262 | p = &node->next; | ||
263 | } | ||
264 | |||
265 | if (node) { | ||
266 | *p = node->next; | ||
267 | node->handler = NULL; | ||
268 | } else | ||
269 | printk("%s: Removing probably wrong IRQ %d\n", | ||
270 | __func__, irq); | ||
271 | |||
272 | if (!irq_list[irq]) { | ||
273 | if (contr->shutdown) | ||
274 | contr->shutdown(irq); | ||
275 | else | ||
276 | contr->disable(irq); | ||
277 | } | ||
278 | |||
279 | spin_unlock_irqrestore(&contr->lock, flags); | ||
280 | } | ||
281 | |||
282 | EXPORT_SYMBOL(free_irq); | ||
283 | |||
284 | void enable_irq(unsigned int irq) | ||
285 | { | ||
286 | struct irq_controller *contr; | ||
287 | unsigned long flags; | ||
288 | |||
289 | if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { | ||
290 | printk("%s: Incorrect IRQ %d\n", | ||
291 | __func__, irq); | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | spin_lock_irqsave(&contr->lock, flags); | ||
296 | if (irq_depth[irq]) { | ||
297 | if (!--irq_depth[irq]) { | ||
298 | if (contr->enable) | ||
299 | contr->enable(irq); | ||
300 | } | ||
301 | } else | ||
302 | WARN_ON(1); | ||
303 | spin_unlock_irqrestore(&contr->lock, flags); | ||
304 | } | ||
305 | |||
306 | EXPORT_SYMBOL(enable_irq); | ||
307 | |||
308 | void disable_irq(unsigned int irq) | ||
309 | { | ||
310 | struct irq_controller *contr; | ||
311 | unsigned long flags; | ||
312 | |||
313 | if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { | ||
314 | printk("%s: Incorrect IRQ %d\n", | ||
315 | __func__, irq); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | spin_lock_irqsave(&contr->lock, flags); | ||
320 | if (!irq_depth[irq]++) { | ||
321 | if (contr->disable) | ||
322 | contr->disable(irq); | ||
323 | } | ||
324 | spin_unlock_irqrestore(&contr->lock, flags); | ||
325 | } | ||
326 | |||
327 | EXPORT_SYMBOL(disable_irq); | ||
328 | |||
329 | void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); | ||
330 | |||
331 | EXPORT_SYMBOL(disable_irq_nosync); | ||
332 | |||
333 | int m68k_irq_startup(unsigned int irq) | ||
334 | { | 136 | { |
335 | if (irq <= IRQ_AUTO_7) | 137 | if (irq <= IRQ_AUTO_7) |
336 | vectors[VEC_SPUR + irq] = auto_inthandler; | 138 | vectors[VEC_SPUR + irq] = auto_inthandler; |
@@ -339,41 +141,21 @@ int m68k_irq_startup(unsigned int irq) | |||
339 | return 0; | 141 | return 0; |
340 | } | 142 | } |
341 | 143 | ||
342 | void m68k_irq_shutdown(unsigned int irq) | 144 | unsigned int m68k_irq_startup(struct irq_data *data) |
343 | { | 145 | { |
344 | if (irq <= IRQ_AUTO_7) | 146 | return m68k_irq_startup_irq(data->irq); |
345 | vectors[VEC_SPUR + irq] = bad_inthandler; | ||
346 | else | ||
347 | vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; | ||
348 | } | 147 | } |
349 | 148 | ||
350 | 149 | void m68k_irq_shutdown(struct irq_data *data) | |
351 | /* | ||
352 | * Do we need these probe functions on the m68k? | ||
353 | * | ||
354 | * ... may be useful with ISA devices | ||
355 | */ | ||
356 | unsigned long probe_irq_on (void) | ||
357 | { | 150 | { |
358 | #ifdef CONFIG_Q40 | 151 | unsigned int irq = data->irq; |
359 | if (MACH_IS_Q40) | ||
360 | return q40_probe_irq_on(); | ||
361 | #endif | ||
362 | return 0; | ||
363 | } | ||
364 | 152 | ||
365 | EXPORT_SYMBOL(probe_irq_on); | 153 | if (irq <= IRQ_AUTO_7) |
366 | 154 | vectors[VEC_SPUR + irq] = bad_inthandler; | |
367 | int probe_irq_off (unsigned long irqs) | 155 | else |
368 | { | 156 | vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; |
369 | #ifdef CONFIG_Q40 | ||
370 | if (MACH_IS_Q40) | ||
371 | return q40_probe_irq_off(irqs); | ||
372 | #endif | ||
373 | return 0; | ||
374 | } | 157 | } |
375 | 158 | ||
376 | EXPORT_SYMBOL(probe_irq_off); | ||
377 | 159 | ||
378 | unsigned int irq_canonicalize(unsigned int irq) | 160 | unsigned int irq_canonicalize(unsigned int irq) |
379 | { | 161 | { |
@@ -386,52 +168,9 @@ unsigned int irq_canonicalize(unsigned int irq) | |||
386 | 168 | ||
387 | EXPORT_SYMBOL(irq_canonicalize); | 169 | EXPORT_SYMBOL(irq_canonicalize); |
388 | 170 | ||
389 | asmlinkage void m68k_handle_int(unsigned int irq) | ||
390 | { | ||
391 | struct irq_node *node; | ||
392 | kstat_cpu(0).irqs[irq]++; | ||
393 | node = irq_list[irq]; | ||
394 | do { | ||
395 | node->handler(irq, node->dev_id); | ||
396 | node = node->next; | ||
397 | } while (node); | ||
398 | } | ||
399 | |||
400 | asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) | ||
401 | { | ||
402 | struct pt_regs *old_regs; | ||
403 | old_regs = set_irq_regs(regs); | ||
404 | m68k_handle_int(irq); | ||
405 | set_irq_regs(old_regs); | ||
406 | } | ||
407 | 171 | ||
408 | asmlinkage void handle_badint(struct pt_regs *regs) | 172 | asmlinkage void handle_badint(struct pt_regs *regs) |
409 | { | 173 | { |
410 | kstat_cpu(0).irqs[0]++; | 174 | atomic_inc(&irq_err_count); |
411 | printk("unexpected interrupt from %u\n", regs->vector); | 175 | pr_warn("unexpected interrupt from %u\n", regs->vector); |
412 | } | ||
413 | |||
414 | int show_interrupts(struct seq_file *p, void *v) | ||
415 | { | ||
416 | struct irq_controller *contr; | ||
417 | struct irq_node *node; | ||
418 | int i = *(loff_t *) v; | ||
419 | |||
420 | /* autovector interrupts */ | ||
421 | if (irq_list[i]) { | ||
422 | contr = irq_controller[i]; | ||
423 | node = irq_list[i]; | ||
424 | seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); | ||
425 | while ((node = node->next)) | ||
426 | seq_printf(p, ", %s", node->devname); | ||
427 | seq_puts(p, "\n"); | ||
428 | } | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | #ifdef CONFIG_PROC_FS | ||
433 | void init_irq_proc(void) | ||
434 | { | ||
435 | /* Insert /proc/irq driver here */ | ||
436 | } | 176 | } |
437 | #endif | ||
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index 2a96bebd896..b403924a1ca 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/irq.h> | ||
14 | 15 | ||
15 | #include <asm/traps.h> | 16 | #include <asm/traps.h> |
16 | #include <asm/bootinfo.h> | 17 | #include <asm/bootinfo.h> |
@@ -20,9 +21,6 @@ | |||
20 | 21 | ||
21 | /* #define DEBUG_IRQS */ | 22 | /* #define DEBUG_IRQS */ |
22 | 23 | ||
23 | extern void mac_enable_irq(unsigned int); | ||
24 | extern void mac_disable_irq(unsigned int); | ||
25 | |||
26 | int baboon_present; | 24 | int baboon_present; |
27 | static volatile struct baboon *baboon; | 25 | static volatile struct baboon *baboon; |
28 | static unsigned char baboon_disabled; | 26 | static unsigned char baboon_disabled; |
@@ -53,7 +51,7 @@ void __init baboon_init(void) | |||
53 | * Baboon interrupt handler. This works a lot like a VIA. | 51 | * Baboon interrupt handler. This works a lot like a VIA. |
54 | */ | 52 | */ |
55 | 53 | ||
56 | static irqreturn_t baboon_irq(int irq, void *dev_id) | 54 | static void baboon_irq(unsigned int irq, struct irq_desc *desc) |
57 | { | 55 | { |
58 | int irq_bit, irq_num; | 56 | int irq_bit, irq_num; |
59 | unsigned char events; | 57 | unsigned char events; |
@@ -64,15 +62,16 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) | |||
64 | (uint) baboon->mb_status); | 62 | (uint) baboon->mb_status); |
65 | #endif | 63 | #endif |
66 | 64 | ||
67 | if (!(events = baboon->mb_ifr & 0x07)) | 65 | events = baboon->mb_ifr & 0x07; |
68 | return IRQ_NONE; | 66 | if (!events) |
67 | return; | ||
69 | 68 | ||
70 | irq_num = IRQ_BABOON_0; | 69 | irq_num = IRQ_BABOON_0; |
71 | irq_bit = 1; | 70 | irq_bit = 1; |
72 | do { | 71 | do { |
73 | if (events & irq_bit) { | 72 | if (events & irq_bit) { |
74 | baboon->mb_ifr &= ~irq_bit; | 73 | baboon->mb_ifr &= ~irq_bit; |
75 | m68k_handle_int(irq_num); | 74 | generic_handle_irq(irq_num); |
76 | } | 75 | } |
77 | irq_bit <<= 1; | 76 | irq_bit <<= 1; |
78 | irq_num++; | 77 | irq_num++; |
@@ -82,7 +81,6 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) | |||
82 | /* for now we need to smash all interrupts */ | 81 | /* for now we need to smash all interrupts */ |
83 | baboon->mb_ifr &= ~events; | 82 | baboon->mb_ifr &= ~events; |
84 | #endif | 83 | #endif |
85 | return IRQ_HANDLED; | ||
86 | } | 84 | } |
87 | 85 | ||
88 | /* | 86 | /* |
@@ -92,8 +90,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) | |||
92 | void __init baboon_register_interrupts(void) | 90 | void __init baboon_register_interrupts(void) |
93 | { | 91 | { |
94 | baboon_disabled = 0; | 92 | baboon_disabled = 0; |
95 | if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon)) | 93 | irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); |
96 | pr_err("Couldn't register baboon interrupt\n"); | ||
97 | } | 94 | } |
98 | 95 | ||
99 | /* | 96 | /* |
@@ -111,7 +108,7 @@ void baboon_irq_enable(int irq) | |||
111 | 108 | ||
112 | baboon_disabled &= ~(1 << irq_idx); | 109 | baboon_disabled &= ~(1 << irq_idx); |
113 | if (!baboon_disabled) | 110 | if (!baboon_disabled) |
114 | mac_enable_irq(IRQ_NUBUS_C); | 111 | mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C)); |
115 | } | 112 | } |
116 | 113 | ||
117 | void baboon_irq_disable(int irq) | 114 | void baboon_irq_disable(int irq) |
@@ -124,7 +121,7 @@ void baboon_irq_disable(int irq) | |||
124 | 121 | ||
125 | baboon_disabled |= 1 << irq_idx; | 122 | baboon_disabled |= 1 << irq_idx; |
126 | if (baboon_disabled) | 123 | if (baboon_disabled) |
127 | mac_disable_irq(IRQ_NUBUS_C); | 124 | mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C)); |
128 | } | 125 | } |
129 | 126 | ||
130 | void baboon_irq_clear(int irq) | 127 | void baboon_irq_clear(int irq) |
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 1ad4e9d80eb..a5462cc0bfd 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c | |||
@@ -305,15 +305,13 @@ void __init iop_register_interrupts(void) | |||
305 | { | 305 | { |
306 | if (iop_ism_present) { | 306 | if (iop_ism_present) { |
307 | if (oss_present) { | 307 | if (oss_present) { |
308 | if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, | 308 | if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0, |
309 | IRQ_FLG_LOCK, "ISM IOP", | 309 | "ISM IOP", (void *)IOP_NUM_ISM)) |
310 | (void *) IOP_NUM_ISM)) | ||
311 | pr_err("Couldn't register ISM IOP interrupt\n"); | 310 | pr_err("Couldn't register ISM IOP interrupt\n"); |
312 | oss_irq_enable(IRQ_MAC_ADB); | 311 | oss_irq_enable(IRQ_MAC_ADB); |
313 | } else { | 312 | } else { |
314 | if (request_irq(IRQ_VIA2_0, iop_ism_irq, | 313 | if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP", |
315 | IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP", | 314 | (void *)IOP_NUM_ISM)) |
316 | (void *) IOP_NUM_ISM)) | ||
317 | pr_err("Couldn't register ISM IOP interrupt\n"); | 315 | pr_err("Couldn't register ISM IOP interrupt\n"); |
318 | } | 316 | } |
319 | if (!iop_alive(iop_base[IOP_NUM_ISM])) { | 317 | if (!iop_alive(iop_base[IOP_NUM_ISM])) { |
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index f92190c159b..ba220b70ab8 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c | |||
@@ -190,14 +190,10 @@ irqreturn_t mac_debug_handler(int, void *); | |||
190 | 190 | ||
191 | /* #define DEBUG_MACINTS */ | 191 | /* #define DEBUG_MACINTS */ |
192 | 192 | ||
193 | void mac_enable_irq(unsigned int irq); | 193 | static struct irq_chip mac_irq_chip = { |
194 | void mac_disable_irq(unsigned int irq); | ||
195 | |||
196 | static struct irq_controller mac_irq_controller = { | ||
197 | .name = "mac", | 194 | .name = "mac", |
198 | .lock = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock), | 195 | .irq_enable = mac_irq_enable, |
199 | .enable = mac_enable_irq, | 196 | .irq_disable = mac_irq_disable, |
200 | .disable = mac_disable_irq, | ||
201 | }; | 197 | }; |
202 | 198 | ||
203 | void __init mac_init_IRQ(void) | 199 | void __init mac_init_IRQ(void) |
@@ -205,7 +201,7 @@ void __init mac_init_IRQ(void) | |||
205 | #ifdef DEBUG_MACINTS | 201 | #ifdef DEBUG_MACINTS |
206 | printk("mac_init_IRQ(): Setting things up...\n"); | 202 | printk("mac_init_IRQ(): Setting things up...\n"); |
207 | #endif | 203 | #endif |
208 | m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, | 204 | m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER, |
209 | NUM_MAC_SOURCES - IRQ_USER); | 205 | NUM_MAC_SOURCES - IRQ_USER); |
210 | /* Make sure the SONIC interrupt is cleared or things get ugly */ | 206 | /* Make sure the SONIC interrupt is cleared or things get ugly */ |
211 | #ifdef SHUTUP_SONIC | 207 | #ifdef SHUTUP_SONIC |
@@ -241,16 +237,17 @@ void __init mac_init_IRQ(void) | |||
241 | } | 237 | } |
242 | 238 | ||
243 | /* | 239 | /* |
244 | * mac_enable_irq - enable an interrupt source | 240 | * mac_irq_enable - enable an interrupt source |
245 | * mac_disable_irq - disable an interrupt source | 241 | * mac_irq_disable - disable an interrupt source |
246 | * mac_clear_irq - clears a pending interrupt | 242 | * mac_clear_irq - clears a pending interrupt |
247 | * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) | 243 | * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending) |
248 | * | 244 | * |
249 | * These routines are just dispatchers to the VIA/OSS/PSC routines. | 245 | * These routines are just dispatchers to the VIA/OSS/PSC routines. |
250 | */ | 246 | */ |
251 | 247 | ||
252 | void mac_enable_irq(unsigned int irq) | 248 | void mac_irq_enable(struct irq_data *data) |
253 | { | 249 | { |
250 | int irq = data->irq; | ||
254 | int irq_src = IRQ_SRC(irq); | 251 | int irq_src = IRQ_SRC(irq); |
255 | 252 | ||
256 | switch(irq_src) { | 253 | switch(irq_src) { |
@@ -283,8 +280,9 @@ void mac_enable_irq(unsigned int irq) | |||
283 | } | 280 | } |
284 | } | 281 | } |
285 | 282 | ||
286 | void mac_disable_irq(unsigned int irq) | 283 | void mac_irq_disable(struct irq_data *data) |
287 | { | 284 | { |
285 | int irq = data->irq; | ||
288 | int irq_src = IRQ_SRC(irq); | 286 | int irq_src = IRQ_SRC(irq); |
289 | 287 | ||
290 | switch(irq_src) { | 288 | switch(irq_src) { |
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index a9c0f5ab4cc..a4c82dab9ff 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/irq.h> | ||
22 | 23 | ||
23 | #include <asm/bootinfo.h> | 24 | #include <asm/bootinfo.h> |
24 | #include <asm/macintosh.h> | 25 | #include <asm/macintosh.h> |
@@ -29,10 +30,7 @@ | |||
29 | int oss_present; | 30 | int oss_present; |
30 | volatile struct mac_oss *oss; | 31 | volatile struct mac_oss *oss; |
31 | 32 | ||
32 | static irqreturn_t oss_irq(int, void *); | 33 | extern void via1_irq(unsigned int irq, struct irq_desc *desc); |
33 | static irqreturn_t oss_nubus_irq(int, void *); | ||
34 | |||
35 | extern irqreturn_t via1_irq(int, void *); | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Initialize the OSS | 36 | * Initialize the OSS |
@@ -60,26 +58,6 @@ void __init oss_init(void) | |||
60 | } | 58 | } |
61 | 59 | ||
62 | /* | 60 | /* |
63 | * Register the OSS and NuBus interrupt dispatchers. | ||
64 | */ | ||
65 | |||
66 | void __init oss_register_interrupts(void) | ||
67 | { | ||
68 | if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, | ||
69 | "scsi", (void *) oss)) | ||
70 | pr_err("Couldn't register %s interrupt\n", "scsi"); | ||
71 | if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, | ||
72 | "nubus", (void *) oss)) | ||
73 | pr_err("Couldn't register %s interrupt\n", "nubus"); | ||
74 | if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, | ||
75 | "sound", (void *) oss)) | ||
76 | pr_err("Couldn't register %s interrupt\n", "sound"); | ||
77 | if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, | ||
78 | "via1", (void *) via1)) | ||
79 | pr_err("Couldn't register %s interrupt\n", "via1"); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Initialize OSS for Nubus access | 61 | * Initialize OSS for Nubus access |
84 | */ | 62 | */ |
85 | 63 | ||
@@ -92,17 +70,17 @@ void __init oss_nubus_init(void) | |||
92 | * and SCSI; everything else is routed to its own autovector IRQ. | 70 | * and SCSI; everything else is routed to its own autovector IRQ. |
93 | */ | 71 | */ |
94 | 72 | ||
95 | static irqreturn_t oss_irq(int irq, void *dev_id) | 73 | static void oss_irq(unsigned int irq, struct irq_desc *desc) |
96 | { | 74 | { |
97 | int events; | 75 | int events; |
98 | 76 | ||
99 | events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); | 77 | events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); |
100 | if (!events) | 78 | if (!events) |
101 | return IRQ_NONE; | 79 | return; |
102 | 80 | ||
103 | #ifdef DEBUG_IRQS | 81 | #ifdef DEBUG_IRQS |
104 | if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { | 82 | if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { |
105 | printk("oss_irq: irq %d events = 0x%04X\n", irq, | 83 | printk("oss_irq: irq %u events = 0x%04X\n", irq, |
106 | (int) oss->irq_pending); | 84 | (int) oss->irq_pending); |
107 | } | 85 | } |
108 | #endif | 86 | #endif |
@@ -113,11 +91,10 @@ static irqreturn_t oss_irq(int irq, void *dev_id) | |||
113 | /* FIXME: call sound handler */ | 91 | /* FIXME: call sound handler */ |
114 | } else if (events & OSS_IP_SCSI) { | 92 | } else if (events & OSS_IP_SCSI) { |
115 | oss->irq_pending &= ~OSS_IP_SCSI; | 93 | oss->irq_pending &= ~OSS_IP_SCSI; |
116 | m68k_handle_int(IRQ_MAC_SCSI); | 94 | generic_handle_irq(IRQ_MAC_SCSI); |
117 | } else { | 95 | } else { |
118 | /* FIXME: error check here? */ | 96 | /* FIXME: error check here? */ |
119 | } | 97 | } |
120 | return IRQ_HANDLED; | ||
121 | } | 98 | } |
122 | 99 | ||
123 | /* | 100 | /* |
@@ -126,13 +103,13 @@ static irqreturn_t oss_irq(int irq, void *dev_id) | |||
126 | * Unlike the VIA/RBV this is on its own autovector interrupt level. | 103 | * Unlike the VIA/RBV this is on its own autovector interrupt level. |
127 | */ | 104 | */ |
128 | 105 | ||
129 | static irqreturn_t oss_nubus_irq(int irq, void *dev_id) | 106 | static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc) |
130 | { | 107 | { |
131 | int events, irq_bit, i; | 108 | int events, irq_bit, i; |
132 | 109 | ||
133 | events = oss->irq_pending & OSS_IP_NUBUS; | 110 | events = oss->irq_pending & OSS_IP_NUBUS; |
134 | if (!events) | 111 | if (!events) |
135 | return IRQ_NONE; | 112 | return; |
136 | 113 | ||
137 | #ifdef DEBUG_NUBUS_INT | 114 | #ifdef DEBUG_NUBUS_INT |
138 | if (console_loglevel > 7) { | 115 | if (console_loglevel > 7) { |
@@ -148,10 +125,21 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id) | |||
148 | irq_bit >>= 1; | 125 | irq_bit >>= 1; |
149 | if (events & irq_bit) { | 126 | if (events & irq_bit) { |
150 | oss->irq_pending &= ~irq_bit; | 127 | oss->irq_pending &= ~irq_bit; |
151 | m68k_handle_int(NUBUS_SOURCE_BASE + i); | 128 | generic_handle_irq(NUBUS_SOURCE_BASE + i); |
152 | } | 129 | } |
153 | } while(events & (irq_bit - 1)); | 130 | } while(events & (irq_bit - 1)); |
154 | return IRQ_HANDLED; | 131 | } |
132 | |||
133 | /* | ||
134 | * Register the OSS and NuBus interrupt dispatchers. | ||
135 | */ | ||
136 | |||
137 | void __init oss_register_interrupts(void) | ||
138 | { | ||
139 | irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); | ||
140 | irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); | ||
141 | irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq); | ||
142 | irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); | ||
155 | } | 143 | } |
156 | 144 | ||
157 | /* | 145 | /* |
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index a4c3eb60706..e6c2d20f328 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/irq.h> | ||
21 | 22 | ||
22 | #include <asm/traps.h> | 23 | #include <asm/traps.h> |
23 | #include <asm/bootinfo.h> | 24 | #include <asm/bootinfo.h> |
@@ -30,8 +31,6 @@ | |||
30 | int psc_present; | 31 | int psc_present; |
31 | volatile __u8 *psc; | 32 | volatile __u8 *psc; |
32 | 33 | ||
33 | irqreturn_t psc_irq(int, void *); | ||
34 | |||
35 | /* | 34 | /* |
36 | * Debugging dump, used in various places to see what's going on. | 35 | * Debugging dump, used in various places to see what's going on. |
37 | */ | 36 | */ |
@@ -112,52 +111,52 @@ void __init psc_init(void) | |||
112 | } | 111 | } |
113 | 112 | ||
114 | /* | 113 | /* |
115 | * Register the PSC interrupt dispatchers for autovector interrupts 3-6. | ||
116 | */ | ||
117 | |||
118 | void __init psc_register_interrupts(void) | ||
119 | { | ||
120 | if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) | ||
121 | pr_err("Couldn't register psc%d interrupt\n", 3); | ||
122 | if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) | ||
123 | pr_err("Couldn't register psc%d interrupt\n", 4); | ||
124 | if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) | ||
125 | pr_err("Couldn't register psc%d interrupt\n", 5); | ||
126 | if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) | ||
127 | pr_err("Couldn't register psc%d interrupt\n", 6); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * PSC interrupt handler. It's a lot like the VIA interrupt handler. | 114 | * PSC interrupt handler. It's a lot like the VIA interrupt handler. |
132 | */ | 115 | */ |
133 | 116 | ||
134 | irqreturn_t psc_irq(int irq, void *dev_id) | 117 | static void psc_irq(unsigned int irq, struct irq_desc *desc) |
135 | { | 118 | { |
136 | int pIFR = pIFRbase + ((int) dev_id); | 119 | unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc); |
137 | int pIER = pIERbase + ((int) dev_id); | 120 | int pIFR = pIFRbase + offset; |
121 | int pIER = pIERbase + offset; | ||
138 | int irq_num; | 122 | int irq_num; |
139 | unsigned char irq_bit, events; | 123 | unsigned char irq_bit, events; |
140 | 124 | ||
141 | #ifdef DEBUG_IRQS | 125 | #ifdef DEBUG_IRQS |
142 | printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n", | 126 | printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n", |
143 | irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); | 127 | irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); |
144 | #endif | 128 | #endif |
145 | 129 | ||
146 | events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; | 130 | events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; |
147 | if (!events) | 131 | if (!events) |
148 | return IRQ_NONE; | 132 | return; |
149 | 133 | ||
150 | irq_num = irq << 3; | 134 | irq_num = irq << 3; |
151 | irq_bit = 1; | 135 | irq_bit = 1; |
152 | do { | 136 | do { |
153 | if (events & irq_bit) { | 137 | if (events & irq_bit) { |
154 | psc_write_byte(pIFR, irq_bit); | 138 | psc_write_byte(pIFR, irq_bit); |
155 | m68k_handle_int(irq_num); | 139 | generic_handle_irq(irq_num); |
156 | } | 140 | } |
157 | irq_num++; | 141 | irq_num++; |
158 | irq_bit <<= 1; | 142 | irq_bit <<= 1; |
159 | } while (events >= irq_bit); | 143 | } while (events >= irq_bit); |
160 | return IRQ_HANDLED; | 144 | } |
145 | |||
146 | /* | ||
147 | * Register the PSC interrupt dispatchers for autovector interrupts 3-6. | ||
148 | */ | ||
149 | |||
150 | void __init psc_register_interrupts(void) | ||
151 | { | ||
152 | irq_set_chained_handler(IRQ_AUTO_3, psc_irq); | ||
153 | irq_set_handler_data(IRQ_AUTO_3, (void *)0x30); | ||
154 | irq_set_chained_handler(IRQ_AUTO_4, psc_irq); | ||
155 | irq_set_handler_data(IRQ_AUTO_4, (void *)0x40); | ||
156 | irq_set_chained_handler(IRQ_AUTO_5, psc_irq); | ||
157 | irq_set_handler_data(IRQ_AUTO_5, (void *)0x50); | ||
158 | irq_set_chained_handler(IRQ_AUTO_6, psc_irq); | ||
159 | irq_set_handler_data(IRQ_AUTO_6, (void *)0x60); | ||
161 | } | 160 | } |
162 | 161 | ||
163 | void psc_irq_enable(int irq) { | 162 | void psc_irq_enable(int irq) { |
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index e71166daec6..f1600ad2662 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/irq.h> | ||
31 | 32 | ||
32 | #include <asm/bootinfo.h> | 33 | #include <asm/bootinfo.h> |
33 | #include <asm/macintosh.h> | 34 | #include <asm/macintosh.h> |
@@ -77,9 +78,6 @@ static int gIER,gIFR,gBufA,gBufB; | |||
77 | static u8 nubus_disabled; | 78 | static u8 nubus_disabled; |
78 | 79 | ||
79 | void via_debug_dump(void); | 80 | void via_debug_dump(void); |
80 | irqreturn_t via1_irq(int, void *); | ||
81 | irqreturn_t via2_irq(int, void *); | ||
82 | irqreturn_t via_nubus_irq(int, void *); | ||
83 | void via_irq_enable(int irq); | 81 | void via_irq_enable(int irq); |
84 | void via_irq_disable(int irq); | 82 | void via_irq_disable(int irq); |
85 | void via_irq_clear(int irq); | 83 | void via_irq_clear(int irq); |
@@ -281,40 +279,11 @@ void __init via_init_clock(irq_handler_t func) | |||
281 | via1[vT1CL] = MAC_CLOCK_LOW; | 279 | via1[vT1CL] = MAC_CLOCK_LOW; |
282 | via1[vT1CH] = MAC_CLOCK_HIGH; | 280 | via1[vT1CH] = MAC_CLOCK_HIGH; |
283 | 281 | ||
284 | if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func)) | 282 | if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func)) |
285 | pr_err("Couldn't register %s interrupt\n", "timer"); | 283 | pr_err("Couldn't register %s interrupt\n", "timer"); |
286 | } | 284 | } |
287 | 285 | ||
288 | /* | 286 | /* |
289 | * Register the interrupt dispatchers for VIA or RBV machines only. | ||
290 | */ | ||
291 | |||
292 | void __init via_register_interrupts(void) | ||
293 | { | ||
294 | if (via_alt_mapping) { | ||
295 | if (request_irq(IRQ_AUTO_1, via1_irq, | ||
296 | IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", | ||
297 | (void *) via1)) | ||
298 | pr_err("Couldn't register %s interrupt\n", "software"); | ||
299 | if (request_irq(IRQ_AUTO_6, via1_irq, | ||
300 | IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", | ||
301 | (void *) via1)) | ||
302 | pr_err("Couldn't register %s interrupt\n", "via1"); | ||
303 | } else { | ||
304 | if (request_irq(IRQ_AUTO_1, via1_irq, | ||
305 | IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", | ||
306 | (void *) via1)) | ||
307 | pr_err("Couldn't register %s interrupt\n", "via1"); | ||
308 | } | ||
309 | if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, | ||
310 | "via2", (void *) via2)) | ||
311 | pr_err("Couldn't register %s interrupt\n", "via2"); | ||
312 | if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, | ||
313 | IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2)) | ||
314 | pr_err("Couldn't register %s interrupt\n", "nubus"); | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Debugging dump, used in various places to see what's going on. | 287 | * Debugging dump, used in various places to see what's going on. |
319 | */ | 288 | */ |
320 | 289 | ||
@@ -446,48 +415,46 @@ void __init via_nubus_init(void) | |||
446 | * via6522.c :-), disable/pending masks added. | 415 | * via6522.c :-), disable/pending masks added. |
447 | */ | 416 | */ |
448 | 417 | ||
449 | irqreturn_t via1_irq(int irq, void *dev_id) | 418 | void via1_irq(unsigned int irq, struct irq_desc *desc) |
450 | { | 419 | { |
451 | int irq_num; | 420 | int irq_num; |
452 | unsigned char irq_bit, events; | 421 | unsigned char irq_bit, events; |
453 | 422 | ||
454 | events = via1[vIFR] & via1[vIER] & 0x7F; | 423 | events = via1[vIFR] & via1[vIER] & 0x7F; |
455 | if (!events) | 424 | if (!events) |
456 | return IRQ_NONE; | 425 | return; |
457 | 426 | ||
458 | irq_num = VIA1_SOURCE_BASE; | 427 | irq_num = VIA1_SOURCE_BASE; |
459 | irq_bit = 1; | 428 | irq_bit = 1; |
460 | do { | 429 | do { |
461 | if (events & irq_bit) { | 430 | if (events & irq_bit) { |
462 | via1[vIFR] = irq_bit; | 431 | via1[vIFR] = irq_bit; |
463 | m68k_handle_int(irq_num); | 432 | generic_handle_irq(irq_num); |
464 | } | 433 | } |
465 | ++irq_num; | 434 | ++irq_num; |
466 | irq_bit <<= 1; | 435 | irq_bit <<= 1; |
467 | } while (events >= irq_bit); | 436 | } while (events >= irq_bit); |
468 | return IRQ_HANDLED; | ||
469 | } | 437 | } |
470 | 438 | ||
471 | irqreturn_t via2_irq(int irq, void *dev_id) | 439 | static void via2_irq(unsigned int irq, struct irq_desc *desc) |
472 | { | 440 | { |
473 | int irq_num; | 441 | int irq_num; |
474 | unsigned char irq_bit, events; | 442 | unsigned char irq_bit, events; |
475 | 443 | ||
476 | events = via2[gIFR] & via2[gIER] & 0x7F; | 444 | events = via2[gIFR] & via2[gIER] & 0x7F; |
477 | if (!events) | 445 | if (!events) |
478 | return IRQ_NONE; | 446 | return; |
479 | 447 | ||
480 | irq_num = VIA2_SOURCE_BASE; | 448 | irq_num = VIA2_SOURCE_BASE; |
481 | irq_bit = 1; | 449 | irq_bit = 1; |
482 | do { | 450 | do { |
483 | if (events & irq_bit) { | 451 | if (events & irq_bit) { |
484 | via2[gIFR] = irq_bit | rbv_clear; | 452 | via2[gIFR] = irq_bit | rbv_clear; |
485 | m68k_handle_int(irq_num); | 453 | generic_handle_irq(irq_num); |
486 | } | 454 | } |
487 | ++irq_num; | 455 | ++irq_num; |
488 | irq_bit <<= 1; | 456 | irq_bit <<= 1; |
489 | } while (events >= irq_bit); | 457 | } while (events >= irq_bit); |
490 | return IRQ_HANDLED; | ||
491 | } | 458 | } |
492 | 459 | ||
493 | /* | 460 | /* |
@@ -495,7 +462,7 @@ irqreturn_t via2_irq(int irq, void *dev_id) | |||
495 | * VIA2 dispatcher as a fast interrupt handler. | 462 | * VIA2 dispatcher as a fast interrupt handler. |
496 | */ | 463 | */ |
497 | 464 | ||
498 | irqreturn_t via_nubus_irq(int irq, void *dev_id) | 465 | void via_nubus_irq(unsigned int irq, struct irq_desc *desc) |
499 | { | 466 | { |
500 | int slot_irq; | 467 | int slot_irq; |
501 | unsigned char slot_bit, events; | 468 | unsigned char slot_bit, events; |
@@ -506,7 +473,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
506 | else | 473 | else |
507 | events &= ~via2[vDirA]; | 474 | events &= ~via2[vDirA]; |
508 | if (!events) | 475 | if (!events) |
509 | return IRQ_NONE; | 476 | return; |
510 | 477 | ||
511 | do { | 478 | do { |
512 | slot_irq = IRQ_NUBUS_F; | 479 | slot_irq = IRQ_NUBUS_F; |
@@ -514,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
514 | do { | 481 | do { |
515 | if (events & slot_bit) { | 482 | if (events & slot_bit) { |
516 | events &= ~slot_bit; | 483 | events &= ~slot_bit; |
517 | m68k_handle_int(slot_irq); | 484 | generic_handle_irq(slot_irq); |
518 | } | 485 | } |
519 | --slot_irq; | 486 | --slot_irq; |
520 | slot_bit >>= 1; | 487 | slot_bit >>= 1; |
@@ -528,7 +495,24 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
528 | else | 495 | else |
529 | events &= ~via2[vDirA]; | 496 | events &= ~via2[vDirA]; |
530 | } while (events); | 497 | } while (events); |
531 | return IRQ_HANDLED; | 498 | } |
499 | |||
500 | /* | ||
501 | * Register the interrupt dispatchers for VIA or RBV machines only. | ||
502 | */ | ||
503 | |||
504 | void __init via_register_interrupts(void) | ||
505 | { | ||
506 | if (via_alt_mapping) { | ||
507 | /* software interrupt */ | ||
508 | irq_set_chained_handler(IRQ_AUTO_1, via1_irq); | ||
509 | /* via1 interrupt */ | ||
510 | irq_set_chained_handler(IRQ_AUTO_6, via1_irq); | ||
511 | } else { | ||
512 | irq_set_chained_handler(IRQ_AUTO_1, via1_irq); | ||
513 | } | ||
514 | irq_set_chained_handler(IRQ_AUTO_2, via2_irq); | ||
515 | irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq); | ||
532 | } | 516 | } |
533 | 517 | ||
534 | void via_irq_enable(int irq) { | 518 | void via_irq_enable(int irq) { |
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 6cb9c3a9b6c..5de924ef42e 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c | |||
@@ -81,7 +81,7 @@ static void mvme147_get_model(char *model) | |||
81 | 81 | ||
82 | void __init mvme147_init_IRQ(void) | 82 | void __init mvme147_init_IRQ(void) |
83 | { | 83 | { |
84 | m68k_setup_user_interrupt(VEC_USER, 192, NULL); | 84 | m68k_setup_user_interrupt(VEC_USER, 192); |
85 | } | 85 | } |
86 | 86 | ||
87 | void __init config_mvme147(void) | 87 | void __init config_mvme147(void) |
@@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id) | |||
114 | void mvme147_sched_init (irq_handler_t timer_routine) | 114 | void mvme147_sched_init (irq_handler_t timer_routine) |
115 | { | 115 | { |
116 | tick_handler = timer_routine; | 116 | tick_handler = timer_routine; |
117 | if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE, | 117 | if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL)) |
118 | "timer 1", NULL)) | ||
119 | pr_err("Couldn't register timer interrupt\n"); | 118 | pr_err("Couldn't register timer interrupt\n"); |
120 | 119 | ||
121 | /* Init the clock with a value */ | 120 | /* Init the clock with a value */ |
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 0b28e262165..31a66d99cbc 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c | |||
@@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(struct seq_file *m) | |||
117 | 117 | ||
118 | static void __init mvme16x_init_IRQ (void) | 118 | static void __init mvme16x_init_IRQ (void) |
119 | { | 119 | { |
120 | m68k_setup_user_interrupt(VEC_USER, 192, NULL); | 120 | m68k_setup_user_interrupt(VEC_USER, 192); |
121 | } | 121 | } |
122 | 122 | ||
123 | #define pcc2chip ((volatile u_char *)0xfff42000) | 123 | #define pcc2chip ((volatile u_char *)0xfff42000) |
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 9f0e3d59bf9..2b888491f29 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c | |||
@@ -15,10 +15,10 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irq.h> | ||
18 | 19 | ||
19 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
20 | #include <asm/system.h> | 21 | #include <asm/system.h> |
21 | #include <asm/irq.h> | ||
22 | #include <asm/traps.h> | 22 | #include <asm/traps.h> |
23 | 23 | ||
24 | #include <asm/q40_master.h> | 24 | #include <asm/q40_master.h> |
@@ -35,35 +35,36 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | static void q40_irq_handler(unsigned int, struct pt_regs *fp); | 37 | static void q40_irq_handler(unsigned int, struct pt_regs *fp); |
38 | static void q40_enable_irq(unsigned int); | 38 | static void q40_irq_enable(struct irq_data *data); |
39 | static void q40_disable_irq(unsigned int); | 39 | static void q40_irq_disable(struct irq_data *data); |
40 | 40 | ||
41 | unsigned short q40_ablecount[35]; | 41 | unsigned short q40_ablecount[35]; |
42 | unsigned short q40_state[35]; | 42 | unsigned short q40_state[35]; |
43 | 43 | ||
44 | static int q40_irq_startup(unsigned int irq) | 44 | static unsigned int q40_irq_startup(struct irq_data *data) |
45 | { | 45 | { |
46 | unsigned int irq = data->irq; | ||
47 | |||
46 | /* test for ISA ints not implemented by HW */ | 48 | /* test for ISA ints not implemented by HW */ |
47 | switch (irq) { | 49 | switch (irq) { |
48 | case 1: case 2: case 8: case 9: | 50 | case 1: case 2: case 8: case 9: |
49 | case 11: case 12: case 13: | 51 | case 11: case 12: case 13: |
50 | printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq); | 52 | printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq); |
51 | return -ENXIO; | 53 | /* FIXME return -ENXIO; */ |
52 | } | 54 | } |
53 | return 0; | 55 | return 0; |
54 | } | 56 | } |
55 | 57 | ||
56 | static void q40_irq_shutdown(unsigned int irq) | 58 | static void q40_irq_shutdown(struct irq_data *data) |
57 | { | 59 | { |
58 | } | 60 | } |
59 | 61 | ||
60 | static struct irq_controller q40_irq_controller = { | 62 | static struct irq_chip q40_irq_chip = { |
61 | .name = "q40", | 63 | .name = "q40", |
62 | .lock = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock), | 64 | .irq_startup = q40_irq_startup, |
63 | .startup = q40_irq_startup, | 65 | .irq_shutdown = q40_irq_shutdown, |
64 | .shutdown = q40_irq_shutdown, | 66 | .irq_enable = q40_irq_enable, |
65 | .enable = q40_enable_irq, | 67 | .irq_disable = q40_irq_disable, |
66 | .disable = q40_disable_irq, | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | /* | 70 | /* |
@@ -81,13 +82,14 @@ static int disabled; | |||
81 | 82 | ||
82 | void __init q40_init_IRQ(void) | 83 | void __init q40_init_IRQ(void) |
83 | { | 84 | { |
84 | m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); | 85 | m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1, |
86 | Q40_IRQ_MAX); | ||
85 | 87 | ||
86 | /* setup handler for ISA ints */ | 88 | /* setup handler for ISA ints */ |
87 | m68k_setup_auto_interrupt(q40_irq_handler); | 89 | m68k_setup_auto_interrupt(q40_irq_handler); |
88 | 90 | ||
89 | m68k_irq_startup(IRQ_AUTO_2); | 91 | m68k_irq_startup_irq(IRQ_AUTO_2); |
90 | m68k_irq_startup(IRQ_AUTO_4); | 92 | m68k_irq_startup_irq(IRQ_AUTO_4); |
91 | 93 | ||
92 | /* now enable some ints.. */ | 94 | /* now enable some ints.. */ |
93 | master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ | 95 | master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ |
@@ -218,11 +220,11 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) | |||
218 | switch (irq) { | 220 | switch (irq) { |
219 | case 4: | 221 | case 4: |
220 | case 6: | 222 | case 6: |
221 | __m68k_handle_int(Q40_IRQ_SAMPLE, fp); | 223 | do_IRQ(Q40_IRQ_SAMPLE, fp); |
222 | return; | 224 | return; |
223 | } | 225 | } |
224 | if (mir & Q40_IRQ_FRAME_MASK) { | 226 | if (mir & Q40_IRQ_FRAME_MASK) { |
225 | __m68k_handle_int(Q40_IRQ_FRAME, fp); | 227 | do_IRQ(Q40_IRQ_FRAME, fp); |
226 | master_outb(-1, FRAME_CLEAR_REG); | 228 | master_outb(-1, FRAME_CLEAR_REG); |
227 | } | 229 | } |
228 | if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { | 230 | if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { |
@@ -257,7 +259,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) | |||
257 | goto iirq; | 259 | goto iirq; |
258 | } | 260 | } |
259 | q40_state[irq] |= IRQ_INPROGRESS; | 261 | q40_state[irq] |= IRQ_INPROGRESS; |
260 | __m68k_handle_int(irq, fp); | 262 | do_IRQ(irq, fp); |
261 | q40_state[irq] &= ~IRQ_INPROGRESS; | 263 | q40_state[irq] &= ~IRQ_INPROGRESS; |
262 | 264 | ||
263 | /* naively enable everything, if that fails than */ | 265 | /* naively enable everything, if that fails than */ |
@@ -288,25 +290,29 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) | |||
288 | mir = master_inb(IIRQ_REG); | 290 | mir = master_inb(IIRQ_REG); |
289 | /* should test whether keyboard irq is really enabled, doing it in defhand */ | 291 | /* should test whether keyboard irq is really enabled, doing it in defhand */ |
290 | if (mir & Q40_IRQ_KEYB_MASK) | 292 | if (mir & Q40_IRQ_KEYB_MASK) |
291 | __m68k_handle_int(Q40_IRQ_KEYBOARD, fp); | 293 | do_IRQ(Q40_IRQ_KEYBOARD, fp); |
292 | 294 | ||
293 | return; | 295 | return; |
294 | } | 296 | } |
295 | 297 | ||
296 | void q40_enable_irq(unsigned int irq) | 298 | void q40_irq_enable(struct irq_data *data) |
297 | { | 299 | { |
300 | unsigned int irq = data->irq; | ||
301 | |||
298 | if (irq >= 5 && irq <= 15) { | 302 | if (irq >= 5 && irq <= 15) { |
299 | mext_disabled--; | 303 | mext_disabled--; |
300 | if (mext_disabled > 0) | 304 | if (mext_disabled > 0) |
301 | printk("q40_enable_irq : nested disable/enable\n"); | 305 | printk("q40_irq_enable : nested disable/enable\n"); |
302 | if (mext_disabled == 0) | 306 | if (mext_disabled == 0) |
303 | master_outb(1, EXT_ENABLE_REG); | 307 | master_outb(1, EXT_ENABLE_REG); |
304 | } | 308 | } |
305 | } | 309 | } |
306 | 310 | ||
307 | 311 | ||
308 | void q40_disable_irq(unsigned int irq) | 312 | void q40_irq_disable(struct irq_data *data) |
309 | { | 313 | { |
314 | unsigned int irq = data->irq; | ||
315 | |||
310 | /* disable ISA iqs : only do something if the driver has been | 316 | /* disable ISA iqs : only do something if the driver has been |
311 | * verified to be Q40 "compatible" - right now IDE, NE2K | 317 | * verified to be Q40 "compatible" - right now IDE, NE2K |
312 | * Any driver should not attempt to sleep across disable_irq !! | 318 | * Any driver should not attempt to sleep across disable_irq !! |
@@ -319,13 +325,3 @@ void q40_disable_irq(unsigned int irq) | |||
319 | printk("disable_irq nesting count %d\n",mext_disabled); | 325 | printk("disable_irq nesting count %d\n",mext_disabled); |
320 | } | 326 | } |
321 | } | 327 | } |
322 | |||
323 | unsigned long q40_probe_irq_on(void) | ||
324 | { | ||
325 | printk("irq probing not working - reconfigure the driver to avoid this\n"); | ||
326 | return -1; | ||
327 | } | ||
328 | int q40_probe_irq_off(unsigned long irqs) | ||
329 | { | ||
330 | return -1; | ||
331 | } | ||
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 6464ad3ae3e..78b60f53e90 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c | |||
@@ -51,25 +51,29 @@ void sun3_disable_irq(unsigned int irq) | |||
51 | 51 | ||
52 | static irqreturn_t sun3_int7(int irq, void *dev_id) | 52 | static irqreturn_t sun3_int7(int irq, void *dev_id) |
53 | { | 53 | { |
54 | *sun3_intreg |= (1 << irq); | 54 | unsigned int cnt; |
55 | if (!(kstat_cpu(0).irqs[irq] % 2000)) | 55 | |
56 | sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]); | 56 | cnt = kstat_irqs_cpu(irq, 0); |
57 | if (!(cnt % 2000)) | ||
58 | sun3_leds(led_pattern[cnt % 16000 / 2000]); | ||
57 | return IRQ_HANDLED; | 59 | return IRQ_HANDLED; |
58 | } | 60 | } |
59 | 61 | ||
60 | static irqreturn_t sun3_int5(int irq, void *dev_id) | 62 | static irqreturn_t sun3_int5(int irq, void *dev_id) |
61 | { | 63 | { |
64 | unsigned int cnt; | ||
65 | |||
62 | #ifdef CONFIG_SUN3 | 66 | #ifdef CONFIG_SUN3 |
63 | intersil_clear(); | 67 | intersil_clear(); |
64 | #endif | 68 | #endif |
65 | *sun3_intreg |= (1 << irq); | ||
66 | #ifdef CONFIG_SUN3 | 69 | #ifdef CONFIG_SUN3 |
67 | intersil_clear(); | 70 | intersil_clear(); |
68 | #endif | 71 | #endif |
69 | xtime_update(1); | 72 | xtime_update(1); |
70 | update_process_times(user_mode(get_irq_regs())); | 73 | update_process_times(user_mode(get_irq_regs())); |
71 | if (!(kstat_cpu(0).irqs[irq] % 20)) | 74 | cnt = kstat_irqs_cpu(irq, 0); |
72 | sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]); | 75 | if (!(cnt % 20)) |
76 | sun3_leds(led_pattern[cnt % 160 / 20]); | ||
73 | return IRQ_HANDLED; | 77 | return IRQ_HANDLED; |
74 | } | 78 | } |
75 | 79 | ||
@@ -79,29 +83,33 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id) | |||
79 | return IRQ_HANDLED; | 83 | return IRQ_HANDLED; |
80 | } | 84 | } |
81 | 85 | ||
82 | static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) | 86 | static void sun3_irq_enable(struct irq_data *data) |
83 | { | 87 | { |
84 | *sun3_intreg &= ~(1 << irq); | 88 | sun3_enable_irq(data->irq); |
89 | }; | ||
85 | 90 | ||
86 | __m68k_handle_int(irq, fp); | 91 | static void sun3_irq_disable(struct irq_data *data) |
87 | } | 92 | { |
93 | sun3_disable_irq(data->irq); | ||
94 | }; | ||
88 | 95 | ||
89 | static struct irq_controller sun3_irq_controller = { | 96 | static struct irq_chip sun3_irq_chip = { |
90 | .name = "sun3", | 97 | .name = "sun3", |
91 | .lock = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock), | 98 | .irq_startup = m68k_irq_startup, |
92 | .startup = m68k_irq_startup, | 99 | .irq_shutdown = m68k_irq_shutdown, |
93 | .shutdown = m68k_irq_shutdown, | 100 | .irq_enable = sun3_irq_enable, |
94 | .enable = sun3_enable_irq, | 101 | .irq_disable = sun3_irq_disable, |
95 | .disable = sun3_disable_irq, | 102 | .irq_mask = sun3_irq_disable, |
103 | .irq_unmask = sun3_irq_enable, | ||
96 | }; | 104 | }; |
97 | 105 | ||
98 | void __init sun3_init_IRQ(void) | 106 | void __init sun3_init_IRQ(void) |
99 | { | 107 | { |
100 | *sun3_intreg = 1; | 108 | *sun3_intreg = 1; |
101 | 109 | ||
102 | m68k_setup_auto_interrupt(sun3_inthandle); | 110 | m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1, |
103 | m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7); | 111 | 7); |
104 | m68k_setup_user_interrupt(VEC_USER, 128, NULL); | 112 | m68k_setup_user_interrupt(VEC_USER, 128); |
105 | 113 | ||
106 | if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) | 114 | if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) |
107 | pr_err("Couldn't register %s interrupt\n", "int5"); | 115 | pr_err("Couldn't register %s interrupt\n", "int5"); |