socrates_fpga_pic.c 8.6 KB

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