intc.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * intc.c -- interrupt controller or ColdFire 5272 SoC
  3. *
  4. * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file COPYING in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/types.h>
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/irq.h>
  15. #include <linux/io.h>
  16. #include <asm/coldfire.h>
  17. #include <asm/mcfsim.h>
  18. #include <asm/traps.h>
  19. /*
  20. * The 5272 ColdFire interrupt controller is nothing like any other
  21. * ColdFire interrupt controller - it truly is completely different.
  22. * Given its age it is unlikely to be used on any other ColdFire CPU.
  23. */
  24. /*
  25. * The masking and priproty setting of interrupts on the 5272 is done
  26. * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
  27. * loose mapping of vector number to register and internal bits, but
  28. * a table is the easiest and quickest way to map them.
  29. */
  30. struct irqmap {
  31. unsigned char icr;
  32. unsigned char index;
  33. unsigned char ack;
  34. };
  35. static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
  36. /*MCF_IRQ_SPURIOUS*/ { .icr = 0, .index = 0, .ack = 0, },
  37. /*MCF_IRQ_EINT1*/ { .icr = MCFSIM_ICR1, .index = 28, .ack = 1, },
  38. /*MCF_IRQ_EINT2*/ { .icr = MCFSIM_ICR1, .index = 24, .ack = 1, },
  39. /*MCF_IRQ_EINT3*/ { .icr = MCFSIM_ICR1, .index = 20, .ack = 1, },
  40. /*MCF_IRQ_EINT4*/ { .icr = MCFSIM_ICR1, .index = 16, .ack = 1, },
  41. /*MCF_IRQ_TIMER1*/ { .icr = MCFSIM_ICR1, .index = 12, .ack = 0, },
  42. /*MCF_IRQ_TIMER2*/ { .icr = MCFSIM_ICR1, .index = 8, .ack = 0, },
  43. /*MCF_IRQ_TIMER3*/ { .icr = MCFSIM_ICR1, .index = 4, .ack = 0, },
  44. /*MCF_IRQ_TIMER4*/ { .icr = MCFSIM_ICR1, .index = 0, .ack = 0, },
  45. /*MCF_IRQ_UART1*/ { .icr = MCFSIM_ICR2, .index = 28, .ack = 0, },
  46. /*MCF_IRQ_UART2*/ { .icr = MCFSIM_ICR2, .index = 24, .ack = 0, },
  47. /*MCF_IRQ_PLIP*/ { .icr = MCFSIM_ICR2, .index = 20, .ack = 0, },
  48. /*MCF_IRQ_PLIA*/ { .icr = MCFSIM_ICR2, .index = 16, .ack = 0, },
  49. /*MCF_IRQ_USB0*/ { .icr = MCFSIM_ICR2, .index = 12, .ack = 0, },
  50. /*MCF_IRQ_USB1*/ { .icr = MCFSIM_ICR2, .index = 8, .ack = 0, },
  51. /*MCF_IRQ_USB2*/ { .icr = MCFSIM_ICR2, .index = 4, .ack = 0, },
  52. /*MCF_IRQ_USB3*/ { .icr = MCFSIM_ICR2, .index = 0, .ack = 0, },
  53. /*MCF_IRQ_USB4*/ { .icr = MCFSIM_ICR3, .index = 28, .ack = 0, },
  54. /*MCF_IRQ_USB5*/ { .icr = MCFSIM_ICR3, .index = 24, .ack = 0, },
  55. /*MCF_IRQ_USB6*/ { .icr = MCFSIM_ICR3, .index = 20, .ack = 0, },
  56. /*MCF_IRQ_USB7*/ { .icr = MCFSIM_ICR3, .index = 16, .ack = 0, },
  57. /*MCF_IRQ_DMA*/ { .icr = MCFSIM_ICR3, .index = 12, .ack = 0, },
  58. /*MCF_IRQ_ERX*/ { .icr = MCFSIM_ICR3, .index = 8, .ack = 0, },
  59. /*MCF_IRQ_ETX*/ { .icr = MCFSIM_ICR3, .index = 4, .ack = 0, },
  60. /*MCF_IRQ_ENTC*/ { .icr = MCFSIM_ICR3, .index = 0, .ack = 0, },
  61. /*MCF_IRQ_QSPI*/ { .icr = MCFSIM_ICR4, .index = 28, .ack = 0, },
  62. /*MCF_IRQ_EINT5*/ { .icr = MCFSIM_ICR4, .index = 24, .ack = 1, },
  63. /*MCF_IRQ_EINT6*/ { .icr = MCFSIM_ICR4, .index = 20, .ack = 1, },
  64. /*MCF_IRQ_SWTO*/ { .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
  65. };
  66. static void intc_irq_mask(unsigned int irq)
  67. {
  68. if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
  69. u32 v;
  70. irq -= MCFINT_VECBASE;
  71. v = 0x8 << intc_irqmap[irq].index;
  72. writel(v, MCF_MBAR + intc_irqmap[irq].icr);
  73. }
  74. }
  75. static void intc_irq_unmask(unsigned int irq)
  76. {
  77. if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
  78. u32 v;
  79. irq -= MCFINT_VECBASE;
  80. v = 0xd << intc_irqmap[irq].index;
  81. writel(v, MCF_MBAR + intc_irqmap[irq].icr);
  82. }
  83. }
  84. static void intc_irq_ack(unsigned int irq)
  85. {
  86. /* Only external interrupts are acked */
  87. if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
  88. irq -= MCFINT_VECBASE;
  89. if (intc_irqmap[irq].ack) {
  90. u32 v;
  91. v = 0xd << intc_irqmap[irq].index;
  92. writel(v, MCF_MBAR + intc_irqmap[irq].icr);
  93. }
  94. }
  95. }
  96. static int intc_irq_set_type(unsigned int irq, unsigned int type)
  97. {
  98. /* We can set the edge type here for external interrupts */
  99. return 0;
  100. }
  101. static struct irq_chip intc_irq_chip = {
  102. .name = "CF-INTC",
  103. .mask = intc_irq_mask,
  104. .unmask = intc_irq_unmask,
  105. .ack = intc_irq_ack,
  106. .set_type = intc_irq_set_type,
  107. };
  108. void __init init_IRQ(void)
  109. {
  110. int irq;
  111. init_vectors();
  112. /* Mask all interrupt sources */
  113. writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
  114. writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
  115. writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
  116. writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
  117. for (irq = 0; (irq < NR_IRQS); irq++) {
  118. irq_desc[irq].status = IRQ_DISABLED;
  119. irq_desc[irq].action = NULL;
  120. irq_desc[irq].depth = 1;
  121. irq_desc[irq].chip = &intc_irq_chip;
  122. intc_irq_set_type(irq, 0);
  123. }
  124. }