irq.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1992 Linus Torvalds
  7. * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
  8. */
  9. #include <linux/init.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/kernel.h>
  12. #include <linux/spinlock.h>
  13. #include <asm/i8259.h>
  14. #include <asm/io.h>
  15. #include <asm/jazz.h>
  16. extern asmlinkage void jazz_handle_int(void);
  17. static DEFINE_SPINLOCK(r4030_lock);
  18. static void enable_r4030_irq(unsigned int irq)
  19. {
  20. unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
  21. unsigned long flags;
  22. spin_lock_irqsave(&r4030_lock, flags);
  23. mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
  24. r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
  25. spin_unlock_irqrestore(&r4030_lock, flags);
  26. }
  27. static unsigned int startup_r4030_irq(unsigned int irq)
  28. {
  29. enable_r4030_irq(irq);
  30. return 0; /* never anything pending */
  31. }
  32. #define shutdown_r4030_irq disable_r4030_irq
  33. void disable_r4030_irq(unsigned int irq)
  34. {
  35. unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
  36. unsigned long flags;
  37. spin_lock_irqsave(&r4030_lock, flags);
  38. mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
  39. r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
  40. spin_unlock_irqrestore(&r4030_lock, flags);
  41. }
  42. #define mask_and_ack_r4030_irq disable_r4030_irq
  43. static void end_r4030_irq(unsigned int irq)
  44. {
  45. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  46. enable_r4030_irq(irq);
  47. }
  48. static struct hw_interrupt_type r4030_irq_type = {
  49. "R4030",
  50. startup_r4030_irq,
  51. shutdown_r4030_irq,
  52. enable_r4030_irq,
  53. disable_r4030_irq,
  54. mask_and_ack_r4030_irq,
  55. end_r4030_irq,
  56. NULL
  57. };
  58. void __init init_r4030_ints(void)
  59. {
  60. int i;
  61. for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
  62. irq_desc[i].status = IRQ_DISABLED;
  63. irq_desc[i].action = 0;
  64. irq_desc[i].depth = 1;
  65. irq_desc[i].handler = &r4030_irq_type;
  66. }
  67. r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
  68. r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
  69. r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */
  70. }
  71. /*
  72. * On systems with i8259-style interrupt controllers we assume for
  73. * driver compatibility reasons interrupts 0 - 15 to be the i8259
  74. * interrupts even if the hardware uses a different interrupt numbering.
  75. */
  76. void __init arch_init_irq(void)
  77. {
  78. set_except_vector(0, jazz_handle_int);
  79. init_i8259_irqs(); /* Integrated i8259 */
  80. init_r4030_ints();
  81. change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
  82. }