irq.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /* arch/arm/plat-s3c64xx/irq.c
  2. *
  3. * Copyright 2008 Openmoko, Inc.
  4. * Copyright 2008 Simtec Electronics
  5. * Ben Dooks <ben@simtec.co.uk>
  6. * http://armlinux.simtec.co.uk/
  7. *
  8. * S3C64XX - Interrupt handling
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/irq.h>
  17. #include <linux/io.h>
  18. #include <asm/hardware/vic.h>
  19. #include <mach/map.h>
  20. #include <plat/regs-timer.h>
  21. #include <plat/cpu.h>
  22. /* Timer interrupt handling */
  23. static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq)
  24. {
  25. generic_handle_irq(sub_irq);
  26. }
  27. static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc)
  28. {
  29. s3c_irq_demux_timer(irq, IRQ_TIMER0);
  30. }
  31. static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc)
  32. {
  33. s3c_irq_demux_timer(irq, IRQ_TIMER1);
  34. }
  35. static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc)
  36. {
  37. s3c_irq_demux_timer(irq, IRQ_TIMER2);
  38. }
  39. static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc)
  40. {
  41. s3c_irq_demux_timer(irq, IRQ_TIMER3);
  42. }
  43. static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc)
  44. {
  45. s3c_irq_demux_timer(irq, IRQ_TIMER4);
  46. }
  47. /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
  48. static void s3c_irq_timer_mask(unsigned int irq)
  49. {
  50. u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
  51. reg &= 0x1f; /* mask out pending interrupts */
  52. reg &= ~(1 << (irq - IRQ_TIMER0));
  53. __raw_writel(reg, S3C64XX_TINT_CSTAT);
  54. }
  55. static void s3c_irq_timer_unmask(unsigned int irq)
  56. {
  57. u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
  58. reg &= 0x1f; /* mask out pending interrupts */
  59. reg |= 1 << (irq - IRQ_TIMER0);
  60. __raw_writel(reg, S3C64XX_TINT_CSTAT);
  61. }
  62. static void s3c_irq_timer_ack(unsigned int irq)
  63. {
  64. u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
  65. reg &= 0x1f;
  66. reg |= (1 << 5) << (irq - IRQ_TIMER0);
  67. __raw_writel(reg, S3C64XX_TINT_CSTAT);
  68. }
  69. static struct irq_chip s3c_irq_timer = {
  70. .name = "s3c-timer",
  71. .mask = s3c_irq_timer_mask,
  72. .unmask = s3c_irq_timer_unmask,
  73. .ack = s3c_irq_timer_ack,
  74. };
  75. struct uart_irq {
  76. void __iomem *regs;
  77. unsigned int base_irq;
  78. unsigned int parent_irq;
  79. };
  80. /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
  81. * are consecutive when looking up the interrupt in the demux routines.
  82. */
  83. static struct uart_irq uart_irqs[] = {
  84. [0] = {
  85. .regs = S3C_VA_UART0,
  86. .base_irq = IRQ_S3CUART_BASE0,
  87. .parent_irq = IRQ_UART0,
  88. },
  89. [1] = {
  90. .regs = S3C_VA_UART1,
  91. .base_irq = IRQ_S3CUART_BASE1,
  92. .parent_irq = IRQ_UART1,
  93. },
  94. [2] = {
  95. .regs = S3C_VA_UART2,
  96. .base_irq = IRQ_S3CUART_BASE2,
  97. .parent_irq = IRQ_UART2,
  98. },
  99. [3] = {
  100. .regs = S3C_VA_UART3,
  101. .base_irq = IRQ_S3CUART_BASE3,
  102. .parent_irq = IRQ_UART3,
  103. },
  104. };
  105. static inline void __iomem *s3c_irq_uart_base(unsigned int irq)
  106. {
  107. struct uart_irq *uirq = get_irq_chip_data(irq);
  108. return uirq->regs;
  109. }
  110. static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
  111. {
  112. return irq & 3;
  113. }
  114. /* UART interrupt registers, not worth adding to seperate include header */
  115. #define S3C64XX_UINTP 0x30
  116. #define S3C64XX_UINTSP 0x34
  117. #define S3C64XX_UINTM 0x38
  118. static void s3c_irq_uart_mask(unsigned int irq)
  119. {
  120. void __iomem *regs = s3c_irq_uart_base(irq);
  121. unsigned int bit = s3c_irq_uart_bit(irq);
  122. u32 reg;
  123. reg = __raw_readl(regs + S3C64XX_UINTM);
  124. reg |= (1 << bit);
  125. __raw_writel(reg, regs + S3C64XX_UINTM);
  126. }
  127. static void s3c_irq_uart_maskack(unsigned int irq)
  128. {
  129. void __iomem *regs = s3c_irq_uart_base(irq);
  130. unsigned int bit = s3c_irq_uart_bit(irq);
  131. u32 reg;
  132. reg = __raw_readl(regs + S3C64XX_UINTM);
  133. reg |= (1 << bit);
  134. __raw_writel(reg, regs + S3C64XX_UINTM);
  135. __raw_writel(1 << bit, regs + S3C64XX_UINTP);
  136. }
  137. static void s3c_irq_uart_unmask(unsigned int irq)
  138. {
  139. void __iomem *regs = s3c_irq_uart_base(irq);
  140. unsigned int bit = s3c_irq_uart_bit(irq);
  141. u32 reg;
  142. reg = __raw_readl(regs + S3C64XX_UINTM);
  143. reg &= ~(1 << bit);
  144. __raw_writel(reg, regs + S3C64XX_UINTM);
  145. }
  146. static void s3c_irq_uart_ack(unsigned int irq)
  147. {
  148. void __iomem *regs = s3c_irq_uart_base(irq);
  149. unsigned int bit = s3c_irq_uart_bit(irq);
  150. __raw_writel(1 << bit, regs + S3C64XX_UINTP);
  151. }
  152. static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
  153. {
  154. struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0];
  155. u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
  156. int base = uirq->base_irq;
  157. if (pend & (1 << 0))
  158. generic_handle_irq(base);
  159. if (pend & (1 << 1))
  160. generic_handle_irq(base + 1);
  161. if (pend & (1 << 2))
  162. generic_handle_irq(base + 2);
  163. if (pend & (1 << 3))
  164. generic_handle_irq(base + 3);
  165. }
  166. static struct irq_chip s3c_irq_uart = {
  167. .name = "s3c-uart",
  168. .mask = s3c_irq_uart_mask,
  169. .unmask = s3c_irq_uart_unmask,
  170. .mask_ack = s3c_irq_uart_maskack,
  171. .ack = s3c_irq_uart_ack,
  172. };
  173. static void __init s3c64xx_uart_irq(struct uart_irq *uirq)
  174. {
  175. void __iomem *reg_base = uirq->regs;
  176. unsigned int irq;
  177. int offs;
  178. /* mask all interrupts at the start. */
  179. __raw_writel(0xf, reg_base + S3C64XX_UINTM);
  180. for (offs = 0; offs < 3; offs++) {
  181. irq = uirq->base_irq + offs;
  182. set_irq_chip(irq, &s3c_irq_uart);
  183. set_irq_chip_data(irq, uirq);
  184. set_irq_handler(irq, handle_level_irq);
  185. set_irq_flags(irq, IRQF_VALID);
  186. }
  187. set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
  188. }
  189. void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
  190. {
  191. int uart, irq;
  192. printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
  193. /* initialise the pair of VICs */
  194. vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid);
  195. vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid);
  196. /* add the timer sub-irqs */
  197. set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0);
  198. set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1);
  199. set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2);
  200. set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3);
  201. set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4);
  202. for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) {
  203. set_irq_chip(irq, &s3c_irq_timer);
  204. set_irq_handler(irq, handle_level_irq);
  205. set_irq_flags(irq, IRQF_VALID);
  206. }
  207. for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++)
  208. s3c64xx_uart_irq(&uart_irqs[uart]);
  209. }