root/arch/mips/sgi-ip22/ip22-int.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. enable_local0_irq
  2. disable_local0_irq
  3. enable_local1_irq
  4. disable_local1_irq
  5. enable_local2_irq
  6. disable_local2_irq
  7. enable_local3_irq
  8. disable_local3_irq
  9. indy_local0_irqdispatch
  10. indy_local1_irqdispatch
  11. indy_buserror_irq
  12. plat_irq_dispatch
  13. arch_init_irq

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * ip22-int.c: Routines for generic manipulation of the INT[23] ASIC
   4  *             found on INDY and Indigo2 workstations.
   5  *
   6  * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
   7  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
   8  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
   9  *                    - Indigo2 changes
  10  *                    - Interrupt handling fixes
  11  * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org)
  12  */
  13 #include <linux/types.h>
  14 #include <linux/init.h>
  15 #include <linux/kernel_stat.h>
  16 #include <linux/interrupt.h>
  17 #include <linux/ftrace.h>
  18 
  19 #include <asm/irq_cpu.h>
  20 #include <asm/sgi/hpc3.h>
  21 #include <asm/sgi/ip22.h>
  22 
  23 /* So far nothing hangs here */
  24 #undef USE_LIO3_IRQ
  25 
  26 struct sgint_regs *sgint;
  27 
  28 static char lc0msk_to_irqnr[256];
  29 static char lc1msk_to_irqnr[256];
  30 static char lc2msk_to_irqnr[256];
  31 static char lc3msk_to_irqnr[256];
  32 
  33 extern int ip22_eisa_init(void);
  34 
  35 static void enable_local0_irq(struct irq_data *d)
  36 {
  37         /* don't allow mappable interrupt to be enabled from setup_irq,
  38          * we have our own way to do so */
  39         if (d->irq != SGI_MAP_0_IRQ)
  40                 sgint->imask0 |= (1 << (d->irq - SGINT_LOCAL0));
  41 }
  42 
  43 static void disable_local0_irq(struct irq_data *d)
  44 {
  45         sgint->imask0 &= ~(1 << (d->irq - SGINT_LOCAL0));
  46 }
  47 
  48 static struct irq_chip ip22_local0_irq_type = {
  49         .name           = "IP22 local 0",
  50         .irq_mask       = disable_local0_irq,
  51         .irq_unmask     = enable_local0_irq,
  52 };
  53 
  54 static void enable_local1_irq(struct irq_data *d)
  55 {
  56         /* don't allow mappable interrupt to be enabled from setup_irq,
  57          * we have our own way to do so */
  58         if (d->irq != SGI_MAP_1_IRQ)
  59                 sgint->imask1 |= (1 << (d->irq - SGINT_LOCAL1));
  60 }
  61 
  62 static void disable_local1_irq(struct irq_data *d)
  63 {
  64         sgint->imask1 &= ~(1 << (d->irq - SGINT_LOCAL1));
  65 }
  66 
  67 static struct irq_chip ip22_local1_irq_type = {
  68         .name           = "IP22 local 1",
  69         .irq_mask       = disable_local1_irq,
  70         .irq_unmask     = enable_local1_irq,
  71 };
  72 
  73 static void enable_local2_irq(struct irq_data *d)
  74 {
  75         sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
  76         sgint->cmeimask0 |= (1 << (d->irq - SGINT_LOCAL2));
  77 }
  78 
  79 static void disable_local2_irq(struct irq_data *d)
  80 {
  81         sgint->cmeimask0 &= ~(1 << (d->irq - SGINT_LOCAL2));
  82         if (!sgint->cmeimask0)
  83                 sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
  84 }
  85 
  86 static struct irq_chip ip22_local2_irq_type = {
  87         .name           = "IP22 local 2",
  88         .irq_mask       = disable_local2_irq,
  89         .irq_unmask     = enable_local2_irq,
  90 };
  91 
  92 static void enable_local3_irq(struct irq_data *d)
  93 {
  94         sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
  95         sgint->cmeimask1 |= (1 << (d->irq - SGINT_LOCAL3));
  96 }
  97 
  98 static void disable_local3_irq(struct irq_data *d)
  99 {
 100         sgint->cmeimask1 &= ~(1 << (d->irq - SGINT_LOCAL3));
 101         if (!sgint->cmeimask1)
 102                 sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
 103 }
 104 
 105 static struct irq_chip ip22_local3_irq_type = {
 106         .name           = "IP22 local 3",
 107         .irq_mask       = disable_local3_irq,
 108         .irq_unmask     = enable_local3_irq,
 109 };
 110 
 111 static void indy_local0_irqdispatch(void)
 112 {
 113         u8 mask = sgint->istat0 & sgint->imask0;
 114         u8 mask2;
 115         int irq;
 116 
 117         if (mask & SGINT_ISTAT0_LIO2) {
 118                 mask2 = sgint->vmeistat & sgint->cmeimask0;
 119                 irq = lc2msk_to_irqnr[mask2];
 120         } else
 121                 irq = lc0msk_to_irqnr[mask];
 122 
 123         /*
 124          * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full
 125          * irq, but failed to latch it into status register
 126          */
 127         if (irq)
 128                 do_IRQ(irq);
 129         else
 130                 do_IRQ(SGINT_LOCAL0 + 0);
 131 }
 132 
 133 static void indy_local1_irqdispatch(void)
 134 {
 135         u8 mask = sgint->istat1 & sgint->imask1;
 136         u8 mask2;
 137         int irq;
 138 
 139         if (mask & SGINT_ISTAT1_LIO3) {
 140                 mask2 = sgint->vmeistat & sgint->cmeimask1;
 141                 irq = lc3msk_to_irqnr[mask2];
 142         } else
 143                 irq = lc1msk_to_irqnr[mask];
 144 
 145         /* if irq == 0, then the interrupt has already been cleared */
 146         if (irq)
 147                 do_IRQ(irq);
 148 }
 149 
 150 extern void ip22_be_interrupt(int irq);
 151 
 152 static void __irq_entry indy_buserror_irq(void)
 153 {
 154         int irq = SGI_BUSERR_IRQ;
 155 
 156         irq_enter();
 157         kstat_incr_irq_this_cpu(irq);
 158         ip22_be_interrupt(irq);
 159         irq_exit();
 160 }
 161 
 162 static struct irqaction local0_cascade = {
 163         .handler        = no_action,
 164         .flags          = IRQF_NO_THREAD,
 165         .name           = "local0 cascade",
 166 };
 167 
 168 static struct irqaction local1_cascade = {
 169         .handler        = no_action,
 170         .flags          = IRQF_NO_THREAD,
 171         .name           = "local1 cascade",
 172 };
 173 
 174 static struct irqaction buserr = {
 175         .handler        = no_action,
 176         .flags          = IRQF_NO_THREAD,
 177         .name           = "Bus Error",
 178 };
 179 
 180 static struct irqaction map0_cascade = {
 181         .handler        = no_action,
 182         .flags          = IRQF_NO_THREAD,
 183         .name           = "mapable0 cascade",
 184 };
 185 
 186 #ifdef USE_LIO3_IRQ
 187 static struct irqaction map1_cascade = {
 188         .handler        = no_action,
 189         .flags          = IRQF_NO_THREAD,
 190         .name           = "mapable1 cascade",
 191 };
 192 #define SGI_INTERRUPTS  SGINT_END
 193 #else
 194 #define SGI_INTERRUPTS  SGINT_LOCAL3
 195 #endif
 196 
 197 extern void indy_8254timer_irq(void);
 198 
 199 /*
 200  * IRQs on the INDY look basically (barring software IRQs which we don't use
 201  * at all) like:
 202  *
 203  *      MIPS IRQ        Source
 204  *      --------        ------
 205  *             0        Software (ignored)
 206  *             1        Software (ignored)
 207  *             2        Local IRQ level zero
 208  *             3        Local IRQ level one
 209  *             4        8254 Timer zero
 210  *             5        8254 Timer one
 211  *             6        Bus Error
 212  *             7        R4k timer (what we use)
 213  *
 214  * We handle the IRQ according to _our_ priority which is:
 215  *
 216  * Highest ----     R4k Timer
 217  *                  Local IRQ zero
 218  *                  Local IRQ one
 219  *                  Bus Error
 220  *                  8254 Timer zero
 221  * Lowest  ----     8254 Timer one
 222  *
 223  * then we just return, if multiple IRQs are pending then we will just take
 224  * another exception, big deal.
 225  */
 226 
 227 asmlinkage void plat_irq_dispatch(void)
 228 {
 229         unsigned int pending = read_c0_status() & read_c0_cause();
 230 
 231         /*
 232          * First we check for r4k counter/timer IRQ.
 233          */
 234         if (pending & CAUSEF_IP7)
 235                 do_IRQ(SGI_TIMER_IRQ);
 236         else if (pending & CAUSEF_IP2)
 237                 indy_local0_irqdispatch();
 238         else if (pending & CAUSEF_IP3)
 239                 indy_local1_irqdispatch();
 240         else if (pending & CAUSEF_IP6)
 241                 indy_buserror_irq();
 242         else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
 243                 indy_8254timer_irq();
 244 }
 245 
 246 void __init arch_init_irq(void)
 247 {
 248         int i;
 249 
 250         /* Init local mask --> irq tables. */
 251         for (i = 0; i < 256; i++) {
 252                 if (i & 0x80) {
 253                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
 254                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
 255                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
 256                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
 257                 } else if (i & 0x40) {
 258                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
 259                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
 260                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
 261                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
 262                 } else if (i & 0x20) {
 263                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
 264                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
 265                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
 266                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
 267                 } else if (i & 0x10) {
 268                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
 269                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
 270                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
 271                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
 272                 } else if (i & 0x08) {
 273                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
 274                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
 275                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
 276                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
 277                 } else if (i & 0x04) {
 278                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
 279                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
 280                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
 281                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
 282                 } else if (i & 0x02) {
 283                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
 284                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
 285                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
 286                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
 287                 } else if (i & 0x01) {
 288                         lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
 289                         lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
 290                         lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
 291                         lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
 292                 } else {
 293                         lc0msk_to_irqnr[i] = 0;
 294                         lc1msk_to_irqnr[i] = 0;
 295                         lc2msk_to_irqnr[i] = 0;
 296                         lc3msk_to_irqnr[i] = 0;
 297                 }
 298         }
 299 
 300         /* Mask out all interrupts. */
 301         sgint->imask0 = 0;
 302         sgint->imask1 = 0;
 303         sgint->cmeimask0 = 0;
 304         sgint->cmeimask1 = 0;
 305 
 306         /* init CPU irqs */
 307         mips_cpu_irq_init();
 308 
 309         for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
 310                 struct irq_chip *handler;
 311 
 312                 if (i < SGINT_LOCAL1)
 313                         handler         = &ip22_local0_irq_type;
 314                 else if (i < SGINT_LOCAL2)
 315                         handler         = &ip22_local1_irq_type;
 316                 else if (i < SGINT_LOCAL3)
 317                         handler         = &ip22_local2_irq_type;
 318                 else
 319                         handler         = &ip22_local3_irq_type;
 320 
 321                 irq_set_chip_and_handler(i, handler, handle_level_irq);
 322         }
 323 
 324         /* vector handler. this register the IRQ as non-sharable */
 325         setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
 326         setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
 327         setup_irq(SGI_BUSERR_IRQ, &buserr);
 328 
 329         /* cascade in cascade. i love Indy ;-) */
 330         setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
 331 #ifdef USE_LIO3_IRQ
 332         setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
 333 #endif
 334 
 335 #ifdef CONFIG_EISA
 336         if (ip22_is_fullhouse())        /* Only Indigo-2 has EISA stuff */
 337                 ip22_eisa_init();
 338 #endif
 339 }

/* [<][>][^][v][top][bottom][index][help] */