mpc52xx_pic.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * arch/ppc/syslib/mpc52xx_pic.c
  3. *
  4. * Programmable Interrupt Controller functions for the Freescale MPC52xx
  5. * embedded CPU.
  6. *
  7. *
  8. * Maintainer : Sylvain Munaut <tnt@246tNt.com>
  9. *
  10. * Based on (well, mostly copied from) the code from the 2.4 kernel by
  11. * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
  12. *
  13. * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
  14. * Copyright (C) 2003 Montavista Software, Inc
  15. *
  16. * This file is licensed under the terms of the GNU General Public License
  17. * version 2. This program is licensed "as is" without any warranty of any
  18. * kind, whether express or implied.
  19. */
  20. #include <linux/stddef.h>
  21. #include <linux/init.h>
  22. #include <linux/sched.h>
  23. #include <linux/signal.h>
  24. #include <linux/stddef.h>
  25. #include <linux/delay.h>
  26. #include <linux/irq.h>
  27. #include <asm/io.h>
  28. #include <asm/processor.h>
  29. #include <asm/system.h>
  30. #include <asm/irq.h>
  31. #include <asm/mpc52xx.h>
  32. static struct mpc52xx_intr __iomem *intr;
  33. static struct mpc52xx_sdma __iomem *sdma;
  34. static void
  35. mpc52xx_ic_disable(unsigned int irq)
  36. {
  37. u32 val;
  38. if (irq == MPC52xx_IRQ0) {
  39. val = in_be32(&intr->ctrl);
  40. val &= ~(1 << 11);
  41. out_be32(&intr->ctrl, val);
  42. }
  43. else if (irq < MPC52xx_IRQ1) {
  44. BUG();
  45. }
  46. else if (irq <= MPC52xx_IRQ3) {
  47. val = in_be32(&intr->ctrl);
  48. val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
  49. out_be32(&intr->ctrl, val);
  50. }
  51. else if (irq < MPC52xx_SDMA_IRQ_BASE) {
  52. val = in_be32(&intr->main_mask);
  53. val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
  54. out_be32(&intr->main_mask, val);
  55. }
  56. else if (irq < MPC52xx_PERP_IRQ_BASE) {
  57. val = in_be32(&sdma->IntMask);
  58. val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
  59. out_be32(&sdma->IntMask, val);
  60. }
  61. else {
  62. val = in_be32(&intr->per_mask);
  63. val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
  64. out_be32(&intr->per_mask, val);
  65. }
  66. }
  67. static void
  68. mpc52xx_ic_enable(unsigned int irq)
  69. {
  70. u32 val;
  71. if (irq == MPC52xx_IRQ0) {
  72. val = in_be32(&intr->ctrl);
  73. val |= 1 << 11;
  74. out_be32(&intr->ctrl, val);
  75. }
  76. else if (irq < MPC52xx_IRQ1) {
  77. BUG();
  78. }
  79. else if (irq <= MPC52xx_IRQ3) {
  80. val = in_be32(&intr->ctrl);
  81. val |= 1 << (10 - (irq - MPC52xx_IRQ1));
  82. out_be32(&intr->ctrl, val);
  83. }
  84. else if (irq < MPC52xx_SDMA_IRQ_BASE) {
  85. val = in_be32(&intr->main_mask);
  86. val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
  87. out_be32(&intr->main_mask, val);
  88. }
  89. else if (irq < MPC52xx_PERP_IRQ_BASE) {
  90. val = in_be32(&sdma->IntMask);
  91. val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
  92. out_be32(&sdma->IntMask, val);
  93. }
  94. else {
  95. val = in_be32(&intr->per_mask);
  96. val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
  97. out_be32(&intr->per_mask, val);
  98. }
  99. }
  100. static void
  101. mpc52xx_ic_ack(unsigned int irq)
  102. {
  103. u32 val;
  104. /*
  105. * Only some irqs are reset here, others in interrupting hardware.
  106. */
  107. switch (irq) {
  108. case MPC52xx_IRQ0:
  109. val = in_be32(&intr->ctrl);
  110. val |= 0x08000000;
  111. out_be32(&intr->ctrl, val);
  112. break;
  113. case MPC52xx_CCS_IRQ:
  114. val = in_be32(&intr->enc_status);
  115. val |= 0x00000400;
  116. out_be32(&intr->enc_status, val);
  117. break;
  118. case MPC52xx_IRQ1:
  119. val = in_be32(&intr->ctrl);
  120. val |= 0x04000000;
  121. out_be32(&intr->ctrl, val);
  122. break;
  123. case MPC52xx_IRQ2:
  124. val = in_be32(&intr->ctrl);
  125. val |= 0x02000000;
  126. out_be32(&intr->ctrl, val);
  127. break;
  128. case MPC52xx_IRQ3:
  129. val = in_be32(&intr->ctrl);
  130. val |= 0x01000000;
  131. out_be32(&intr->ctrl, val);
  132. break;
  133. default:
  134. if (irq >= MPC52xx_SDMA_IRQ_BASE
  135. && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
  136. out_be32(&sdma->IntPend,
  137. 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
  138. }
  139. break;
  140. }
  141. }
  142. static void
  143. mpc52xx_ic_disable_and_ack(unsigned int irq)
  144. {
  145. mpc52xx_ic_disable(irq);
  146. mpc52xx_ic_ack(irq);
  147. }
  148. static void
  149. mpc52xx_ic_end(unsigned int irq)
  150. {
  151. if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  152. mpc52xx_ic_enable(irq);
  153. }
  154. static struct hw_interrupt_type mpc52xx_ic = {
  155. .typename = " MPC52xx ",
  156. .enable = mpc52xx_ic_enable,
  157. .disable = mpc52xx_ic_disable,
  158. .ack = mpc52xx_ic_disable_and_ack,
  159. .end = mpc52xx_ic_end,
  160. };
  161. void __init
  162. mpc52xx_init_irq(void)
  163. {
  164. int i;
  165. u32 intr_ctrl;
  166. /* Remap the necessary zones */
  167. intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
  168. sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
  169. if ((intr==NULL) || (sdma==NULL))
  170. panic("Can't ioremap PIC/SDMA register for init_irq !");
  171. /* Disable all interrupt sources. */
  172. out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
  173. out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
  174. out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
  175. out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
  176. intr_ctrl = in_be32(&intr->ctrl);
  177. intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
  178. intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
  179. 0x00001000 | /* MEE master external enable */
  180. 0x00000000 | /* 0 means disable IRQ 0-3 */
  181. 0x00000001; /* CEb route critical normally */
  182. out_be32(&intr->ctrl, intr_ctrl);
  183. /* Zero a bunch of the priority settings. */
  184. out_be32(&intr->per_pri1, 0);
  185. out_be32(&intr->per_pri2, 0);
  186. out_be32(&intr->per_pri3, 0);
  187. out_be32(&intr->main_pri1, 0);
  188. out_be32(&intr->main_pri2, 0);
  189. /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
  190. for (i = 0; i < NR_IRQS; i++) {
  191. irq_desc[i].handler = &mpc52xx_ic;
  192. irq_desc[i].status = IRQ_LEVEL;
  193. }
  194. #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
  195. for (i=0 ; i<4 ; i++) {
  196. int mode;
  197. mode = IRQn_MODE(intr_ctrl,i);
  198. if ((mode == 0x1) || (mode == 0x2))
  199. irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
  200. }
  201. }
  202. int
  203. mpc52xx_get_irq(struct pt_regs *regs)
  204. {
  205. u32 status;
  206. int irq = -1;
  207. status = in_be32(&intr->enc_status);
  208. if (status & 0x00000400) { /* critical */
  209. irq = (status >> 8) & 0x3;
  210. if (irq == 2) /* high priority peripheral */
  211. goto peripheral;
  212. irq += MPC52xx_CRIT_IRQ_BASE;
  213. }
  214. else if (status & 0x00200000) { /* main */
  215. irq = (status >> 16) & 0x1f;
  216. if (irq == 4) /* low priority peripheral */
  217. goto peripheral;
  218. irq += MPC52xx_MAIN_IRQ_BASE;
  219. }
  220. else if (status & 0x20000000) { /* peripheral */
  221. peripheral:
  222. irq = (status >> 24) & 0x1f;
  223. if (irq == 0) { /* bestcomm */
  224. status = in_be32(&sdma->IntPend);
  225. irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
  226. }
  227. else
  228. irq += MPC52xx_PERP_IRQ_BASE;
  229. }
  230. return irq;
  231. }