aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac/psc.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2011-08-10 06:48:29 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2011-11-08 16:35:50 -0500
commit9145db564eae98134de8eb8d64b47d7177eccfdd (patch)
tree7d0e25514abba33b6082f5a13963442cf390a058 /arch/m68k/mac/psc.c
parentddc7fd25d09678f8252c0321ef4b66e8451abe7d (diff)
m68k/mac: Optimize interrupts using chain handlers
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/mac/psc.c')
-rw-r--r--arch/m68k/mac/psc.c74
1 files changed, 57 insertions, 17 deletions
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 0a34b7afc376..52840b8c03b8 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -33,8 +33,6 @@
33int psc_present; 33int psc_present;
34volatile __u8 *psc; 34volatile __u8 *psc;
35 35
36irqreturn_t psc_irq(int, void *);
37
38/* 36/*
39 * Debugging dump, used in various places to see what's going on. 37 * Debugging dump, used in various places to see what's going on.
40 */ 38 */
@@ -115,26 +113,40 @@ void __init psc_init(void)
115} 113}
116 114
117/* 115/*
118 * Register the PSC interrupt dispatchers for autovector interrupts 3-6. 116 * PSC interrupt handler. It's a lot like the VIA interrupt handler.
119 */ 117 */
120 118
121void __init psc_register_interrupts(void) 119#ifdef CONFIG_GENERIC_HARDIRQS
120static void psc_irq(unsigned int irq, struct irq_desc *desc)
122{ 121{
123 if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) 122 unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
124 pr_err("Couldn't register psc%d interrupt\n", 3); 123 int pIFR = pIFRbase + offset;
125 if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) 124 int pIER = pIERbase + offset;
126 pr_err("Couldn't register psc%d interrupt\n", 4); 125 int irq_num;
127 if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) 126 unsigned char irq_bit, events;
128 pr_err("Couldn't register psc%d interrupt\n", 5);
129 if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
130 pr_err("Couldn't register psc%d interrupt\n", 6);
131}
132 127
133/* 128#ifdef DEBUG_IRQS
134 * PSC interrupt handler. It's a lot like the VIA interrupt handler. 129 printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
135 */ 130 irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
131#endif
136 132
137irqreturn_t psc_irq(int irq, void *dev_id) 133 events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
134 if (!events)
135 return;
136
137 irq_num = irq << 3;
138 irq_bit = 1;
139 do {
140 if (events & irq_bit) {
141 psc_write_byte(pIFR, irq_bit);
142 generic_handle_irq(irq_num);
143 }
144 irq_num++;
145 irq_bit <<= 1;
146 } while (events >= irq_bit);
147}
148#else
149static irqreturn_t psc_irq(int irq, void *dev_id)
138{ 150{
139 int pIFR = pIFRbase + ((int) dev_id); 151 int pIFR = pIFRbase + ((int) dev_id);
140 int pIER = pIERbase + ((int) dev_id); 152 int pIER = pIERbase + ((int) dev_id);
@@ -162,6 +174,34 @@ irqreturn_t psc_irq(int irq, void *dev_id)
162 } while (events >= irq_bit); 174 } while (events >= irq_bit);
163 return IRQ_HANDLED; 175 return IRQ_HANDLED;
164} 176}
177#endif
178
179/*
180 * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
181 */
182
183void __init psc_register_interrupts(void)
184{
185#ifdef CONFIG_GENERIC_HARDIRQS
186 irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
187 irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
188 irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
189 irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
190 irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
191 irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
192 irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
193 irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
194#else /* !CONFIG_GENERIC_HARDIRQS */
195 if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
196 pr_err("Couldn't register psc%d interrupt\n", 3);
197 if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
198 pr_err("Couldn't register psc%d interrupt\n", 4);
199 if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
200 pr_err("Couldn't register psc%d interrupt\n", 5);
201 if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
202 pr_err("Couldn't register psc%d interrupt\n", 6);
203#endif /* !CONFIG_GENERIC_HARDIRQS */
204}
165 205
166void psc_irq_enable(int irq) { 206void psc_irq_enable(int irq) {
167 int irq_src = IRQ_SRC(irq); 207 int irq_src = IRQ_SRC(irq);