1/*
2 * Copyright (c) 2024 Baumer Electric AG
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/**
8 * @brief Assembler-hooks specific to Nuclei's Extended Core Interrupt Controller
9 */
10
11#include <zephyr/arch/cpu.h>
12
13
14GTEXT(__soc_handle_irq)
15/*
16 * In an ECLIC, pending interrupts don't have to be cleared by hand.
17 * In vectored mode, interrupts are cleared automatically.
18 * In non-vectored mode, interrupts are cleared when writing the mnxti register (done in
19 * __soc_handle_all_irqs).
20 * Thus this function can directly return.
21 */
22SECTION_FUNC(exception.other, __soc_handle_irq)
23	ret
24
25GTEXT(__soc_handle_all_irqs)
26
27#ifdef CONFIG_TRACING
28/* imports */
29GTEXT(sys_trace_isr_enter)
30GTEXT(sys_trace_isr_exit)
31#endif
32
33/*
34 * This function services and clears all pending interrupts for an ECLIC in non-vectored mode.
35 */
36SECTION_FUNC(exception.other, __soc_handle_all_irqs)
37	addi sp, sp, -16
38	sw ra, 0(sp)
39
40	/* Read and clear mnxti to get highest current interrupt and enable interrupts. Will return
41	 * original interrupt if no others appear. */
42	csrrci a0, 0x345, MSTATUS_IEN
43	beqz a0, irq_done /* Check if original interrupt vanished. */
44
45irq_loop:
46
47#ifdef CONFIG_TRACING_ISR
48	call sys_trace_isr_enter
49#endif
50
51	/* Call corresponding registered function in _sw_isr_table. a0 is offset in pointer with
52	 * the mtvt, sw irq table is 2-pointer wide -> shift by one. */
53	csrr t0, 0x307 /* mtvt */
54	sub a0, a0, t0
55	la t0, _sw_isr_table
56	slli a0, a0, (1)
57	add t0, t0, a0
58
59	/* Load argument in a0 register */
60	lw a0, 0(t0)
61
62	/* Load ISR function address in register t1 */
63	lw t1, RV_REGSIZE(t0)
64
65	/* Call ISR function */
66	jalr ra, t1, 0
67
68#ifdef CONFIG_TRACING_ISR
69	call sys_trace_isr_exit
70#endif
71
72	/* Read and clear mnxti to get highest current interrupt and enable interrupts. */
73	csrrci a0, 0x345, MSTATUS_IEN
74	bnez a0, irq_loop
75
76irq_done:
77	lw ra, 0(sp)
78	addi sp, sp, 16
79	ret
80