socrates_fpga_pic.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright (C) 2008 Ilya Yanok, Emcraft Systems
  3. *
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. */
  10. #include <linux/irq.h>
  11. #include <linux/of_address.h>
  12. #include <linux/of_irq.h>
  13. #include <linux/of_platform.h>
  14. #include <linux/io.h>
  15. /*
  16. * The FPGA supports 9 interrupt sources, which can be routed to 3
  17. * interrupt request lines of the MPIC. The line to be used can be
  18. * specified through the third cell of FDT property "interrupts".
  19. */
  20. #define SOCRATES_FPGA_NUM_IRQS 9
  21. #define FPGA_PIC_IRQCFG (0x0)
  22. #define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n))
  23. #define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
  24. struct socrates_fpga_irq_info {
  25. unsigned int irq_line;
  26. int type;
  27. };
  28. /*
  29. * Interrupt routing and type table
  30. *
  31. * IRQ_TYPE_NONE means the interrupt type is configurable,
  32. * otherwise it's fixed to the specified value.
  33. */
  34. static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
  35. [0] = {0, IRQ_TYPE_NONE},
  36. [1] = {0, IRQ_TYPE_LEVEL_HIGH},
  37. [2] = {0, IRQ_TYPE_LEVEL_LOW},
  38. [3] = {0, IRQ_TYPE_NONE},
  39. [4] = {0, IRQ_TYPE_NONE},
  40. [5] = {0, IRQ_TYPE_NONE},
  41. [6] = {0, IRQ_TYPE_NONE},
  42. [7] = {0, IRQ_TYPE_NONE},
  43. [8] = {0, IRQ_TYPE_LEVEL_HIGH},
  44. };
  45. static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
  46. static void __iomem *socrates_fpga_pic_iobase;
  47. static struct irq_domain *socrates_fpga_pic_irq_host;
  48. static unsigned int socrates_fpga_irqs[3];
  49. static inline uint32_t socrates_fpga_pic_read(int reg)
  50. {
  51. return in_be32(socrates_fpga_pic_iobase + reg);
  52. }
  53. static inline void socrates_fpga_pic_write(int reg, uint32_t val)
  54. {
  55. out_be32(socrates_fpga_pic_iobase + reg, val);
  56. }
  57. static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
  58. {
  59. uint32_t cause;
  60. unsigned long flags;
  61. int i;
  62. /* Check irq line routed to the MPIC */
  63. for (i = 0; i < 3; i++) {
  64. if (irq == socrates_fpga_irqs[i])
  65. break;
  66. }
  67. if (i == 3)
  68. return NO_IRQ;
  69. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  70. cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
  71. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  72. for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
  73. if (cause >> (i + 16))
  74. break;
  75. }
  76. return irq_linear_revmap(socrates_fpga_pic_irq_host,
  77. (irq_hw_number_t)i);
  78. }
  79. void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
  80. {
  81. struct irq_chip *chip = irq_desc_get_chip(desc);
  82. unsigned int cascade_irq;
  83. /*
  84. * See if we actually have an interrupt, call generic handling code if
  85. * we do.
  86. */
  87. cascade_irq = socrates_fpga_pic_get_irq(irq);
  88. if (cascade_irq != NO_IRQ)
  89. generic_handle_irq(cascade_irq);
  90. chip->irq_eoi(&desc->irq_data);
  91. }
  92. static void socrates_fpga_pic_ack(struct irq_data *d)
  93. {
  94. unsigned long flags;
  95. unsigned int irq_line, hwirq = irqd_to_hwirq(d);
  96. uint32_t mask;
  97. irq_line = fpga_irqs[hwirq].irq_line;
  98. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  99. mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
  100. & SOCRATES_FPGA_IRQ_MASK;
  101. mask |= (1 << (hwirq + 16));
  102. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
  103. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  104. }
  105. static void socrates_fpga_pic_mask(struct irq_data *d)
  106. {
  107. unsigned long flags;
  108. unsigned int hwirq = irqd_to_hwirq(d);
  109. int irq_line;
  110. u32 mask;
  111. irq_line = fpga_irqs[hwirq].irq_line;
  112. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  113. mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
  114. & SOCRATES_FPGA_IRQ_MASK;
  115. mask &= ~(1 << hwirq);
  116. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
  117. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  118. }
  119. static void socrates_fpga_pic_mask_ack(struct irq_data *d)
  120. {
  121. unsigned long flags;
  122. unsigned int hwirq = irqd_to_hwirq(d);
  123. int irq_line;
  124. u32 mask;
  125. irq_line = fpga_irqs[hwirq].irq_line;
  126. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  127. mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
  128. & SOCRATES_FPGA_IRQ_MASK;
  129. mask &= ~(1 << hwirq);
  130. mask |= (1 << (hwirq + 16));
  131. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
  132. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  133. }
  134. static void socrates_fpga_pic_unmask(struct irq_data *d)
  135. {
  136. unsigned long flags;
  137. unsigned int hwirq = irqd_to_hwirq(d);
  138. int irq_line;
  139. u32 mask;
  140. irq_line = fpga_irqs[hwirq].irq_line;
  141. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  142. mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
  143. & SOCRATES_FPGA_IRQ_MASK;
  144. mask |= (1 << hwirq);
  145. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
  146. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  147. }
  148. static void socrates_fpga_pic_eoi(struct irq_data *d)
  149. {
  150. unsigned long flags;
  151. unsigned int hwirq = irqd_to_hwirq(d);
  152. int irq_line;
  153. u32 mask;
  154. irq_line = fpga_irqs[hwirq].irq_line;
  155. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  156. mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
  157. & SOCRATES_FPGA_IRQ_MASK;
  158. mask |= (1 << (hwirq + 16));
  159. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
  160. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  161. }
  162. static int socrates_fpga_pic_set_type(struct irq_data *d,
  163. unsigned int flow_type)
  164. {
  165. unsigned long flags;
  166. unsigned int hwirq = irqd_to_hwirq(d);
  167. int polarity;
  168. u32 mask;
  169. if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
  170. return -EINVAL;
  171. switch (flow_type & IRQ_TYPE_SENSE_MASK) {
  172. case IRQ_TYPE_LEVEL_HIGH:
  173. polarity = 1;
  174. break;
  175. case IRQ_TYPE_LEVEL_LOW:
  176. polarity = 0;
  177. break;
  178. default:
  179. return -EINVAL;
  180. }
  181. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  182. mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
  183. if (polarity)
  184. mask |= (1 << hwirq);
  185. else
  186. mask &= ~(1 << hwirq);
  187. socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
  188. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  189. return 0;
  190. }
  191. static struct irq_chip socrates_fpga_pic_chip = {
  192. .name = "FPGA-PIC",
  193. .irq_ack = socrates_fpga_pic_ack,
  194. .irq_mask = socrates_fpga_pic_mask,
  195. .irq_mask_ack = socrates_fpga_pic_mask_ack,
  196. .irq_unmask = socrates_fpga_pic_unmask,
  197. .irq_eoi = socrates_fpga_pic_eoi,
  198. .irq_set_type = socrates_fpga_pic_set_type,
  199. };
  200. static int socrates_fpga_pic_host_map(struct irq_domain *h, unsigned int virq,
  201. irq_hw_number_t hwirq)
  202. {
  203. /* All interrupts are LEVEL sensitive */
  204. irq_set_status_flags(virq, IRQ_LEVEL);
  205. irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip,
  206. handle_fasteoi_irq);
  207. return 0;
  208. }
  209. static int socrates_fpga_pic_host_xlate(struct irq_domain *h,
  210. struct device_node *ct, const u32 *intspec, unsigned int intsize,
  211. irq_hw_number_t *out_hwirq, unsigned int *out_flags)
  212. {
  213. struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
  214. *out_hwirq = intspec[0];
  215. if (fpga_irq->type == IRQ_TYPE_NONE) {
  216. /* type is configurable */
  217. if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
  218. intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
  219. pr_warning("FPGA PIC: invalid irq type, "
  220. "setting default active low\n");
  221. *out_flags = IRQ_TYPE_LEVEL_LOW;
  222. } else {
  223. *out_flags = intspec[1];
  224. }
  225. } else {
  226. /* type is fixed */
  227. *out_flags = fpga_irq->type;
  228. }
  229. /* Use specified interrupt routing */
  230. if (intspec[2] <= 2)
  231. fpga_irq->irq_line = intspec[2];
  232. else
  233. pr_warning("FPGA PIC: invalid irq routing\n");
  234. return 0;
  235. }
  236. static const struct irq_domain_ops socrates_fpga_pic_host_ops = {
  237. .map = socrates_fpga_pic_host_map,
  238. .xlate = socrates_fpga_pic_host_xlate,
  239. };
  240. void socrates_fpga_pic_init(struct device_node *pic)
  241. {
  242. unsigned long flags;
  243. int i;
  244. /* Setup an irq_domain structure */
  245. socrates_fpga_pic_irq_host = irq_domain_add_linear(pic,
  246. SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops, NULL);
  247. if (socrates_fpga_pic_irq_host == NULL) {
  248. pr_err("FPGA PIC: Unable to allocate host\n");
  249. return;
  250. }
  251. for (i = 0; i < 3; i++) {
  252. socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
  253. if (socrates_fpga_irqs[i] == NO_IRQ) {
  254. pr_warning("FPGA PIC: can't get irq%d.\n", i);
  255. continue;
  256. }
  257. irq_set_chained_handler(socrates_fpga_irqs[i],
  258. socrates_fpga_pic_cascade);
  259. }
  260. socrates_fpga_pic_iobase = of_iomap(pic, 0);
  261. raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
  262. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
  263. SOCRATES_FPGA_IRQ_MASK << 16);
  264. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
  265. SOCRATES_FPGA_IRQ_MASK << 16);
  266. socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
  267. SOCRATES_FPGA_IRQ_MASK << 16);
  268. raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
  269. pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
  270. }