Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 6ea0f26a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Palmer Dabbelt
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarPalmer Dabbelt <palmer@sifive.com>
parent bec2e6ac
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -168,8 +168,8 @@ ENTRY(handle_exception)

	/* Handle interrupts */
	move a0, sp /* pt_regs */
	REG_L a1, handle_arch_irq
	jr a1
	move a1, s4 /* scause */
	tail do_IRQ
1:
	/* Exceptions run with interrupts enabled */
	csrs sstatus, SR_SIE
+43 −9
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2012 Regents of the University of California
 * Copyright (C) 2017 SiFive
 *
 *   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.
 * Copyright (C) 2018 Christoph Hellwig
 */

#include <linux/interrupt.h>
#include <linux/irqchip.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)
{
	irqchip_init();