1 /*
2  * Copyright (c) 2019 Song Qiang <songqiang1304521@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @brief DMA low level driver implementation for F2/F4/F7 series SoCs.
9  */
10 
11 #include "dma_stm32.h"
12 
13 #define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(dma_stm32_v1);
16 
17 /* DMA burst length */
18 #define BURST_TRANS_LENGTH_1			0
19 
dma_stm32_id_to_stream(uint32_t id)20 uint32_t dma_stm32_id_to_stream(uint32_t id)
21 {
22 	static const uint32_t stream_nr[] = {
23 		LL_DMA_STREAM_0,
24 		LL_DMA_STREAM_1,
25 		LL_DMA_STREAM_2,
26 		LL_DMA_STREAM_3,
27 		LL_DMA_STREAM_4,
28 		LL_DMA_STREAM_5,
29 		LL_DMA_STREAM_6,
30 		LL_DMA_STREAM_7,
31 	};
32 
33 	__ASSERT_NO_MSG(id < ARRAY_SIZE(stream_nr));
34 
35 	return stream_nr[id];
36 }
37 
38 #if !defined(CONFIG_DMAMUX_STM32)
dma_stm32_slot_to_channel(uint32_t slot)39 uint32_t dma_stm32_slot_to_channel(uint32_t slot)
40 {
41 	static const uint32_t channel_nr[] = {
42 		LL_DMA_CHANNEL_0,
43 		LL_DMA_CHANNEL_1,
44 		LL_DMA_CHANNEL_2,
45 		LL_DMA_CHANNEL_3,
46 		LL_DMA_CHANNEL_4,
47 		LL_DMA_CHANNEL_5,
48 		LL_DMA_CHANNEL_6,
49 		LL_DMA_CHANNEL_7,
50 	};
51 
52 	__ASSERT_NO_MSG(slot < ARRAY_SIZE(channel_nr));
53 
54 	return channel_nr[slot];
55 }
56 #endif
57 
dma_stm32_clear_ht(DMA_TypeDef * DMAx,uint32_t id)58 void dma_stm32_clear_ht(DMA_TypeDef *DMAx, uint32_t id)
59 {
60 	static const dma_stm32_clear_flag_func func[] = {
61 		LL_DMA_ClearFlag_HT0,
62 		LL_DMA_ClearFlag_HT1,
63 		LL_DMA_ClearFlag_HT2,
64 		LL_DMA_ClearFlag_HT3,
65 		LL_DMA_ClearFlag_HT4,
66 		LL_DMA_ClearFlag_HT5,
67 		LL_DMA_ClearFlag_HT6,
68 		LL_DMA_ClearFlag_HT7,
69 	};
70 
71 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
72 
73 	func[id](DMAx);
74 }
75 
dma_stm32_clear_tc(DMA_TypeDef * DMAx,uint32_t id)76 void dma_stm32_clear_tc(DMA_TypeDef *DMAx, uint32_t id)
77 {
78 	static const dma_stm32_clear_flag_func func[] = {
79 		LL_DMA_ClearFlag_TC0,
80 		LL_DMA_ClearFlag_TC1,
81 		LL_DMA_ClearFlag_TC2,
82 		LL_DMA_ClearFlag_TC3,
83 		LL_DMA_ClearFlag_TC4,
84 		LL_DMA_ClearFlag_TC5,
85 		LL_DMA_ClearFlag_TC6,
86 		LL_DMA_ClearFlag_TC7,
87 	};
88 
89 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
90 
91 	func[id](DMAx);
92 }
93 
dma_stm32_is_ht_active(DMA_TypeDef * DMAx,uint32_t id)94 bool dma_stm32_is_ht_active(DMA_TypeDef *DMAx, uint32_t id)
95 {
96 	static const dma_stm32_check_flag_func func[] = {
97 		LL_DMA_IsActiveFlag_HT0,
98 		LL_DMA_IsActiveFlag_HT1,
99 		LL_DMA_IsActiveFlag_HT2,
100 		LL_DMA_IsActiveFlag_HT3,
101 		LL_DMA_IsActiveFlag_HT4,
102 		LL_DMA_IsActiveFlag_HT5,
103 		LL_DMA_IsActiveFlag_HT6,
104 		LL_DMA_IsActiveFlag_HT7,
105 	};
106 
107 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
108 
109 	return func[id](DMAx);
110 }
111 
dma_stm32_is_tc_active(DMA_TypeDef * DMAx,uint32_t id)112 bool dma_stm32_is_tc_active(DMA_TypeDef *DMAx, uint32_t id)
113 {
114 	static const dma_stm32_check_flag_func func[] = {
115 		LL_DMA_IsActiveFlag_TC0,
116 		LL_DMA_IsActiveFlag_TC1,
117 		LL_DMA_IsActiveFlag_TC2,
118 		LL_DMA_IsActiveFlag_TC3,
119 		LL_DMA_IsActiveFlag_TC4,
120 		LL_DMA_IsActiveFlag_TC5,
121 		LL_DMA_IsActiveFlag_TC6,
122 		LL_DMA_IsActiveFlag_TC7,
123 	};
124 
125 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
126 
127 	return func[id](DMAx);
128 }
129 
dma_stm32_clear_te(DMA_TypeDef * DMAx,uint32_t id)130 void dma_stm32_clear_te(DMA_TypeDef *DMAx, uint32_t id)
131 {
132 	static const dma_stm32_clear_flag_func func[] = {
133 		LL_DMA_ClearFlag_TE0,
134 		LL_DMA_ClearFlag_TE1,
135 		LL_DMA_ClearFlag_TE2,
136 		LL_DMA_ClearFlag_TE3,
137 		LL_DMA_ClearFlag_TE4,
138 		LL_DMA_ClearFlag_TE5,
139 		LL_DMA_ClearFlag_TE6,
140 		LL_DMA_ClearFlag_TE7,
141 	};
142 
143 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
144 
145 	func[id](DMAx);
146 }
147 
dma_stm32_clear_dme(DMA_TypeDef * DMAx,uint32_t id)148 void dma_stm32_clear_dme(DMA_TypeDef *DMAx, uint32_t id)
149 {
150 	static const dma_stm32_clear_flag_func func[] = {
151 		LL_DMA_ClearFlag_DME0,
152 		LL_DMA_ClearFlag_DME1,
153 		LL_DMA_ClearFlag_DME2,
154 		LL_DMA_ClearFlag_DME3,
155 		LL_DMA_ClearFlag_DME4,
156 		LL_DMA_ClearFlag_DME5,
157 		LL_DMA_ClearFlag_DME6,
158 		LL_DMA_ClearFlag_DME7,
159 	};
160 
161 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
162 
163 	func[id](DMAx);
164 }
165 
dma_stm32_clear_fe(DMA_TypeDef * DMAx,uint32_t id)166 void dma_stm32_clear_fe(DMA_TypeDef *DMAx, uint32_t id)
167 {
168 	static const dma_stm32_clear_flag_func func[] = {
169 		LL_DMA_ClearFlag_FE0,
170 		LL_DMA_ClearFlag_FE1,
171 		LL_DMA_ClearFlag_FE2,
172 		LL_DMA_ClearFlag_FE3,
173 		LL_DMA_ClearFlag_FE4,
174 		LL_DMA_ClearFlag_FE5,
175 		LL_DMA_ClearFlag_FE6,
176 		LL_DMA_ClearFlag_FE7,
177 	};
178 
179 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
180 
181 	func[id](DMAx);
182 }
183 
dma_stm32_is_te_active(DMA_TypeDef * DMAx,uint32_t id)184 bool dma_stm32_is_te_active(DMA_TypeDef *DMAx, uint32_t id)
185 {
186 	static const dma_stm32_check_flag_func func[] = {
187 		LL_DMA_IsActiveFlag_TE0,
188 		LL_DMA_IsActiveFlag_TE1,
189 		LL_DMA_IsActiveFlag_TE2,
190 		LL_DMA_IsActiveFlag_TE3,
191 		LL_DMA_IsActiveFlag_TE4,
192 		LL_DMA_IsActiveFlag_TE5,
193 		LL_DMA_IsActiveFlag_TE6,
194 		LL_DMA_IsActiveFlag_TE7,
195 	};
196 
197 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
198 
199 	return func[id](DMAx);
200 }
201 
dma_stm32_is_dme_active(DMA_TypeDef * DMAx,uint32_t id)202 bool dma_stm32_is_dme_active(DMA_TypeDef *DMAx, uint32_t id)
203 {
204 	static const dma_stm32_check_flag_func func[] = {
205 		LL_DMA_IsActiveFlag_DME0,
206 		LL_DMA_IsActiveFlag_DME1,
207 		LL_DMA_IsActiveFlag_DME2,
208 		LL_DMA_IsActiveFlag_DME3,
209 		LL_DMA_IsActiveFlag_DME4,
210 		LL_DMA_IsActiveFlag_DME5,
211 		LL_DMA_IsActiveFlag_DME6,
212 		LL_DMA_IsActiveFlag_DME7,
213 	};
214 
215 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
216 
217 	return func[id](DMAx);
218 }
219 
dma_stm32_is_fe_active(DMA_TypeDef * DMAx,uint32_t id)220 bool dma_stm32_is_fe_active(DMA_TypeDef *DMAx, uint32_t id)
221 {
222 	static const dma_stm32_check_flag_func func[] = {
223 		LL_DMA_IsActiveFlag_FE0,
224 		LL_DMA_IsActiveFlag_FE1,
225 		LL_DMA_IsActiveFlag_FE2,
226 		LL_DMA_IsActiveFlag_FE3,
227 		LL_DMA_IsActiveFlag_FE4,
228 		LL_DMA_IsActiveFlag_FE5,
229 		LL_DMA_IsActiveFlag_FE6,
230 		LL_DMA_IsActiveFlag_FE7,
231 	};
232 
233 	__ASSERT_NO_MSG(id < ARRAY_SIZE(func));
234 
235 	return func[id](DMAx);
236 }
237 
stm32_dma_dump_stream_irq(DMA_TypeDef * dma,uint32_t id)238 void stm32_dma_dump_stream_irq(DMA_TypeDef *dma, uint32_t id)
239 {
240 	LOG_INF("tc: %d, ht: %d, te: %d, dme: %d, fe: %d",
241 		dma_stm32_is_tc_active(dma, id),
242 		dma_stm32_is_ht_active(dma, id),
243 		dma_stm32_is_te_active(dma, id),
244 		dma_stm32_is_dme_active(dma, id),
245 		dma_stm32_is_fe_active(dma, id));
246 }
247 
stm32_dma_is_tc_irq_active(DMA_TypeDef * dma,uint32_t id)248 inline bool stm32_dma_is_tc_irq_active(DMA_TypeDef *dma, uint32_t id)
249 {
250 	return LL_DMA_IsEnabledIT_TC(dma, dma_stm32_id_to_stream(id)) &&
251 	       dma_stm32_is_tc_active(dma, id);
252 }
253 
stm32_dma_is_ht_irq_active(DMA_TypeDef * dma,uint32_t id)254 inline bool stm32_dma_is_ht_irq_active(DMA_TypeDef *dma, uint32_t id)
255 {
256 	return LL_DMA_IsEnabledIT_HT(dma, dma_stm32_id_to_stream(id)) &&
257 	       dma_stm32_is_ht_active(dma, id);
258 }
259 
stm32_dma_is_te_irq_active(DMA_TypeDef * dma,uint32_t id)260 static inline bool stm32_dma_is_te_irq_active(DMA_TypeDef *dma, uint32_t id)
261 {
262 	return LL_DMA_IsEnabledIT_TE(dma, dma_stm32_id_to_stream(id)) &&
263 	       dma_stm32_is_te_active(dma, id);
264 }
265 
stm32_dma_is_dme_irq_active(DMA_TypeDef * dma,uint32_t id)266 static inline bool stm32_dma_is_dme_irq_active(DMA_TypeDef *dma, uint32_t id)
267 {
268 	return LL_DMA_IsEnabledIT_DME(dma, dma_stm32_id_to_stream(id)) &&
269 	       dma_stm32_is_dme_active(dma, id);
270 }
271 
stm32_dma_is_fe_irq_active(DMA_TypeDef * dma,uint32_t id)272 static inline bool stm32_dma_is_fe_irq_active(DMA_TypeDef *dma, uint32_t id)
273 {
274 	return LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
275 	       dma_stm32_is_fe_active(dma, id);
276 }
277 
stm32_dma_is_irq_active(DMA_TypeDef * dma,uint32_t id)278 bool stm32_dma_is_irq_active(DMA_TypeDef *dma, uint32_t id)
279 {
280 	return stm32_dma_is_tc_irq_active(dma, id) ||
281 	       stm32_dma_is_ht_irq_active(dma, id) ||
282 	       stm32_dma_is_te_irq_active(dma, id) ||
283 	       stm32_dma_is_dme_irq_active(dma, id) ||
284 	       stm32_dma_is_fe_irq_active(dma, id);
285 }
286 
stm32_dma_clear_stream_irq(DMA_TypeDef * dma,uint32_t id)287 void stm32_dma_clear_stream_irq(DMA_TypeDef *dma, uint32_t id)
288 {
289 	dma_stm32_clear_te(dma, id);
290 	dma_stm32_clear_dme(dma, id);
291 	dma_stm32_clear_fe(dma, id);
292 }
293 
stm32_dma_is_irq_happened(DMA_TypeDef * dma,uint32_t id)294 bool stm32_dma_is_irq_happened(DMA_TypeDef *dma, uint32_t id)
295 {
296 	if (LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
297 	    dma_stm32_is_fe_active(dma, id)) {
298 		return true;
299 	}
300 
301 	return false;
302 }
303 
stm32_dma_is_unexpected_irq_happened(DMA_TypeDef * dma,uint32_t id)304 bool stm32_dma_is_unexpected_irq_happened(DMA_TypeDef *dma, uint32_t id)
305 {
306 	if (LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
307 	    dma_stm32_is_fe_active(dma, id)) {
308 		LOG_ERR("FiFo error.");
309 		stm32_dma_dump_stream_irq(dma, id);
310 		stm32_dma_clear_stream_irq(dma, id);
311 
312 		return true;
313 	}
314 
315 	return false;
316 }
317 
stm32_dma_enable_stream(DMA_TypeDef * dma,uint32_t id)318 void stm32_dma_enable_stream(DMA_TypeDef *dma, uint32_t id)
319 {
320 	LL_DMA_EnableStream(dma, dma_stm32_id_to_stream(id));
321 }
322 
stm32_dma_is_enabled_stream(DMA_TypeDef * dma,uint32_t id)323 bool stm32_dma_is_enabled_stream(DMA_TypeDef *dma, uint32_t id)
324 {
325 	if (LL_DMA_IsEnabledStream(dma, dma_stm32_id_to_stream(id)) == 1) {
326 		return true;
327 	}
328 	return false;
329 }
330 
stm32_dma_disable_stream(DMA_TypeDef * dma,uint32_t id)331 int stm32_dma_disable_stream(DMA_TypeDef *dma, uint32_t id)
332 {
333 	LL_DMA_DisableStream(dma, dma_stm32_id_to_stream(id));
334 
335 	while (stm32_dma_is_enabled_stream(dma, id)) {
336 	}
337 
338 	dma_stm32_clear_tc(dma, id);
339 
340 	return 0;
341 }
342 
stm32_dma_disable_fifo_irq(DMA_TypeDef * dma,uint32_t id)343 void stm32_dma_disable_fifo_irq(DMA_TypeDef *dma, uint32_t id)
344 {
345 	LL_DMA_DisableIT_FE(dma, dma_stm32_id_to_stream(id));
346 }
347 
348 #if !defined(CONFIG_DMAMUX_STM32)
stm32_dma_config_channel_function(DMA_TypeDef * dma,uint32_t id,uint32_t slot)349 void stm32_dma_config_channel_function(DMA_TypeDef *dma, uint32_t id,
350 					uint32_t slot)
351 {
352 	LL_DMA_SetChannelSelection(dma, dma_stm32_id_to_stream(id),
353 			dma_stm32_slot_to_channel(slot));
354 }
355 #endif
356 
stm32_dma_get_mburst(struct dma_config * config,bool source_periph)357 uint32_t stm32_dma_get_mburst(struct dma_config *config, bool source_periph)
358 {
359 	uint32_t memory_burst;
360 
361 	if (source_periph) {
362 		memory_burst = config->dest_burst_length;
363 	} else {
364 		memory_burst = config->source_burst_length;
365 	}
366 
367 	switch (memory_burst) {
368 	case 1:
369 		return LL_DMA_MBURST_SINGLE;
370 	case 4:
371 		return LL_DMA_MBURST_INC4;
372 	case 8:
373 		return LL_DMA_MBURST_INC8;
374 	case 16:
375 		return LL_DMA_MBURST_INC16;
376 	default:
377 		LOG_ERR("Memory burst size error,"
378 			"using single burst as default");
379 		return LL_DMA_MBURST_SINGLE;
380 	}
381 }
382 
stm32_dma_get_pburst(struct dma_config * config,bool source_periph)383 uint32_t stm32_dma_get_pburst(struct dma_config *config, bool source_periph)
384 {
385 	uint32_t periph_burst;
386 
387 	if (source_periph) {
388 		periph_burst = config->source_burst_length;
389 	} else {
390 		periph_burst = config->dest_burst_length;
391 	}
392 
393 	switch (periph_burst) {
394 	case 1:
395 		return LL_DMA_PBURST_SINGLE;
396 	case 4:
397 		return LL_DMA_PBURST_INC4;
398 	case 8:
399 		return LL_DMA_PBURST_INC8;
400 	case 16:
401 		return LL_DMA_PBURST_INC16;
402 	default:
403 		LOG_ERR("Peripheral burst size error,"
404 			"using single burst as default");
405 		return LL_DMA_PBURST_SINGLE;
406 	}
407 }
408 
409 /*
410  * This function checks if the msize, mburst and fifo level is
411  * compatible. If they are not compatible, refer to the 'FIFO'
412  * section in the 'DMA' chapter in the Reference Manual for more
413  * information.
414  * This function does not have the obligation of checking the parameters.
415  */
stm32_dma_check_fifo_mburst(LL_DMA_InitTypeDef * DMAx)416 bool stm32_dma_check_fifo_mburst(LL_DMA_InitTypeDef *DMAx)
417 {
418 	uint32_t msize = DMAx->MemoryOrM2MDstDataSize;
419 	uint32_t fifo_level = DMAx->FIFOThreshold;
420 	uint32_t mburst = DMAx->MemBurst;
421 
422 	switch (msize) {
423 	case LL_DMA_MDATAALIGN_BYTE:
424 		switch (mburst) {
425 		case LL_DMA_MBURST_INC4:
426 			return true;
427 		case LL_DMA_MBURST_INC8:
428 			if (fifo_level == LL_DMA_FIFOTHRESHOLD_1_2 ||
429 			    fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
430 				return true;
431 			}
432 			break;
433 		case LL_DMA_MBURST_INC16:
434 			if (fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
435 				return true;
436 			}
437 			break;
438 		}
439 		break;
440 	case LL_DMA_MDATAALIGN_HALFWORD:
441 		switch (mburst) {
442 		case LL_DMA_MBURST_INC4:
443 			if (fifo_level == LL_DMA_FIFOTHRESHOLD_1_2 ||
444 			    fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
445 				return true;
446 			}
447 			break;
448 		case LL_DMA_MBURST_INC8:
449 			if (fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
450 				return true;
451 			}
452 			break;
453 		}
454 		break;
455 	case LL_DMA_MDATAALIGN_WORD:
456 		if (mburst == LL_DMA_MBURST_INC4 &&
457 		    fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
458 			return true;
459 		}
460 	}
461 
462 	/* Other combinations are forbidden. */
463 	return false;
464 }
465 
stm32_dma_get_fifo_threshold(uint16_t fifo_mode_control)466 uint32_t stm32_dma_get_fifo_threshold(uint16_t fifo_mode_control)
467 {
468 	switch (fifo_mode_control) {
469 	case 0:
470 		return LL_DMA_FIFOTHRESHOLD_1_4;
471 	case 1:
472 		return LL_DMA_FIFOTHRESHOLD_1_2;
473 	case 2:
474 		return LL_DMA_FIFOTHRESHOLD_3_4;
475 	case 3:
476 		return LL_DMA_FIFOTHRESHOLD_FULL;
477 	default:
478 		LOG_WRN("FIFO threshold parameter error, reset to 1/4");
479 		return LL_DMA_FIFOTHRESHOLD_1_4;
480 	}
481 }
482