|  | /* | 
|  | * Copyright (c) 2018 Foundries.io Ltd | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <offsets.h> | 
|  | #include <zephyr/toolchain.h> | 
|  |  | 
|  | #include <soc.h> | 
|  |  | 
|  | /* Exports */ | 
|  | GTEXT(__soc_handle_irq) | 
|  | #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | 
|  | GTEXT(__soc_save_context) | 
|  | GTEXT(__soc_restore_context) | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * With a0 == irq_num, this is equivalent to: | 
|  | * | 
|  | * EVENT_UNIT->INTPTPENDCLEAR = (1U << irq_num); | 
|  | * | 
|  | * We could write this routine in C, but the assembly | 
|  | * that's calling us requires that a0 still contain irq_num | 
|  | * on return, and assuming nobody would ever change a | 
|  | * C implementation in a way that silently clobbers it | 
|  | * is playing with fire. Instead, we play tricks in | 
|  | * soc_context.h so that offsets.h contains a pointer to | 
|  | * INTPTPENDCLEAR. | 
|  | */ | 
|  | SECTION_FUNC(exception.other, __soc_handle_irq) | 
|  | la t0, __EVENT_INTPTPENDCLEAR | 
|  | li t1, 1 | 
|  | sll t1, t1, a0 | 
|  | sw t1, 0x00(t0) | 
|  | ret | 
|  |  | 
|  | #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | 
|  | /* | 
|  | * The RI5CY core has ISA extensions for faster loop performance | 
|  | * that use extra registers. | 
|  | * | 
|  | * If the toolchain generates instructions that use them, they must be saved | 
|  | * prior to handling an interrupt/exception. This case is handled using | 
|  | * Zephyr's generic RISC-V mechanism for soc-specific context. | 
|  | * | 
|  | * For details, see the Kconfig help for CONFIG_RISCV_SOC_CONTEXT_SAVE. | 
|  | */ | 
|  | SECTION_FUNC(exception.other, __soc_save_context) | 
|  | #ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY | 
|  | csrr t0, RI5CY_LPSTART0 | 
|  | csrr t1, RI5CY_LPEND0 | 
|  | csrr t2, RI5CY_LPCOUNT0 | 
|  | sw t0, __soc_esf_t_lpstart0_OFFSET(a0) | 
|  | sw t1, __soc_esf_t_lpend0_OFFSET(a0) | 
|  | sw t2, __soc_esf_t_lpcount0_OFFSET(a0) | 
|  | csrr t0, RI5CY_LPSTART1 | 
|  | csrr t1, RI5CY_LPEND1 | 
|  | csrr t2, RI5CY_LPCOUNT1 | 
|  | sw t0, __soc_esf_t_lpstart1_OFFSET(a0) | 
|  | sw t1, __soc_esf_t_lpend1_OFFSET(a0) | 
|  | sw t2, __soc_esf_t_lpcount1_OFFSET(a0) | 
|  | #endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */ | 
|  |  | 
|  | ret | 
|  |  | 
|  | SECTION_FUNC(exception.other, __soc_restore_context) | 
|  | #ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY | 
|  | lw t0, __soc_esf_t_lpstart0_OFFSET(a0) | 
|  | lw t1, __soc_esf_t_lpend0_OFFSET(a0) | 
|  | lw t2, __soc_esf_t_lpcount0_OFFSET(a0) | 
|  | csrw RI5CY_LPSTART0, t0 | 
|  | csrw RI5CY_LPEND0, t1 | 
|  | csrw RI5CY_LPCOUNT0, t2 | 
|  | lw t0, __soc_esf_t_lpstart1_OFFSET(a0) | 
|  | lw t1, __soc_esf_t_lpend1_OFFSET(a0) | 
|  | lw t2, __soc_esf_t_lpcount1_OFFSET(a0) | 
|  | csrw RI5CY_LPSTART1, t0 | 
|  | csrw RI5CY_LPEND1, t1 | 
|  | csrw RI5CY_LPCOUNT1, t2 | 
|  | #endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */ | 
|  |  | 
|  | ret | 
|  | #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ |