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 RISC-V Core Local Interrupt Controller
9 */
10
11#include <zephyr/arch/cpu.h>
12#include "intc_clic.h"
13
14#ifdef CONFIG_64BIT
15	/* register-wide load/store based on ld/sd (XLEN = 64) */
16
17	.macro lr, rd, mem
18	ld \rd, \mem
19	.endm
20
21	.macro sr, rs, mem
22	sd \rs, \mem
23	.endm
24
25#else
26	/* register-wide load/store based on lw/sw (XLEN = 32) */
27
28	.macro lr, rd, mem
29	lw \rd, \mem
30	.endm
31
32	.macro sr, rs, mem
33	sw \rs, \mem
34	.endm
35
36#endif
37
38GTEXT(__soc_handle_irq)
39/*
40 * In an CLIC, pending interrupts don't have to be cleared by hand.
41 * In vectored mode, interrupts are cleared automatically.
42 * In non-vectored mode, interrupts are cleared when writing the mnxti register (done in
43 * __soc_handle_all_irqs).
44 * Thus this function can directly return.
45 */
46SECTION_FUNC(exception.other, __soc_handle_irq)
47	ret
48
49GTEXT(__soc_handle_all_irqs)
50
51#ifdef CONFIG_TRACING
52/* imports */
53GTEXT(sys_trace_isr_enter)
54GTEXT(sys_trace_isr_exit)
55#endif
56
57/*
58 * This function services and clears all pending interrupts for an CLIC in non-vectored mode.
59 */
60SECTION_FUNC(exception.other, __soc_handle_all_irqs)
61	addi sp, sp, -16
62	sr ra, 0(sp)
63
64	/* Read and clear mnxti to get highest current interrupt and enable interrupts. Will return
65	 * original interrupt if no others appear. */
66	csrrci a0, CSR_MNXTI, MSTATUS_IEN
67	beqz a0, irq_done /* Check if original interrupt vanished. */
68
69irq_loop:
70
71#ifdef CONFIG_TRACING_ISR
72	call sys_trace_isr_enter
73#endif
74
75	/* Call corresponding registered function in _sw_isr_table. a0 is offset in pointer with
76	 * the mtvt, sw irq table is 2-pointer wide -> shift by one. */
77	csrr t0, CSR_MTVT
78	sub a0, a0, t0
79	la t0, _sw_isr_table
80	slli a0, a0, (1)
81	add t0, t0, a0
82
83	/* Load argument in a0 register */
84	lr a0, 0(t0)
85
86	/* Load ISR function address in register t1 */
87	lr t1, RV_REGSIZE(t0)
88
89	/* Call ISR function */
90	jalr ra, t1, 0
91
92#ifdef CONFIG_TRACING_ISR
93	call sys_trace_isr_exit
94#endif
95
96	/* Read and clear mnxti to get highest current interrupt and enable interrupts. */
97	csrrci a0, CSR_MNXTI, MSTATUS_IEN
98	bnez a0, irq_loop
99
100irq_done:
101	lr ra, 0(sp)
102	addi sp, sp, 16
103	ret
104