1 /*
2 * Copyright (c) 2020 STMicroelectronics
3 * Copyright (c) 2023 Jeroen van Dooren, Nobleo Technology
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @brief Common part of DMAMUX drivers for stm32.
10 * @note api functions named dmamux_stm32_
11 * are calling the dma_stm32 corresponding function
12 * implemented in dma_stm32.c
13 */
14
15 #include <soc.h>
16 #include <stm32_ll_dmamux.h>
17 #include <zephyr/init.h>
18 #include <zephyr/drivers/dma.h>
19 #include <zephyr/drivers/clock_control.h>
20 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
21
22 #include "dma_stm32.h"
23 #ifdef CONFIG_DMA_STM32_BDMA
24 #include "dma_stm32_bdma.h"
25 #endif
26
27 #include <zephyr/logging/log.h>
28 LOG_MODULE_REGISTER(dmamux_stm32, CONFIG_DMA_LOG_LEVEL);
29
30 #define DT_DRV_COMPAT st_stm32_dmamux
31
32 /* this is the configuration of one dmamux channel */
33 struct dmamux_stm32_channel {
34 /* pointer to the associated dma instance */
35 const struct device *dev_dma;
36 /* ref of the associated dma stream for this instance */
37 uint8_t dma_id;
38 };
39
40 /* the table of all the dmamux channel */
41 struct dmamux_stm32_data {
42 void *callback_arg;
43 void (*dmamux_callback)(void *arg, uint32_t id,
44 int error_code);
45 };
46
47 /* this is the configuration of the dmamux IP */
48 struct dmamux_stm32_config {
49 #if DT_INST_NODE_HAS_PROP(0, clocks)
50 struct stm32_pclken pclken;
51 #endif
52 uint32_t base;
53 uint8_t channel_nb; /* total nb of channels */
54 uint8_t gen_nb; /* total nb of Request generator */
55 uint8_t req_nb; /* total nb of Peripheral Request inputs */
56 const struct dmamux_stm32_channel *mux_channels;
57 };
58
59 /*
60 * LISTIFY is used to generate arrays with function pointers to check
61 * and clear interrupt flags using LL functions
62 */
63 #define DMAMUX_CHANNEL(i, _) LL_DMAMUX_CHANNEL_ ## i
64 #define IS_ACTIVE_FLAG_SOX(i, _) LL_DMAMUX_IsActiveFlag_SO ## i
65 #define CLEAR_FLAG_SOX(i, _) LL_DMAMUX_ClearFlag_SO ## i
66 #define IS_ACTIVE_FLAG_RGOX(i, _) LL_DMAMUX_IsActiveFlag_RGO ## i
67 #define CLEAR_FLAG_RGOX(i, _) LL_DMAMUX_ClearFlag_RGO ## i
68
69 uint32_t table_ll_channel[] = {
70 LISTIFY(DT_INST_PROP(0, dma_channels), DMAMUX_CHANNEL, (,))
71 };
72
73 uint32_t (*func_ll_is_active_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
74 LISTIFY(DT_INST_PROP(0, dma_channels), IS_ACTIVE_FLAG_SOX, (,))
75 };
76
77 void (*func_ll_clear_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
78 LISTIFY(DT_INST_PROP(0, dma_channels), CLEAR_FLAG_SOX, (,))
79 };
80
81 uint32_t (*func_ll_is_active_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
82 LISTIFY(DT_INST_PROP(0, dma_generators), IS_ACTIVE_FLAG_RGOX, (,))
83 };
84
85 void (*func_ll_clear_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
86 LISTIFY(DT_INST_PROP(0, dma_generators), CLEAR_FLAG_RGOX, (,))
87 };
88
89 typedef int (*dma_configure_fn)(const struct device *dev, uint32_t id, struct dma_config *config);
90 typedef int (*dma_start_fn)(const struct device *dev, uint32_t id);
91 typedef int (*dma_stop_fn)(const struct device *dev, uint32_t id);
92 typedef int (*dma_reload_fn)(const struct device *dev, uint32_t id,
93 uint32_t src, uint32_t dst, size_t size);
94 typedef int (*dma_status_fn)(const struct device *dev, uint32_t id,
95 struct dma_status *stat);
96
97 struct dmamux_stm32_dma_fops {
98 dma_configure_fn configure;
99 dma_start_fn start;
100 dma_stop_fn stop;
101 dma_reload_fn reload;
102 dma_status_fn get_status;
103 };
104
105 #if (defined(CONFIG_DMA_STM32_V1) || defined(CONFIG_DMA_STM32_V2)) && \
106 DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux1), okay)
107 static const struct dmamux_stm32_dma_fops dmamux1 = {
108 dma_stm32_configure,
109 dma_stm32_start,
110 dma_stm32_stop,
111 dma_stm32_reload,
112 dma_stm32_get_status,
113 };
114 #endif
115
116 #if defined(CONFIG_DMA_STM32_BDMA) && DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux2), okay)
117 static const struct dmamux_stm32_dma_fops dmamux2 = {
118 bdma_stm32_configure,
119 bdma_stm32_start,
120 bdma_stm32_stop,
121 bdma_stm32_reload,
122 bdma_stm32_get_status
123 };
124 #endif /* CONFIG_DMA_STM32_BDMA */
125
get_dma_fops(const struct dmamux_stm32_config * dev_config)126 const struct dmamux_stm32_dma_fops *get_dma_fops(const struct dmamux_stm32_config *dev_config)
127 {
128 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux1), okay)
129 if (dev_config->base == DT_REG_ADDR(DT_NODELABEL(dmamux1))) {
130 return &dmamux1;
131 }
132 #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux1), okay) */
133
134 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux2), okay)
135 if (dev_config->base == DT_REG_ADDR(DT_NODELABEL(dmamux2))) {
136 return &dmamux2;
137 }
138 #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux2), okay) */
139
140 __ASSERT(false, "Unknown dma base address %x", dev_config->base);
141 return (void *)0;
142 }
143
dmamux_stm32_configure(const struct device * dev,uint32_t id,struct dma_config * config)144 int dmamux_stm32_configure(const struct device *dev, uint32_t id,
145 struct dma_config *config)
146 {
147 /* device is the dmamux, id is the dmamux channel from 0 */
148 const struct dmamux_stm32_config *dev_config = dev->config;
149 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
150
151 /*
152 * request line ID for this mux channel is stored
153 * in the dma_slot parameter
154 */
155 int request_id = config->dma_slot;
156
157 if (request_id > dev_config->req_nb + dev_config->gen_nb) {
158 LOG_ERR("request ID %d is not valid.", request_id);
159 return -EINVAL;
160 }
161
162 /* check if this channel is valid */
163 if (id >= dev_config->channel_nb) {
164 LOG_ERR("channel ID %d is too big.", id);
165 return -EINVAL;
166 }
167
168 /*
169 * Also configures the corresponding dma channel
170 * instance is given by the dev_dma
171 * stream is given by the index i
172 * config is directly this dma_config
173 */
174
175 /*
176 * This dmamux channel 'id' is now used for this peripheral request
177 * It gives this mux request ID to the dma through the config.dma_slot
178 */
179 if (dma_device->configure(dev_config->mux_channels[id].dev_dma,
180 dev_config->mux_channels[id].dma_id, config) != 0) {
181 LOG_ERR("cannot configure the dmamux.");
182 return -EINVAL;
183 }
184
185 /* set the Request Line ID to this dmamux channel i */
186 DMAMUX_Channel_TypeDef *dmamux =
187 (DMAMUX_Channel_TypeDef *)dev_config->base;
188
189
190 LL_DMAMUX_SetRequestID(dmamux, id, request_id);
191
192 return 0;
193 }
194
dmamux_stm32_start(const struct device * dev,uint32_t id)195 int dmamux_stm32_start(const struct device *dev, uint32_t id)
196 {
197 const struct dmamux_stm32_config *dev_config = dev->config;
198 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
199
200 /* check if this channel is valid */
201 if (id >= dev_config->channel_nb) {
202 LOG_ERR("channel ID %d is too big.", id);
203 return -EINVAL;
204 }
205
206 if (dma_device->start(dev_config->mux_channels[id].dev_dma,
207 dev_config->mux_channels[id].dma_id) != 0) {
208 LOG_ERR("cannot start the dmamux channel %d.", id);
209 return -EINVAL;
210 }
211
212 return 0;
213 }
214
dmamux_stm32_stop(const struct device * dev,uint32_t id)215 int dmamux_stm32_stop(const struct device *dev, uint32_t id)
216 {
217 const struct dmamux_stm32_config *dev_config = dev->config;
218 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
219
220 /* check if this channel is valid */
221 if (id >= dev_config->channel_nb) {
222 LOG_ERR("channel ID %d is too big.", id);
223 return -EINVAL;
224 }
225
226 if (dma_device->stop(dev_config->mux_channels[id].dev_dma,
227 dev_config->mux_channels[id].dma_id) != 0) {
228 LOG_ERR("cannot stop the dmamux channel %d.", id);
229 return -EINVAL;
230 }
231
232 return 0;
233 }
234
dmamux_stm32_reload(const struct device * dev,uint32_t id,uint32_t src,uint32_t dst,size_t size)235 int dmamux_stm32_reload(const struct device *dev, uint32_t id,
236 uint32_t src, uint32_t dst, size_t size)
237 {
238 const struct dmamux_stm32_config *dev_config = dev->config;
239 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
240
241 /* check if this channel is valid */
242 if (id >= dev_config->channel_nb) {
243 LOG_ERR("channel ID %d is too big.", id);
244 return -EINVAL;
245 }
246
247 if (dma_device->reload(dev_config->mux_channels[id].dev_dma,
248 dev_config->mux_channels[id].dma_id,
249 src, dst, size) != 0) {
250 LOG_ERR("cannot reload the dmamux channel %d.", id);
251 return -EINVAL;
252 }
253
254 return 0;
255 }
256
dmamux_stm32_get_status(const struct device * dev,uint32_t id,struct dma_status * stat)257 int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
258 struct dma_status *stat)
259 {
260 const struct dmamux_stm32_config *dev_config = dev->config;
261 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
262
263 /* check if this channel is valid */
264 if (id >= dev_config->channel_nb) {
265 LOG_ERR("channel ID %d is too big.", id);
266 return -EINVAL;
267 }
268
269 if (dma_device->get_status(dev_config->mux_channels[id].dev_dma,
270 dev_config->mux_channels[id].dma_id, stat) != 0) {
271 LOG_ERR("cannot get the status of dmamux channel %d.", id);
272 return -EINVAL;
273 }
274
275 return 0;
276 }
277
dmamux_stm32_init(const struct device * dev)278 static int dmamux_stm32_init(const struct device *dev)
279 {
280 const struct dmamux_stm32_config *config = dev->config;
281 #if DT_INST_NODE_HAS_PROP(0, clocks)
282 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
283
284 if (!device_is_ready(clk)) {
285 LOG_ERR("clock control device not ready");
286 return -ENODEV;
287 }
288
289 if (clock_control_on(clk,
290 (clock_control_subsys_t) &config->pclken) != 0) {
291 LOG_ERR("clock op failed\n");
292 return -EIO;
293 }
294 #endif /* DT_INST_NODE_HAS_PROP(0, clocks) */
295
296 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux1), okay)
297 /* DMA 1 and DMA2 for DMAMUX1, BDMA for DMAMUX2 */
298 if (config->base == DT_REG_ADDR(DT_NODELABEL(dmamux1))) {
299 /* DMAs assigned to DMAMUX channels at build time might not be ready. */
300 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dma1), okay)
301 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma1))) == false) {
302 return -ENODEV;
303 }
304 #endif
305 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dma2), okay)
306 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma2))) == false) {
307 return -ENODEV;
308 }
309 #endif
310 }
311 #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux1), okay) */
312
313 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dmamux2), okay) && DT_NODE_HAS_STATUS(DT_NODELABEL(bdma1), okay)
314 if (config->base == DT_REG_ADDR(DT_NODELABEL(dmamux2))) {
315 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(bdma1))) == false) {
316 return -ENODEV;
317 }
318 }
319 #endif
320 return 0;
321 }
322
323 static const struct dma_driver_api dma_funcs = {
324 .reload = dmamux_stm32_reload,
325 .config = dmamux_stm32_configure,
326 .start = dmamux_stm32_start,
327 .stop = dmamux_stm32_stop,
328 .get_status = dmamux_stm32_get_status,
329 };
330
331 /*
332 * Each dmamux channel is hardwired to one dma controllers dma channel.
333 * DMAMUX_CHANNEL_INIT_X macros resolve this mapping at build time for each
334 * dmamux channel using the dma dt properties dma_offset and dma_requests,
335 * such that it can be stored in dmamux_stm32_channels_X configuration.
336 * The Macros to get the corresponding dma device binding and dma channel
337 * for a given dmamux channel, are currently valid for series having
338 * up to 2 dmamuxes and up to 3 dmas.
339 */
340
341 #define DMA_1_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma1), dma_offset, 0)
342 #define DMA_1_END_DMAMUX_CHANNEL (DMA_1_BEGIN_DMAMUX_CHANNEL + \
343 DT_PROP_OR(DT_NODELABEL(dma1), dma_requests, 0))
344 #define DEV_DMA1 COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(dma1), okay), \
345 DEVICE_DT_GET(DT_NODELABEL(dma1)), NULL)
346
347 #define DMA_2_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma2), dma_offset, 0)
348 #define DMA_2_END_DMAMUX_CHANNEL (DMA_2_BEGIN_DMAMUX_CHANNEL + \
349 DT_PROP_OR(DT_NODELABEL(dma2), dma_requests, 0))
350 #define DEV_DMA2 COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(dma2), okay), \
351 DEVICE_DT_GET(DT_NODELABEL(dma2)), NULL)
352
353 #define BDMA_1_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(bdma1), dma_offset, 0)
354 #define BDMA_1_END_DMAMUX_CHANNEL (BDMA_1_BEGIN_DMAMUX_CHANNEL + \
355 DT_PROP_OR(DT_NODELABEL(bdma1), dma_requests, 0))
356 #define DEV_BDMA COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(bdma1), okay), \
357 DEVICE_DT_GET(DT_NODELABEL(bdma1)), NULL)
358
359 #define DEV_DMA_BINDING(mux_channel) \
360 ((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? DEV_DMA1 : DEV_DMA2)
361
362 #define DEV_BDMA_BINDING(mux_channel) \
363 (DEV_BDMA)
364
365
366 #define DMA_CHANNEL(mux_channel) \
367 ((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? \
368 (mux_channel + 1) : (mux_channel - DMA_2_BEGIN_DMAMUX_CHANNEL + 1))
369
370 #define BDMA_CHANNEL(mux_channel) \
371 ((mux_channel < BDMA_1_END_DMAMUX_CHANNEL) ? \
372 (mux_channel) : 0 /* not supported */)
373
374 /*
375 * H7 series implements DMAMUX1 and DMAMUX2
376 * DMAMUX1 is used by DMA1 and DMA2
377 * DMAMUX2 is used by BDMA
378 *
379 * Note: Instance Number (or index) has no guarantee to which dmamux it refers
380 */
381
382 #define INIT_DMAMUX1_CHANNEL(x, ...) \
383 { .dev_dma = DEV_DMA_BINDING(x), .dma_id = DMA_CHANNEL(x), }
384 #define INIT_DMAMUX2_CHANNEL(x, ...) \
385 { .dev_dma = DEV_BDMA_BINDING(x), .dma_id = BDMA_CHANNEL(x), }
386
387 #if DT_SAME_NODE(DT_DRV_INST(0), DT_NODELABEL(dmamux1))
388 #define INIT_INST0_CHANNEL(x, ...) INIT_DMAMUX1_CHANNEL(x, ...)
389 #define INIT_INST1_CHANNEL(x, ...) INIT_DMAMUX2_CHANNEL(x, ...)
390 #else
391 #define INIT_INST0_CHANNEL(x, ...) INIT_DMAMUX2_CHANNEL(x, ...)
392 #define INIT_INST1_CHANNEL(x, ...) INIT_DMAMUX1_CHANNEL(x, ...)
393 #endif
394
395 #define DMAMUX_CHANNELS_INIT(index, count) \
396 LISTIFY(count, INIT_INST##index##_CHANNEL, (,))
397
398 #define DMAMUX_CLOCK_INIT(index) \
399 COND_CODE_1(DT_INST_NODE_HAS_PROP(index, clocks), \
400 (.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
401 .enr = DT_INST_CLOCKS_CELL(index, bits)},), \
402 ())
403
404 #define DMAMUX_INIT(index) \
405 static const struct dmamux_stm32_channel \
406 dmamux_stm32_channels_##index[DT_INST_PROP(index, dma_channels)] = { \
407 DMAMUX_CHANNELS_INIT(index, DT_INST_PROP(index, dma_channels))\
408 }; \
409 \
410 const struct dmamux_stm32_config dmamux_stm32_config_##index = { \
411 DMAMUX_CLOCK_INIT(index) \
412 .base = DT_INST_REG_ADDR(index), \
413 .channel_nb = DT_INST_PROP(index, dma_channels), \
414 .gen_nb = DT_INST_PROP(index, dma_generators), \
415 .req_nb = DT_INST_PROP(index, dma_requests), \
416 .mux_channels = dmamux_stm32_channels_##index, \
417 }; \
418 \
419 static struct dmamux_stm32_data dmamux_stm32_data_##index; \
420 \
421 DEVICE_DT_INST_DEFINE(index, \
422 &dmamux_stm32_init, \
423 NULL, \
424 &dmamux_stm32_data_##index, &dmamux_stm32_config_##index,\
425 PRE_KERNEL_1, CONFIG_DMAMUX_STM32_INIT_PRIORITY, \
426 &dma_funcs);
427
428 DT_INST_FOREACH_STATUS_OKAY(DMAMUX_INIT)
429
430 /*
431 * Make sure that this driver is initialized after the DMA driver (higher priority)
432 */
433 BUILD_ASSERT(CONFIG_DMAMUX_STM32_INIT_PRIORITY >= CONFIG_DMA_INIT_PRIORITY,
434 "CONFIG_DMAMUX_STM32_INIT_PRIORITY must be higher than CONFIG_DMA_INIT_PRIORITY");
435