irq.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
  3. *
  4. * May be copied or modified under the terms of the GNU General Public
  5. * License. See linux/COPYING for more information.
  6. *
  7. * Looks after interrupts on the HARP board.
  8. *
  9. * Bases on the IPR irq system
  10. */
  11. #include <linux/init.h>
  12. #include <linux/irq.h>
  13. #include <asm/system.h>
  14. #include <asm/io.h>
  15. #include <asm/harp/harp.h>
  16. #define NUM_EXTERNAL_IRQS 16
  17. // Early versions of the STB1 Overdrive required this nasty frig
  18. //#define INVERT_INTMASK_WRITES
  19. static void enable_harp_irq(unsigned int irq);
  20. static void disable_harp_irq(unsigned int irq);
  21. /* shutdown is same as "disable" */
  22. #define shutdown_harp_irq disable_harp_irq
  23. static void mask_and_ack_harp(unsigned int);
  24. static void end_harp_irq(unsigned int irq);
  25. static unsigned int startup_harp_irq(unsigned int irq)
  26. {
  27. enable_harp_irq(irq);
  28. return 0; /* never anything pending */
  29. }
  30. static struct hw_interrupt_type harp_irq_type = {
  31. .typename = "Harp-IRQ",
  32. .startup = startup_harp_irq,
  33. .shutdown = shutdown_harp_irq,
  34. .enable = enable_harp_irq,
  35. .disable = disable_harp_irq,
  36. .ack = mask_and_ack_harp,
  37. .end = end_harp_irq
  38. };
  39. static void disable_harp_irq(unsigned int irq)
  40. {
  41. unsigned val, flags;
  42. unsigned maskReg;
  43. unsigned mask;
  44. int pri;
  45. if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
  46. return;
  47. pri = 15 - irq;
  48. if (pri < 8) {
  49. maskReg = EPLD_INTMASK0;
  50. } else {
  51. maskReg = EPLD_INTMASK1;
  52. pri -= 8;
  53. }
  54. local_irq_save(flags);
  55. mask = ctrl_inl(maskReg);
  56. mask &= (~(1 << pri));
  57. #if defined(INVERT_INTMASK_WRITES)
  58. mask ^= 0xff;
  59. #endif
  60. ctrl_outl(mask, maskReg);
  61. local_irq_restore(flags);
  62. }
  63. static void enable_harp_irq(unsigned int irq)
  64. {
  65. unsigned flags;
  66. unsigned maskReg;
  67. unsigned mask;
  68. int pri;
  69. if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
  70. return;
  71. pri = 15 - irq;
  72. if (pri < 8) {
  73. maskReg = EPLD_INTMASK0;
  74. } else {
  75. maskReg = EPLD_INTMASK1;
  76. pri -= 8;
  77. }
  78. local_irq_save(flags);
  79. mask = ctrl_inl(maskReg);
  80. mask |= (1 << pri);
  81. #if defined(INVERT_INTMASK_WRITES)
  82. mask ^= 0xff;
  83. #endif
  84. ctrl_outl(mask, maskReg);
  85. local_irq_restore(flags);
  86. }
  87. /* This functions sets the desired irq handler to be an overdrive type */
  88. static void __init make_harp_irq(unsigned int irq)
  89. {
  90. disable_irq_nosync(irq);
  91. irq_desc[irq].chip = &harp_irq_type;
  92. disable_harp_irq(irq);
  93. }
  94. static void mask_and_ack_harp(unsigned int irq)
  95. {
  96. disable_harp_irq(irq);
  97. }
  98. static void end_harp_irq(unsigned int irq)
  99. {
  100. enable_harp_irq(irq);
  101. }
  102. void __init init_harp_irq(void)
  103. {
  104. int i;
  105. #if !defined(INVERT_INTMASK_WRITES)
  106. // On the harp these are set to enable an interrupt
  107. ctrl_outl(0x00, EPLD_INTMASK0);
  108. ctrl_outl(0x00, EPLD_INTMASK1);
  109. #else
  110. // On the Overdrive the data is inverted before being stored in the reg
  111. ctrl_outl(0xff, EPLD_INTMASK0);
  112. ctrl_outl(0xff, EPLD_INTMASK1);
  113. #endif
  114. for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
  115. make_harp_irq(i);
  116. }
  117. }