1/*
2 * Copyright (c) 2018 Foundries.io Ltd
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <zephyr/offsets.h>
8#include <zephyr/toolchain.h>
9
10#include <soc.h>
11
12/* Exports */
13GTEXT(__soc_handle_irq)
14#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
15GTEXT(__soc_save_context)
16GTEXT(__soc_restore_context)
17#endif
18
19/*
20 * With a0 == irq_num, this is equivalent to:
21 *
22 * EVENT_UNIT->INTPTPENDCLEAR = (1U << irq_num);
23 *
24 * We could write this routine in C, but the assembly
25 * that's calling us requires that a0 still contain irq_num
26 * on return, and assuming nobody would ever change a
27 * C implementation in a way that silently clobbers it
28 * is playing with fire. Instead, we play tricks in
29 * soc_context.h so that offsets.h contains a pointer to
30 * INTPTPENDCLEAR.
31 */
32SECTION_FUNC(exception.other, __soc_handle_irq)
33	la t0, __EVENT_INTPTPENDCLEAR
34	li t1, 1
35	sll t1, t1, a0
36	sw t1, 0x00(t0)
37	ret
38
39#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
40/*
41 * The RI5CY core has ISA extensions for faster loop performance
42 * that use extra registers.
43 *
44 * If the toolchain generates instructions that use them, they must be saved
45 * prior to handling an interrupt/exception. This case is handled using
46 * Zephyr's generic RISC-V mechanism for soc-specific context.
47 *
48 * For details, see the Kconfig help for CONFIG_RISCV_SOC_CONTEXT_SAVE.
49 */
50SECTION_FUNC(exception.other, __soc_save_context)
51#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
52	csrr t0, RI5CY_LPSTART0
53	csrr t1, RI5CY_LPEND0
54	csrr t2, RI5CY_LPCOUNT0
55	sw t0, __soc_esf_t_lpstart0_OFFSET(a0)
56	sw t1, __soc_esf_t_lpend0_OFFSET(a0)
57	sw t2, __soc_esf_t_lpcount0_OFFSET(a0)
58	csrr t0, RI5CY_LPSTART1
59	csrr t1, RI5CY_LPEND1
60	csrr t2, RI5CY_LPCOUNT1
61	sw t0, __soc_esf_t_lpstart1_OFFSET(a0)
62	sw t1, __soc_esf_t_lpend1_OFFSET(a0)
63	sw t2, __soc_esf_t_lpcount1_OFFSET(a0)
64#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
65
66	ret
67
68SECTION_FUNC(exception.other, __soc_restore_context)
69#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
70	lw t0, __soc_esf_t_lpstart0_OFFSET(a0)
71	lw t1, __soc_esf_t_lpend0_OFFSET(a0)
72	lw t2, __soc_esf_t_lpcount0_OFFSET(a0)
73	csrw RI5CY_LPSTART0, t0
74	csrw RI5CY_LPEND0, t1
75	csrw RI5CY_LPCOUNT0, t2
76	lw t0, __soc_esf_t_lpstart1_OFFSET(a0)
77	lw t1, __soc_esf_t_lpend1_OFFSET(a0)
78	lw t2, __soc_esf_t_lpcount1_OFFSET(a0)
79	csrw RI5CY_LPSTART1, t0
80	csrw RI5CY_LPEND1, t1
81	csrw RI5CY_LPCOUNT1, t2
82#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
83
84	ret
85#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
86