arch: riscv: make __soc_is_irq optional
It looks like all SoCs in tree check if an exception comes from an IRQ the same way, so let's provide a common logic by default, still customizable if the SoC selects RISCV_SOC_ISR_CHECK. Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
parent
49e2bc69a2
commit
68799d507d
7 changed files with 21 additions and 66 deletions
|
@ -172,6 +172,13 @@ config RISCV_HAS_CLIC
|
|||
help
|
||||
Does the SOC provide support for a Core-Local Interrupt Controller (CLIC).
|
||||
|
||||
config RISCV_SOC_EXCEPTION_FROM_IRQ
|
||||
bool
|
||||
help
|
||||
Option selected by SoCs that require a custom mechanism to check if
|
||||
an exception is the result of an interrupt or not. If selected,
|
||||
__soc_is_irq() needs to be implemented by the SoC.
|
||||
|
||||
config RISCV_SOC_INTERRUPT_INIT
|
||||
bool "SOC-based interrupt initialization"
|
||||
help
|
||||
|
|
|
@ -51,7 +51,9 @@
|
|||
|
||||
/* imports */
|
||||
GDATA(_sw_isr_table)
|
||||
#ifdef CONFIG_RISCV_SOC_EXCEPTION_FROM_IRQ
|
||||
GTEXT(__soc_is_irq)
|
||||
#endif
|
||||
GTEXT(__soc_handle_irq)
|
||||
GTEXT(_Fault)
|
||||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
|
||||
|
@ -95,7 +97,8 @@ GTEXT(_isr_wrapper)
|
|||
* what standard behavior is defined). Hence, the arch level code expects
|
||||
* the following functions to be provided at the SOC level:
|
||||
*
|
||||
* - __soc_is_irq: decide if we're handling an interrupt or an exception
|
||||
* - __soc_is_irq (optional): decide if we're handling an interrupt or an
|
||||
exception
|
||||
* - __soc_handle_irq: handle SoC-specific details for a pending IRQ
|
||||
* (e.g. clear a pending bit in a SoC-specific register)
|
||||
*
|
||||
|
@ -288,10 +291,14 @@ no_fp: /* increment _current->arch.exception_depth */
|
|||
* function (that needs to be implemented by each SOC). The result is
|
||||
* returned via register a0 (1: interrupt, 0 exception)
|
||||
*/
|
||||
#ifdef CONFIG_RISCV_SOC_EXCEPTION_FROM_IRQ
|
||||
jal ra, __soc_is_irq
|
||||
|
||||
/* If a0 != 0, jump to is_interrupt */
|
||||
bnez a0, is_interrupt
|
||||
#else
|
||||
csrr t0, mcause
|
||||
srli t0, t0, RISCV_MCAUSE_IRQ_POS
|
||||
bnez t0, is_interrupt
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the exception is the result of an ECALL, check whether to
|
||||
|
|
|
@ -39,9 +39,11 @@ extern "C" {
|
|||
#define RISCV_IRQ_MEXT 11
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define RISCV_MCAUSE_IRQ_BIT (1 << 63)
|
||||
#define RISCV_MCAUSE_IRQ_POS 63U
|
||||
#define RISCV_MCAUSE_IRQ_BIT BIT64(RISCV_MCAUSE_IRQ_POS)
|
||||
#else
|
||||
#define RISCV_MCAUSE_IRQ_BIT (1 << 31)
|
||||
#define RISCV_MCAUSE_IRQ_POS 31U
|
||||
#define RISCV_MCAUSE_IRQ_BIT BIT(RISCV_MCAUSE_IRQ_POS)
|
||||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
|
|
@ -32,30 +32,3 @@ SECTION_FUNC(exception.other, __soc_handle_irq)
|
|||
|
||||
/* Return */
|
||||
ret
|
||||
|
||||
/*
|
||||
* __soc_is_irq is defined as .weak to allow re-implementation by
|
||||
* SOCs that do not truly follow the riscv privilege specification.
|
||||
*/
|
||||
WTEXT(__soc_is_irq)
|
||||
|
||||
/*
|
||||
* SOC-specific function to determine if the exception is the result of a
|
||||
* an interrupt or an exception
|
||||
* return 1 (interrupt) or 0 (exception)
|
||||
*
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
/* Read mcause and check if interrupt bit is set */
|
||||
csrr t0, mcause
|
||||
li t1, RISCV_MCAUSE_IRQ_BIT
|
||||
and t0, t0, t1
|
||||
|
||||
/* If interrupt bit is not set, return with 0 */
|
||||
addi a0, x0, 0
|
||||
beqz t0, not_interrupt
|
||||
addi a0, a0, 1
|
||||
|
||||
not_interrupt:
|
||||
/* return */
|
||||
ret
|
||||
|
|
|
@ -7,15 +7,9 @@
|
|||
#include <zephyr/toolchain.h>
|
||||
|
||||
/* Exports */
|
||||
GTEXT(__soc_is_irq)
|
||||
GTEXT(__soc_handle_irq)
|
||||
GTEXT(soc_intr_get_next_source)
|
||||
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
csrr a0, mcause
|
||||
srli a0, a0, 31
|
||||
ret
|
||||
|
||||
SECTION_FUNC(exception.other, __soc_handle_irq)
|
||||
addi sp, sp,-4
|
||||
sw ra, 0x00(sp)
|
||||
|
|
|
@ -25,21 +25,3 @@ GTEXT(__soc_handle_irq)
|
|||
*/
|
||||
SECTION_FUNC(exception.other, __soc_handle_irq)
|
||||
j get_irq
|
||||
|
||||
/*
|
||||
* __soc_is_irq is defined as .weak to allow re-implementation by
|
||||
* SOCs that does not truely follow the riscv privilege specification.
|
||||
*/
|
||||
WTEXT(__soc_is_irq)
|
||||
|
||||
/*
|
||||
* SOC-specific function to determine if the exception is the result of a
|
||||
* an interrupt or an exception
|
||||
* return 1 (interrupt) or 0 (exception)
|
||||
*
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
/* Read mcause and check if interrupt bit (bit 31) is set */
|
||||
csrr a0, mcause
|
||||
srli a0, a0, 31
|
||||
ret
|
||||
|
|
|
@ -10,22 +10,12 @@
|
|||
#include <soc.h>
|
||||
|
||||
/* Exports */
|
||||
GTEXT(__soc_is_irq)
|
||||
GTEXT(__soc_handle_irq)
|
||||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
|
||||
GTEXT(__soc_save_context)
|
||||
GTEXT(__soc_restore_context)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether we're in an IRQ is bog-standard RISC-V on this SoC:
|
||||
* yes if the top mcause bit is set, otherwise no.
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
csrr a0, mcause
|
||||
srli a0, a0, 31
|
||||
ret
|
||||
|
||||
/*
|
||||
* With a0 == irq_num, this is equivalent to:
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue