3
3
* Copyright (c) 2017 RnDity Sp. z o.o.
4
4
* Copyright (c) 2019-23 Linaro Limited
5
5
* Copyright (C) 2025 Savoir-faire Linux, Inc.
6
+ * Copyright (c) 2025 Alexander Kozhinov <[email protected] >
6
7
*
7
8
* SPDX-License-Identifier: Apache-2.0
8
9
*/
9
10
10
11
/**
11
- * @brief Driver for External interrupt/event controller in STM32 MCUs
12
+ * @brief Driver for STM32 External interrupt/event controller
12
13
*/
13
14
14
- #define EXTI_NODE DT_INST(0, st_stm32_exti)
15
-
16
15
#include <zephyr/device.h>
17
16
#include <soc.h>
18
17
#include <stm32_ll_bus.h>
23
22
#include <zephyr/sys/util.h>
24
23
#include <zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h> /* For STM32L0 series */
25
24
#include <zephyr/drivers/interrupt_controller/gpio_intc_stm32.h>
25
+ #include <zephyr/drivers/interrupt_controller/intc_exti_stm32.h>
26
26
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
27
27
#include <zephyr/irq.h>
28
28
29
29
#include "stm32_hsem.h"
30
+ #include "intc_exti_stm32_priv.h"
30
31
31
32
/** @brief EXTI lines range mapped to a single interrupt line */
32
33
struct stm32_exti_range {
33
- /** Start of the range */
34
+ /* Start of the range */
34
35
uint8_t start ;
35
- /** Range length */
36
+ /* Range length */
36
37
uint8_t len ;
37
38
};
38
39
39
- #define NUM_EXTI_LINES DT_PROP(EXTI_NODE, num_lines)
40
+ #define EXTI_NUM_LINES_TOTAL DT_PROP(EXTI_NODE, num_lines)
41
+ #define NUM_EXTI_LINES DT_PROP(EXTI_NODE, num_gpio_lines)
42
+
43
+ BUILD_ASSERT (EXTI_NUM_LINES_TOTAL >= NUM_EXTI_LINES ,
44
+ "The total number of EXTI lines must be greater or equal than the number of GPIO lines" );
40
45
41
46
static IRQn_Type exti_irq_table [NUM_EXTI_LINES ] = {[0 ... NUM_EXTI_LINES - 1 ] = 0xFF };
42
47
@@ -47,11 +52,13 @@ struct __exti_cb {
47
52
};
48
53
49
54
/* EXTI driver data */
50
- struct stm32_exti_data {
55
+ struct stm32_intc_gpio_data {
51
56
/* per-line callbacks */
52
57
struct __exti_cb cb [NUM_EXTI_LINES ];
53
58
};
54
59
60
+ static struct stm32_intc_gpio_data intc_gpio_data ;
61
+
55
62
/**
56
63
* @returns the LL_<PPP>_EXTI_LINE_xxx define that corresponds to specified @p linenum
57
64
* This value can be used with the LL EXTI source configuration functions.
@@ -72,54 +79,6 @@ static inline uint32_t stm32_exti_linenum_to_src_cfg_line(gpio_pin_t linenum)
72
79
#endif
73
80
}
74
81
75
- /**
76
- * @brief Checks interrupt pending bit for specified EXTI line
77
- *
78
- * @param line EXTI line number
79
- */
80
- static inline int stm32_exti_is_pending (stm32_gpio_irq_line_t line )
81
- {
82
- #if DT_HAS_COMPAT_STATUS_OKAY (st_stm32g0_exti )
83
- return (LL_EXTI_IsActiveRisingFlag_0_31 (line ) ||
84
- LL_EXTI_IsActiveFallingFlag_0_31 (line ));
85
- #elif defined(CONFIG_SOC_SERIES_STM32H7X ) && defined(CONFIG_CPU_CORTEX_M4 )
86
- return LL_C2_EXTI_IsActiveFlag_0_31 (line );
87
- #elif defined(CONFIG_SOC_SERIES_STM32MP2X )
88
- return LL_EXTI_IsActiveRisingFlag_0_31 (EXTI2 , line ) ||
89
- LL_EXTI_IsActiveFallingFlag_0_31 (EXTI2 , line );
90
- #else
91
- return LL_EXTI_IsActiveFlag_0_31 (line );
92
- #endif
93
- }
94
-
95
- /**
96
- * @brief Clears interrupt pending bit for specified EXTI line
97
- *
98
- * @param line EXTI line number
99
- */
100
- static inline void stm32_exti_clear_pending (stm32_gpio_irq_line_t line )
101
- {
102
- #if DT_HAS_COMPAT_STATUS_OKAY (st_stm32g0_exti )
103
- LL_EXTI_ClearRisingFlag_0_31 (line );
104
- LL_EXTI_ClearFallingFlag_0_31 (line );
105
- #elif defined(CONFIG_SOC_SERIES_STM32H7X ) && defined(CONFIG_CPU_CORTEX_M4 )
106
- LL_C2_EXTI_ClearFlag_0_31 (line );
107
- #elif defined(CONFIG_SOC_SERIES_STM32MP2X )
108
- LL_EXTI_ClearRisingFlag_0_31 (EXTI2 , line );
109
- LL_EXTI_ClearFallingFlag_0_31 (EXTI2 , line );
110
- #else
111
- LL_EXTI_ClearFlag_0_31 (line );
112
- #endif
113
- }
114
-
115
- /**
116
- * @returns the LL_EXTI_LINE_n define for EXTI line number @p linenum
117
- */
118
- static inline stm32_gpio_irq_line_t linenum_to_ll_exti_line (gpio_pin_t linenum )
119
- {
120
- return BIT (linenum );
121
- }
122
-
123
82
/**
124
83
* @returns EXTI line number for LL_EXTI_LINE_n define
125
84
*/
@@ -135,68 +94,34 @@ static inline gpio_pin_t ll_exti_line_to_linenum(stm32_gpio_irq_line_t line)
135
94
*
136
95
* @param exti_range Pointer to a exti_range structure
137
96
*/
138
- static void stm32_exti_isr (const void * exti_range )
97
+ static void stm32_intc_gpio_isr (const void * exti_range )
139
98
{
140
- const struct device * dev = DEVICE_DT_GET (EXTI_NODE );
141
- struct stm32_exti_data * data = dev -> data ;
99
+ struct stm32_intc_gpio_data * data = & intc_gpio_data ;
142
100
const struct stm32_exti_range * range = exti_range ;
143
101
stm32_gpio_irq_line_t line ;
144
102
uint32_t line_num ;
145
103
146
104
/* see which bits are set */
147
105
for (uint8_t i = 0 ; i <= range -> len ; i ++ ) {
148
106
line_num = range -> start + i ;
149
- line = linenum_to_ll_exti_line (line_num );
150
107
151
108
/* check if interrupt is pending */
152
- if (stm32_exti_is_pending (line ) != 0 ) {
109
+ if (stm32_exti_is_pending (line_num ) ) {
153
110
/* clear pending interrupt */
154
- stm32_exti_clear_pending (line );
111
+ stm32_exti_clear_pending (line_num );
155
112
156
113
/* run callback only if one is registered */
157
114
if (!data -> cb [line_num ].cb ) {
158
115
continue ;
159
116
}
160
117
161
118
/* `line` can be passed as-is because LL_EXTI_LINE_n is (1 << n) */
119
+ line = exti_linenum_to_ll_exti_line (line_num );
162
120
data -> cb [line_num ].cb (line , data -> cb [line_num ].data );
163
121
}
164
122
}
165
123
}
166
124
167
- /** Enables the peripheral clock required to access EXTI registers */
168
- static int stm32_exti_enable_registers (void )
169
- {
170
- /* Initialize to 0 for series where there is nothing to do. */
171
- int ret = 0 ;
172
- #if defined(CONFIG_SOC_SERIES_STM32F2X ) || \
173
- defined(CONFIG_SOC_SERIES_STM32F3X ) || \
174
- defined(CONFIG_SOC_SERIES_STM32F4X ) || \
175
- defined(CONFIG_SOC_SERIES_STM32F7X ) || \
176
- defined(CONFIG_SOC_SERIES_STM32H7X ) || \
177
- defined(CONFIG_SOC_SERIES_STM32H7RSX ) || \
178
- defined(CONFIG_SOC_SERIES_STM32L1X ) || \
179
- defined(CONFIG_SOC_SERIES_STM32L4X ) || \
180
- defined(CONFIG_SOC_SERIES_STM32G4X )
181
- const struct device * const clk = DEVICE_DT_GET (STM32_CLOCK_CONTROL_NODE );
182
- struct stm32_pclken pclken = {
183
- #if defined(CONFIG_SOC_SERIES_STM32H7X )
184
- .bus = STM32_CLOCK_BUS_APB4 ,
185
- .enr = LL_APB4_GRP1_PERIPH_SYSCFG
186
- #elif defined(CONFIG_SOC_SERIES_STM32H7RSX )
187
- .bus = STM32_CLOCK_BUS_APB4 ,
188
- .enr = LL_APB4_GRP1_PERIPH_SBS
189
- #else
190
- .bus = STM32_CLOCK_BUS_APB2 ,
191
- .enr = LL_APB2_GRP1_PERIPH_SYSCFG
192
- #endif /* CONFIG_SOC_SERIES_STM32H7X */
193
- };
194
-
195
- ret = clock_control_on (clk , (clock_control_subsys_t ) & pclken );
196
- #endif
197
- return ret ;
198
- }
199
-
200
125
static void stm32_fill_irq_table (int8_t start , int8_t len , int32_t irqn )
201
126
{
202
127
for (int i = 0 ; i < len ; i ++ ) {
@@ -206,7 +131,7 @@ static void stm32_fill_irq_table(int8_t start, int8_t len, int32_t irqn)
206
131
207
132
/* This macro:
208
133
* - populates line_range_x from line_range dt property
209
- * - fill exti_irq_table through stm32_fill_irq_table()
134
+ * - fills exti_irq_table through stm32_fill_irq_table()
210
135
* - calls IRQ_CONNECT for each interrupt and matching line_range
211
136
*/
212
137
#define STM32_EXTI_INIT_LINE_RANGE (node_id , interrupts , idx ) \
@@ -219,28 +144,21 @@ static void stm32_fill_irq_table(int8_t start, int8_t len, int32_t irqn)
219
144
DT_IRQ_BY_IDX(node_id, idx, irq)); \
220
145
IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), \
221
146
DT_IRQ_BY_IDX(node_id, idx, priority), \
222
- stm32_exti_isr , &line_range_##idx, 0);
147
+ stm32_intc_gpio_isr , &line_range_##idx, 0);
223
148
224
149
/**
225
150
* @brief Initializes the EXTI GPIO interrupt controller driver
226
151
*/
227
- static int stm32_exti_init ( const struct device * dev )
152
+ static int stm32_exti_gpio_intc_init ( void )
228
153
{
229
- ARG_UNUSED (dev );
230
-
231
154
DT_FOREACH_PROP_ELEM (EXTI_NODE ,
232
155
interrupt_names ,
233
156
STM32_EXTI_INIT_LINE_RANGE );
234
157
235
- return stm32_exti_enable_registers () ;
158
+ return 0 ;
236
159
}
237
160
238
- static struct stm32_exti_data exti_data ;
239
- DEVICE_DT_DEFINE (EXTI_NODE , & stm32_exti_init ,
240
- NULL ,
241
- & exti_data , NULL ,
242
- PRE_KERNEL_1 , CONFIG_INTC_INIT_PRIORITY ,
243
- NULL );
161
+ SYS_INIT (stm32_exti_gpio_intc_init , PRE_KERNEL_1 , CONFIG_INTC_INIT_PRIORITY );
244
162
245
163
/**
246
164
* @brief EXTI GPIO interrupt controller API implementation
@@ -260,7 +178,7 @@ DEVICE_DT_DEFINE(EXTI_NODE, &stm32_exti_init,
260
178
stm32_gpio_irq_line_t stm32_gpio_intc_get_pin_irq_line (uint32_t port , gpio_pin_t pin )
261
179
{
262
180
ARG_UNUSED (port );
263
- return linenum_to_ll_exti_line (pin );
181
+ return exti_linenum_to_ll_exti_line (pin );
264
182
}
265
183
266
184
void stm32_gpio_intc_enable_line (stm32_gpio_irq_line_t line )
@@ -275,27 +193,15 @@ void stm32_gpio_intc_enable_line(stm32_gpio_irq_line_t line)
275
193
__ASSERT_NO_MSG (irqnum != 0xFF );
276
194
277
195
/* Enable requested line interrupt */
278
- #if defined(CONFIG_SOC_SERIES_STM32H7X ) && defined(CONFIG_CPU_CORTEX_M4 )
279
- LL_C2_EXTI_EnableIT_0_31 (line );
280
- #elif defined(CONFIG_SOC_SERIES_STM32MP2X )
281
- LL_C2_EXTI_EnableIT_0_31 (EXTI2 , line );
282
- #else
283
- LL_EXTI_EnableIT_0_31 (line );
284
- #endif
196
+ EXTI_ENABLE_IT (0 _31 , line );
285
197
286
198
/* Enable exti irq interrupt */
287
199
irq_enable (irqnum );
288
200
}
289
201
290
202
void stm32_gpio_intc_disable_line (stm32_gpio_irq_line_t line )
291
203
{
292
- #if defined(CONFIG_SOC_SERIES_STM32H7X ) && defined(CONFIG_CPU_CORTEX_M4 )
293
- LL_C2_EXTI_DisableIT_0_31 (line );
294
- #elif defined(CONFIG_SOC_SERIES_STM32MP2X )
295
- LL_C2_EXTI_DisableIT_0_31 (EXTI2 , line );
296
- #else
297
- LL_EXTI_DisableIT_0_31 (line );
298
- #endif
204
+ EXTI_DISABLE_IT (0 _31 , line );
299
205
}
300
206
301
207
void stm32_gpio_intc_select_line_trigger (stm32_gpio_irq_line_t line , uint32_t trg )
@@ -322,20 +228,20 @@ void stm32_gpio_intc_select_line_trigger(stm32_gpio_irq_line_t line, uint32_t tr
322
228
break ;
323
229
#else /* CONFIG_SOC_SERIES_STM32MP2X */
324
230
case STM32_GPIO_IRQ_TRIG_NONE :
325
- LL_EXTI_DisableRisingTrig_0_31 ( line );
326
- LL_EXTI_DisableFallingTrig_0_31 ( line );
231
+ EXTI_DISABLE_RISING_TRIG ( 0 _31 , line );
232
+ EXTI_DISABLE_FALLING_TRIG ( 0 _31 , line );
327
233
break ;
328
234
case STM32_GPIO_IRQ_TRIG_RISING :
329
- LL_EXTI_EnableRisingTrig_0_31 ( line );
330
- LL_EXTI_DisableFallingTrig_0_31 ( line );
235
+ EXTI_ENABLE_RISING_TRIG ( 0 _31 , line );
236
+ EXTI_DISABLE_FALLING_TRIG ( 0 _31 , line );
331
237
break ;
332
238
case STM32_GPIO_IRQ_TRIG_FALLING :
333
- LL_EXTI_EnableFallingTrig_0_31 ( line );
334
- LL_EXTI_DisableRisingTrig_0_31 ( line );
239
+ EXTI_ENABLE_FALLING_TRIG ( 0 _31 , line );
240
+ EXTI_DISABLE_RISING_TRIG ( 0 _31 , line );
335
241
break ;
336
242
case STM32_GPIO_IRQ_TRIG_BOTH :
337
- LL_EXTI_EnableRisingTrig_0_31 ( line );
338
- LL_EXTI_EnableFallingTrig_0_31 ( line );
243
+ EXTI_ENABLE_RISING_TRIG ( 0 _31 , line );
244
+ EXTI_ENABLE_FALLING_TRIG ( 0 _31 , line );
339
245
break ;
340
246
#endif /* CONFIG_SOC_SERIES_STM32MP2X */
341
247
default :
@@ -347,15 +253,14 @@ void stm32_gpio_intc_select_line_trigger(stm32_gpio_irq_line_t line, uint32_t tr
347
253
348
254
int stm32_gpio_intc_set_irq_callback (stm32_gpio_irq_line_t line , stm32_gpio_irq_cb_t cb , void * user )
349
255
{
350
- const struct device * const dev = DEVICE_DT_GET (EXTI_NODE );
351
- struct stm32_exti_data * data = dev -> data ;
256
+ struct stm32_intc_gpio_data * data = & intc_gpio_data ;
352
257
uint32_t line_num = ll_exti_line_to_linenum (line );
353
258
354
259
if ((data -> cb [line_num ].cb == cb ) && (data -> cb [line_num ].data == user )) {
355
260
return 0 ;
356
261
}
357
262
358
- /* if callback already exists/maybe- running return busy */
263
+ /* if callback already exists/is running, return busy */
359
264
if (data -> cb [line_num ].cb != NULL ) {
360
265
return - EBUSY ;
361
266
}
@@ -368,8 +273,7 @@ int stm32_gpio_intc_set_irq_callback(stm32_gpio_irq_line_t line, stm32_gpio_irq_
368
273
369
274
void stm32_gpio_intc_remove_irq_callback (stm32_gpio_irq_line_t line )
370
275
{
371
- const struct device * const dev = DEVICE_DT_GET (EXTI_NODE );
372
- struct stm32_exti_data * data = dev -> data ;
276
+ struct stm32_intc_gpio_data * data = & intc_gpio_data ;
373
277
uint32_t line_num = ll_exti_line_to_linenum (line );
374
278
375
279
data -> cb [line_num ].cb = NULL ;
0 commit comments