1 /*
2  * Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_
8 #define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_
9 
10 #include <zephyr/device.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/sys/util_macro.h>
13 #include <zephyr/drivers/interrupt_controller/intc_exti_stm32.h>
14 
15 #include <stm32_ll_bus.h>
16 #include <stm32_ll_exti.h>
17 #include <stm32_ll_system.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * NOTE: This implementation currently does not support configurations where a
25  * single CPU has access to multiple EXTI instances. Supporting multiple EXTI
26  * instances per CPU (such as possible on STM32MP2 series with both M33 and M0+
27  * cores) will require changes to this macro and potentially other parts of the
28  * driver.
29  */
30 #define EXTI_NODE	DT_INST(0, st_stm32_exti)
31 
32 /**
33  * STM32MP1 has up to 96 EXTI lines (RM0475, Table 112. STM32MP13xx EXTI Events),
34  * but some ranges contain only direct lines, so the LL functions that are
35  * only valid for configurable lines are not provided for these ranges.
36  * However, we are relying on all these functions being present as part of our
37  * utility macros. Define dummy stubs for these functions to allow the main driver
38  * to work properly on this special series.
39  *
40  * NOTE: These stubs are only for compatibility and will assert if called for
41  * unsupported lines. Always ensure the correct line range is used.
42  */
43 
44 #define STM32_EXTI_TOTAL_LINES_NUM	DT_PROP(EXTI_NODE, num_lines)
45 
46 /**
47  * @brief Define CPU number suffix for STM32 series.
48  */
49 #if (defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)) || \
50 	(defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(CONFIG_CPU_CORTEX_M33))
51 #define CPU_NR	_C2
52 #elif defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(CONFIG_CPU_CORTEX_M0)
53 #define CPU_NR	_C3
54 #else
55 /* NOTE: usually one CPU (e.g. C1) only is omitted and leaved empty */
56 #define CPU_NR
57 #endif
58 
59 /**
60  * @brief Define EXTI_LL_INST for STM32MP2X series, since it may have multiple instances
61  * For all other than STM32MP2X series the EXTI instance is defined within LL driver
62  * itself s.t. EXTI_LL_INST will be empty.
63  */
64 #if defined(CONFIG_SOC_SERIES_STM32MP2X)
65 #define EXTI_LL_INST	((EXTI_TypeDef *)DT_REG_ADDR(EXTI_NODE)),
66 #else /* CONFIG_SOC_SERIES_STM32MP2X */
67 #define EXTI_LL_INST
68 #endif /* CONFIG_SOC_SERIES_STM32MP2X */
69 
70 
71 #define EXTI_LINE_NOT_SUPP_ASSERT(line)			\
72 {							\
73 	LOG_ERR("Unsupported line number %u", line);	\
74 	__ASSERT_NO_MSG(0);				\
75 }
76 
77 #define EXTI_LINE_NOP(line)	\
78 {				\
79 	ARG_UNUSED(line);	\
80 }
81 
82 #if defined(CONFIG_SOC_SERIES_STM32MP1X) || defined(CONFIG_SOC_SERIES_STM32MP13X)
83 
84 /*
85  * NOTE: There is currently no other option than to define LL_ prefixed functions
86  * that are missing in the original drivers as stubs for unsupported EXTI lines.
87  * This is required for compatibility across all STM32 series, until a more
88  * flexible solution is available.
89  */
90 #define LL_EXTI_IsActiveRisingFlag_32_63(line)	0
91 #define LL_EXTI_IsActiveFallingFlag_32_63(line)	0
92 
93 #define LL_EXTI_ClearRisingFlag_32_63(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
94 #define LL_EXTI_ClearFallingFlag_32_63(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
95 #define LL_EXTI_GenerateSWI_32_63(line)		EXTI_LINE_NOT_SUPP_ASSERT(line)
96 
97 #define LL_EXTI_EnableRisingTrig_32_63(line)	EXTI_LINE_NOP(line)
98 #define LL_EXTI_EnableFallingTrig_32_63(line)	EXTI_LINE_NOP(line)
99 #define LL_EXTI_DisableRisingTrig_32_63(line)	EXTI_LINE_NOP(line)
100 #define LL_EXTI_DisableFallingTrig_32_63(line)	EXTI_LINE_NOP(line)
101 #define LL_EXTI_EnableEvent_32_63(line)		EXTI_LINE_NOP(line)
102 #define LL_EXTI_DisableEvent_32_63(line)	EXTI_LINE_NOP(line)
103 
104 #if defined(CONFIG_SOC_SERIES_STM32MP13X)
105 
106 #define LL_EXTI_IsActiveRisingFlag_64_95(line)	0
107 #define LL_EXTI_IsActiveFallingFlag_64_95(line)	0
108 
109 #define LL_EXTI_ClearRisingFlag_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
110 #define LL_EXTI_ClearFallingFlag_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
111 #define LL_EXTI_GenerateSWI_64_95(line)		EXTI_LINE_NOT_SUPP_ASSERT(line)
112 #define LL_EXTI_EnableRisingTrig_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
113 #define LL_EXTI_DisableRisingTrig_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
114 #define LL_EXTI_EnableFallingTrig_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
115 #define LL_EXTI_DisableFallingTrig_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
116 #define LL_EXTI_EnableEvent_64_95(line)		EXTI_LINE_NOT_SUPP_ASSERT(line)
117 #define LL_EXTI_DisableEvent_64_95(line)	EXTI_LINE_NOT_SUPP_ASSERT(line)
118 
119 #endif /* !CONFIG_SOC_SERIES_STM32MP13X */
120 
121 #endif /* CONFIG_SOC_SERIES_STM32MP1X || CONFIG_SOC_SERIES_STM32MP13X */
122 
123 
124 /* Define general macros line-range independent */
125 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) || defined(CONFIG_SOC_SERIES_STM32MP2X)
126 
127 #if defined(CONFIG_SOC_SERIES_STM32MP2X)
128 
129 #define EXTI_IS_ACTIVE_RISING_FLAG(line_range, line)	\
130 	CONCAT(LL, _EXTI_IsActiveRisingFlag_##line_range)(EXTI_LL_INST line)
131 #define EXTI_IS_ACTIVE_FALLING_FLAG(line_range, line)	\
132 	CONCAT(LL, _EXTI_IsActiveFallingFlag_##line_range)(EXTI_LL_INST line)
133 
134 #define EXTI_CLEAR_RISING_FLAG(line_range, line)	\
135 	CONCAT(LL, _EXTI_ClearRisingFlag_##line_range)(EXTI_LL_INST line)
136 #define EXTI_CLEAR_FALLING_FLAG(line_range, line)	\
137 	CONCAT(LL, _EXTI_ClearFallingFlag_##line_range)(EXTI_LL_INST line)
138 
139 #else /* !CONFIG_SOC_SERIES_STM32MP2X */
140 
141 #define EXTI_IS_ACTIVE_RISING_FLAG(line_range, line)	\
142 	CONCAT(LL, CPU_NR, _EXTI_IsActiveRisingFlag_##line_range)(EXTI_LL_INST line)
143 #define EXTI_IS_ACTIVE_FALLING_FLAG(line_range, line)	\
144 	CONCAT(LL, CPU_NR, _EXTI_IsActiveFallingFlag_##line_range)(EXTI_LL_INST line)
145 
146 #define EXTI_CLEAR_RISING_FLAG(line_range, line)	\
147 	CONCAT(LL, CPU_NR, _EXTI_ClearRisingFlag_##line_range)(EXTI_LL_INST line)
148 #define EXTI_CLEAR_FALLING_FLAG(line_range, line)	\
149 	CONCAT(LL, CPU_NR, _EXTI_ClearFallingFlag_##line_range)(EXTI_LL_INST line)
150 
151 #endif /* CONFIG_SOC_SERIES_STM32MP2X */
152 
153 #define EXTI_CLEAR_FLAG(line_range, line)			\
154 	{							\
155 		EXTI_CLEAR_RISING_FLAG(line_range, (line));	\
156 		EXTI_CLEAR_FALLING_FLAG(line_range, (line));	\
157 	}
158 #define EXTI_IS_ACTIVE_FLAG(line_range, line)			\
159 	(EXTI_IS_ACTIVE_RISING_FLAG(line_range, (line)) ||	\
160 	 EXTI_IS_ACTIVE_FALLING_FLAG(line_range, (line)))
161 
162 #else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) */
163 
164 #define EXTI_CLEAR_FLAG(line_range, line)			\
165 	CONCAT(LL, CPU_NR, _EXTI_ClearFlag_##line_range)(line)
166 #define EXTI_IS_ACTIVE_FLAG(line_range, line)		\
167 	CONCAT(LL, CPU_NR, _EXTI_IsActiveFlag_##line_range)(line)
168 
169 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) */
170 
171 
172 /* Define general macros line-range independent */
173 #define EXTI_ENABLE_IT(line_range, line)		\
174 	CONCAT(LL, CPU_NR, _EXTI_EnableIT_##line_range)(EXTI_LL_INST line)
175 #define EXTI_DISABLE_IT(line_range, line)		\
176 	CONCAT(LL, CPU_NR, _EXTI_DisableIT_##line_range)(EXTI_LL_INST line)
177 #define EXTI_ENABLE_EVENT(line_range, line)		\
178 	CONCAT(LL, CPU_NR, _EXTI_EnableEvent_##line_range)(EXTI_LL_INST line)
179 #define EXTI_DISABLE_EVENT(line_range, line)		\
180 	CONCAT(LL, CPU_NR, _EXTI_DisableEvent_##line_range)(EXTI_LL_INST line)
181 #define EXTI_ENABLE_RISING_TRIG(line_range, line)	\
182 	CONCAT(LL, _EXTI_EnableRisingTrig_##line_range)(EXTI_LL_INST line)
183 #define EXTI_ENABLE_FALLING_TRIG(line_range, line)	\
184 	CONCAT(LL, _EXTI_EnableFallingTrig_##line_range)(EXTI_LL_INST line)
185 #define EXTI_DISABLE_FALLING_TRIG(line_range, line)	\
186 	CONCAT(LL, _EXTI_DisableFallingTrig_##line_range)(EXTI_LL_INST line)
187 #define EXTI_DISABLE_RISING_TRIG(line_range, line)	\
188 	CONCAT(LL, _EXTI_DisableRisingTrig_##line_range)(EXTI_LL_INST line)
189 #define EXTI_GENERATE_SWI(line_range, line)		\
190 	CONCAT(LL, _EXTI_GenerateSWI_##line_range)(EXTI_LL_INST line)
191 
192 /**
193  * @returns LL_EXTI_LINE_n define corresponding to EXTI line number
194  */
exti_linenum_to_ll_exti_line(uint32_t line_num)195 static inline uint32_t exti_linenum_to_ll_exti_line(uint32_t line_num)
196 {
197 	return BIT(line_num % 32);
198 }
199 
200 #ifdef __cplusplus
201 }
202 #endif
203 
204 #endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_ */
205