irq.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * arch/arm/mach-ns9xxx/irq.c
  3. *
  4. * Copyright (C) 2006,2007 by Digi International Inc.
  5. * All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published by
  9. * the Free Software Foundation.
  10. */
  11. #include <linux/interrupt.h>
  12. #include <asm/mach/irq.h>
  13. #include <asm/mach-types.h>
  14. #include <asm/arch-ns9xxx/regs-sys.h>
  15. #include <asm/arch-ns9xxx/irqs.h>
  16. #include <asm/arch-ns9xxx/board.h>
  17. #include "generic.h"
  18. static void ns9xxx_ack_irq_timer(unsigned int irq)
  19. {
  20. u32 tc = SYS_TC(irq - IRQ_TIMER0);
  21. /*
  22. * If the timer is programmed to halt on terminal count, the
  23. * timer must be disabled before clearing the interrupt.
  24. */
  25. if (REGGET(tc, SYS_TCx, REN) == 0) {
  26. REGSET(tc, SYS_TCx, TEN, DIS);
  27. SYS_TC(irq - IRQ_TIMER0) = tc;
  28. }
  29. REGSET(tc, SYS_TCx, INTC, SET);
  30. SYS_TC(irq - IRQ_TIMER0) = tc;
  31. REGSET(tc, SYS_TCx, INTC, UNSET);
  32. SYS_TC(irq - IRQ_TIMER0) = tc;
  33. }
  34. static void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
  35. [IRQ_TIMER0] = ns9xxx_ack_irq_timer,
  36. [IRQ_TIMER1] = ns9xxx_ack_irq_timer,
  37. [IRQ_TIMER2] = ns9xxx_ack_irq_timer,
  38. [IRQ_TIMER3] = ns9xxx_ack_irq_timer,
  39. };
  40. static void ns9xxx_mask_irq(unsigned int irq)
  41. {
  42. /* XXX: better use cpp symbols */
  43. SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
  44. }
  45. static void ns9xxx_ack_irq(unsigned int irq)
  46. {
  47. if (!ns9xxx_ack_irq_functions[irq]) {
  48. printk(KERN_ERR "no ack function for irq %u\n", irq);
  49. BUG();
  50. }
  51. ns9xxx_ack_irq_functions[irq](irq);
  52. SYS_ISRADDR = 0;
  53. }
  54. static void ns9xxx_maskack_irq(unsigned int irq)
  55. {
  56. ns9xxx_mask_irq(irq);
  57. ns9xxx_ack_irq(irq);
  58. }
  59. static void ns9xxx_unmask_irq(unsigned int irq)
  60. {
  61. /* XXX: better use cpp symbols */
  62. SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
  63. }
  64. static struct irq_chip ns9xxx_chip = {
  65. .ack = ns9xxx_ack_irq,
  66. .mask = ns9xxx_mask_irq,
  67. .mask_ack = ns9xxx_maskack_irq,
  68. .unmask = ns9xxx_unmask_irq,
  69. };
  70. void __init ns9xxx_init_irq(void)
  71. {
  72. int i;
  73. /* disable all IRQs */
  74. for (i = 0; i < 8; ++i)
  75. SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
  76. (4 * i + 2) << 8 | (4 * i + 3);
  77. /* simple interrupt prio table:
  78. * prio(x) < prio(y) <=> x < y
  79. */
  80. for (i = 0; i < 32; ++i)
  81. SYS_IVA(i) = i;
  82. for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
  83. set_irq_chip(i, &ns9xxx_chip);
  84. set_irq_handler(i, handle_level_irq);
  85. set_irq_flags(i, IRQF_VALID);
  86. }
  87. }