1
1
/*
2
- * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
2
+ * Copyright (c) 2021-2025 Espressif Systems (Shanghai) Co., Ltd.
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
19
19
#include <zephyr/sw_isr_table.h>
20
20
#include <riscv/interrupt.h>
21
21
22
- #define ESP32C3_INTC_DEFAULT_PRIO 15
23
-
24
22
#include <zephyr/logging/log.h>
25
- LOG_MODULE_REGISTER (intc_esp32c3 , CONFIG_LOG_DEFAULT_LEVEL );
23
+ LOG_MODULE_REGISTER (intc_esp32 , CONFIG_LOG_DEFAULT_LEVEL );
26
24
27
25
/*
28
26
* Define this to debug the choices made when allocating the interrupt. This leads to much debugging
@@ -35,132 +33,118 @@ LOG_MODULE_REGISTER(intc_esp32c3, CONFIG_LOG_DEFAULT_LEVEL);
35
33
# define INTC_LOG (...) do {} while (0)
36
34
#endif
37
35
38
- #define ESP32C3_INTC_DEFAULT_PRIORITY 15
39
- #define ESP32C3_INTC_DEFAULT_THRESHOLD 1
40
- #define ESP32C3_INTC_DISABLED_SLOT 31
41
- #define ESP32C3_INTC_SRCS_PER_IRQ 2
42
- #define ESP32C3_INTC_AVAILABLE_IRQS 30
36
+ #define ESP32_INTC_DEFAULT_PRIORITY 15
37
+ #define ESP32_INTC_DEFAULT_THRESHOLD 1
38
+ #define ESP32_INTC_DISABLED_SLOT 31
39
+ #define ESP32_INTC_SRCS_PER_IRQ 2
43
40
41
+ /* Define maximum interrupt sources per SoC */
44
42
#if defined(CONFIG_SOC_SERIES_ESP32C6 )
45
-
46
- #define IRQ_NA 0xFF /* IRQ not available */
47
- #define IRQ_FREE 0xFE
48
-
49
- #define ESP32C6_INTC_SRCS_PER_IRQ 2
50
- #define ESP32C6_INTC_AVAILABLE_IRQS 31
51
-
52
- /* Interrupt overview for ESP32C6:
53
- * - 0, 3, 4, and 7 are used by the CPU for core-local interrupts (CLINT)
54
- * - 1 is used for Wi-Fi in Espressif HAL
55
- * - 2, 5, 6, 8 .. 31 are available for Zephyr
56
- * - 31 is reserved for disabled interrupts
43
+ /*
44
+ * Interrupt reserved mask
45
+ * 0 is reserved
46
+ * 1 is for Wi-Fi
47
+ * 3, 4 and 7 are unavailable for PULP CPU as they are bound to Core-Local Interrupts (CLINT)
48
+ */
49
+ #define RSVD_MASK (BIT(0) | BIT(1) | BIT(3) | BIT(4) | BIT(7))
50
+ #define ESP_INTC_AVAILABLE_IRQS 31
51
+ #else
52
+ /*
53
+ * Interrupt reserved mask
54
+ * 1 is for Wi-Fi
57
55
*/
58
- static uint8_t esp_intr_irq_alloc [ESP32C6_INTC_AVAILABLE_IRQS ][ESP32C6_INTC_SRCS_PER_IRQ ] = {
59
- [0 ] = {IRQ_NA , IRQ_NA },
60
- [1 ] = {IRQ_NA , IRQ_NA },
61
- [2 ] = {IRQ_FREE , IRQ_FREE },
62
- [3 ] = {IRQ_NA , IRQ_NA },
63
- [4 ] = {IRQ_NA , IRQ_NA },
64
- [5 ... 6 ] = {IRQ_FREE , IRQ_FREE },
65
- [7 ] = {IRQ_NA , IRQ_NA },
66
- [8 ... 30 ] = {IRQ_FREE , IRQ_FREE }
67
- };
56
+ #define RSVD_MASK (BIT(0) | BIT(1))
57
+ #define ESP_INTC_AVAILABLE_IRQS 30
68
58
#endif
69
59
70
- #define STATUS_MASK_NUM 3
60
+ /* Single array for IRQ allocation */
61
+ static uint8_t esp_intr_irq_alloc [ESP_INTC_AVAILABLE_IRQS * ESP32_INTC_SRCS_PER_IRQ ];
71
62
72
- static uint32_t esp_intr_enabled_mask [STATUS_MASK_NUM ] = {0 , 0 , 0 };
63
+ #define ESP_INTR_IDX (irq , slot ) ((irq % ESP_INTC_AVAILABLE_IRQS) * ESP32_INTC_SRCS_PER_IRQ + slot)
64
+
65
+ #define STATUS_MASK_NUM 3
73
66
74
- #if defined( CONFIG_SOC_SERIES_ESP32C2 ) || defined( CONFIG_SOC_SERIES_ESP32C3 )
67
+ static uint32_t esp_intr_enabled_mask [ STATUS_MASK_NUM ] = { 0 , 0 , 0 };
75
68
76
69
static uint32_t esp_intr_find_irq_for_source (uint32_t source )
77
70
{
78
- /* in general case, each 2 sources goes routed to
79
- * 1 IRQ line.
80
- */
81
- uint32_t irq = (source / ESP32C3_INTC_SRCS_PER_IRQ );
82
-
83
- if (irq > ESP32C3_INTC_AVAILABLE_IRQS ) {
84
- INTC_LOG ("Clamping the source: %d no more IRQs available" , source );
85
- irq = ESP32C3_INTC_AVAILABLE_IRQS ;
86
- } else if (irq == 0 ) {
87
- irq = 1 ;
71
+ if (source >= ETS_MAX_INTR_SOURCE ) {
72
+ return IRQ_NA ;
88
73
}
89
74
90
- INTC_LOG ( "Found IRQ: %d for source: %d" , irq , source ) ;
75
+ uint32_t irq = source / ESP32_INTC_SRCS_PER_IRQ ;
91
76
92
- return irq ;
93
- }
77
+ /* Check if the derived IRQ is usable first */
78
+ for (int j = 0 ; j < ESP32_INTC_SRCS_PER_IRQ ; j ++ ) {
79
+ int idx = ESP_INTR_IDX (irq , j );
94
80
95
- #elif defined(CONFIG_SOC_SERIES_ESP32C6 )
81
+ /* Ensure idx is within a valid range */
82
+ if (idx >= ARRAY_SIZE (esp_intr_irq_alloc )) {
83
+ continue ;
84
+ }
96
85
97
- static uint32_t esp_intr_find_irq_for_source (uint32_t source )
98
- {
99
- uint32_t irq = IRQ_NA ;
100
- uint32_t irq_free = IRQ_NA ;
101
- uint8_t * irq_ptr = NULL ;
102
-
103
- /* First allocate one source per IRQ, then two
104
- * if there are more sources than free IRQs
105
- */
106
- for (int j = 0 ; j < ESP32C6_INTC_SRCS_PER_IRQ ; j ++ ) {
107
- for (int i = 0 ; i < ESP32C6_INTC_AVAILABLE_IRQS ; i ++ ) {
108
- /* Find first free slot but keep searching to see
109
- * if source is already associated to an IRQ
110
- */
111
- if (esp_intr_irq_alloc [i ][j ] == source ) {
112
- /* Source is already associated to an IRQ */
113
- irq = i ;
114
- goto found ;
115
- } else if ((irq_free == IRQ_NA ) && (esp_intr_irq_alloc [i ][j ] == IRQ_FREE )) {
116
- irq_free = i ;
117
- irq_ptr = & esp_intr_irq_alloc [i ][j ];
118
- }
86
+ /* If source is already assigned, return the IRQ */
87
+ if (esp_intr_irq_alloc [idx ] == source ) {
88
+ return irq ;
119
89
}
120
- }
121
90
122
- if ( irq_ptr != NULL ) {
123
- * irq_ptr = ( uint8_t ) source ;
124
- irq = irq_free ;
125
- } else {
126
- return IRQ_NA ;
91
+ /* If slot is free, allocate it */
92
+ if ( esp_intr_irq_alloc [ idx ] == IRQ_FREE ) {
93
+ esp_intr_irq_alloc [ idx ] = source ;
94
+ return irq ;
95
+ }
127
96
}
128
97
129
- found :
130
- INTC_LOG ("Found IRQ: %d for source: %d" , irq , source );
98
+ /* If derived IRQ is full, search for another available IRQ */
99
+ for (irq = 0 ; irq < ESP_INTC_AVAILABLE_IRQS ; irq ++ ) {
100
+ if (RSVD_MASK & (1U << irq )) {
101
+ continue ;
102
+ }
103
+ for (int j = 0 ; j < ESP32_INTC_SRCS_PER_IRQ ; j ++ ) {
104
+ int idx = ESP_INTR_IDX (irq , j );
131
105
132
- return irq ;
133
- }
106
+ /* Ensure idx is within a valid range */
107
+ if (idx >= ARRAY_SIZE (esp_intr_irq_alloc )) {
108
+ continue ;
109
+ }
134
110
135
- #endif
111
+ /* If source is already assigned, return this IRQ */
112
+ if (esp_intr_irq_alloc [idx ] == source ) {
113
+ return irq ;
114
+ }
136
115
137
- void esp_intr_initialize (void )
138
- {
139
- /* IRQ 31 is reserved for disabled interrupts,
140
- * so route all sources to it
141
- */
142
- for (int i = 0 ; i < ESP32C3_INTC_AVAILABLE_IRQS + 2 ; i ++ ) {
143
- irq_disable (i );
116
+ /* If slot is free, allocate it */
117
+ if (esp_intr_irq_alloc [idx ] == IRQ_FREE ) {
118
+ esp_intr_irq_alloc [idx ] = source ;
119
+ return irq ;
120
+ }
121
+ }
144
122
}
145
123
124
+ /* No available slot found */
125
+ return IRQ_NA ;
126
+ }
127
+
128
+ void esp_intr_initialize (void )
129
+ {
146
130
for (int i = 0 ; i < ETS_MAX_INTR_SOURCE ; i ++ ) {
147
- esp_rom_intr_matrix_set (0 , i , ESP32C3_INTC_DISABLED_SLOT );
131
+ esp_rom_intr_matrix_set (0 , i , ESP32_INTC_DISABLED_SLOT );
148
132
}
149
133
150
- #if defined(CONFIG_SOC_SERIES_ESP32C6 )
151
- /* Clear up IRQ allocation */
152
- for (int j = 0 ; j < ESP32C6_INTC_SRCS_PER_IRQ ; j ++ ) {
153
- for (int i = 0 ; i < ESP32C6_INTC_AVAILABLE_IRQS ; i ++ ) {
154
- /* screen out reserved IRQs */
155
- if (esp_intr_irq_alloc [i ][j ] != IRQ_NA ) {
156
- esp_intr_irq_alloc [i ][j ] = IRQ_FREE ;
134
+ for (int irq = 0 ; irq < ESP_INTC_AVAILABLE_IRQS ; irq ++ ) {
135
+ for (int j = 0 ; j < ESP32_INTC_SRCS_PER_IRQ ; j ++ ) {
136
+ int idx = ESP_INTR_IDX (irq , j );
137
+
138
+ if (RSVD_MASK & (1U << irq )) {
139
+ esp_intr_irq_alloc [idx ] = IRQ_NA ;
140
+ } else {
141
+ esp_intr_irq_alloc [idx ] = IRQ_FREE ;
157
142
}
158
143
}
159
144
}
160
- #endif
161
145
162
- /* set global esp32c3's INTC masking level */
163
- esprv_intc_int_set_threshold (ESP32C3_INTC_DEFAULT_THRESHOLD );
146
+ /* set global INTC masking level */
147
+ esprv_intc_int_set_threshold (ESP32_INTC_DEFAULT_THRESHOLD );
164
148
}
165
149
166
150
int esp_intr_alloc (int source ,
@@ -181,21 +165,19 @@ int esp_intr_alloc(int source,
181
165
}
182
166
183
167
uint32_t key = irq_lock ();
168
+ uint32_t irq = esp_intr_find_irq_for_source (source );
169
+
170
+ if (irq == IRQ_NA ) {
171
+ irq_unlock (key );
172
+ return - ENOMEM ;
173
+ }
184
174
185
175
irq_connect_dynamic (source ,
186
- ESP32C3_INTC_DEFAULT_PRIORITY ,
176
+ ESP32_INTC_DEFAULT_PRIORITY ,
187
177
handler ,
188
178
arg ,
189
179
0 );
190
180
191
- if (source < 32 ) {
192
- esp_intr_enabled_mask [0 ] |= (1 << source );
193
- } else if (source < 64 ) {
194
- esp_intr_enabled_mask [1 ] |= (1 << (source - 32 ));
195
- } else if (source < 96 ) {
196
- esp_intr_enabled_mask [2 ] |= (1 << (source - 64 ));
197
- }
198
-
199
181
INTC_LOG ("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X" ,
200
182
esp_intr_enabled_mask [0 ], esp_intr_enabled_mask [1 ], esp_intr_enabled_mask [2 ]);
201
183
@@ -215,19 +197,20 @@ int esp_intr_disable(int source)
215
197
216
198
esp_rom_intr_matrix_set (0 ,
217
199
source ,
218
- ESP32C3_INTC_DISABLED_SLOT );
200
+ ESP32_INTC_DISABLED_SLOT );
219
201
220
- #if defined(CONFIG_SOC_SERIES_ESP32C6 )
221
- for (int j = 0 ; j < ESP32C6_INTC_SRCS_PER_IRQ ; j ++ ) {
222
- for (int i = 0 ; i < ESP32C6_INTC_AVAILABLE_IRQS ; i ++ ) {
223
- if (esp_intr_irq_alloc [i ][j ] == source ) {
224
- esp_intr_irq_alloc [i ][j ] = IRQ_FREE ;
225
- goto freed ;
202
+ for (int i = 0 ; i < ESP_INTC_AVAILABLE_IRQS ; i ++ ) {
203
+ if (RSVD_MASK & (1U << i )) {
204
+ continue ;
205
+ }
206
+ for (int j = 0 ; j < ESP32_INTC_SRCS_PER_IRQ ; j ++ ) {
207
+ int idx = ESP_INTR_IDX (i , j );
208
+
209
+ if (esp_intr_irq_alloc [idx ] == source ) {
210
+ esp_intr_irq_alloc [idx ] = IRQ_FREE ;
226
211
}
227
212
}
228
213
}
229
- freed :
230
- #endif
231
214
232
215
if (source < 32 ) {
233
216
esp_intr_enabled_mask [0 ] &= ~(1 << source );
@@ -254,12 +237,10 @@ int esp_intr_enable(int source)
254
237
uint32_t key = irq_lock ();
255
238
uint32_t irq = esp_intr_find_irq_for_source (source );
256
239
257
- #if defined(CONFIG_SOC_SERIES_ESP32C6 )
258
240
if (irq == IRQ_NA ) {
259
241
irq_unlock (key );
260
242
return - ENOMEM ;
261
243
}
262
- #endif
263
244
264
245
esp_rom_intr_matrix_set (0 , source , irq );
265
246
@@ -274,7 +255,7 @@ int esp_intr_enable(int source)
274
255
INTC_LOG ("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X" ,
275
256
esp_intr_enabled_mask [0 ], esp_intr_enabled_mask [1 ], esp_intr_enabled_mask [2 ]);
276
257
277
- esprv_intc_int_set_priority (irq , ESP32C3_INTC_DEFAULT_PRIO );
258
+ esprv_intc_int_set_priority (irq , ESP32_INTC_DEFAULT_PRIORITY );
278
259
esprv_intc_int_set_type (irq , INTR_TYPE_LEVEL );
279
260
esprv_intc_int_enable (1 << irq );
280
261
@@ -290,7 +271,7 @@ uint32_t esp_intr_get_enabled_intmask(int status_mask_number)
290
271
291
272
if (status_mask_number < STATUS_MASK_NUM ) {
292
273
return esp_intr_enabled_mask [status_mask_number ];
293
- } else {
294
- return 0 ; /* error */
295
274
}
275
+
276
+ return 0 ;
296
277
}
0 commit comments