xilinx_pic.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * arch/ppc/syslib/xilinx_pic.c
  3. *
  4. * Interrupt controller driver for Xilinx Virtex-II Pro.
  5. *
  6. * Author: MontaVista Software, Inc.
  7. * source@mvista.com
  8. *
  9. * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under
  10. * the terms of the GNU General Public License version 2. This program
  11. * is licensed "as is" without any warranty of any kind, whether express
  12. * or implied.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/irq.h>
  16. #include <asm/io.h>
  17. #include <asm/xparameters.h>
  18. #include <asm/ibm4xx.h>
  19. #include <asm/machdep.h>
  20. /* No one else should require these constants, so define them locally here. */
  21. #define ISR 0 /* Interrupt Status Register */
  22. #define IPR 1 /* Interrupt Pending Register */
  23. #define IER 2 /* Interrupt Enable Register */
  24. #define IAR 3 /* Interrupt Acknowledge Register */
  25. #define SIE 4 /* Set Interrupt Enable bits */
  26. #define CIE 5 /* Clear Interrupt Enable bits */
  27. #define IVR 6 /* Interrupt Vector Register */
  28. #define MER 7 /* Master Enable Register */
  29. #if XPAR_XINTC_USE_DCR == 0
  30. static volatile u32 *intc;
  31. #define intc_out_be32(addr, mask) out_be32((addr), (mask))
  32. #define intc_in_be32(addr) in_be32((addr))
  33. #else
  34. #define intc XPAR_INTC_0_BASEADDR
  35. #define intc_out_be32(addr, mask) mtdcr((addr), (mask))
  36. #define intc_in_be32(addr) mfdcr((addr))
  37. #endif
  38. static void
  39. xilinx_intc_enable(unsigned int irq)
  40. {
  41. unsigned long mask = (0x00000001 << (irq & 31));
  42. pr_debug("enable: %d\n", irq);
  43. intc_out_be32(intc + SIE, mask);
  44. }
  45. static void
  46. xilinx_intc_disable(unsigned int irq)
  47. {
  48. unsigned long mask = (0x00000001 << (irq & 31));
  49. pr_debug("disable: %d\n", irq);
  50. intc_out_be32(intc + CIE, mask);
  51. }
  52. static void
  53. xilinx_intc_disable_and_ack(unsigned int irq)
  54. {
  55. unsigned long mask = (0x00000001 << (irq & 31));
  56. pr_debug("disable_and_ack: %d\n", irq);
  57. intc_out_be32(intc + CIE, mask);
  58. if (!(irq_desc[irq].status & IRQ_LEVEL))
  59. intc_out_be32(intc + IAR, mask); /* ack edge triggered intr */
  60. }
  61. static void
  62. xilinx_intc_end(unsigned int irq)
  63. {
  64. unsigned long mask = (0x00000001 << (irq & 31));
  65. pr_debug("end: %d\n", irq);
  66. if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
  67. intc_out_be32(intc + SIE, mask);
  68. /* ack level sensitive intr */
  69. if (irq_desc[irq].status & IRQ_LEVEL)
  70. intc_out_be32(intc + IAR, mask);
  71. }
  72. }
  73. static struct hw_interrupt_type xilinx_intc = {
  74. .typename = "Xilinx Interrupt Controller",
  75. .enable = xilinx_intc_enable,
  76. .disable = xilinx_intc_disable,
  77. .ack = xilinx_intc_disable_and_ack,
  78. .end = xilinx_intc_end,
  79. };
  80. int
  81. xilinx_pic_get_irq(struct pt_regs *regs)
  82. {
  83. int irq;
  84. /*
  85. * NOTE: This function is the one that needs to be improved in
  86. * order to handle multiple interrupt controllers. It currently
  87. * is hardcoded to check for interrupts only on the first INTC.
  88. */
  89. irq = intc_in_be32(intc + IVR);
  90. if (irq != -1)
  91. irq = irq;
  92. pr_debug("get_irq: %d\n", irq);
  93. return (irq);
  94. }
  95. void __init
  96. ppc4xx_pic_init(void)
  97. {
  98. int i;
  99. /*
  100. * NOTE: The assumption here is that NR_IRQS is 32 or less
  101. * (NR_IRQS is 32 for PowerPC 405 cores by default).
  102. */
  103. #if (NR_IRQS > 32)
  104. #error NR_IRQS > 32 not supported
  105. #endif
  106. #if XPAR_XINTC_USE_DCR == 0
  107. intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
  108. printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX mapped to 0x%08lX\n",
  109. (unsigned long) XPAR_INTC_0_BASEADDR, (unsigned long) intc);
  110. #else
  111. printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX (DCR)\n",
  112. (unsigned long) XPAR_INTC_0_BASEADDR);
  113. #endif
  114. /*
  115. * Disable all external interrupts until they are
  116. * explicity requested.
  117. */
  118. intc_out_be32(intc + IER, 0);
  119. /* Acknowledge any pending interrupts just in case. */
  120. intc_out_be32(intc + IAR, ~(u32) 0);
  121. /* Turn on the Master Enable. */
  122. intc_out_be32(intc + MER, 0x3UL);
  123. ppc_md.get_irq = xilinx_pic_get_irq;
  124. for (i = 0; i < NR_IRQS; ++i) {
  125. irq_desc[i].handler = &xilinx_intc;
  126. if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i))
  127. irq_desc[i].status &= ~IRQ_LEVEL;
  128. else
  129. irq_desc[i].status |= IRQ_LEVEL;
  130. }
  131. }