irq-gemini.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * irqchip for the Cortina Systems Gemini Copyright (C) 2017 Linus
  3. * Walleij <linus.walleij@linaro.org>
  4. *
  5. * Based on arch/arm/mach-gemini/irq.c
  6. * Copyright (C) 2001-2006 Storlink, Corp.
  7. * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
  8. */
  9. #include <linux/bitops.h>
  10. #include <linux/irq.h>
  11. #include <linux/io.h>
  12. #include <linux/irqchip.h>
  13. #include <linux/irqchip/versatile-fpga.h>
  14. #include <linux/irqdomain.h>
  15. #include <linux/module.h>
  16. #include <linux/of.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of_irq.h>
  19. #include <linux/cpu.h>
  20. #include <asm/exception.h>
  21. #include <asm/mach/irq.h>
  22. #define GEMINI_NUM_IRQS 32
  23. #define GEMINI_IRQ_SOURCE(base_addr) (base_addr + 0x00)
  24. #define GEMINI_IRQ_MASK(base_addr) (base_addr + 0x04)
  25. #define GEMINI_IRQ_CLEAR(base_addr) (base_addr + 0x08)
  26. #define GEMINI_IRQ_MODE(base_addr) (base_addr + 0x0C)
  27. #define GEMINI_IRQ_POLARITY(base_addr) (base_addr + 0x10)
  28. #define GEMINI_IRQ_STATUS(base_addr) (base_addr + 0x14)
  29. #define GEMINI_FIQ_SOURCE(base_addr) (base_addr + 0x20)
  30. #define GEMINI_FIQ_MASK(base_addr) (base_addr + 0x24)
  31. #define GEMINI_FIQ_CLEAR(base_addr) (base_addr + 0x28)
  32. #define GEMINI_FIQ_MODE(base_addr) (base_addr + 0x2C)
  33. #define GEMINI_FIQ_POLARITY(base_addr) (base_addr + 0x30)
  34. #define GEMINI_FIQ_STATUS(base_addr) (base_addr + 0x34)
  35. /**
  36. * struct gemini_irq_data - irq data container for the Gemini IRQ controller
  37. * @base: memory offset in virtual memory
  38. * @chip: chip container for this instance
  39. * @domain: IRQ domain for this instance
  40. */
  41. struct gemini_irq_data {
  42. void __iomem *base;
  43. struct irq_chip chip;
  44. struct irq_domain *domain;
  45. };
  46. static void gemini_irq_mask(struct irq_data *d)
  47. {
  48. struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
  49. unsigned int mask;
  50. mask = readl(GEMINI_IRQ_MASK(g->base));
  51. mask &= ~BIT(irqd_to_hwirq(d));
  52. writel(mask, GEMINI_IRQ_MASK(g->base));
  53. }
  54. static void gemini_irq_unmask(struct irq_data *d)
  55. {
  56. struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
  57. unsigned int mask;
  58. mask = readl(GEMINI_IRQ_MASK(g->base));
  59. mask |= BIT(irqd_to_hwirq(d));
  60. writel(mask, GEMINI_IRQ_MASK(g->base));
  61. }
  62. static void gemini_irq_ack(struct irq_data *d)
  63. {
  64. struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
  65. writel(BIT(irqd_to_hwirq(d)), GEMINI_IRQ_CLEAR(g->base));
  66. }
  67. static int gemini_irq_set_type(struct irq_data *d, unsigned int trigger)
  68. {
  69. struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
  70. int offset = irqd_to_hwirq(d);
  71. u32 mode, polarity;
  72. mode = readl(GEMINI_IRQ_MODE(g->base));
  73. polarity = readl(GEMINI_IRQ_POLARITY(g->base));
  74. if (trigger & (IRQ_TYPE_LEVEL_HIGH)) {
  75. irq_set_handler_locked(d, handle_level_irq);
  76. /* Disable edge detection */
  77. mode &= ~BIT(offset);
  78. polarity &= ~BIT(offset);
  79. } else if (trigger & IRQ_TYPE_EDGE_RISING) {
  80. irq_set_handler_locked(d, handle_edge_irq);
  81. mode |= BIT(offset);
  82. polarity |= BIT(offset);
  83. } else if (trigger & IRQ_TYPE_EDGE_FALLING) {
  84. irq_set_handler_locked(d, handle_edge_irq);
  85. mode |= BIT(offset);
  86. polarity &= ~BIT(offset);
  87. } else {
  88. irq_set_handler_locked(d, handle_bad_irq);
  89. pr_warn("GEMINI IRQ: no supported trigger selected for line %d\n",
  90. offset);
  91. }
  92. writel(mode, GEMINI_IRQ_MODE(g->base));
  93. writel(polarity, GEMINI_IRQ_POLARITY(g->base));
  94. return 0;
  95. }
  96. static struct irq_chip gemini_irq_chip = {
  97. .name = "GEMINI",
  98. .irq_ack = gemini_irq_ack,
  99. .irq_mask = gemini_irq_mask,
  100. .irq_unmask = gemini_irq_unmask,
  101. .irq_set_type = gemini_irq_set_type,
  102. };
  103. /* Local static for the IRQ entry call */
  104. static struct gemini_irq_data girq;
  105. asmlinkage void __exception_irq_entry gemini_irqchip_handle_irq(struct pt_regs *regs)
  106. {
  107. struct gemini_irq_data *g = &girq;
  108. int irq;
  109. u32 status;
  110. while ((status = readl(GEMINI_IRQ_STATUS(g->base)))) {
  111. irq = ffs(status) - 1;
  112. handle_domain_irq(g->domain, irq, regs);
  113. }
  114. }
  115. static int gemini_irqdomain_map(struct irq_domain *d, unsigned int irq,
  116. irq_hw_number_t hwirq)
  117. {
  118. struct gemini_irq_data *g = d->host_data;
  119. irq_set_chip_data(irq, g);
  120. /* All IRQs should set up their type, flags as bad by default */
  121. irq_set_chip_and_handler(irq, &gemini_irq_chip, handle_bad_irq);
  122. irq_set_probe(irq);
  123. return 0;
  124. }
  125. static void gemini_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
  126. {
  127. irq_set_chip_and_handler(irq, NULL, NULL);
  128. irq_set_chip_data(irq, NULL);
  129. }
  130. static const struct irq_domain_ops gemini_irqdomain_ops = {
  131. .map = gemini_irqdomain_map,
  132. .unmap = gemini_irqdomain_unmap,
  133. .xlate = irq_domain_xlate_onetwocell,
  134. };
  135. int __init gemini_of_init_irq(struct device_node *node,
  136. struct device_node *parent)
  137. {
  138. struct gemini_irq_data *g = &girq;
  139. /*
  140. * Disable the idle handler by default since it is buggy
  141. * For more info see arch/arm/mach-gemini/idle.c
  142. */
  143. cpu_idle_poll_ctrl(true);
  144. g->base = of_iomap(node, 0);
  145. WARN(!g->base, "unable to map gemini irq registers\n");
  146. /* Disable all interrupts */
  147. writel(0, GEMINI_IRQ_MASK(g->base));
  148. writel(0, GEMINI_FIQ_MASK(g->base));
  149. g->domain = irq_domain_add_simple(node, GEMINI_NUM_IRQS, 0,
  150. &gemini_irqdomain_ops, g);
  151. set_handle_irq(gemini_irqchip_handle_irq);
  152. return 0;
  153. }
  154. IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller",
  155. gemini_of_init_irq);