socrates_fpga_pic.c 8.2 KB

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