irq.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2012 Regents of the University of California
  4. * Copyright (C) 2017 SiFive
  5. * Copyright (C) 2018 Christoph Hellwig
  6. */
  7. #include <linux/interrupt.h>
  8. #include <linux/irqchip.h>
  9. #include <linux/irqdomain.h>
  10. /*
  11. * Possible interrupt causes:
  12. */
  13. #define INTERRUPT_CAUSE_SOFTWARE 1
  14. #define INTERRUPT_CAUSE_TIMER 5
  15. #define INTERRUPT_CAUSE_EXTERNAL 9
  16. /*
  17. * The high order bit of the trap cause register is always set for
  18. * interrupts, which allows us to differentiate them from exceptions
  19. * quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we
  20. * need to mask it off.
  21. */
  22. #define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1))
  23. asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause)
  24. {
  25. struct pt_regs *old_regs = set_irq_regs(regs);
  26. irq_enter();
  27. switch (cause & ~INTERRUPT_CAUSE_FLAG) {
  28. case INTERRUPT_CAUSE_TIMER:
  29. riscv_timer_interrupt();
  30. break;
  31. #ifdef CONFIG_SMP
  32. case INTERRUPT_CAUSE_SOFTWARE:
  33. /*
  34. * We only use software interrupts to pass IPIs, so if a non-SMP
  35. * system gets one, then we don't know what to do.
  36. */
  37. riscv_software_interrupt();
  38. break;
  39. #endif
  40. case INTERRUPT_CAUSE_EXTERNAL:
  41. handle_arch_irq(regs);
  42. break;
  43. default:
  44. panic("unexpected interrupt cause");
  45. }
  46. irq_exit();
  47. set_irq_regs(old_regs);
  48. }
  49. void __init init_IRQ(void)
  50. {
  51. irqchip_init();
  52. }