0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/types.h>
0014 #include <linux/init.h>
0015 #include <linux/kernel_stat.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/ftrace.h>
0018
0019 #include <asm/irq_cpu.h>
0020 #include <asm/sgi/hpc3.h>
0021 #include <asm/sgi/ip22.h>
0022
0023
0024 #undef USE_LIO3_IRQ
0025
0026 struct sgint_regs *sgint;
0027
0028 static char lc0msk_to_irqnr[256];
0029 static char lc1msk_to_irqnr[256];
0030 static char lc2msk_to_irqnr[256];
0031 static char lc3msk_to_irqnr[256];
0032
0033 extern int ip22_eisa_init(void);
0034
0035 static void enable_local0_irq(struct irq_data *d)
0036 {
0037
0038
0039 if (d->irq != SGI_MAP_0_IRQ)
0040 sgint->imask0 |= (1 << (d->irq - SGINT_LOCAL0));
0041 }
0042
0043 static void disable_local0_irq(struct irq_data *d)
0044 {
0045 sgint->imask0 &= ~(1 << (d->irq - SGINT_LOCAL0));
0046 }
0047
0048 static struct irq_chip ip22_local0_irq_type = {
0049 .name = "IP22 local 0",
0050 .irq_mask = disable_local0_irq,
0051 .irq_unmask = enable_local0_irq,
0052 };
0053
0054 static void enable_local1_irq(struct irq_data *d)
0055 {
0056
0057
0058 if (d->irq != SGI_MAP_1_IRQ)
0059 sgint->imask1 |= (1 << (d->irq - SGINT_LOCAL1));
0060 }
0061
0062 static void disable_local1_irq(struct irq_data *d)
0063 {
0064 sgint->imask1 &= ~(1 << (d->irq - SGINT_LOCAL1));
0065 }
0066
0067 static struct irq_chip ip22_local1_irq_type = {
0068 .name = "IP22 local 1",
0069 .irq_mask = disable_local1_irq,
0070 .irq_unmask = enable_local1_irq,
0071 };
0072
0073 static void enable_local2_irq(struct irq_data *d)
0074 {
0075 sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
0076 sgint->cmeimask0 |= (1 << (d->irq - SGINT_LOCAL2));
0077 }
0078
0079 static void disable_local2_irq(struct irq_data *d)
0080 {
0081 sgint->cmeimask0 &= ~(1 << (d->irq - SGINT_LOCAL2));
0082 if (!sgint->cmeimask0)
0083 sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
0084 }
0085
0086 static struct irq_chip ip22_local2_irq_type = {
0087 .name = "IP22 local 2",
0088 .irq_mask = disable_local2_irq,
0089 .irq_unmask = enable_local2_irq,
0090 };
0091
0092 static void enable_local3_irq(struct irq_data *d)
0093 {
0094 sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
0095 sgint->cmeimask1 |= (1 << (d->irq - SGINT_LOCAL3));
0096 }
0097
0098 static void disable_local3_irq(struct irq_data *d)
0099 {
0100 sgint->cmeimask1 &= ~(1 << (d->irq - SGINT_LOCAL3));
0101 if (!sgint->cmeimask1)
0102 sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
0103 }
0104
0105 static struct irq_chip ip22_local3_irq_type = {
0106 .name = "IP22 local 3",
0107 .irq_mask = disable_local3_irq,
0108 .irq_unmask = enable_local3_irq,
0109 };
0110
0111 static void indy_local0_irqdispatch(void)
0112 {
0113 u8 mask = sgint->istat0 & sgint->imask0;
0114 u8 mask2;
0115 int irq;
0116
0117 if (mask & SGINT_ISTAT0_LIO2) {
0118 mask2 = sgint->vmeistat & sgint->cmeimask0;
0119 irq = lc2msk_to_irqnr[mask2];
0120 } else
0121 irq = lc0msk_to_irqnr[mask];
0122
0123
0124
0125
0126
0127 if (irq)
0128 do_IRQ(irq);
0129 else
0130 do_IRQ(SGINT_LOCAL0 + 0);
0131 }
0132
0133 static void indy_local1_irqdispatch(void)
0134 {
0135 u8 mask = sgint->istat1 & sgint->imask1;
0136 u8 mask2;
0137 int irq;
0138
0139 if (mask & SGINT_ISTAT1_LIO3) {
0140 mask2 = sgint->vmeistat & sgint->cmeimask1;
0141 irq = lc3msk_to_irqnr[mask2];
0142 } else
0143 irq = lc1msk_to_irqnr[mask];
0144
0145
0146 if (irq)
0147 do_IRQ(irq);
0148 }
0149
0150 extern void ip22_be_interrupt(int irq);
0151
0152 static void __irq_entry indy_buserror_irq(void)
0153 {
0154 int irq = SGI_BUSERR_IRQ;
0155
0156 irq_enter();
0157 kstat_incr_irq_this_cpu(irq);
0158 ip22_be_interrupt(irq);
0159 irq_exit();
0160 }
0161
0162 #ifdef USE_LIO3_IRQ
0163 #define SGI_INTERRUPTS SGINT_END
0164 #else
0165 #define SGI_INTERRUPTS SGINT_LOCAL3
0166 #endif
0167
0168 extern void indy_8254timer_irq(void);
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 asmlinkage void plat_irq_dispatch(void)
0199 {
0200 unsigned int pending = read_c0_status() & read_c0_cause();
0201
0202
0203
0204
0205 if (pending & CAUSEF_IP7)
0206 do_IRQ(SGI_TIMER_IRQ);
0207 else if (pending & CAUSEF_IP2)
0208 indy_local0_irqdispatch();
0209 else if (pending & CAUSEF_IP3)
0210 indy_local1_irqdispatch();
0211 else if (pending & CAUSEF_IP6)
0212 indy_buserror_irq();
0213 else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
0214 indy_8254timer_irq();
0215 }
0216
0217 void __init arch_init_irq(void)
0218 {
0219 int i;
0220
0221
0222 for (i = 0; i < 256; i++) {
0223 if (i & 0x80) {
0224 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
0225 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
0226 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
0227 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
0228 } else if (i & 0x40) {
0229 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
0230 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
0231 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
0232 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
0233 } else if (i & 0x20) {
0234 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
0235 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
0236 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
0237 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
0238 } else if (i & 0x10) {
0239 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
0240 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
0241 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
0242 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
0243 } else if (i & 0x08) {
0244 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
0245 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
0246 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
0247 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
0248 } else if (i & 0x04) {
0249 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
0250 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
0251 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
0252 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
0253 } else if (i & 0x02) {
0254 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
0255 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
0256 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
0257 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
0258 } else if (i & 0x01) {
0259 lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
0260 lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
0261 lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
0262 lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
0263 } else {
0264 lc0msk_to_irqnr[i] = 0;
0265 lc1msk_to_irqnr[i] = 0;
0266 lc2msk_to_irqnr[i] = 0;
0267 lc3msk_to_irqnr[i] = 0;
0268 }
0269 }
0270
0271
0272 sgint->imask0 = 0;
0273 sgint->imask1 = 0;
0274 sgint->cmeimask0 = 0;
0275 sgint->cmeimask1 = 0;
0276
0277
0278 mips_cpu_irq_init();
0279
0280 for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
0281 struct irq_chip *handler;
0282
0283 if (i < SGINT_LOCAL1)
0284 handler = &ip22_local0_irq_type;
0285 else if (i < SGINT_LOCAL2)
0286 handler = &ip22_local1_irq_type;
0287 else if (i < SGINT_LOCAL3)
0288 handler = &ip22_local2_irq_type;
0289 else
0290 handler = &ip22_local3_irq_type;
0291
0292 irq_set_chip_and_handler(i, handler, handle_level_irq);
0293 }
0294
0295
0296 if (request_irq(SGI_LOCAL_0_IRQ, no_action, IRQF_NO_THREAD,
0297 "local0 cascade", NULL))
0298 pr_err("Failed to register local0 cascade interrupt\n");
0299 if (request_irq(SGI_LOCAL_1_IRQ, no_action, IRQF_NO_THREAD,
0300 "local1 cascade", NULL))
0301 pr_err("Failed to register local1 cascade interrupt\n");
0302 if (request_irq(SGI_BUSERR_IRQ, no_action, IRQF_NO_THREAD,
0303 "Bus Error", NULL))
0304 pr_err("Failed to register Bus Error interrupt\n");
0305
0306
0307 if (request_irq(SGI_MAP_0_IRQ, no_action, IRQF_NO_THREAD,
0308 "mapable0 cascade", NULL))
0309 pr_err("Failed to register mapable0 cascade interrupt\n");
0310 #ifdef USE_LIO3_IRQ
0311 if (request_irq(SGI_MAP_1_IRQ, no_action, IRQF_NO_THREAD,
0312 "mapable1 cascade", NULL))
0313 pr_err("Failed to register mapable1 cascade interrupt\n");
0314 #endif
0315
0316 #ifdef CONFIG_EISA
0317 if (ip22_is_fullhouse())
0318 ip22_eisa_init();
0319 #endif
0320 }