1 /*
2  * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdint.h>
7 #include <stddef.h>
8 #include <assert.h>
9 #include "soc/soc.h"
10 #include "riscv/interrupt.h"
11 #include "soc/interrupt_reg.h"
12 #include "riscv/csr.h"
13 #include "esp_attr.h"
14 
15 #define RV_INT_COUNT 32
16 
assert_valid_rv_int_num(int rv_int_num)17 static inline void assert_valid_rv_int_num(int rv_int_num)
18 {
19     assert(rv_int_num != 0 && rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number");
20 }
21 
22 /*************************** Software interrupt dispatcher ***************************/
23 
24 
25 typedef struct {
26     intr_handler_t handler;
27     void *arg;
28 } intr_handler_item_t;
29 
30 static intr_handler_item_t s_intr_handlers[32];
31 
intr_handler_set(int int_no,intr_handler_t fn,void * arg)32 void intr_handler_set(int int_no, intr_handler_t fn, void *arg)
33 {
34     assert_valid_rv_int_num(int_no);
35 
36     s_intr_handlers[int_no] = (intr_handler_item_t) {
37         .handler = fn,
38         .arg = arg
39     };
40 }
41 
intr_handler_get(int rv_int_num)42 intr_handler_t intr_handler_get(int rv_int_num)
43 {
44     return s_intr_handlers[rv_int_num].handler;
45 }
46 
intr_handler_get_arg(int rv_int_num)47 void *intr_handler_get_arg(int rv_int_num)
48 {
49     return s_intr_handlers[rv_int_num].arg;
50 }
51 
52 /* called from vectors.S */
_global_interrupt_handler(intptr_t sp,int mcause)53 void _global_interrupt_handler(intptr_t sp, int mcause)
54 {
55     intr_handler_item_t it = s_intr_handlers[mcause];
56     if (it.handler) {
57         (*it.handler)(it.arg);
58     }
59 }
60 
61 /*************************** RISC-V interrupt enable/disable ***************************/
62 
intr_matrix_route(int intr_src,int intr_num)63 void intr_matrix_route(int intr_src, int intr_num)
64 {
65     assert(intr_num != 0);
66 
67     REG_WRITE(DR_REG_INTERRUPT_BASE + 4 * intr_src, intr_num);
68 }
69 
esprv_intc_get_interrupt_unmask(void)70 uint32_t esprv_intc_get_interrupt_unmask(void)
71 {
72     return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
73 }
74 
75 /*************************** ESP-RV Interrupt Controller ***************************/
76 
esprv_intc_int_get_type(int intr_num)77 enum intr_type esprv_intc_int_get_type(int intr_num)
78 {
79     uint32_t intr_type_reg = REG_READ(INTERRUPT_CORE0_CPU_INT_TYPE_REG);
80     return (intr_type_reg & (1 << intr_num)) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
81 }
82 
esprv_intc_int_get_priority(int rv_int_num)83 int esprv_intc_int_get_priority(int rv_int_num)
84 {
85     uint32_t intr_priority_reg = REG_READ(INTC_INT_PRIO_REG(rv_int_num));
86     return intr_priority_reg;
87 }
88 
89 /*************************** Exception names. Used in .gdbinit file. ***************************/
90 
91 const char *riscv_excp_names[16] __attribute__((used)) = {
92     "misaligned_fetch",
93     "fault_fetch",
94     "illegal_instruction",
95     "breakpoint",
96     "misaligned_load",
97     "fault_load",
98     "misaligned_store",
99     "fault_store",
100     "user_ecall",
101     "supervisor_ecall",
102     "hypervisor_ecall",
103     "machine_ecall",
104     "exec_page_fault",
105     "load_page_fault",
106     "reserved",
107     "store_page_fault"
108 };
109