Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * arch/m68k/q40/q40ints.c |
| 3 | * |
| 4 | * Copyright (C) 1999,2001 Richard Zidlicky |
| 5 | * |
| 6 | * This file is subject to the terms and conditions of the GNU General Public |
| 7 | * License. See the file COPYING in the main directory of this archive |
| 8 | * for more details. |
| 9 | * |
| 10 | * .. used to be loosely based on bvme6000ints.c |
| 11 | * |
| 12 | */ |
| 13 | |
| 14 | #include <linux/types.h> |
| 15 | #include <linux/kernel.h> |
| 16 | #include <linux/errno.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 | #include <linux/interrupt.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 19 | #include <asm/ptrace.h> |
| 20 | #include <asm/system.h> |
| 21 | #include <asm/irq.h> |
| 22 | #include <asm/traps.h> |
| 23 | |
| 24 | #include <asm/q40_master.h> |
| 25 | #include <asm/q40ints.h> |
| 26 | |
| 27 | /* |
| 28 | * Q40 IRQs are defined as follows: |
| 29 | * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs |
| 30 | * 16-31: reserved |
| 31 | * 32 : keyboard int |
| 32 | * 33 : frame int (50/200 Hz periodic timer) |
| 33 | * 34 : sample int (10/20 KHz periodic timer) |
| 34 | * |
| 35 | */ |
| 36 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 37 | static void q40_irq_handler(unsigned int, struct pt_regs *fp); |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 38 | static void q40_irq_enable(struct irq_data *data); |
| 39 | static void q40_irq_disable(struct irq_data *data); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 41 | unsigned short q40_ablecount[35]; |
| 42 | unsigned short q40_state[35]; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 | |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 44 | static unsigned int q40_irq_startup(struct irq_data *data) |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 45 | { |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 46 | unsigned int irq = data->irq; |
| 47 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 48 | /* test for ISA ints not implemented by HW */ |
| 49 | switch (irq) { |
| 50 | case 1: case 2: case 8: case 9: |
| 51 | case 11: case 12: case 13: |
Harvey Harrison | f85e7cd | 2008-04-28 02:13:49 -0700 | [diff] [blame] | 52 | printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq); |
Geert Uytterhoeven | c288bf2 | 2011-04-13 22:31:28 +0200 | [diff] [blame] | 53 | /* FIXME return -ENXIO; */ |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 54 | } |
| 55 | return 0; |
| 56 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 | |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 58 | static void q40_irq_shutdown(struct irq_data *data) |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 59 | { |
| 60 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 | |
Geert Uytterhoeven | c288bf2 | 2011-04-13 22:31:28 +0200 | [diff] [blame] | 62 | static struct irq_chip q40_irq_chip = { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 63 | .name = "q40", |
Geert Uytterhoeven | c288bf2 | 2011-04-13 22:31:28 +0200 | [diff] [blame] | 64 | .irq_startup = q40_irq_startup, |
| 65 | .irq_shutdown = q40_irq_shutdown, |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 66 | .irq_enable = q40_irq_enable, |
| 67 | .irq_disable = q40_irq_disable, |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 68 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 | |
| 70 | /* |
| 71 | * void q40_init_IRQ (void) |
| 72 | * |
| 73 | * Parameters: None |
| 74 | * |
| 75 | * Returns: Nothing |
| 76 | * |
| 77 | * This function is called during kernel startup to initialize |
| 78 | * the q40 IRQ handling routines. |
| 79 | */ |
| 80 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 81 | static int disabled; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 82 | |
Al Viro | 66a3f82 | 2007-07-20 04:33:28 +0100 | [diff] [blame] | 83 | void __init q40_init_IRQ(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | { |
Geert Uytterhoeven | edb3472 | 2011-06-01 11:15:21 +0200 | [diff] [blame] | 85 | m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1, |
| 86 | Q40_IRQ_MAX); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | |
| 88 | /* setup handler for ISA ints */ |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 89 | m68k_setup_auto_interrupt(q40_irq_handler); |
| 90 | |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 91 | m68k_irq_startup_irq(IRQ_AUTO_2); |
| 92 | m68k_irq_startup_irq(IRQ_AUTO_4); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | |
| 94 | /* now enable some ints.. */ |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 95 | master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | |
| 97 | /* make sure keyboard IRQ is disabled */ |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 98 | master_outb(0, KEY_IRQ_ENABLE_REG); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 99 | } |
| 100 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 101 | |
| 102 | /* |
| 103 | * this stuff doesn't really belong here.. |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 104 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 | |
| 106 | int ql_ticks; /* 200Hz ticks since last jiffie */ |
| 107 | static int sound_ticks; |
| 108 | |
| 109 | #define SVOL 45 |
| 110 | |
| 111 | void q40_mksound(unsigned int hz, unsigned int ticks) |
| 112 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 113 | /* for now ignore hz, except that hz==0 switches off sound */ |
| 114 | /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ |
| 115 | if (hz == 0) { |
| 116 | if (sound_ticks) |
| 117 | sound_ticks = 1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 118 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 119 | *DAC_LEFT = 128; |
| 120 | *DAC_RIGHT = 128; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 121 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 122 | return; |
| 123 | } |
| 124 | /* sound itself is done in q40_timer_int */ |
| 125 | if (sound_ticks == 0) |
| 126 | sound_ticks = 1000; /* pretty long beep */ |
| 127 | sound_ticks = ticks << 1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 128 | } |
| 129 | |
David Howells | 40220c1 | 2006-10-09 12:19:47 +0100 | [diff] [blame] | 130 | static irq_handler_t q40_timer_routine; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 131 | |
Al Viro | 2850bc2 | 2006-10-07 14:16:45 +0100 | [diff] [blame] | 132 | static irqreturn_t q40_timer_int (int irq, void * dev) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 133 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 134 | ql_ticks = ql_ticks ? 0 : 1; |
| 135 | if (sound_ticks) { |
| 136 | unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; |
| 137 | sound_ticks--; |
| 138 | *DAC_LEFT=sval; |
| 139 | *DAC_RIGHT=sval; |
| 140 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 141 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 142 | if (!ql_ticks) |
Al Viro | 2850bc2 | 2006-10-07 14:16:45 +0100 | [diff] [blame] | 143 | q40_timer_routine(irq, dev); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 144 | return IRQ_HANDLED; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | } |
| 146 | |
David Howells | 40220c1 | 2006-10-09 12:19:47 +0100 | [diff] [blame] | 147 | void q40_sched_init (irq_handler_t timer_routine) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 148 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 149 | int timer_irq; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 151 | q40_timer_routine = timer_routine; |
| 152 | timer_irq = Q40_IRQ_FRAME; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 154 | if (request_irq(timer_irq, q40_timer_int, 0, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 155 | "timer", q40_timer_int)) |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 156 | panic("Couldn't register timer int"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 158 | master_outb(-1, FRAME_CLEAR_REG); |
| 159 | master_outb( 1, FRAME_RATE_REG); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | |
| 163 | /* |
| 164 | * tables to translate bits into IRQ numbers |
| 165 | * it is a good idea to order the entries by priority |
| 166 | * |
| 167 | */ |
| 168 | |
| 169 | struct IRQ_TABLE{ unsigned mask; int irq ;}; |
| 170 | #if 0 |
| 171 | static struct IRQ_TABLE iirqs[]={ |
| 172 | {Q40_IRQ_FRAME_MASK,Q40_IRQ_FRAME}, |
| 173 | {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD}, |
| 174 | {0,0}}; |
| 175 | #endif |
| 176 | static struct IRQ_TABLE eirqs[] = { |
| 177 | { .mask = Q40_IRQ3_MASK, .irq = 3 }, /* ser 1 */ |
| 178 | { .mask = Q40_IRQ4_MASK, .irq = 4 }, /* ser 2 */ |
| 179 | { .mask = Q40_IRQ14_MASK, .irq = 14 }, /* IDE 1 */ |
| 180 | { .mask = Q40_IRQ15_MASK, .irq = 15 }, /* IDE 2 */ |
| 181 | { .mask = Q40_IRQ6_MASK, .irq = 6 }, /* floppy, handled elsewhere */ |
| 182 | { .mask = Q40_IRQ7_MASK, .irq = 7 }, /* par */ |
| 183 | { .mask = Q40_IRQ5_MASK, .irq = 5 }, |
| 184 | { .mask = Q40_IRQ10_MASK, .irq = 10 }, |
| 185 | {0,0} |
| 186 | }; |
| 187 | |
| 188 | /* complain only this many times about spurious ints : */ |
Simon Arlott | 0c79cf6 | 2007-10-20 01:20:32 +0200 | [diff] [blame] | 189 | static int ccleirq=60; /* ISA dev IRQs*/ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 190 | /*static int cclirq=60;*/ /* internal */ |
| 191 | |
| 192 | /* FIXME: add shared ints,mask,unmask,probing.... */ |
| 193 | |
| 194 | #define IRQ_INPROGRESS 1 |
| 195 | /*static unsigned short saved_mask;*/ |
| 196 | //static int do_tint=0; |
| 197 | |
| 198 | #define DEBUG_Q40INT |
| 199 | /*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */ |
| 200 | |
| 201 | static int mext_disabled=0; /* ext irq disabled by master chip? */ |
| 202 | static int aliased_irq=0; /* how many times inside handler ?*/ |
| 203 | |
| 204 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 205 | /* got interrupt, dispatch to ISA or keyboard/timer IRQs */ |
| 206 | static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 207 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 208 | unsigned mir, mer; |
| 209 | int i; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 210 | |
| 211 | //repeat: |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 212 | mir = master_inb(IIRQ_REG); |
| 213 | #ifdef CONFIG_BLK_DEV_FD |
| 214 | if ((mir & Q40_IRQ_EXT_MASK) && |
| 215 | (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) { |
| 216 | floppy_hardint(); |
| 217 | return; |
| 218 | } |
| 219 | #endif |
| 220 | switch (irq) { |
| 221 | case 4: |
| 222 | case 6: |
Geert Uytterhoeven | 1425df8 | 2011-07-01 20:39:19 +0200 | [diff] [blame^] | 223 | do_IRQ(Q40_IRQ_SAMPLE, fp); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 224 | return; |
| 225 | } |
| 226 | if (mir & Q40_IRQ_FRAME_MASK) { |
Geert Uytterhoeven | 1425df8 | 2011-07-01 20:39:19 +0200 | [diff] [blame^] | 227 | do_IRQ(Q40_IRQ_FRAME, fp); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 228 | master_outb(-1, FRAME_CLEAR_REG); |
| 229 | } |
| 230 | if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { |
| 231 | mer = master_inb(EIRQ_REG); |
| 232 | for (i = 0; eirqs[i].mask; i++) { |
| 233 | if (mer & eirqs[i].mask) { |
| 234 | irq = eirqs[i].irq; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | /* |
| 236 | * There is a little mess wrt which IRQ really caused this irq request. The |
| 237 | * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they |
| 238 | * are read - which is long after the request came in. In theory IRQs should |
Simon Arlott | 0c79cf6 | 2007-10-20 01:20:32 +0200 | [diff] [blame] | 239 | * not just go away but they occasionally do |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 240 | */ |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 241 | if (irq > 4 && irq <= 15 && mext_disabled) { |
| 242 | /*aliased_irq++;*/ |
| 243 | goto iirq; |
| 244 | } |
| 245 | if (q40_state[irq] & IRQ_INPROGRESS) { |
| 246 | /* some handlers do local_irq_enable() for irq latency reasons, */ |
| 247 | /* however reentering an active irq handler is not permitted */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 248 | #ifdef IP_USE_DISABLE |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 249 | /* in theory this is the better way to do it because it still */ |
| 250 | /* lets through eg the serial irqs, unfortunately it crashes */ |
| 251 | disable_irq(irq); |
| 252 | disabled = 1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 253 | #else |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 254 | /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n", |
| 255 | irq, disabled ? "already" : "not yet"); */ |
| 256 | fp->sr = (((fp->sr) & (~0x700))+0x200); |
| 257 | disabled = 1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 | #endif |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 259 | goto iirq; |
| 260 | } |
| 261 | q40_state[irq] |= IRQ_INPROGRESS; |
Geert Uytterhoeven | 1425df8 | 2011-07-01 20:39:19 +0200 | [diff] [blame^] | 262 | do_IRQ(irq, fp); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 263 | q40_state[irq] &= ~IRQ_INPROGRESS; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 265 | /* naively enable everything, if that fails than */ |
| 266 | /* this function will be reentered immediately thus */ |
| 267 | /* getting another chance to disable the IRQ */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 269 | if (disabled) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 270 | #ifdef IP_USE_DISABLE |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 271 | if (irq > 4) { |
| 272 | disabled = 0; |
| 273 | enable_irq(irq); |
| 274 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 275 | #else |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 276 | disabled = 0; |
| 277 | /*printk("reenabling irq %d\n", irq); */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 278 | #endif |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 279 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 280 | // used to do 'goto repeat;' here, this delayed bh processing too long |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 281 | return; |
| 282 | } |
| 283 | } |
| 284 | if (mer && ccleirq > 0 && !aliased_irq) { |
| 285 | printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer); |
| 286 | ccleirq--; |
| 287 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 288 | } |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 289 | iirq: |
| 290 | mir = master_inb(IIRQ_REG); |
| 291 | /* should test whether keyboard irq is really enabled, doing it in defhand */ |
| 292 | if (mir & Q40_IRQ_KEYB_MASK) |
Geert Uytterhoeven | 1425df8 | 2011-07-01 20:39:19 +0200 | [diff] [blame^] | 293 | do_IRQ(Q40_IRQ_KEYBOARD, fp); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 294 | |
| 295 | return; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 296 | } |
| 297 | |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 298 | void q40_irq_enable(struct irq_data *data) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 299 | { |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 300 | unsigned int irq = data->irq; |
| 301 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 302 | if (irq >= 5 && irq <= 15) { |
| 303 | mext_disabled--; |
| 304 | if (mext_disabled > 0) |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 305 | printk("q40_irq_enable : nested disable/enable\n"); |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 306 | if (mext_disabled == 0) |
| 307 | master_outb(1, EXT_ENABLE_REG); |
| 308 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 309 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 310 | |
| 311 | |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 312 | void q40_irq_disable(struct irq_data *data) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 313 | { |
Geert Uytterhoeven | e8abf5e | 2011-04-17 22:53:04 +0200 | [diff] [blame] | 314 | unsigned int irq = data->irq; |
| 315 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 316 | /* disable ISA iqs : only do something if the driver has been |
| 317 | * verified to be Q40 "compatible" - right now IDE, NE2K |
| 318 | * Any driver should not attempt to sleep across disable_irq !! |
| 319 | */ |
| 320 | |
| 321 | if (irq >= 5 && irq <= 15) { |
| 322 | master_outb(0, EXT_ENABLE_REG); |
| 323 | mext_disabled++; |
| 324 | if (mext_disabled > 1) |
| 325 | printk("disable_irq nesting count %d\n",mext_disabled); |
| 326 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 327 | } |
| 328 | |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 329 | unsigned long q40_probe_irq_on(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 330 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 331 | printk("irq probing not working - reconfigure the driver to avoid this\n"); |
| 332 | return -1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 333 | } |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 334 | int q40_probe_irq_off(unsigned long irqs) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 335 | { |
Roman Zippel | 77dda33 | 2006-06-25 05:47:05 -0700 | [diff] [blame] | 336 | return -1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 337 | } |