irq-bcm2836.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Root interrupt controller for the BCM2836 (Raspberry Pi 2).
  3. *
  4. * Copyright 2015 Broadcom
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/cpu.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of_irq.h>
  19. #include <linux/irqchip.h>
  20. #include <linux/irqdomain.h>
  21. #include <linux/irqchip/irq-bcm2836.h>
  22. #include <asm/exception.h>
  23. struct bcm2836_arm_irqchip_intc {
  24. struct irq_domain *domain;
  25. void __iomem *base;
  26. };
  27. static struct bcm2836_arm_irqchip_intc intc __read_mostly;
  28. static void bcm2836_arm_irqchip_mask_per_cpu_irq(unsigned int reg_offset,
  29. unsigned int bit,
  30. int cpu)
  31. {
  32. void __iomem *reg = intc.base + reg_offset + 4 * cpu;
  33. writel(readl(reg) & ~BIT(bit), reg);
  34. }
  35. static void bcm2836_arm_irqchip_unmask_per_cpu_irq(unsigned int reg_offset,
  36. unsigned int bit,
  37. int cpu)
  38. {
  39. void __iomem *reg = intc.base + reg_offset + 4 * cpu;
  40. writel(readl(reg) | BIT(bit), reg);
  41. }
  42. static void bcm2836_arm_irqchip_mask_timer_irq(struct irq_data *d)
  43. {
  44. bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
  45. d->hwirq - LOCAL_IRQ_CNTPSIRQ,
  46. smp_processor_id());
  47. }
  48. static void bcm2836_arm_irqchip_unmask_timer_irq(struct irq_data *d)
  49. {
  50. bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
  51. d->hwirq - LOCAL_IRQ_CNTPSIRQ,
  52. smp_processor_id());
  53. }
  54. static struct irq_chip bcm2836_arm_irqchip_timer = {
  55. .name = "bcm2836-timer",
  56. .irq_mask = bcm2836_arm_irqchip_mask_timer_irq,
  57. .irq_unmask = bcm2836_arm_irqchip_unmask_timer_irq,
  58. };
  59. static void bcm2836_arm_irqchip_mask_pmu_irq(struct irq_data *d)
  60. {
  61. writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_CLR);
  62. }
  63. static void bcm2836_arm_irqchip_unmask_pmu_irq(struct irq_data *d)
  64. {
  65. writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_SET);
  66. }
  67. static struct irq_chip bcm2836_arm_irqchip_pmu = {
  68. .name = "bcm2836-pmu",
  69. .irq_mask = bcm2836_arm_irqchip_mask_pmu_irq,
  70. .irq_unmask = bcm2836_arm_irqchip_unmask_pmu_irq,
  71. };
  72. static void bcm2836_arm_irqchip_mask_gpu_irq(struct irq_data *d)
  73. {
  74. }
  75. static void bcm2836_arm_irqchip_unmask_gpu_irq(struct irq_data *d)
  76. {
  77. }
  78. static struct irq_chip bcm2836_arm_irqchip_gpu = {
  79. .name = "bcm2836-gpu",
  80. .irq_mask = bcm2836_arm_irqchip_mask_gpu_irq,
  81. .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq,
  82. };
  83. static int bcm2836_map(struct irq_domain *d, unsigned int irq,
  84. irq_hw_number_t hw)
  85. {
  86. struct irq_chip *chip;
  87. switch (hw) {
  88. case LOCAL_IRQ_CNTPSIRQ:
  89. case LOCAL_IRQ_CNTPNSIRQ:
  90. case LOCAL_IRQ_CNTHPIRQ:
  91. case LOCAL_IRQ_CNTVIRQ:
  92. chip = &bcm2836_arm_irqchip_timer;
  93. break;
  94. case LOCAL_IRQ_GPU_FAST:
  95. chip = &bcm2836_arm_irqchip_gpu;
  96. break;
  97. case LOCAL_IRQ_PMU_FAST:
  98. chip = &bcm2836_arm_irqchip_pmu;
  99. break;
  100. default:
  101. pr_warn_once("Unexpected hw irq: %lu\n", hw);
  102. return -EINVAL;
  103. }
  104. irq_set_percpu_devid(irq);
  105. irq_domain_set_info(d, irq, hw, chip, d->host_data,
  106. handle_percpu_devid_irq, NULL, NULL);
  107. irq_set_status_flags(irq, IRQ_NOAUTOEN);
  108. return 0;
  109. }
  110. static void
  111. __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
  112. {
  113. int cpu = smp_processor_id();
  114. u32 stat;
  115. stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
  116. if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {
  117. #ifdef CONFIG_SMP
  118. void __iomem *mailbox0 = (intc.base +
  119. LOCAL_MAILBOX0_CLR0 + 16 * cpu);
  120. u32 mbox_val = readl(mailbox0);
  121. u32 ipi = ffs(mbox_val) - 1;
  122. writel(1 << ipi, mailbox0);
  123. handle_IPI(ipi, regs);
  124. #endif
  125. } else if (stat) {
  126. u32 hwirq = ffs(stat) - 1;
  127. handle_domain_irq(intc.domain, hwirq, regs);
  128. }
  129. }
  130. #ifdef CONFIG_SMP
  131. static void bcm2836_arm_irqchip_send_ipi(const struct cpumask *mask,
  132. unsigned int ipi)
  133. {
  134. int cpu;
  135. void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
  136. /*
  137. * Ensure that stores to normal memory are visible to the
  138. * other CPUs before issuing the IPI.
  139. */
  140. smp_wmb();
  141. for_each_cpu(cpu, mask) {
  142. writel(1 << ipi, mailbox0_base + 16 * cpu);
  143. }
  144. }
  145. static int bcm2836_cpu_starting(unsigned int cpu)
  146. {
  147. bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
  148. cpu);
  149. return 0;
  150. }
  151. static int bcm2836_cpu_dying(unsigned int cpu)
  152. {
  153. bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
  154. cpu);
  155. return 0;
  156. }
  157. #endif
  158. static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
  159. .xlate = irq_domain_xlate_onetwocell,
  160. .map = bcm2836_map,
  161. };
  162. static void
  163. bcm2836_arm_irqchip_smp_init(void)
  164. {
  165. #ifdef CONFIG_SMP
  166. /* Unmask IPIs to the boot CPU. */
  167. cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,
  168. "irqchip/bcm2836:starting", bcm2836_cpu_starting,
  169. bcm2836_cpu_dying);
  170. set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
  171. #endif
  172. }
  173. /*
  174. * The LOCAL_IRQ_CNT* timer firings are based off of the external
  175. * oscillator with some scaling. The firmware sets up CNTFRQ to
  176. * report 19.2Mhz, but doesn't set up the scaling registers.
  177. */
  178. static void bcm2835_init_local_timer_frequency(void)
  179. {
  180. /*
  181. * Set the timer to source from the 19.2Mhz crystal clock (bit
  182. * 8 unset), and only increment by 1 instead of 2 (bit 9
  183. * unset).
  184. */
  185. writel(0, intc.base + LOCAL_CONTROL);
  186. /*
  187. * Set the timer prescaler to 1:1 (timer freq = input freq *
  188. * 2**31 / prescaler)
  189. */
  190. writel(0x80000000, intc.base + LOCAL_PRESCALER);
  191. }
  192. static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
  193. struct device_node *parent)
  194. {
  195. intc.base = of_iomap(node, 0);
  196. if (!intc.base) {
  197. panic("%pOF: unable to map local interrupt registers\n", node);
  198. }
  199. bcm2835_init_local_timer_frequency();
  200. intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
  201. &bcm2836_arm_irqchip_intc_ops,
  202. NULL);
  203. if (!intc.domain)
  204. panic("%pOF: unable to create IRQ domain\n", node);
  205. bcm2836_arm_irqchip_smp_init();
  206. set_handle_irq(bcm2836_arm_irqchip_handle_irq);
  207. return 0;
  208. }
  209. IRQCHIP_DECLARE(bcm2836_arm_irqchip_l1_intc, "brcm,bcm2836-l1-intc",
  210. bcm2836_arm_irqchip_l1_intc_of_init);