irq.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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/sysdev.h>
  26. #include <linux/io.h>
  27. #include <mach/hardware.h>
  28. #include <asm/irq.h>
  29. #include <asm/mach/irq.h>
  30. #include <mach/regs-irq.h>
  31. #include <mach/regs-gpio.h>
  32. static void ks8695_irq_mask(struct irq_data *d)
  33. {
  34. unsigned long inten;
  35. inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
  36. inten &= ~(1 << d->irq);
  37. __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
  38. }
  39. static void ks8695_irq_unmask(struct irq_data *d)
  40. {
  41. unsigned long inten;
  42. inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
  43. inten |= (1 << d->irq);
  44. __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
  45. }
  46. static void ks8695_irq_ack(struct irq_data *d)
  47. {
  48. __raw_writel((1 << d->irq), KS8695_IRQ_VA + KS8695_INTST);
  49. }
  50. static struct irq_chip ks8695_irq_level_chip;
  51. static struct irq_chip ks8695_irq_edge_chip;
  52. static int ks8695_irq_set_type(struct irq_data *d, unsigned int type)
  53. {
  54. unsigned long ctrl, mode;
  55. unsigned short level_triggered = 0;
  56. ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  57. switch (type) {
  58. case IRQ_TYPE_LEVEL_HIGH:
  59. mode = IOPC_TM_HIGH;
  60. level_triggered = 1;
  61. break;
  62. case IRQ_TYPE_LEVEL_LOW:
  63. mode = IOPC_TM_LOW;
  64. level_triggered = 1;
  65. break;
  66. case IRQ_TYPE_EDGE_RISING:
  67. mode = IOPC_TM_RISING;
  68. break;
  69. case IRQ_TYPE_EDGE_FALLING:
  70. mode = IOPC_TM_FALLING;
  71. break;
  72. case IRQ_TYPE_EDGE_BOTH:
  73. mode = IOPC_TM_EDGE;
  74. break;
  75. default:
  76. return -EINVAL;
  77. }
  78. switch (d->irq) {
  79. case KS8695_IRQ_EXTERN0:
  80. ctrl &= ~IOPC_IOEINT0TM;
  81. ctrl |= IOPC_IOEINT0_MODE(mode);
  82. break;
  83. case KS8695_IRQ_EXTERN1:
  84. ctrl &= ~IOPC_IOEINT1TM;
  85. ctrl |= IOPC_IOEINT1_MODE(mode);
  86. break;
  87. case KS8695_IRQ_EXTERN2:
  88. ctrl &= ~IOPC_IOEINT2TM;
  89. ctrl |= IOPC_IOEINT2_MODE(mode);
  90. break;
  91. case KS8695_IRQ_EXTERN3:
  92. ctrl &= ~IOPC_IOEINT3TM;
  93. ctrl |= IOPC_IOEINT3_MODE(mode);
  94. break;
  95. default:
  96. return -EINVAL;
  97. }
  98. if (level_triggered) {
  99. irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip,
  100. handle_level_irq);
  101. }
  102. else {
  103. irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip,
  104. handle_edge_irq);
  105. }
  106. __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
  107. return 0;
  108. }
  109. static struct irq_chip ks8695_irq_level_chip = {
  110. .irq_ack = ks8695_irq_mask,
  111. .irq_mask = ks8695_irq_mask,
  112. .irq_unmask = ks8695_irq_unmask,
  113. .irq_set_type = ks8695_irq_set_type,
  114. };
  115. static struct irq_chip ks8695_irq_edge_chip = {
  116. .irq_ack = ks8695_irq_ack,
  117. .irq_mask = ks8695_irq_mask,
  118. .irq_unmask = ks8695_irq_unmask,
  119. .irq_set_type = ks8695_irq_set_type,
  120. };
  121. void __init ks8695_init_irq(void)
  122. {
  123. unsigned int irq;
  124. /* Disable all interrupts initially */
  125. __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC);
  126. __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN);
  127. for (irq = 0; irq < NR_IRQS; irq++) {
  128. switch (irq) {
  129. /* Level-triggered interrupts */
  130. case KS8695_IRQ_BUS_ERROR:
  131. case KS8695_IRQ_UART_MODEM_STATUS:
  132. case KS8695_IRQ_UART_LINE_STATUS:
  133. case KS8695_IRQ_UART_RX:
  134. case KS8695_IRQ_COMM_TX:
  135. case KS8695_IRQ_COMM_RX:
  136. irq_set_chip_and_handler(irq,
  137. &ks8695_irq_level_chip,
  138. handle_level_irq);
  139. break;
  140. /* Edge-triggered interrupts */
  141. default:
  142. /* clear pending bit */
  143. ks8695_irq_ack(irq_get_irq_data(irq));
  144. irq_set_chip_and_handler(irq,
  145. &ks8695_irq_edge_chip,
  146. handle_edge_irq);
  147. }
  148. set_irq_flags(irq, IRQF_VALID);
  149. }
  150. }