1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 /** @page PLIC
19 *
20 * Introduction
21 * ===============
22 * platform-level interrupt controller (PLIC)
23 *
24 * API Reference
25 * ===============
26 * Header File: plic.h
27 */
28
29 #ifndef INTERRUPT_H
30 #define INTERRUPT_H
31 #include "core.h"
32
33 #include "compiler.h"
34 #include "reg_include/register_b91.h"
35
36 typedef struct {
37 unsigned char preempt_en;
38 unsigned char threshold;
39 } preempt_config_t;
40
41 extern unsigned char g_plic_preempt_en;
42
43 typedef enum {
44 IRQ0_EXCEPTION,
45 IRQ1_SYSTIMER,
46 IRQ2_ALG,
47 IRQ3_TIMER1,
48 IRQ4_TIMER0,
49 IRQ5_DMA,
50 IRQ6_BMC,
51 IRQ7_USB_CTRL_EP_SETUP,
52 IRQ8_USB_CTRL_EP_DATA,
53 IRQ9_USB_CTRL_EP_STATUS,
54 IRQ10_USB_CTRL_EP_SETINF,
55 IRQ11_USB_ENDPOINT,
56 IRQ12_ZB_DM,
57 IRQ13_ZB_BLE,
58 IRQ14_ZB_BT,
59 IRQ15_ZB_RT,
60 IRQ16_PWM,
61 IRQ17_PKE,
62 IRQ18_UART1,
63 IRQ19_UART0,
64 IRQ20_DFIFO,
65 IRQ21_I2C,
66 IRQ22_SPI_AHB,
67 IRQ23_SPI_APB,
68 IRQ24_USB_PWDN,
69 IRQ25_GPIO,
70 IRQ26_GPIO2RISC0,
71 IRQ27_GPIO2RISC1,
72 IRQ28_SOFT,
73
74 IRQ29_NPE_BUS0,
75 IRQ30_NPE_BUS1,
76 IRQ31_NPE_BUS2,
77 IRQ32_NPE_BUS3,
78 IRQ33_NPE_BUS4,
79
80 IRQ34_USB_250US,
81 IRQ35_USB_RESET,
82 IRQ36_NPE_BUS7,
83 IRQ37_NPE_BUS8,
84
85 IRQ42_NPE_BUS13 = 42,
86 IRQ43_NPE_BUS14,
87 IRQ44_NPE_BUS15,
88
89 IRQ46_NPE_BUS17 = 46,
90
91 IRQ50_NPE_BUS21 = 50,
92 IRQ51_NPE_BUS22,
93 IRQ52_NPE_BUS23,
94 IRQ53_NPE_BUS24,
95 IRQ54_NPE_BUS25,
96 IRQ55_NPE_BUS26,
97 IRQ56_NPE_BUS27,
98 IRQ57_NPE_BUS28,
99 IRQ58_NPE_BUS29,
100 IRQ59_NPE_BUS30,
101 IRQ60_NPE_BUS31,
102
103 IRQ61_NPE_COMB,
104 IRQ62_PM_TM,
105 IRQ63_EOC,
106 } irq_source_e;
107
108 typedef enum {
109 IRQ_PRI_LEV0, // Never interrupt
110 IRQ_PRI_LEV1,
111 IRQ_PRI_LEV2,
112 IRQ_PRI_LEV3,
113 } irq_priority_e;
114
115 /**
116 * @brief This function serves to set plic feature.
117 * @param[in] feature - preemptive priority interrupt feature and the vector mode.
118 * @return none
119 */
plic_set_feature(feature_e feature)120 static inline void plic_set_feature(feature_e feature)
121 {
122 reg_irq_feature = feature; // enable vectored in PLIC
123 }
124
125 /**
126 * @brief This function serves to enable preemptive priority interrupt feature.
127 * @return none
128 */
plic_preempt_feature_en(void)129 static inline void plic_preempt_feature_en(void)
130 {
131 reg_irq_feature |= FLD_FEATURE_PREEMPT_PRIORITY_INT_EN;
132 g_plic_preempt_en = 1;
133 }
134
135 /**
136 * @brief This function serves to enable preemptive priority interrupt feature.
137 * @return none
138 */
plic_preempt_feature_dis(void)139 static inline void plic_preempt_feature_dis(void)
140 {
141 reg_irq_feature &= (~FLD_FEATURE_PREEMPT_PRIORITY_INT_EN);
142 g_plic_preempt_en = 0;
143 }
144
145 /**
146 * @brief This function serves to set plic pending.
147 * @param[in] src - interrupt source.
148 * @return none
149 */
plic_set_pending(irq_source_e src)150 static inline void plic_set_pending(irq_source_e src)
151 {
152 reg_irq_pending(src) = BIT(src % 32);
153 }
154
155 /**
156 * @brief This function serves to set Priority Threshold,
157 * Only active interrupts with priorities strictly greater than the threshold will cause interrupt.
158 * @param[in] threshold - threshold level.
159 * @return none
160 */
plic_set_threshold(unsigned char threshold)161 static inline void plic_set_threshold(unsigned char threshold)
162 {
163 reg_irq_threshold = threshold;
164 }
165
166 /**
167 * @brief This function serves to set preemptive priority level,
168 * the priority value 0 is reserved to mean "never interrupt".
169 * The larger the priority value, the higher the interrupt priority.
170 * @param[in] src- interrupt source.
171 * @param[in] priority- priority level.
172 * @return none
173 */
plic_set_priority(irq_source_e src,irq_priority_e priority)174 static inline void plic_set_priority(irq_source_e src, irq_priority_e priority)
175 {
176 reg_irq_src_priority(src) = priority;
177 }
178
179 /**
180 * @brief This function serves to enable plic interrupt source.
181 * @param[in] src - interrupt source.
182 * @return none
183 */
plic_interrupt_enable(irq_source_e src)184 static inline void plic_interrupt_enable(irq_source_e src)
185 {
186 reg_irq_src(src) |= BIT(src % 32);
187 }
188
189 /**
190 * @brief This function serves to disable plic interrupt source.
191 * @param[in] src - interrupt source.
192 * @return none
193 */
plic_interrupt_disable(irq_source_e src)194 static inline void plic_interrupt_disable(irq_source_e src)
195 {
196 reg_irq_src(src) &= (~BIT(src % 32));
197 }
198
199 /**
200 * @brief This function serves to clear interrupt source has completed.
201 * @param[in] src - interrupt source.
202 * @return none
203 */
plic_interrupt_complete(irq_source_e src)204 static inline void plic_interrupt_complete(irq_source_e src)
205 {
206 reg_irq_done = src;
207 }
208
209 /**
210 * @brief This function serves to claim interrupt.
211 * @return it return the source id which interrupted in irq_source_e enum .
212 */
plic_interrupt_claim(void)213 static inline unsigned int plic_interrupt_claim(void)
214 {
215 return reg_irq_done;
216 }
217
218 /**
219 * @brief This function serves to config plic when enter some function process such as flash.
220 * @param[in] preempt_en - 1 can disturb by interrupt, 0 can't disturb by interrupt.
221 * @param[in] threshold - interrupt threshold.when the interrupt priority> interrupt threshold,
222 * the function process will be disturb by interrupt.
223 * @return none
224 */
225 _attribute_ram_code_sec_noinline_ unsigned int plic_enter_critical_sec(unsigned char preempt_en,
226 unsigned char threshold);
227
228 /**
229 * @brief This function serves to config plic when exit some function process such as flash.
230 * @param[in] preempt_en - 1 can disturb by interrupt, 0 can disturb by interrupt.
231 * @param[in] r - the value of mie register to restore.
232 * @return none
233 */
234 _attribute_ram_code_sec_noinline_ void plic_exit_critical_sec(unsigned char preempt_en, unsigned int r);
235
236 #endif
237