irq.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * arch/arm/mach-ks8695/irq.c
  3. *
  4. * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
  5. * Copyright (C) 2006 Simtec Electronics
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <linux/init.h>
  22. #include <linux/module.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/ioport.h>
  25. #include <linux/ptrace.h>
  26. #include <linux/sysdev.h>
  27. #include <asm/hardware.h>
  28. #include <asm/irq.h>
  29. #include <asm/io.h>
  30. #include <asm/mach/irq.h>
  31. #include <asm/arch/regs-irq.h>
  32. #include <asm/arch/regs-gpio.h>
  33. static void ks8695_irq_mask(unsigned int irqno)
  34. {
  35. unsigned long inten;
  36. inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
  37. inten &= ~(1 << irqno);
  38. __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
  39. }
  40. static void ks8695_irq_unmask(unsigned int irqno)
  41. {
  42. unsigned long inten;
  43. inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
  44. inten |= (1 << irqno);
  45. __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
  46. }
  47. static void ks8695_irq_ack(unsigned int irqno)
  48. {
  49. __raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST);
  50. }
  51. static struct irq_chip ks8695_irq_level_chip;
  52. static struct irq_chip ks8695_irq_edge_chip;
  53. static int ks8695_irq_set_type(unsigned int irqno, unsigned int type)
  54. {
  55. unsigned long ctrl, mode;
  56. unsigned short level_triggered = 0;
  57. ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  58. switch (type) {
  59. case IRQT_HIGH:
  60. mode = IOPC_TM_HIGH;
  61. level_triggered = 1;
  62. break;
  63. case IRQT_LOW:
  64. mode = IOPC_TM_LOW;
  65. level_triggered = 1;
  66. break;
  67. case IRQT_RISING:
  68. mode = IOPC_TM_RISING;
  69. break;
  70. case IRQT_FALLING:
  71. mode = IOPC_TM_FALLING;
  72. break;
  73. case IRQT_BOTHEDGE:
  74. mode = IOPC_TM_EDGE;
  75. break;
  76. default:
  77. return -EINVAL;
  78. }
  79. switch (irqno) {
  80. case KS8695_IRQ_EXTERN0:
  81. ctrl &= ~IOPC_IOEINT0TM;
  82. ctrl |= IOPC_IOEINT0_MODE(mode);
  83. break;
  84. case KS8695_IRQ_EXTERN1:
  85. ctrl &= ~IOPC_IOEINT1TM;
  86. ctrl |= IOPC_IOEINT1_MODE(mode);
  87. break;
  88. case KS8695_IRQ_EXTERN2:
  89. ctrl &= ~IOPC_IOEINT2TM;
  90. ctrl |= IOPC_IOEINT2_MODE(mode);
  91. break;
  92. case KS8695_IRQ_EXTERN3:
  93. ctrl &= ~IOPC_IOEINT3TM;
  94. ctrl |= IOPC_IOEINT3_MODE(mode);
  95. break;
  96. default:
  97. return -EINVAL;
  98. }
  99. if (level_triggered) {
  100. set_irq_chip(irqno, &ks8695_irq_level_chip);
  101. set_irq_handler(irqno, handle_level_irq);
  102. }
  103. else {
  104. set_irq_chip(irqno, &ks8695_irq_edge_chip);
  105. set_irq_handler(irqno, handle_edge_irq);
  106. }
  107. __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
  108. return 0;
  109. }
  110. static struct irq_chip ks8695_irq_level_chip = {
  111. .ack = ks8695_irq_mask,
  112. .mask = ks8695_irq_mask,
  113. .unmask = ks8695_irq_unmask,
  114. .set_type = ks8695_irq_set_type,
  115. };
  116. static struct irq_chip ks8695_irq_edge_chip = {
  117. .ack = ks8695_irq_ack,
  118. .mask = ks8695_irq_mask,
  119. .unmask = ks8695_irq_unmask,
  120. .set_type = ks8695_irq_set_type,
  121. };
  122. void __init ks8695_init_irq(void)
  123. {
  124. unsigned int irq;
  125. /* Disable all interrupts initially */
  126. __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC);
  127. __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN);
  128. for (irq = 0; irq < NR_IRQS; irq++) {
  129. switch (irq) {
  130. /* Level-triggered interrupts */
  131. case KS8695_IRQ_BUS_ERROR:
  132. case KS8695_IRQ_UART_MODEM_STATUS:
  133. case KS8695_IRQ_UART_LINE_STATUS:
  134. case KS8695_IRQ_UART_RX:
  135. case KS8695_IRQ_COMM_TX:
  136. case KS8695_IRQ_COMM_RX:
  137. set_irq_chip(irq, &ks8695_irq_level_chip);
  138. set_irq_handler(irq, handle_level_irq);
  139. break;
  140. /* Edge-triggered interrupts */
  141. default:
  142. ks8695_irq_ack(irq); /* clear pending bit */
  143. set_irq_chip(irq, &ks8695_irq_edge_chip);
  144. set_irq_handler(irq, handle_edge_irq);
  145. }
  146. set_irq_flags(irq, IRQF_VALID);
  147. }
  148. }