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