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 8 #include <linux/interrupt.h> 9 #include <linux/irqchip.h> 10 #include <linux/irqdomain.h> 11 #include <linux/seq_file.h> 12 #include <asm/smp.h> 13 14 /* 15 * Possible interrupt causes: 16 */ 17 #define INTERRUPT_CAUSE_SOFTWARE 1 18 #define INTERRUPT_CAUSE_TIMER 5 19 #define INTERRUPT_CAUSE_EXTERNAL 9 20 21 /* 22 * The high order bit of the trap cause register is always set for 23 * interrupts, which allows us to differentiate them from exceptions 24 * quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we 25 * need to mask it off. 26 */ 27 #define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1)) 28 29 int arch_show_interrupts(struct seq_file *p, int prec) 30 { 31 show_ipi_stats(p, prec); 32 return 0; 33 } 34 35 asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) 36 { 37 struct pt_regs *old_regs = set_irq_regs(regs); 38 39 irq_enter(); 40 switch (regs->scause & ~INTERRUPT_CAUSE_FLAG) { 41 case INTERRUPT_CAUSE_TIMER: 42 riscv_timer_interrupt(); 43 break; 44 #ifdef CONFIG_SMP 45 case INTERRUPT_CAUSE_SOFTWARE: 46 /* 47 * We only use software interrupts to pass IPIs, so if a non-SMP 48 * system gets one, then we don't know what to do. 49 */ 50 riscv_software_interrupt(); 51 break; 52 #endif 53 case INTERRUPT_CAUSE_EXTERNAL: 54 handle_arch_irq(regs); 55 break; 56 default: 57 panic("unexpected interrupt cause"); 58 } 59 irq_exit(); 60 61 set_irq_regs(old_regs); 62 } 63 64 void __init init_IRQ(void) 65 { 66 irqchip_init(); 67 } 68