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 IRQ_S_SOFT 18 #define INTERRUPT_CAUSE_TIMER IRQ_S_TIMER 19 #define INTERRUPT_CAUSE_EXTERNAL IRQ_S_EXT 20 21 int arch_show_interrupts(struct seq_file *p, int prec) 22 { 23 show_ipi_stats(p, prec); 24 return 0; 25 } 26 27 asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) 28 { 29 struct pt_regs *old_regs = set_irq_regs(regs); 30 31 irq_enter(); 32 switch (regs->scause & ~SCAUSE_IRQ_FLAG) { 33 case INTERRUPT_CAUSE_TIMER: 34 riscv_timer_interrupt(); 35 break; 36 #ifdef CONFIG_SMP 37 case INTERRUPT_CAUSE_SOFTWARE: 38 /* 39 * We only use software interrupts to pass IPIs, so if a non-SMP 40 * system gets one, then we don't know what to do. 41 */ 42 riscv_software_interrupt(); 43 break; 44 #endif 45 case INTERRUPT_CAUSE_EXTERNAL: 46 handle_arch_irq(regs); 47 break; 48 default: 49 pr_alert("unexpected interrupt cause 0x%lx", regs->scause); 50 BUG(); 51 } 52 irq_exit(); 53 54 set_irq_regs(old_regs); 55 } 56 57 void __init init_IRQ(void) 58 { 59 irqchip_init(); 60 } 61