root/arch/mips/sgi-ip32/ip32-irq.c

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

DEFINITIONS

This source file includes following definitions.
  1. flush_crime_bus
  2. flush_mace_bus
  3. crime_enable_irq
  4. crime_disable_irq
  5. crime_edge_mask_and_ack_irq
  6. enable_macepci_irq
  7. disable_macepci_irq
  8. enable_maceisa_irq
  9. disable_maceisa_irq
  10. mask_and_ack_maceisa_irq
  11. enable_mace_irq
  12. disable_mace_irq
  13. ip32_unknown_interrupt
  14. ip32_irq0
  15. ip32_irq1
  16. ip32_irq2
  17. ip32_irq3
  18. ip32_irq4
  19. ip32_irq5
  20. plat_irq_dispatch
  21. arch_init_irq

   1 /*
   2  * Code to handle IP32 IRQs
   3  *
   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
   6  * for more details.
   7  *
   8  * Copyright (C) 2000 Harald Koerfgen
   9  * Copyright (C) 2001 Keith M Wesolowski
  10  */
  11 #include <linux/init.h>
  12 #include <linux/kernel_stat.h>
  13 #include <linux/types.h>
  14 #include <linux/interrupt.h>
  15 #include <linux/irq.h>
  16 #include <linux/bitops.h>
  17 #include <linux/kernel.h>
  18 #include <linux/mm.h>
  19 #include <linux/random.h>
  20 #include <linux/sched.h>
  21 #include <linux/sched/debug.h>
  22 
  23 #include <asm/irq_cpu.h>
  24 #include <asm/mipsregs.h>
  25 #include <asm/signal.h>
  26 #include <asm/time.h>
  27 #include <asm/ip32/crime.h>
  28 #include <asm/ip32/mace.h>
  29 #include <asm/ip32/ip32_ints.h>
  30 
  31 /* issue a PIO read to make sure no PIO writes are pending */
  32 static inline void flush_crime_bus(void)
  33 {
  34         crime->control;
  35 }
  36 
  37 static inline void flush_mace_bus(void)
  38 {
  39         mace->perif.ctrl.misc;
  40 }
  41 
  42 /*
  43  * O2 irq map
  44  *
  45  * IP0 -> software (ignored)
  46  * IP1 -> software (ignored)
  47  * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ???
  48  * IP3 -> (irq1) X unknown
  49  * IP4 -> (irq2) X unknown
  50  * IP5 -> (irq3) X unknown
  51  * IP6 -> (irq4) X unknown
  52  * IP7 -> (irq5) 7 CPU count/compare timer (system timer)
  53  *
  54  * crime: (C)
  55  *
  56  * CRIME_INT_STAT 31:0:
  57  *
  58  * 0  ->  8  Video in 1
  59  * 1  ->  9 Video in 2
  60  * 2  -> 10  Video out
  61  * 3  -> 11  Mace ethernet
  62  * 4  -> S  SuperIO sub-interrupt
  63  * 5  -> M  Miscellaneous sub-interrupt
  64  * 6  -> A  Audio sub-interrupt
  65  * 7  -> 15  PCI bridge errors
  66  * 8  -> 16  PCI SCSI aic7xxx 0
  67  * 9  -> 17 PCI SCSI aic7xxx 1
  68  * 10 -> 18 PCI slot 0
  69  * 11 -> 19 unused (PCI slot 1)
  70  * 12 -> 20 unused (PCI slot 2)
  71  * 13 -> 21 unused (PCI shared 0)
  72  * 14 -> 22 unused (PCI shared 1)
  73  * 15 -> 23 unused (PCI shared 2)
  74  * 16 -> 24 GBE0 (E)
  75  * 17 -> 25 GBE1 (E)
  76  * 18 -> 26 GBE2 (E)
  77  * 19 -> 27 GBE3 (E)
  78  * 20 -> 28 CPU errors
  79  * 21 -> 29 Memory errors
  80  * 22 -> 30 RE empty edge (E)
  81  * 23 -> 31 RE full edge (E)
  82  * 24 -> 32 RE idle edge (E)
  83  * 25 -> 33 RE empty level
  84  * 26 -> 34 RE full level
  85  * 27 -> 35 RE idle level
  86  * 28 -> 36 unused (software 0) (E)
  87  * 29 -> 37 unused (software 1) (E)
  88  * 30 -> 38 unused (software 2) - crime 1.5 CPU SysCorError (E)
  89  * 31 -> 39 VICE
  90  *
  91  * S, M, A: Use the MACE ISA interrupt register
  92  * MACE_ISA_INT_STAT 31:0
  93  *
  94  * 0-7 -> 40-47 Audio
  95  * 8 -> 48 RTC
  96  * 9 -> 49 Keyboard
  97  * 10 -> X Keyboard polled
  98  * 11 -> 51 Mouse
  99  * 12 -> X Mouse polled
 100  * 13-15 -> 53-55 Count/compare timers
 101  * 16-19 -> 56-59 Parallel (16 E)
 102  * 20-25 -> 60-62 Serial 1 (22 E)
 103  * 26-31 -> 66-71 Serial 2 (28 E)
 104  *
 105  * Note that this means IRQs 12-14, 50, and 52 do not exist.  This is a
 106  * different IRQ map than IRIX uses, but that's OK as Linux irq handling
 107  * is quite different anyway.
 108  */
 109 
 110 /* Some initial interrupts to set up */
 111 extern irqreturn_t crime_memerr_intr(int irq, void *dev_id);
 112 extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id);
 113 
 114 static struct irqaction memerr_irq = {
 115         .handler = crime_memerr_intr,
 116         .name = "CRIME memory error",
 117 };
 118 
 119 static struct irqaction cpuerr_irq = {
 120         .handler = crime_cpuerr_intr,
 121         .name = "CRIME CPU error",
 122 };
 123 
 124 /*
 125  * This is for pure CRIME interrupts - ie not MACE.  The advantage?
 126  * We get to split the register in half and do faster lookups.
 127  */
 128 
 129 static uint64_t crime_mask;
 130 
 131 static inline void crime_enable_irq(struct irq_data *d)
 132 {
 133         unsigned int bit = d->irq - CRIME_IRQ_BASE;
 134 
 135         crime_mask |= 1 << bit;
 136         crime->imask = crime_mask;
 137 }
 138 
 139 static inline void crime_disable_irq(struct irq_data *d)
 140 {
 141         unsigned int bit = d->irq - CRIME_IRQ_BASE;
 142 
 143         crime_mask &= ~(1 << bit);
 144         crime->imask = crime_mask;
 145         flush_crime_bus();
 146 }
 147 
 148 static struct irq_chip crime_level_interrupt = {
 149         .name           = "IP32 CRIME",
 150         .irq_mask       = crime_disable_irq,
 151         .irq_unmask     = crime_enable_irq,
 152 };
 153 
 154 static void crime_edge_mask_and_ack_irq(struct irq_data *d)
 155 {
 156         unsigned int bit = d->irq - CRIME_IRQ_BASE;
 157         uint64_t crime_int;
 158 
 159         /* Edge triggered interrupts must be cleared. */
 160         crime_int = crime->hard_int;
 161         crime_int &= ~(1 << bit);
 162         crime->hard_int = crime_int;
 163 
 164         crime_disable_irq(d);
 165 }
 166 
 167 static struct irq_chip crime_edge_interrupt = {
 168         .name           = "IP32 CRIME",
 169         .irq_ack        = crime_edge_mask_and_ack_irq,
 170         .irq_mask       = crime_disable_irq,
 171         .irq_mask_ack   = crime_edge_mask_and_ack_irq,
 172         .irq_unmask     = crime_enable_irq,
 173 };
 174 
 175 /*
 176  * This is for MACE PCI interrupts.  We can decrease bus traffic by masking
 177  * as close to the source as possible.  This also means we can take the
 178  * next chunk of the CRIME register in one piece.
 179  */
 180 
 181 static unsigned long macepci_mask;
 182 
 183 static void enable_macepci_irq(struct irq_data *d)
 184 {
 185         macepci_mask |= MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ);
 186         mace->pci.control = macepci_mask;
 187         crime_mask |= 1 << (d->irq - CRIME_IRQ_BASE);
 188         crime->imask = crime_mask;
 189 }
 190 
 191 static void disable_macepci_irq(struct irq_data *d)
 192 {
 193         crime_mask &= ~(1 << (d->irq - CRIME_IRQ_BASE));
 194         crime->imask = crime_mask;
 195         flush_crime_bus();
 196         macepci_mask &= ~MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ);
 197         mace->pci.control = macepci_mask;
 198         flush_mace_bus();
 199 }
 200 
 201 static struct irq_chip ip32_macepci_interrupt = {
 202         .name = "IP32 MACE PCI",
 203         .irq_mask = disable_macepci_irq,
 204         .irq_unmask = enable_macepci_irq,
 205 };
 206 
 207 /* This is used for MACE ISA interrupts.  That means bits 4-6 in the
 208  * CRIME register.
 209  */
 210 
 211 #define MACEISA_AUDIO_INT       (MACEISA_AUDIO_SW_INT |         \
 212                                  MACEISA_AUDIO_SC_INT |         \
 213                                  MACEISA_AUDIO1_DMAT_INT |      \
 214                                  MACEISA_AUDIO1_OF_INT |        \
 215                                  MACEISA_AUDIO2_DMAT_INT |      \
 216                                  MACEISA_AUDIO2_MERR_INT |      \
 217                                  MACEISA_AUDIO3_DMAT_INT |      \
 218                                  MACEISA_AUDIO3_MERR_INT)
 219 #define MACEISA_MISC_INT        (MACEISA_RTC_INT |              \
 220                                  MACEISA_KEYB_INT |             \
 221                                  MACEISA_KEYB_POLL_INT |        \
 222                                  MACEISA_MOUSE_INT |            \
 223                                  MACEISA_MOUSE_POLL_INT |       \
 224                                  MACEISA_TIMER0_INT |           \
 225                                  MACEISA_TIMER1_INT |           \
 226                                  MACEISA_TIMER2_INT)
 227 #define MACEISA_SUPERIO_INT     (MACEISA_PARALLEL_INT |         \
 228                                  MACEISA_PAR_CTXA_INT |         \
 229                                  MACEISA_PAR_CTXB_INT |         \
 230                                  MACEISA_PAR_MERR_INT |         \
 231                                  MACEISA_SERIAL1_INT |          \
 232                                  MACEISA_SERIAL1_TDMAT_INT |    \
 233                                  MACEISA_SERIAL1_TDMAPR_INT |   \
 234                                  MACEISA_SERIAL1_TDMAME_INT |   \
 235                                  MACEISA_SERIAL1_RDMAT_INT |    \
 236                                  MACEISA_SERIAL1_RDMAOR_INT |   \
 237                                  MACEISA_SERIAL2_INT |          \
 238                                  MACEISA_SERIAL2_TDMAT_INT |    \
 239                                  MACEISA_SERIAL2_TDMAPR_INT |   \
 240                                  MACEISA_SERIAL2_TDMAME_INT |   \
 241                                  MACEISA_SERIAL2_RDMAT_INT |    \
 242                                  MACEISA_SERIAL2_RDMAOR_INT)
 243 
 244 static unsigned long maceisa_mask;
 245 
 246 static void enable_maceisa_irq(struct irq_data *d)
 247 {
 248         unsigned int crime_int = 0;
 249 
 250         pr_debug("maceisa enable: %u\n", d->irq);
 251 
 252         switch (d->irq) {
 253         case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ:
 254                 crime_int = MACE_AUDIO_INT;
 255                 break;
 256         case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ:
 257                 crime_int = MACE_MISC_INT;
 258                 break;
 259         case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ:
 260                 crime_int = MACE_SUPERIO_INT;
 261                 break;
 262         }
 263         pr_debug("crime_int %08x enabled\n", crime_int);
 264         crime_mask |= crime_int;
 265         crime->imask = crime_mask;
 266         maceisa_mask |= 1 << (d->irq - MACEISA_AUDIO_SW_IRQ);
 267         mace->perif.ctrl.imask = maceisa_mask;
 268 }
 269 
 270 static void disable_maceisa_irq(struct irq_data *d)
 271 {
 272         unsigned int crime_int = 0;
 273 
 274         maceisa_mask &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ));
 275         if (!(maceisa_mask & MACEISA_AUDIO_INT))
 276                 crime_int |= MACE_AUDIO_INT;
 277         if (!(maceisa_mask & MACEISA_MISC_INT))
 278                 crime_int |= MACE_MISC_INT;
 279         if (!(maceisa_mask & MACEISA_SUPERIO_INT))
 280                 crime_int |= MACE_SUPERIO_INT;
 281         crime_mask &= ~crime_int;
 282         crime->imask = crime_mask;
 283         flush_crime_bus();
 284         mace->perif.ctrl.imask = maceisa_mask;
 285         flush_mace_bus();
 286 }
 287 
 288 static void mask_and_ack_maceisa_irq(struct irq_data *d)
 289 {
 290         unsigned long mace_int;
 291 
 292         /* edge triggered */
 293         mace_int = mace->perif.ctrl.istat;
 294         mace_int &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ));
 295         mace->perif.ctrl.istat = mace_int;
 296 
 297         disable_maceisa_irq(d);
 298 }
 299 
 300 static struct irq_chip ip32_maceisa_level_interrupt = {
 301         .name           = "IP32 MACE ISA",
 302         .irq_mask       = disable_maceisa_irq,
 303         .irq_unmask     = enable_maceisa_irq,
 304 };
 305 
 306 static struct irq_chip ip32_maceisa_edge_interrupt = {
 307         .name           = "IP32 MACE ISA",
 308         .irq_ack        = mask_and_ack_maceisa_irq,
 309         .irq_mask       = disable_maceisa_irq,
 310         .irq_mask_ack   = mask_and_ack_maceisa_irq,
 311         .irq_unmask     = enable_maceisa_irq,
 312 };
 313 
 314 /* This is used for regular non-ISA, non-PCI MACE interrupts.  That means
 315  * bits 0-3 and 7 in the CRIME register.
 316  */
 317 
 318 static void enable_mace_irq(struct irq_data *d)
 319 {
 320         unsigned int bit = d->irq - CRIME_IRQ_BASE;
 321 
 322         crime_mask |= (1 << bit);
 323         crime->imask = crime_mask;
 324 }
 325 
 326 static void disable_mace_irq(struct irq_data *d)
 327 {
 328         unsigned int bit = d->irq - CRIME_IRQ_BASE;
 329 
 330         crime_mask &= ~(1 << bit);
 331         crime->imask = crime_mask;
 332         flush_crime_bus();
 333 }
 334 
 335 static struct irq_chip ip32_mace_interrupt = {
 336         .name = "IP32 MACE",
 337         .irq_mask = disable_mace_irq,
 338         .irq_unmask = enable_mace_irq,
 339 };
 340 
 341 static void ip32_unknown_interrupt(void)
 342 {
 343         printk("Unknown interrupt occurred!\n");
 344         printk("cp0_status: %08x\n", read_c0_status());
 345         printk("cp0_cause: %08x\n", read_c0_cause());
 346         printk("CRIME intr mask: %016lx\n", crime->imask);
 347         printk("CRIME intr status: %016lx\n", crime->istat);
 348         printk("CRIME hardware intr register: %016lx\n", crime->hard_int);
 349         printk("MACE ISA intr mask: %08lx\n", mace->perif.ctrl.imask);
 350         printk("MACE ISA intr status: %08lx\n", mace->perif.ctrl.istat);
 351         printk("MACE PCI control register: %08x\n", mace->pci.control);
 352 
 353         printk("Register dump:\n");
 354         show_regs(get_irq_regs());
 355 
 356         printk("Please mail this report to linux-mips@linux-mips.org\n");
 357         printk("Spinning...");
 358         while(1) ;
 359 }
 360 
 361 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
 362 /* change this to loop over all edge-triggered irqs, exception masked out ones */
 363 static void ip32_irq0(void)
 364 {
 365         uint64_t crime_int;
 366         int irq = 0;
 367 
 368         /*
 369          * Sanity check interrupt numbering enum.
 370          * MACE got 32 interrupts and there are 32 MACE ISA interrupts daisy
 371          * chained.
 372          */
 373         BUILD_BUG_ON(CRIME_VICE_IRQ - MACE_VID_IN1_IRQ != 31);
 374         BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31);
 375 
 376         crime_int = crime->istat & crime_mask;
 377 
 378         /* crime sometime delivers spurious interrupts, ignore them */
 379         if (unlikely(crime_int == 0))
 380                 return;
 381 
 382         irq = MACE_VID_IN1_IRQ + __ffs(crime_int);
 383 
 384         if (crime_int & CRIME_MACEISA_INT_MASK) {
 385                 unsigned long mace_int = mace->perif.ctrl.istat;
 386                 irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ;
 387         }
 388 
 389         pr_debug("*irq %u*\n", irq);
 390         do_IRQ(irq);
 391 }
 392 
 393 static void ip32_irq1(void)
 394 {
 395         ip32_unknown_interrupt();
 396 }
 397 
 398 static void ip32_irq2(void)
 399 {
 400         ip32_unknown_interrupt();
 401 }
 402 
 403 static void ip32_irq3(void)
 404 {
 405         ip32_unknown_interrupt();
 406 }
 407 
 408 static void ip32_irq4(void)
 409 {
 410         ip32_unknown_interrupt();
 411 }
 412 
 413 static void ip32_irq5(void)
 414 {
 415         do_IRQ(MIPS_CPU_IRQ_BASE + 7);
 416 }
 417 
 418 asmlinkage void plat_irq_dispatch(void)
 419 {
 420         unsigned int pending = read_c0_status() & read_c0_cause();
 421 
 422         if (likely(pending & IE_IRQ0))
 423                 ip32_irq0();
 424         else if (unlikely(pending & IE_IRQ1))
 425                 ip32_irq1();
 426         else if (unlikely(pending & IE_IRQ2))
 427                 ip32_irq2();
 428         else if (unlikely(pending & IE_IRQ3))
 429                 ip32_irq3();
 430         else if (unlikely(pending & IE_IRQ4))
 431                 ip32_irq4();
 432         else if (likely(pending & IE_IRQ5))
 433                 ip32_irq5();
 434 }
 435 
 436 void __init arch_init_irq(void)
 437 {
 438         unsigned int irq;
 439 
 440         /* Install our interrupt handler, then clear and disable all
 441          * CRIME and MACE interrupts. */
 442         crime->imask = 0;
 443         crime->hard_int = 0;
 444         crime->soft_int = 0;
 445         mace->perif.ctrl.istat = 0;
 446         mace->perif.ctrl.imask = 0;
 447 
 448         mips_cpu_irq_init();
 449         for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) {
 450                 switch (irq) {
 451                 case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ:
 452                         irq_set_chip_and_handler_name(irq,
 453                                                       &ip32_mace_interrupt,
 454                                                       handle_level_irq,
 455                                                       "level");
 456                         break;
 457 
 458                 case MACEPCI_SCSI0_IRQ ...  MACEPCI_SHARED2_IRQ:
 459                         irq_set_chip_and_handler_name(irq,
 460                                                       &ip32_macepci_interrupt,
 461                                                       handle_level_irq,
 462                                                       "level");
 463                         break;
 464 
 465                 case CRIME_CPUERR_IRQ:
 466                 case CRIME_MEMERR_IRQ:
 467                         irq_set_chip_and_handler_name(irq,
 468                                                       &crime_level_interrupt,
 469                                                       handle_level_irq,
 470                                                       "level");
 471                         break;
 472 
 473                 case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ:
 474                 case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ:
 475                 case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ:
 476                 case CRIME_VICE_IRQ:
 477                         irq_set_chip_and_handler_name(irq,
 478                                                       &crime_edge_interrupt,
 479                                                       handle_edge_irq,
 480                                                       "edge");
 481                         break;
 482 
 483                 case MACEISA_PARALLEL_IRQ:
 484                 case MACEISA_SERIAL1_TDMAPR_IRQ:
 485                 case MACEISA_SERIAL2_TDMAPR_IRQ:
 486                         irq_set_chip_and_handler_name(irq,
 487                                                       &ip32_maceisa_edge_interrupt,
 488                                                       handle_edge_irq,
 489                                                       "edge");
 490                         break;
 491 
 492                 default:
 493                         irq_set_chip_and_handler_name(irq,
 494                                                       &ip32_maceisa_level_interrupt,
 495                                                       handle_level_irq,
 496                                                       "level");
 497                         break;
 498                 }
 499         }
 500         setup_irq(CRIME_MEMERR_IRQ, &memerr_irq);
 501         setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq);
 502 
 503 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 504         change_c0_status(ST0_IM, ALLINTS);
 505 }

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