irq-riscv-intc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2012 Regents of the University of California
  4. * Copyright (C) 2017-2018 SiFive
  5. * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  6. */
  7. #define pr_fmt(fmt) "riscv-intc: " fmt
  8. #include <linux/atomic.h>
  9. #include <linux/bits.h>
  10. #include <linux/cpu.h>
  11. #include <linux/irq.h>
  12. #include <linux/irqchip.h>
  13. #include <linux/irqdomain.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/module.h>
  16. #include <linux/of.h>
  17. #include <linux/smp.h>
  18. static struct irq_domain *intc_domain;
  19. static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
  20. {
  21. unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
  22. if (unlikely(cause >= BITS_PER_LONG))
  23. panic("unexpected interrupt cause");
  24. switch (cause) {
  25. #ifdef CONFIG_SMP
  26. case RV_IRQ_SOFT:
  27. /*
  28. * We only use software interrupts to pass IPIs, so if a
  29. * non-SMP system gets one, then we don't know what to do.
  30. */
  31. handle_IPI(regs);
  32. break;
  33. #endif
  34. default:
  35. generic_handle_domain_irq(intc_domain, cause);
  36. break;
  37. }
  38. }
  39. /*
  40. * On RISC-V systems local interrupts are masked or unmasked by writing
  41. * the SIE (Supervisor Interrupt Enable) CSR. As CSRs can only be written
  42. * on the local hart, these functions can only be called on the hart that
  43. * corresponds to the IRQ chip.
  44. */
  45. static void riscv_intc_irq_mask(struct irq_data *d)
  46. {
  47. csr_clear(CSR_IE, BIT(d->hwirq));
  48. }
  49. static void riscv_intc_irq_unmask(struct irq_data *d)
  50. {
  51. csr_set(CSR_IE, BIT(d->hwirq));
  52. }
  53. static int riscv_intc_cpu_starting(unsigned int cpu)
  54. {
  55. csr_set(CSR_IE, BIT(RV_IRQ_SOFT));
  56. return 0;
  57. }
  58. static int riscv_intc_cpu_dying(unsigned int cpu)
  59. {
  60. csr_clear(CSR_IE, BIT(RV_IRQ_SOFT));
  61. return 0;
  62. }
  63. static struct irq_chip riscv_intc_chip = {
  64. .name = "RISC-V INTC",
  65. .irq_mask = riscv_intc_irq_mask,
  66. .irq_unmask = riscv_intc_irq_unmask,
  67. };
  68. static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
  69. irq_hw_number_t hwirq)
  70. {
  71. irq_set_percpu_devid(irq);
  72. irq_domain_set_info(d, irq, hwirq, &riscv_intc_chip, d->host_data,
  73. handle_percpu_devid_irq, NULL, NULL);
  74. return 0;
  75. }
  76. static const struct irq_domain_ops riscv_intc_domain_ops = {
  77. .map = riscv_intc_domain_map,
  78. .xlate = irq_domain_xlate_onecell,
  79. };
  80. static int __init riscv_intc_init(struct device_node *node,
  81. struct device_node *parent)
  82. {
  83. int rc;
  84. unsigned long hartid;
  85. rc = riscv_of_parent_hartid(node, &hartid);
  86. if (rc < 0) {
  87. pr_warn("unable to find hart id for %pOF\n", node);
  88. return 0;
  89. }
  90. /*
  91. * The DT will have one INTC DT node under each CPU (or HART)
  92. * DT node so riscv_intc_init() function will be called once
  93. * for each INTC DT node. We only need to do INTC initialization
  94. * for the INTC DT node belonging to boot CPU (or boot HART).
  95. */
  96. if (riscv_hartid_to_cpuid(hartid) != smp_processor_id()) {
  97. /*
  98. * The INTC nodes of each CPU are suppliers for downstream
  99. * interrupt controllers (such as PLIC, IMSIC and APLIC
  100. * direct-mode) so we should mark an INTC node as initialized
  101. * if we are not creating IRQ domain for it.
  102. */
  103. fwnode_dev_initialized(of_fwnode_handle(node), true);
  104. return 0;
  105. }
  106. intc_domain = irq_domain_add_linear(node, BITS_PER_LONG,
  107. &riscv_intc_domain_ops, NULL);
  108. if (!intc_domain) {
  109. pr_err("unable to add IRQ domain\n");
  110. return -ENXIO;
  111. }
  112. rc = set_handle_irq(&riscv_intc_irq);
  113. if (rc) {
  114. pr_err("failed to set irq handler\n");
  115. return rc;
  116. }
  117. cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_STARTING,
  118. "irqchip/riscv/intc:starting",
  119. riscv_intc_cpu_starting,
  120. riscv_intc_cpu_dying);
  121. pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
  122. return 0;
  123. }
  124. IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);