irq.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* -------------------------------------------------------------------- */
  2. /* setup_voyagergx.c: */
  3. /* -------------------------------------------------------------------- */
  4. /* This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. Copyright 2003 (c) Lineo uSolutions,Inc.
  16. */
  17. #include <linux/interrupt.h>
  18. #include <linux/init.h>
  19. #include <linux/io.h>
  20. #include <asm/voyagergx.h>
  21. #include <asm/rts7751r2d.h>
  22. enum {
  23. UNUSED = 0,
  24. /* voyager specific interrupt sources */
  25. UP, G54, G53, G52, G51, G50, G49, G48,
  26. I2C, PW, DMA, PCI, I2S, AC, US,
  27. U1, U0, CV, MC, S1, S0,
  28. UH, TWOD, ZD, PV, CI,
  29. };
  30. static struct intc_vect vectors[] = {
  31. INTC_IRQ(UP, IRQ_SM501_UP), INTC_IRQ(G54, IRQ_SM501_G54),
  32. INTC_IRQ(G53, IRQ_SM501_G53), INTC_IRQ(G52, IRQ_SM501_G52),
  33. INTC_IRQ(G51, IRQ_SM501_G51), INTC_IRQ(G50, IRQ_SM501_G50),
  34. INTC_IRQ(G49, IRQ_SM501_G49), INTC_IRQ(G48, IRQ_SM501_G48),
  35. INTC_IRQ(I2C, IRQ_SM501_I2C), INTC_IRQ(PW, IRQ_SM501_PW),
  36. INTC_IRQ(DMA, IRQ_SM501_DMA), INTC_IRQ(PCI, IRQ_SM501_PCI),
  37. INTC_IRQ(I2S, IRQ_SM501_I2S), INTC_IRQ(AC, IRQ_SM501_AC),
  38. INTC_IRQ(US, IRQ_SM501_US), INTC_IRQ(U1, IRQ_SM501_U1),
  39. INTC_IRQ(U0, IRQ_SM501_U0), INTC_IRQ(CV, IRQ_SM501_CV),
  40. INTC_IRQ(MC, IRQ_SM501_MC), INTC_IRQ(S1, IRQ_SM501_S1),
  41. INTC_IRQ(S0, IRQ_SM501_S0), INTC_IRQ(UH, IRQ_SM501_UH),
  42. INTC_IRQ(TWOD, IRQ_SM501_2D), INTC_IRQ(ZD, IRQ_SM501_ZD),
  43. INTC_IRQ(PV, IRQ_SM501_PV), INTC_IRQ(CI, IRQ_SM501_CI),
  44. };
  45. static struct intc_mask_reg mask_registers[] = {
  46. { VOYAGER_INT_MASK, 1, 32, /* "Interrupt Mask", MMIO_base + 0x30 */
  47. { UP, G54, G53, G52, G51, G50, G49, G48,
  48. I2C, PW, 0, DMA, PCI, I2S, AC, US,
  49. 0, 0, U1, U0, CV, MC, S1, S0,
  50. 0, UH, 0, 0, TWOD, ZD, PV, CI } },
  51. };
  52. static DECLARE_INTC_DESC(intc_desc, "voyagergx", vectors,
  53. NULL, NULL, mask_registers, NULL, NULL);
  54. static unsigned int voyagergx_stat2irq[32] = {
  55. IRQ_SM501_CI, IRQ_SM501_PV, IRQ_SM501_ZD, IRQ_SM501_2D,
  56. 0, 0, IRQ_SM501_UH, 0,
  57. IRQ_SM501_S0, IRQ_SM501_S1, IRQ_SM501_MC, IRQ_SM501_CV,
  58. IRQ_SM501_U0, IRQ_SM501_U1, 0, 0,
  59. IRQ_SM501_US, IRQ_SM501_AC, IRQ_SM501_I2S, IRQ_SM501_PCI,
  60. IRQ_SM501_DMA, 0, IRQ_SM501_PW, IRQ_SM501_I2C,
  61. IRQ_SM501_G48, IRQ_SM501_G49, IRQ_SM501_G50, IRQ_SM501_G51,
  62. IRQ_SM501_G52, IRQ_SM501_G53, IRQ_SM501_G54, IRQ_SM501_UP
  63. };
  64. static void voyagergx_irq_demux(unsigned int irq, struct irq_desc *desc)
  65. {
  66. unsigned long intv = ctrl_inl(INT_STATUS);
  67. struct irq_desc *ext_desc;
  68. unsigned int ext_irq;
  69. unsigned int k = 0;
  70. while (intv) {
  71. ext_irq = voyagergx_stat2irq[k];
  72. if (ext_irq && (intv & 1)) {
  73. ext_desc = irq_desc + ext_irq;
  74. handle_level_irq(ext_irq, ext_desc);
  75. }
  76. intv >>= 1;
  77. k++;
  78. }
  79. }
  80. void __init setup_voyagergx_irq(void)
  81. {
  82. printk(KERN_INFO "VoyagerGX on irq %d (mapped into %d to %d)\n",
  83. IRQ_VOYAGER,
  84. VOYAGER_IRQ_BASE,
  85. VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
  86. register_intc_controller(&intc_desc);
  87. set_irq_chained_handler(IRQ_VOYAGER, voyagergx_irq_demux);
  88. }