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