irq-xilinx-intc.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
  3. * Copyright (C) 2012-2013 Xilinx, Inc.
  4. * Copyright (C) 2007-2009 PetaLogix
  5. * Copyright (C) 2006 Atmark Techno, Inc.
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. */
  11. #include <linux/irqdomain.h>
  12. #include <linux/irq.h>
  13. #include <linux/irqchip.h>
  14. #include <linux/irqchip/chained_irq.h>
  15. #include <linux/of_address.h>
  16. #include <linux/io.h>
  17. #include <linux/jump_label.h>
  18. #include <linux/bug.h>
  19. #include <linux/of_irq.h>
  20. /* No one else should require these constants, so define them locally here. */
  21. #define ISR 0x00 /* Interrupt Status Register */
  22. #define IPR 0x04 /* Interrupt Pending Register */
  23. #define IER 0x08 /* Interrupt Enable Register */
  24. #define IAR 0x0c /* Interrupt Acknowledge Register */
  25. #define SIE 0x10 /* Set Interrupt Enable bits */
  26. #define CIE 0x14 /* Clear Interrupt Enable bits */
  27. #define IVR 0x18 /* Interrupt Vector Register */
  28. #define MER 0x1c /* Master Enable Register */
  29. #define MER_ME (1<<0)
  30. #define MER_HIE (1<<1)
  31. static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
  32. struct xintc_irq_chip {
  33. void __iomem *base;
  34. struct irq_domain *root_domain;
  35. u32 intr_mask;
  36. };
  37. static struct xintc_irq_chip *xintc_irqc;
  38. static void xintc_write(int reg, u32 data)
  39. {
  40. if (static_branch_unlikely(&xintc_is_be))
  41. iowrite32be(data, xintc_irqc->base + reg);
  42. else
  43. iowrite32(data, xintc_irqc->base + reg);
  44. }
  45. static unsigned int xintc_read(int reg)
  46. {
  47. if (static_branch_unlikely(&xintc_is_be))
  48. return ioread32be(xintc_irqc->base + reg);
  49. else
  50. return ioread32(xintc_irqc->base + reg);
  51. }
  52. static void intc_enable_or_unmask(struct irq_data *d)
  53. {
  54. unsigned long mask = 1 << d->hwirq;
  55. pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);
  56. /* ack level irqs because they can't be acked during
  57. * ack function since the handle_level_irq function
  58. * acks the irq before calling the interrupt handler
  59. */
  60. if (irqd_is_level_type(d))
  61. xintc_write(IAR, mask);
  62. xintc_write(SIE, mask);
  63. }
  64. static void intc_disable_or_mask(struct irq_data *d)
  65. {
  66. pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
  67. xintc_write(CIE, 1 << d->hwirq);
  68. }
  69. static void intc_ack(struct irq_data *d)
  70. {
  71. pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
  72. xintc_write(IAR, 1 << d->hwirq);
  73. }
  74. static void intc_mask_ack(struct irq_data *d)
  75. {
  76. unsigned long mask = 1 << d->hwirq;
  77. pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
  78. xintc_write(CIE, mask);
  79. xintc_write(IAR, mask);
  80. }
  81. static struct irq_chip intc_dev = {
  82. .name = "Xilinx INTC",
  83. .irq_unmask = intc_enable_or_unmask,
  84. .irq_mask = intc_disable_or_mask,
  85. .irq_ack = intc_ack,
  86. .irq_mask_ack = intc_mask_ack,
  87. };
  88. unsigned int xintc_get_irq(void)
  89. {
  90. unsigned int hwirq, irq = -1;
  91. hwirq = xintc_read(IVR);
  92. if (hwirq != -1U)
  93. irq = irq_find_mapping(xintc_irqc->root_domain, hwirq);
  94. pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
  95. return irq;
  96. }
  97. static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
  98. {
  99. if (xintc_irqc->intr_mask & (1 << hw)) {
  100. irq_set_chip_and_handler_name(irq, &intc_dev,
  101. handle_edge_irq, "edge");
  102. irq_clear_status_flags(irq, IRQ_LEVEL);
  103. } else {
  104. irq_set_chip_and_handler_name(irq, &intc_dev,
  105. handle_level_irq, "level");
  106. irq_set_status_flags(irq, IRQ_LEVEL);
  107. }
  108. return 0;
  109. }
  110. static const struct irq_domain_ops xintc_irq_domain_ops = {
  111. .xlate = irq_domain_xlate_onetwocell,
  112. .map = xintc_map,
  113. };
  114. static void xil_intc_irq_handler(struct irq_desc *desc)
  115. {
  116. struct irq_chip *chip = irq_desc_get_chip(desc);
  117. u32 pending;
  118. chained_irq_enter(chip, desc);
  119. do {
  120. pending = xintc_get_irq();
  121. if (pending == -1U)
  122. break;
  123. generic_handle_irq(pending);
  124. } while (true);
  125. chained_irq_exit(chip, desc);
  126. }
  127. static int __init xilinx_intc_of_init(struct device_node *intc,
  128. struct device_node *parent)
  129. {
  130. u32 nr_irq;
  131. int ret, irq;
  132. struct xintc_irq_chip *irqc;
  133. if (xintc_irqc) {
  134. pr_err("irq-xilinx: Multiple instances aren't supported\n");
  135. return -EINVAL;
  136. }
  137. irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
  138. if (!irqc)
  139. return -ENOMEM;
  140. xintc_irqc = irqc;
  141. irqc->base = of_iomap(intc, 0);
  142. BUG_ON(!irqc->base);
  143. ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
  144. if (ret < 0) {
  145. pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n");
  146. goto err_alloc;
  147. }
  148. ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask);
  149. if (ret < 0) {
  150. pr_warn("irq-xilinx: unable to read xlnx,kind-of-intr\n");
  151. irqc->intr_mask = 0;
  152. }
  153. if (irqc->intr_mask >> nr_irq)
  154. pr_warn("irq-xilinx: mismatch in kind-of-intr param\n");
  155. pr_info("irq-xilinx: %pOF: num_irq=%d, edge=0x%x\n",
  156. intc, nr_irq, irqc->intr_mask);
  157. /*
  158. * Disable all external interrupts until they are
  159. * explicity requested.
  160. */
  161. xintc_write(IER, 0);
  162. /* Acknowledge any pending interrupts just in case. */
  163. xintc_write(IAR, 0xffffffff);
  164. /* Turn on the Master Enable. */
  165. xintc_write(MER, MER_HIE | MER_ME);
  166. if (!(xintc_read(MER) & (MER_HIE | MER_ME))) {
  167. static_branch_enable(&xintc_is_be);
  168. xintc_write(MER, MER_HIE | MER_ME);
  169. }
  170. irqc->root_domain = irq_domain_add_linear(intc, nr_irq,
  171. &xintc_irq_domain_ops, irqc);
  172. if (!irqc->root_domain) {
  173. pr_err("irq-xilinx: Unable to create IRQ domain\n");
  174. goto err_alloc;
  175. }
  176. if (parent) {
  177. irq = irq_of_parse_and_map(intc, 0);
  178. if (irq) {
  179. irq_set_chained_handler_and_data(irq,
  180. xil_intc_irq_handler,
  181. irqc);
  182. } else {
  183. pr_err("irq-xilinx: interrupts property not in DT\n");
  184. ret = -EINVAL;
  185. goto err_alloc;
  186. }
  187. } else {
  188. irq_set_default_host(irqc->root_domain);
  189. }
  190. return 0;
  191. err_alloc:
  192. xintc_irqc = NULL;
  193. kfree(irqc);
  194. return ret;
  195. }
  196. IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
  197. IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init);