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 typedef int (*dma_configure_fn)(const struct device *dev, uint32_t id, struct dma_config *config);
60 typedef int (*dma_start_fn)(const struct device *dev, uint32_t id);
61 typedef int (*dma_stop_fn)(const struct device *dev, uint32_t id);
62 typedef int (*dma_reload_fn)(const struct device *dev, uint32_t id,
63 uint32_t src, uint32_t dst, size_t size);
64 typedef int (*dma_status_fn)(const struct device *dev, uint32_t id,
65 struct dma_status *stat);
66
67 struct dmamux_stm32_dma_fops {
68 dma_configure_fn configure;
69 dma_start_fn start;
70 dma_stop_fn stop;
71 dma_reload_fn reload;
72 dma_status_fn get_status;
73 };
74
75 #if (defined(CONFIG_DMA_STM32_V1) || defined(CONFIG_DMA_STM32_V2)) && \
76 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux1))
77 static const struct dmamux_stm32_dma_fops dmamux1 = {
78 dma_stm32_configure,
79 dma_stm32_start,
80 dma_stm32_stop,
81 dma_stm32_reload,
82 dma_stm32_get_status,
83 };
84 #endif
85
86 #if defined(CONFIG_DMA_STM32_BDMA) && DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux2))
87 static const struct dmamux_stm32_dma_fops dmamux2 = {
88 bdma_stm32_configure,
89 bdma_stm32_start,
90 bdma_stm32_stop,
91 bdma_stm32_reload,
92 bdma_stm32_get_status
93 };
94 #endif /* CONFIG_DMA_STM32_BDMA */
95
get_dma_fops(const struct dmamux_stm32_config * dev_config)96 const struct dmamux_stm32_dma_fops *get_dma_fops(const struct dmamux_stm32_config *dev_config)
97 {
98 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux1))
99 if (dev_config->base == DT_REG_ADDR(DT_NODELABEL(dmamux1))) {
100 return &dmamux1;
101 }
102 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux1)) */
103
104 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux2))
105 if (dev_config->base == DT_REG_ADDR(DT_NODELABEL(dmamux2))) {
106 return &dmamux2;
107 }
108 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux2)) */
109
110 __ASSERT(false, "Unknown dma base address %x", dev_config->base);
111 return (void *)0;
112 }
113
dmamux_stm32_configure(const struct device * dev,uint32_t id,struct dma_config * config)114 int dmamux_stm32_configure(const struct device *dev, uint32_t id,
115 struct dma_config *config)
116 {
117 /* device is the dmamux, id is the dmamux channel from 0 */
118 const struct dmamux_stm32_config *dev_config = dev->config;
119 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
120
121 /*
122 * request line ID for this mux channel is stored
123 * in the dma_slot parameter
124 */
125 int request_id = config->dma_slot;
126
127 if (request_id > dev_config->req_nb + dev_config->gen_nb) {
128 LOG_ERR("request ID %d is not valid.", request_id);
129 return -EINVAL;
130 }
131
132 /* check if this channel is valid */
133 if (id >= dev_config->channel_nb) {
134 LOG_ERR("channel ID %d is too big.", id);
135 return -EINVAL;
136 }
137
138 /*
139 * Also configures the corresponding dma channel
140 * instance is given by the dev_dma
141 * stream is given by the index i
142 * config is directly this dma_config
143 */
144
145 /*
146 * This dmamux channel 'id' is now used for this peripheral request
147 * It gives this mux request ID to the dma through the config.dma_slot
148 */
149 if (dma_device->configure(dev_config->mux_channels[id].dev_dma,
150 dev_config->mux_channels[id].dma_id, config) != 0) {
151 LOG_ERR("cannot configure the dmamux.");
152 return -EINVAL;
153 }
154
155 /* set the Request Line ID to this dmamux channel i */
156 DMAMUX_Channel_TypeDef *dmamux =
157 (DMAMUX_Channel_TypeDef *)dev_config->base;
158
159
160 LL_DMAMUX_SetRequestID(dmamux, id, request_id);
161
162 return 0;
163 }
164
dmamux_stm32_start(const struct device * dev,uint32_t id)165 int dmamux_stm32_start(const struct device *dev, uint32_t id)
166 {
167 const struct dmamux_stm32_config *dev_config = dev->config;
168 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
169
170 /* check if this channel is valid */
171 if (id >= dev_config->channel_nb) {
172 LOG_ERR("channel ID %d is too big.", id);
173 return -EINVAL;
174 }
175
176 if (dma_device->start(dev_config->mux_channels[id].dev_dma,
177 dev_config->mux_channels[id].dma_id) != 0) {
178 LOG_ERR("cannot start the dmamux channel %d.", id);
179 return -EINVAL;
180 }
181
182 return 0;
183 }
184
dmamux_stm32_stop(const struct device * dev,uint32_t id)185 int dmamux_stm32_stop(const struct device *dev, uint32_t id)
186 {
187 const struct dmamux_stm32_config *dev_config = dev->config;
188 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
189
190 /* check if this channel is valid */
191 if (id >= dev_config->channel_nb) {
192 LOG_ERR("channel ID %d is too big.", id);
193 return -EINVAL;
194 }
195
196 if (dma_device->stop(dev_config->mux_channels[id].dev_dma,
197 dev_config->mux_channels[id].dma_id) != 0) {
198 LOG_ERR("cannot stop the dmamux channel %d.", id);
199 return -EINVAL;
200 }
201
202 return 0;
203 }
204
dmamux_stm32_reload(const struct device * dev,uint32_t id,uint32_t src,uint32_t dst,size_t size)205 int dmamux_stm32_reload(const struct device *dev, uint32_t id,
206 uint32_t src, uint32_t dst, size_t size)
207 {
208 const struct dmamux_stm32_config *dev_config = dev->config;
209 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
210
211 /* check if this channel is valid */
212 if (id >= dev_config->channel_nb) {
213 LOG_ERR("channel ID %d is too big.", id);
214 return -EINVAL;
215 }
216
217 if (dma_device->reload(dev_config->mux_channels[id].dev_dma,
218 dev_config->mux_channels[id].dma_id,
219 src, dst, size) != 0) {
220 LOG_ERR("cannot reload the dmamux channel %d.", id);
221 return -EINVAL;
222 }
223
224 return 0;
225 }
226
dmamux_stm32_get_status(const struct device * dev,uint32_t id,struct dma_status * stat)227 int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
228 struct dma_status *stat)
229 {
230 const struct dmamux_stm32_config *dev_config = dev->config;
231 const struct dmamux_stm32_dma_fops *dma_device = get_dma_fops(dev_config);
232
233 /* check if this channel is valid */
234 if (id >= dev_config->channel_nb) {
235 LOG_ERR("channel ID %d is too big.", id);
236 return -EINVAL;
237 }
238
239 if (dma_device->get_status(dev_config->mux_channels[id].dev_dma,
240 dev_config->mux_channels[id].dma_id, stat) != 0) {
241 LOG_ERR("cannot get the status of dmamux channel %d.", id);
242 return -EINVAL;
243 }
244
245 return 0;
246 }
247
dmamux_stm32_init(const struct device * dev)248 static int dmamux_stm32_init(const struct device *dev)
249 {
250 const struct dmamux_stm32_config *config = dev->config;
251 #if DT_INST_NODE_HAS_PROP(0, clocks)
252 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
253
254 if (!device_is_ready(clk)) {
255 LOG_ERR("clock control device not ready");
256 return -ENODEV;
257 }
258
259 if (clock_control_on(clk,
260 (clock_control_subsys_t) &config->pclken) != 0) {
261 LOG_ERR("clock op failed\n");
262 return -EIO;
263 }
264 #endif /* DT_INST_NODE_HAS_PROP(0, clocks) */
265
266 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux1))
267 /* DMA 1 and DMA2 for DMAMUX1, BDMA for DMAMUX2 */
268 if (config->base == DT_REG_ADDR(DT_NODELABEL(dmamux1))) {
269 /* DMAs assigned to DMAMUX channels at build time might not be ready. */
270 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dma1))
271 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma1))) == false) {
272 return -ENODEV;
273 }
274 #endif
275 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dma2))
276 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma2))) == false) {
277 return -ENODEV;
278 }
279 #endif
280 }
281 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux1)) */
282
283 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmamux2)) && DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(bdma1))
284 if (config->base == DT_REG_ADDR(DT_NODELABEL(dmamux2))) {
285 if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(bdma1))) == false) {
286 return -ENODEV;
287 }
288 }
289 #endif
290 return 0;
291 }
292
293 static DEVICE_API(dma, dma_funcs) = {
294 .reload = dmamux_stm32_reload,
295 .config = dmamux_stm32_configure,
296 .start = dmamux_stm32_start,
297 .stop = dmamux_stm32_stop,
298 .get_status = dmamux_stm32_get_status,
299 };
300
301 /*
302 * Each dmamux channel is hardwired to one dma controllers dma channel.
303 * DMAMUX_CHANNEL_INIT_X macros resolve this mapping at build time for each
304 * dmamux channel using the dma dt properties dma_offset and dma_requests,
305 * such that it can be stored in dmamux_stm32_channels_X configuration.
306 * The Macros to get the corresponding dma device binding and dma channel
307 * for a given dmamux channel, are currently valid for series having
308 * up to 2 dmamuxes and up to 3 dmas.
309 */
310
311 #define DMA_1_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma1), dma_offset, 0)
312 #define DMA_1_END_DMAMUX_CHANNEL (DMA_1_BEGIN_DMAMUX_CHANNEL + \
313 DT_PROP_OR(DT_NODELABEL(dma1), dma_requests, 0))
314 #define DEV_DMA1 COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dma1)), \
315 DEVICE_DT_GET(DT_NODELABEL(dma1)), NULL)
316
317 #define DMA_2_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma2), dma_offset, 0)
318 #define DMA_2_END_DMAMUX_CHANNEL (DMA_2_BEGIN_DMAMUX_CHANNEL + \
319 DT_PROP_OR(DT_NODELABEL(dma2), dma_requests, 0))
320 #define DEV_DMA2 COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dma2)), \
321 DEVICE_DT_GET(DT_NODELABEL(dma2)), NULL)
322
323 #define BDMA_1_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(bdma1), dma_offset, 0)
324 #define BDMA_1_END_DMAMUX_CHANNEL (BDMA_1_BEGIN_DMAMUX_CHANNEL + \
325 DT_PROP_OR(DT_NODELABEL(bdma1), dma_requests, 0))
326 #define DEV_BDMA COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(bdma1)), \
327 DEVICE_DT_GET(DT_NODELABEL(bdma1)), NULL)
328
329 #define DEV_DMA_BINDING(mux_channel) \
330 ((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? DEV_DMA1 : DEV_DMA2)
331
332 #define DEV_BDMA_BINDING(mux_channel) \
333 (DEV_BDMA)
334
335
336 #define DMA_CHANNEL(mux_channel) \
337 ((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? \
338 (mux_channel + 1) : (mux_channel - DMA_2_BEGIN_DMAMUX_CHANNEL + 1))
339
340 #define BDMA_CHANNEL(mux_channel) \
341 ((mux_channel < BDMA_1_END_DMAMUX_CHANNEL) ? \
342 (mux_channel) : 0 /* not supported */)
343
344 /*
345 * H7 series implements DMAMUX1 and DMAMUX2
346 * DMAMUX1 is used by DMA1 and DMA2
347 * DMAMUX2 is used by BDMA
348 *
349 * Note: Instance Number (or index) has no guarantee to which dmamux it refers
350 */
351
352 #define INIT_DMAMUX1_CHANNEL(x, ...) \
353 { .dev_dma = DEV_DMA_BINDING(x), .dma_id = DMA_CHANNEL(x), }
354 #define INIT_DMAMUX2_CHANNEL(x, ...) \
355 { .dev_dma = DEV_BDMA_BINDING(x), .dma_id = BDMA_CHANNEL(x), }
356
357 #if DT_SAME_NODE(DT_DRV_INST(0), DT_NODELABEL(dmamux1))
358 #define INIT_INST0_CHANNEL(x, ...) INIT_DMAMUX1_CHANNEL(x, ...)
359 #define INIT_INST1_CHANNEL(x, ...) INIT_DMAMUX2_CHANNEL(x, ...)
360 #else
361 #define INIT_INST0_CHANNEL(x, ...) INIT_DMAMUX2_CHANNEL(x, ...)
362 #define INIT_INST1_CHANNEL(x, ...) INIT_DMAMUX1_CHANNEL(x, ...)
363 #endif
364
365 #define DMAMUX_CHANNELS_INIT(index, count) \
366 LISTIFY(count, INIT_INST##index##_CHANNEL, (,))
367
368 #define DMAMUX_CLOCK_INIT(index) \
369 COND_CODE_1(DT_INST_NODE_HAS_PROP(index, clocks), \
370 (.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
371 .enr = DT_INST_CLOCKS_CELL(index, bits)},), \
372 ())
373
374 #define DMAMUX_INIT(index) \
375 static const struct dmamux_stm32_channel \
376 dmamux_stm32_channels_##index[DT_INST_PROP(index, dma_channels)] = { \
377 DMAMUX_CHANNELS_INIT(index, DT_INST_PROP(index, dma_channels))\
378 }; \
379 \
380 const struct dmamux_stm32_config dmamux_stm32_config_##index = { \
381 DMAMUX_CLOCK_INIT(index) \
382 .base = DT_INST_REG_ADDR(index), \
383 .channel_nb = DT_INST_PROP(index, dma_channels), \
384 .gen_nb = DT_INST_PROP(index, dma_generators), \
385 .req_nb = DT_INST_PROP(index, dma_requests), \
386 .mux_channels = dmamux_stm32_channels_##index, \
387 }; \
388 \
389 static struct dmamux_stm32_data dmamux_stm32_data_##index; \
390 \
391 DEVICE_DT_INST_DEFINE(index, \
392 &dmamux_stm32_init, \
393 NULL, \
394 &dmamux_stm32_data_##index, &dmamux_stm32_config_##index,\
395 PRE_KERNEL_1, CONFIG_DMAMUX_STM32_INIT_PRIORITY, \
396 &dma_funcs);
397
398 DT_INST_FOREACH_STATUS_OKAY(DMAMUX_INIT)
399
400 /*
401 * Make sure that this driver is initialized after the DMA driver (higher priority)
402 */
403 BUILD_ASSERT(CONFIG_DMAMUX_STM32_INIT_PRIORITY >= CONFIG_DMA_INIT_PRIORITY,
404 "CONFIG_DMAMUX_STM32_INIT_PRIORITY must be higher than CONFIG_DMA_INIT_PRIORITY");
405