irq.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * linux/arch/sh/boards/ec3104/irq.c
  3. * EC3104 companion chip support
  4. *
  5. * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
  6. *
  7. */
  8. #include <asm/io.h>
  9. #include <asm/irq.h>
  10. #include <asm/ec3104/ec3104.h>
  11. /* This is for debugging mostly; here's the table that I intend to keep
  12. * in here:
  13. *
  14. * index function base addr power interrupt bit
  15. * 0 power b0ec0000 --- 00000001 (unused)
  16. * 1 irqs b0ec1000 --- 00000002 (unused)
  17. * 2 ?? b0ec2000 b0ec0008 00000004
  18. * 3 PS2 (1) b0ec3000 b0ec000c 00000008
  19. * 4 PS2 (2) b0ec4000 b0ec0010 00000010
  20. * 5 ?? b0ec5000 b0ec0014 00000020
  21. * 6 I2C b0ec6000 b0ec0018 00000040
  22. * 7 serial (1) b0ec7000 b0ec001c 00000080
  23. * 8 serial (2) b0ec8000 b0ec0020 00000100
  24. * 9 serial (3) b0ec9000 b0ec0024 00000200
  25. * 10 serial (4) b0eca000 b0ec0028 00000400
  26. * 12 GPIO (1) b0ecc000 b0ec0030
  27. * 13 GPIO (2) b0ecc000 b0ec0030
  28. * 16 pcmcia (1) b0ed0000 b0ec0040 00010000
  29. * 17 pcmcia (2) b0ed1000 b0ec0044 00020000
  30. */
  31. /* I used the register names from another interrupt controller I worked with,
  32. * since it seems to be identical to the ec3104 except that all bits are
  33. * inverted:
  34. *
  35. * IRR: Interrupt Request Register (pending and enabled interrupts)
  36. * IMR: Interrupt Mask Register (which interrupts are enabled)
  37. * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
  38. *
  39. * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all
  40. * IRQs seem to be level-triggered.
  41. */
  42. #define EC3104_IRR (EC3104_BASE + 0x1000)
  43. #define EC3104_IMR (EC3104_BASE + 0x1004)
  44. #define EC3104_IPR (EC3104_BASE + 0x1008)
  45. #define ctrl_readl(addr) (*(volatile u32 *)(addr))
  46. #define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
  47. #define ctrl_readb(addr) (*(volatile u8 *)(addr))
  48. static char *ec3104_name(unsigned index)
  49. {
  50. switch(index) {
  51. case 0:
  52. return "power management";
  53. case 1:
  54. return "interrupts";
  55. case 3:
  56. return "PS2 (1)";
  57. case 4:
  58. return "PS2 (2)";
  59. case 5:
  60. return "I2C (1)";
  61. case 6:
  62. return "I2C (2)";
  63. case 7:
  64. return "serial (1)";
  65. case 8:
  66. return "serial (2)";
  67. case 9:
  68. return "serial (3)";
  69. case 10:
  70. return "serial (4)";
  71. case 16:
  72. return "pcmcia (1)";
  73. case 17:
  74. return "pcmcia (2)";
  75. default: {
  76. static char buf[32];
  77. sprintf(buf, "unknown (%d)", index);
  78. return buf;
  79. }
  80. }
  81. }
  82. int get_pending_interrupts(char *buf)
  83. {
  84. u32 ipr;
  85. u32 bit;
  86. char *p = buf;
  87. p += sprintf(p, "pending: (");
  88. ipr = ctrl_inl(EC3104_IPR);
  89. for (bit = 1; bit < 32; bit++)
  90. if (!(ipr & (1<<bit)))
  91. p += sprintf(p, "%s ", ec3104_name(bit));
  92. p += sprintf(p, ")\n");
  93. return p - buf;
  94. }
  95. static inline u32 ec3104_irq2mask(unsigned int irq)
  96. {
  97. return (1 << (irq - EC3104_IRQBASE));
  98. }
  99. static inline void mask_ec3104_irq(unsigned int irq)
  100. {
  101. u32 mask;
  102. mask = ctrl_readl(EC3104_IMR);
  103. mask |= ec3104_irq2mask(irq);
  104. ctrl_writel(mask, EC3104_IMR);
  105. }
  106. static inline void unmask_ec3104_irq(unsigned int irq)
  107. {
  108. u32 mask;
  109. mask = ctrl_readl(EC3104_IMR);
  110. mask &= ~ec3104_irq2mask(irq);
  111. ctrl_writel(mask, EC3104_IMR);
  112. }
  113. static void disable_ec3104_irq(unsigned int irq)
  114. {
  115. mask_ec3104_irq(irq);
  116. }
  117. static void enable_ec3104_irq(unsigned int irq)
  118. {
  119. unmask_ec3104_irq(irq);
  120. }
  121. static void mask_and_ack_ec3104_irq(unsigned int irq)
  122. {
  123. mask_ec3104_irq(irq);
  124. }
  125. static void end_ec3104_irq(unsigned int irq)
  126. {
  127. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  128. unmask_ec3104_irq(irq);
  129. }
  130. static unsigned int startup_ec3104_irq(unsigned int irq)
  131. {
  132. unmask_ec3104_irq(irq);
  133. return 0;
  134. }
  135. static void shutdown_ec3104_irq(unsigned int irq)
  136. {
  137. mask_ec3104_irq(irq);
  138. }
  139. static struct hw_interrupt_type ec3104_int = {
  140. .typename = "EC3104",
  141. .enable = enable_ec3104_irq,
  142. .disable = disable_ec3104_irq,
  143. .ack = mask_and_ack_ec3104_irq,
  144. .end = end_ec3104_irq,
  145. .startup = startup_ec3104_irq,
  146. .shutdown = shutdown_ec3104_irq,
  147. };
  148. /* Yuck. the _demux API is ugly */
  149. int ec3104_irq_demux(int irq)
  150. {
  151. if (irq == EC3104_IRQ) {
  152. unsigned int mask;
  153. mask = ctrl_readl(EC3104_IRR);
  154. if (mask == 0xffffffff)
  155. return EC3104_IRQ;
  156. else
  157. return EC3104_IRQBASE + ffz(mask);
  158. }
  159. return irq;
  160. }