|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
1 | 2 | /*
|
2 | 3 | * Copyright (C) 2012 Regents of the University of California
|
3 | 4 | * Copyright (C) 2017 SiFive
|
4 |
| - * |
5 |
| - * This program is free software; you can redistribute it and/or |
6 |
| - * modify it under the terms of the GNU General Public License |
7 |
| - * as published by the Free Software Foundation, version 2. |
8 |
| - * |
9 |
| - * This program is distributed in the hope that it will be useful, |
10 |
| - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
| - * GNU General Public License for more details. |
| 5 | + * Copyright (C) 2018 Christoph Hellwig |
13 | 6 | */
|
14 | 7 |
|
15 | 8 | #include <linux/interrupt.h>
|
16 | 9 | #include <linux/irqchip.h>
|
17 | 10 | #include <linux/irqdomain.h>
|
18 | 11 |
|
| 12 | +/* |
| 13 | + * Possible interrupt causes: |
| 14 | + */ |
| 15 | +#define INTERRUPT_CAUSE_SOFTWARE 1 |
| 16 | +#define INTERRUPT_CAUSE_TIMER 5 |
| 17 | +#define INTERRUPT_CAUSE_EXTERNAL 9 |
| 18 | + |
| 19 | +/* |
| 20 | + * The high order bit of the trap cause register is always set for |
| 21 | + * interrupts, which allows us to differentiate them from exceptions |
| 22 | + * quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we |
| 23 | + * need to mask it off. |
| 24 | + */ |
| 25 | +#define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1)) |
| 26 | + |
| 27 | +asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause) |
| 28 | +{ |
| 29 | + struct pt_regs *old_regs = set_irq_regs(regs); |
| 30 | + |
| 31 | + irq_enter(); |
| 32 | + switch (cause & ~INTERRUPT_CAUSE_FLAG) { |
| 33 | +#ifdef CONFIG_SMP |
| 34 | + case INTERRUPT_CAUSE_SOFTWARE: |
| 35 | + /* |
| 36 | + * We only use software interrupts to pass IPIs, so if a non-SMP |
| 37 | + * system gets one, then we don't know what to do. |
| 38 | + */ |
| 39 | + riscv_software_interrupt(); |
| 40 | + break; |
| 41 | +#endif |
| 42 | + case INTERRUPT_CAUSE_EXTERNAL: |
| 43 | + handle_arch_irq(regs); |
| 44 | + break; |
| 45 | + default: |
| 46 | + panic("unexpected interrupt cause"); |
| 47 | + } |
| 48 | + irq_exit(); |
| 49 | + |
| 50 | + set_irq_regs(old_regs); |
| 51 | +} |
| 52 | + |
19 | 53 | void __init init_IRQ(void)
|
20 | 54 | {
|
21 | 55 | irqchip_init();
|
|
0 commit comments