You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.2 KiB
103 lines
2.2 KiB
/* |
|
* Copyright (c) 2024 Baumer Electric AG |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
/** |
|
* @brief Assembler-hooks specific to RISC-V Core Local Interrupt Controller |
|
*/ |
|
|
|
#include <zephyr/arch/cpu.h> |
|
#include "intc_clic.h" |
|
|
|
#ifdef CONFIG_64BIT |
|
/* register-wide load/store based on ld/sd (XLEN = 64) */ |
|
|
|
.macro lr, rd, mem |
|
ld \rd, \mem |
|
.endm |
|
|
|
.macro sr, rs, mem |
|
sd \rs, \mem |
|
.endm |
|
|
|
#else |
|
/* register-wide load/store based on lw/sw (XLEN = 32) */ |
|
|
|
.macro lr, rd, mem |
|
lw \rd, \mem |
|
.endm |
|
|
|
.macro sr, rs, mem |
|
sw \rs, \mem |
|
.endm |
|
|
|
#endif |
|
|
|
GTEXT(__soc_handle_irq) |
|
/* |
|
* In an CLIC, pending interrupts don't have to be cleared by hand. |
|
* In vectored mode, interrupts are cleared automatically. |
|
* In non-vectored mode, interrupts are cleared when writing the mnxti register (done in |
|
* __soc_handle_all_irqs). |
|
* Thus this function can directly return. |
|
*/ |
|
SECTION_FUNC(exception.other, __soc_handle_irq) |
|
ret |
|
|
|
GTEXT(__soc_handle_all_irqs) |
|
|
|
#ifdef CONFIG_TRACING |
|
/* imports */ |
|
GTEXT(sys_trace_isr_enter) |
|
GTEXT(sys_trace_isr_exit) |
|
#endif |
|
|
|
/* |
|
* This function services and clears all pending interrupts for an CLIC in non-vectored mode. |
|
*/ |
|
SECTION_FUNC(exception.other, __soc_handle_all_irqs) |
|
addi sp, sp, -16 |
|
sr ra, 0(sp) |
|
|
|
/* Read and clear mnxti to get highest current interrupt and enable interrupts. Will return |
|
* original interrupt if no others appear. */ |
|
csrrci a0, CSR_MNXTI, MSTATUS_IEN |
|
beqz a0, irq_done /* Check if original interrupt vanished. */ |
|
|
|
irq_loop: |
|
|
|
#ifdef CONFIG_TRACING_ISR |
|
call sys_trace_isr_enter |
|
#endif |
|
|
|
/* Call corresponding registered function in _sw_isr_table. a0 is offset in pointer with |
|
* the mtvt, sw irq table is 2-pointer wide -> shift by one. */ |
|
csrr t0, CSR_MTVT |
|
sub a0, a0, t0 |
|
la t0, _sw_isr_table |
|
slli a0, a0, (1) |
|
add t0, t0, a0 |
|
|
|
/* Load argument in a0 register */ |
|
lr a0, 0(t0) |
|
|
|
/* Load ISR function address in register t1 */ |
|
lr t1, RV_REGSIZE(t0) |
|
|
|
/* Call ISR function */ |
|
jalr ra, t1, 0 |
|
|
|
#ifdef CONFIG_TRACING_ISR |
|
call sys_trace_isr_exit |
|
#endif |
|
|
|
/* Read and clear mnxti to get highest current interrupt and enable interrupts. */ |
|
csrrci a0, CSR_MNXTI, MSTATUS_IEN |
|
bnez a0, irq_loop |
|
|
|
irq_done: |
|
lr ra, 0(sp) |
|
addi sp, sp, 16 |
|
ret
|
|
|