1 /*
2 * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <kernel_internal.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/arch/riscv/csr.h>
11 #include <zephyr/irq_multilevel.h>
12 #include <zephyr/sw_isr_table.h>
13
14 #ifdef CONFIG_RISCV_HAS_PLIC
15 #include <zephyr/drivers/interrupt_controller/riscv_plic.h>
16 #endif
17
18 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
19
z_irq_spurious(const void * unused)20 FUNC_NORETURN void z_irq_spurious(const void *unused)
21 {
22 #ifdef CONFIG_EMPTY_IRQ_SPURIOUS
23 while (1) {
24 }
25
26 CODE_UNREACHABLE;
27 #else
28 unsigned long mcause;
29
30 ARG_UNUSED(unused);
31
32 mcause = csr_read(mcause);
33
34 mcause &= CONFIG_RISCV_MCAUSE_EXCEPTION_MASK;
35
36 LOG_ERR("Spurious interrupt detected! IRQ: %ld", mcause);
37 #if defined(CONFIG_RISCV_HAS_PLIC)
38 if (mcause == RISCV_IRQ_MEXT) {
39 unsigned int save_irq = riscv_plic_get_irq();
40 const struct device *save_dev = riscv_plic_get_dev();
41
42 LOG_ERR("PLIC interrupt line causing the IRQ: %d (%p)", save_irq, save_dev);
43 }
44 #endif
45 z_riscv_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
46 #endif /* CONFIG_EMPTY_IRQ_SPURIOUS */
47 }
48
49 #ifdef CONFIG_DYNAMIC_INTERRUPTS
arch_irq_connect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)50 int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
51 void (*routine)(const void *parameter),
52 const void *parameter, uint32_t flags)
53 {
54 z_isr_install(irq + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, routine, parameter);
55
56 #if defined(CONFIG_RISCV_HAS_PLIC) || defined(CONFIG_RISCV_HAS_CLIC)
57 z_riscv_irq_priority_set(irq, priority, flags);
58 #else
59 ARG_UNUSED(flags);
60 ARG_UNUSED(priority);
61 #endif
62 return irq;
63 }
64
65 #ifdef CONFIG_SHARED_INTERRUPTS
arch_irq_disconnect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)66 int arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
67 void (*routine)(const void *parameter), const void *parameter,
68 uint32_t flags)
69 {
70 ARG_UNUSED(priority);
71 ARG_UNUSED(flags);
72
73 return z_isr_uninstall(irq + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, routine,
74 parameter);
75 }
76 #endif /* CONFIG_SHARED_INTERRUPTS */
77 #endif /* CONFIG_DYNAMIC_INTERRUPTS */
78