mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
RISC-V: implement low-level interrupt handling
Add support for a routine that dispatches exceptions with the interrupt flags set to either the IPI or irqdomain code (and the clock source in the future). Loosely based on the irq-riscv-int.c irqchip driver from the RISC-V tree. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
bec2e6ac35
commit
6ea0f26a79
2 changed files with 45 additions and 11 deletions
|
@ -168,8 +168,8 @@ ENTRY(handle_exception)
|
||||||
|
|
||||||
/* Handle interrupts */
|
/* Handle interrupts */
|
||||||
move a0, sp /* pt_regs */
|
move a0, sp /* pt_regs */
|
||||||
REG_L a1, handle_arch_irq
|
move a1, s4 /* scause */
|
||||||
jr a1
|
tail do_IRQ
|
||||||
1:
|
1:
|
||||||
/* Exceptions run with interrupts enabled */
|
/* Exceptions run with interrupts enabled */
|
||||||
csrs sstatus, SR_SIE
|
csrs sstatus, SR_SIE
|
||||||
|
|
|
@ -1,21 +1,55 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 Regents of the University of California
|
* Copyright (C) 2012 Regents of the University of California
|
||||||
* Copyright (C) 2017 SiFive
|
* Copyright (C) 2017 SiFive
|
||||||
*
|
* Copyright (C) 2018 Christoph Hellwig
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation, version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irqchip.h>
|
#include <linux/irqchip.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible interrupt causes:
|
||||||
|
*/
|
||||||
|
#define INTERRUPT_CAUSE_SOFTWARE 1
|
||||||
|
#define INTERRUPT_CAUSE_TIMER 5
|
||||||
|
#define INTERRUPT_CAUSE_EXTERNAL 9
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The high order bit of the trap cause register is always set for
|
||||||
|
* interrupts, which allows us to differentiate them from exceptions
|
||||||
|
* quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we
|
||||||
|
* need to mask it off.
|
||||||
|
*/
|
||||||
|
#define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1))
|
||||||
|
|
||||||
|
asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause)
|
||||||
|
{
|
||||||
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
|
|
||||||
|
irq_enter();
|
||||||
|
switch (cause & ~INTERRUPT_CAUSE_FLAG) {
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
case INTERRUPT_CAUSE_SOFTWARE:
|
||||||
|
/*
|
||||||
|
* We only use software interrupts to pass IPIs, so if a non-SMP
|
||||||
|
* system gets one, then we don't know what to do.
|
||||||
|
*/
|
||||||
|
riscv_software_interrupt();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case INTERRUPT_CAUSE_EXTERNAL:
|
||||||
|
handle_arch_irq(regs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("unexpected interrupt cause");
|
||||||
|
}
|
||||||
|
irq_exit();
|
||||||
|
|
||||||
|
set_irq_regs(old_regs);
|
||||||
|
}
|
||||||
|
|
||||||
void __init init_IRQ(void)
|
void __init init_IRQ(void)
|
||||||
{
|
{
|
||||||
irqchip_init();
|
irqchip_init();
|
||||||
|
|
Loading…
Reference in a new issue