Line data Source code
1 1 : /*
2 : * Copyright (c) 2016 Intel Corporation
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @ingroup dma_interface
10 : * @brief Main header file for DMA (Direct Memory Access) driver API.
11 : */
12 :
13 : #ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_H_
14 : #define ZEPHYR_INCLUDE_DRIVERS_DMA_H_
15 :
16 : #include <zephyr/kernel.h>
17 : #include <zephyr/device.h>
18 :
19 : #ifdef __cplusplus
20 : extern "C" {
21 : #endif
22 :
23 : /**
24 : * @brief Interfaces for DMA (Direct Memory Access) controllers.
25 : * @defgroup dma_interface DMA
26 : * @since 1.5
27 : * @version 1.0.0
28 : * @ingroup io_interfaces
29 : * @{
30 : */
31 :
32 : /**
33 : * @brief DMA channel direction
34 : */
35 1 : enum dma_channel_direction {
36 : /** Memory to memory */
37 : MEMORY_TO_MEMORY = 0x0,
38 : /** Memory to peripheral */
39 : MEMORY_TO_PERIPHERAL,
40 : /** Peripheral to memory */
41 : PERIPHERAL_TO_MEMORY,
42 : /** Peripheral to peripheral */
43 : PERIPHERAL_TO_PERIPHERAL,
44 : /** Host to memory */
45 : HOST_TO_MEMORY,
46 : /** Memory to host */
47 : MEMORY_TO_HOST,
48 :
49 : /**
50 : * Number of all common channel directions.
51 : */
52 : DMA_CHANNEL_DIRECTION_COMMON_COUNT,
53 :
54 : /**
55 : * This and higher values are dma controller or soc specific.
56 : * Refer to the specified dma driver header file.
57 : */
58 : DMA_CHANNEL_DIRECTION_PRIV_START = DMA_CHANNEL_DIRECTION_COMMON_COUNT,
59 :
60 : /**
61 : * Maximum allowed value (3 bit field!)
62 : */
63 : DMA_CHANNEL_DIRECTION_MAX = 0x7
64 : };
65 :
66 : /**
67 : * @brief DMA address adjustment
68 : *
69 : * Valid values for @a source_addr_adj and @a dest_addr_adj
70 : */
71 1 : enum dma_addr_adj {
72 : /** Increment the address */
73 : DMA_ADDR_ADJ_INCREMENT,
74 : /** Decrement the address */
75 : DMA_ADDR_ADJ_DECREMENT,
76 : /** No change the address */
77 : DMA_ADDR_ADJ_NO_CHANGE,
78 : };
79 :
80 : /**
81 : * @brief DMA channel attributes
82 : */
83 0 : enum dma_channel_filter {
84 : DMA_CHANNEL_NORMAL, /* normal DMA channel */
85 : DMA_CHANNEL_PERIODIC, /* can be triggered by periodic sources */
86 : };
87 :
88 : /**
89 : * @brief DMA attributes
90 : */
91 0 : enum dma_attribute_type {
92 : DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT,
93 : DMA_ATTR_BUFFER_SIZE_ALIGNMENT,
94 : DMA_ATTR_COPY_ALIGNMENT,
95 : DMA_ATTR_MAX_BLOCK_COUNT,
96 : };
97 :
98 : /**
99 : * @struct dma_block_config
100 : * @brief DMA block configuration structure.
101 : *
102 : * Aside from source address, destination address, and block size many of these options are hardware
103 : * and driver dependent.
104 : */
105 1 : struct dma_block_config {
106 : #ifdef CONFIG_DMA_64BIT
107 : /** block starting address at source */
108 : uint64_t source_address;
109 : /** block starting address at destination */
110 : uint64_t dest_address;
111 : #else
112 : /** block starting address at source */
113 1 : uint32_t source_address;
114 : /** block starting address at destination */
115 1 : uint32_t dest_address;
116 : #endif
117 : /** Address adjustment at gather boundary */
118 1 : uint32_t source_gather_interval;
119 : /** Address adjustment at scatter boundary */
120 1 : uint32_t dest_scatter_interval;
121 : /** Continuous transfer count between scatter boundaries */
122 1 : uint16_t dest_scatter_count;
123 : /** Continuous transfer count between gather boundaries */
124 1 : uint16_t source_gather_count;
125 : /** Number of bytes to be transferred for this block */
126 1 : uint32_t block_size;
127 : /** Pointer to next block in a transfer list */
128 1 : struct dma_block_config *next_block;
129 : /** Enable source gathering when set to 1 */
130 1 : uint16_t source_gather_en : 1;
131 : /** Enable destination scattering when set to 1 */
132 1 : uint16_t dest_scatter_en : 1;
133 : /**
134 : * Source address adjustment option
135 : *
136 : * - 0b00 increment
137 : * - 0b01 decrement
138 : * - 0b10 no change
139 : */
140 1 : uint16_t source_addr_adj : 2;
141 : /**
142 : * Destination address adjustment
143 : *
144 : * - 0b00 increment
145 : * - 0b01 decrement
146 : * - 0b10 no change
147 : */
148 1 : uint16_t dest_addr_adj : 2;
149 : /** Reload source address at the end of block transfer */
150 1 : uint16_t source_reload_en : 1;
151 : /** Reload destination address at the end of block transfer */
152 1 : uint16_t dest_reload_en : 1;
153 : /** FIFO fill before starting transfer, HW specific meaning */
154 1 : uint16_t fifo_mode_control : 4;
155 : /**
156 : * Transfer flow control mode
157 : *
158 : * - 0b0 source request service upon data availability
159 : * - 0b1 source request postponed until destination request happens
160 : */
161 1 : uint16_t flow_control_mode : 1;
162 :
163 : uint16_t _reserved : 3;
164 : };
165 :
166 : /** The DMA callback event has occurred at the completion of a transfer list */
167 1 : #define DMA_STATUS_COMPLETE 0
168 : /** The DMA callback has occurred at the completion of a single transfer block in a transfer list */
169 1 : #define DMA_STATUS_BLOCK 1
170 :
171 : /**
172 : * @typedef dma_callback_t
173 : * @brief Callback function for DMA transfer completion
174 : *
175 : * If enabled, callback function will be invoked at transfer or block completion,
176 : * or when an error happens.
177 : * In circular mode, @p status indicates that the DMA device has reached either
178 : * the end of the buffer (DMA_STATUS_COMPLETE) or a water mark (DMA_STATUS_BLOCK).
179 : *
180 : * @param dev Pointer to the DMA device calling the callback.
181 : * @param user_data A pointer to some user data or NULL
182 : * @param channel The channel number
183 : * @param status Status of the transfer
184 : * - DMA_STATUS_COMPLETE buffer fully consumed
185 : * - DMA_STATUS_BLOCK buffer consumption reached a configured block
186 : * or water mark
187 : * - A negative errno otherwise
188 : */
189 1 : typedef void (*dma_callback_t)(const struct device *dev, void *user_data,
190 : uint32_t channel, int status);
191 :
192 : /**
193 : * @struct dma_config
194 : * @brief DMA configuration structure.
195 : */
196 1 : struct dma_config {
197 : /** Which peripheral and direction, HW specific */
198 1 : uint32_t dma_slot : 8;
199 : /**
200 : * Direction the transfers are occurring
201 : *
202 : * - 0b000 memory to memory,
203 : * - 0b001 memory to peripheral,
204 : * - 0b010 peripheral to memory,
205 : * - 0b011 peripheral to peripheral,
206 : * - 0b100 host to memory
207 : * - 0b101 memory to host
208 : * - others hardware specific
209 : */
210 1 : uint32_t channel_direction : 3;
211 : /**
212 : * Completion callback enable
213 : *
214 : * - 0b0 callback invoked at transfer list completion only
215 : * - 0b1 callback invoked at completion of each block
216 : */
217 1 : uint32_t complete_callback_en : 1;
218 : /**
219 : * Error callback disable
220 : *
221 : * - 0b0 error callback enabled
222 : * - 0b1 error callback disabled
223 : */
224 1 : uint32_t error_callback_dis : 1;
225 : /**
226 : * Source handshake, HW specific
227 : *
228 : * - 0b0 HW
229 : * - 0b1 SW
230 : */
231 1 : uint32_t source_handshake : 1;
232 : /**
233 : * Destination handshake, HW specific
234 : *
235 : * - 0b0 HW
236 : * - 0b1 SW
237 : */
238 1 : uint32_t dest_handshake : 1;
239 : /**
240 : * Channel priority for arbitration, HW specific
241 : */
242 1 : uint32_t channel_priority : 4;
243 : /** Source chaining enable, HW specific */
244 1 : uint32_t source_chaining_en : 1;
245 : /** Destination chaining enable, HW specific */
246 1 : uint32_t dest_chaining_en : 1;
247 : /** Linked channel, HW specific */
248 1 : uint32_t linked_channel : 7;
249 : /** Cyclic transfer list, HW specific */
250 1 : uint32_t cyclic : 1;
251 :
252 : uint32_t _reserved : 3;
253 : /** Width of source data (in bytes) */
254 1 : uint32_t source_data_size : 16;
255 : /** Width of destination data (in bytes) */
256 1 : uint32_t dest_data_size : 16;
257 : /** Source burst length in bytes */
258 1 : uint32_t source_burst_length : 16;
259 : /** Destination burst length in bytes */
260 1 : uint32_t dest_burst_length : 16;
261 : /** Number of blocks in transfer list */
262 1 : uint32_t block_count;
263 : /** Pointer to the first block in the transfer list */
264 1 : struct dma_block_config *head_block;
265 : /** Optional attached user data for callbacks */
266 1 : void *user_data;
267 : /** Optional callback for completion and error events */
268 1 : dma_callback_t dma_callback;
269 : };
270 :
271 : /**
272 : * DMA runtime status structure
273 : */
274 1 : struct dma_status {
275 : /** Is the current DMA transfer busy or idle */
276 1 : bool busy;
277 : /** Direction for the transfer */
278 1 : enum dma_channel_direction dir;
279 : /** Pending length to be transferred in bytes, HW specific */
280 1 : uint32_t pending_length;
281 : /** Available buffers space, HW specific */
282 1 : uint32_t free;
283 : /** Write position in circular DMA buffer, HW specific */
284 1 : uint32_t write_position;
285 : /** Read position in circular DMA buffer, HW specific */
286 1 : uint32_t read_position;
287 : /** Total copied, HW specific */
288 1 : uint64_t total_copied;
289 : };
290 :
291 : /**
292 : * DMA context structure
293 : * Note: the dma_context shall be the first member
294 : * of DMA client driver Data, got by dev->data
295 : */
296 1 : struct dma_context {
297 : /** magic code to identify the context */
298 1 : int32_t magic;
299 : /** number of dma channels */
300 1 : int dma_channels;
301 : /** atomic holding bit flags for each channel to mark as used/unused */
302 1 : atomic_t *atomic;
303 : };
304 :
305 : /** Magic code to identify context content */
306 1 : #define DMA_MAGIC 0x47494749
307 :
308 : /**
309 : * @cond INTERNAL_HIDDEN
310 : *
311 : * These are for internal use only, so skip these in
312 : * public documentation.
313 : */
314 : typedef int (*dma_api_config)(const struct device *dev, uint32_t channel,
315 : struct dma_config *config);
316 :
317 : #ifdef CONFIG_DMA_64BIT
318 : typedef int (*dma_api_reload)(const struct device *dev, uint32_t channel,
319 : uint64_t src, uint64_t dst, size_t size);
320 : #else
321 : typedef int (*dma_api_reload)(const struct device *dev, uint32_t channel,
322 : uint32_t src, uint32_t dst, size_t size);
323 : #endif
324 :
325 : typedef int (*dma_api_start)(const struct device *dev, uint32_t channel);
326 :
327 : typedef int (*dma_api_stop)(const struct device *dev, uint32_t channel);
328 :
329 : typedef int (*dma_api_suspend)(const struct device *dev, uint32_t channel);
330 :
331 : typedef int (*dma_api_resume)(const struct device *dev, uint32_t channel);
332 :
333 : typedef int (*dma_api_get_status)(const struct device *dev, uint32_t channel,
334 : struct dma_status *status);
335 :
336 : typedef int (*dma_api_get_attribute)(const struct device *dev, uint32_t type, uint32_t *value);
337 :
338 : /**
339 : * @typedef dma_chan_filter
340 : * @brief channel filter function call
341 : *
342 : * filter function that is used to find the matched internal dma channel
343 : * provide by caller
344 : *
345 : * @param dev Pointer to the DMA device instance
346 : * @param channel the channel id to use
347 : * @param filter_param filter function parameter, can be NULL
348 : *
349 : * @retval True on filter matched otherwise return False.
350 : */
351 : typedef bool (*dma_api_chan_filter)(const struct device *dev,
352 : int channel, void *filter_param);
353 :
354 : /**
355 : * @typedef dma_chan_release
356 : * @brief channel release function call
357 : *
358 : * used to release channel resources "allocated" during the
359 : * request phase. These resources can refer to enabled PDs, IRQs
360 : * etc...
361 : *
362 : * @param dev Pointer to the DMA device instance
363 : * @param channel channel id to use
364 : */
365 : typedef void (*dma_api_chan_release)(const struct device *dev,
366 : uint32_t channel);
367 :
368 : __subsystem struct dma_driver_api {
369 : dma_api_config config;
370 : dma_api_reload reload;
371 : dma_api_start start;
372 : dma_api_stop stop;
373 : dma_api_suspend suspend;
374 : dma_api_resume resume;
375 : dma_api_get_status get_status;
376 : dma_api_get_attribute get_attribute;
377 : dma_api_chan_filter chan_filter;
378 : dma_api_chan_release chan_release;
379 : };
380 : /**
381 : * @endcond
382 : */
383 :
384 : /**
385 : * @brief Configure individual channel for DMA transfer.
386 : *
387 : * @param dev Pointer to the device structure for the driver instance.
388 : * @param channel Numeric identification of the channel to configure
389 : * @param config Data structure containing the intended configuration for the
390 : * selected channel
391 : *
392 : * @retval 0 if successful.
393 : * @retval Negative errno code if failure.
394 : */
395 1 : static inline int dma_config(const struct device *dev, uint32_t channel,
396 : struct dma_config *config)
397 : {
398 : const struct dma_driver_api *api =
399 : (const struct dma_driver_api *)dev->api;
400 :
401 : return api->config(dev, channel, config);
402 : }
403 :
404 : /**
405 : * @brief Reload buffer(s) for a DMA channel
406 : *
407 : * @param dev Pointer to the device structure for the driver instance.
408 : * @param channel Numeric identification of the channel to configure
409 : * selected channel
410 : * @param src source address for the DMA transfer
411 : * @param dst destination address for the DMA transfer
412 : * @param size size of DMA transfer
413 : *
414 : * @retval 0 if successful.
415 : * @retval Negative errno code if failure.
416 : */
417 : #ifdef CONFIG_DMA_64BIT
418 : static inline int dma_reload(const struct device *dev, uint32_t channel,
419 : uint64_t src, uint64_t dst, size_t size)
420 : #else
421 1 : static inline int dma_reload(const struct device *dev, uint32_t channel,
422 : uint32_t src, uint32_t dst, size_t size)
423 : #endif
424 : {
425 : const struct dma_driver_api *api =
426 : (const struct dma_driver_api *)dev->api;
427 :
428 : if (api->reload) {
429 : return api->reload(dev, channel, src, dst, size);
430 : }
431 :
432 : return -ENOSYS;
433 : }
434 :
435 : /**
436 : * @brief Enables DMA channel and starts the transfer, the channel must be
437 : * configured beforehand.
438 : *
439 : * Implementations must check the validity of the channel ID passed in and
440 : * return -EINVAL if it is invalid.
441 : *
442 : * Start is allowed on channels that have already been started and must report
443 : * success.
444 : *
445 : * @funcprops \isr_ok
446 : *
447 : * @param dev Pointer to the device structure for the driver instance.
448 : * @param channel Numeric identification of the channel where the transfer will
449 : * be processed
450 : *
451 : * @retval 0 if successful.
452 : * @retval Negative errno code if failure.
453 : */
454 1 : static inline int dma_start(const struct device *dev, uint32_t channel)
455 : {
456 : const struct dma_driver_api *api =
457 : (const struct dma_driver_api *)dev->api;
458 :
459 : return api->start(dev, channel);
460 : }
461 :
462 : /**
463 : * @brief Stops the DMA transfer and disables the channel.
464 : *
465 : * Implementations must check the validity of the channel ID passed in and
466 : * return -EINVAL if it is invalid.
467 : *
468 : * Stop is allowed on channels that have already been stopped and must report
469 : * success.
470 : *
471 : * @funcprops \isr_ok
472 : *
473 : * @param dev Pointer to the device structure for the driver instance.
474 : * @param channel Numeric identification of the channel where the transfer was
475 : * being processed
476 : *
477 : * @retval 0 if successful.
478 : * @retval Negative errno code if failure.
479 : */
480 1 : static inline int dma_stop(const struct device *dev, uint32_t channel)
481 : {
482 : const struct dma_driver_api *api =
483 : (const struct dma_driver_api *)dev->api;
484 :
485 : return api->stop(dev, channel);
486 : }
487 :
488 :
489 : /**
490 : * @brief Suspend a DMA channel transfer
491 : *
492 : * Implementations must check the validity of the channel state and ID passed
493 : * in and return -EINVAL if either are invalid.
494 : *
495 : * @funcprops \isr_ok
496 : *
497 : * @param dev Pointer to the device structure for the driver instance.
498 : * @param channel Numeric identification of the channel to suspend
499 : *
500 : * @retval 0 If successful.
501 : * @retval -ENOSYS If not implemented.
502 : * @retval -EINVAL If invalid channel id or state.
503 : * @retval -errno Other negative errno code failure.
504 : */
505 1 : static inline int dma_suspend(const struct device *dev, uint32_t channel)
506 : {
507 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
508 :
509 : if (api->suspend == NULL) {
510 : return -ENOSYS;
511 : }
512 : return api->suspend(dev, channel);
513 : }
514 :
515 : /**
516 : * @brief Resume a DMA channel transfer
517 : *
518 : * Implementations must check the validity of the channel state and ID passed
519 : * in and return -EINVAL if either are invalid.
520 : *
521 : * @funcprops \isr_ok
522 : *
523 : * @param dev Pointer to the device structure for the driver instance.
524 : * @param channel Numeric identification of the channel to resume
525 : *
526 : * @retval 0 If successful.
527 : * @retval -ENOSYS If not implemented
528 : * @retval -EINVAL If invalid channel id or state.
529 : * @retval -errno Other negative errno code failure.
530 : */
531 1 : static inline int dma_resume(const struct device *dev, uint32_t channel)
532 : {
533 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
534 :
535 : if (api->resume == NULL) {
536 : return -ENOSYS;
537 : }
538 : return api->resume(dev, channel);
539 : }
540 :
541 : /**
542 : * @brief request DMA channel.
543 : *
544 : * request DMA channel resources
545 : * return -EINVAL if there is no valid channel available.
546 : *
547 : * @note It is safe to use this function in contexts where blocking
548 : * is not allowed, e.g. ISR, provided the implementation of the filter
549 : * function does not block.
550 : *
551 : * @param dev Pointer to the device structure for the driver instance.
552 : * @param filter_param filter function parameter
553 : *
554 : * @retval dma channel if successful.
555 : * @retval Negative errno code if failure.
556 : */
557 1 : static inline int dma_request_channel(const struct device *dev, void *filter_param)
558 : {
559 : int i = 0;
560 : int channel = -EINVAL;
561 : const struct dma_driver_api *api =
562 : (const struct dma_driver_api *)dev->api;
563 : /* dma_context shall be the first one in dev data */
564 : struct dma_context *dma_ctx = (struct dma_context *)dev->data;
565 :
566 : if (dma_ctx->magic != DMA_MAGIC) {
567 : return channel;
568 : }
569 :
570 : for (i = 0; i < dma_ctx->dma_channels; i++) {
571 : if (!atomic_test_and_set_bit(dma_ctx->atomic, i)) {
572 : if (api->chan_filter &&
573 : !api->chan_filter(dev, i, filter_param)) {
574 : atomic_clear_bit(dma_ctx->atomic, i);
575 : continue;
576 : }
577 : channel = i;
578 : break;
579 : }
580 : }
581 :
582 : return channel;
583 : }
584 :
585 : /**
586 : * @brief release DMA channel.
587 : *
588 : * release DMA channel resources
589 : *
590 : * @note It is safe to use this function in contexts where blocking
591 : * is not allowed, e.g. ISR, provided the implementation of the release
592 : * function does not block.
593 : *
594 : * @param dev Pointer to the device structure for the driver instance.
595 : * @param channel channel number
596 : *
597 : */
598 1 : static inline void dma_release_channel(const struct device *dev, uint32_t channel)
599 : {
600 : const struct dma_driver_api *api =
601 : (const struct dma_driver_api *)dev->api;
602 : struct dma_context *dma_ctx = (struct dma_context *)dev->data;
603 :
604 : if (dma_ctx->magic != DMA_MAGIC) {
605 : return;
606 : }
607 :
608 : if ((int)channel < dma_ctx->dma_channels) {
609 : if (api->chan_release) {
610 : api->chan_release(dev, channel);
611 : }
612 :
613 : atomic_clear_bit(dma_ctx->atomic, channel);
614 : }
615 :
616 : }
617 :
618 : /**
619 : * @brief DMA channel filter.
620 : *
621 : * filter channel by attribute
622 : *
623 : * @param dev Pointer to the device structure for the driver instance.
624 : * @param channel channel number
625 : * @param filter_param filter attribute
626 : *
627 : * @retval Negative errno code if not support
628 : *
629 : */
630 1 : static inline int dma_chan_filter(const struct device *dev, int channel, void *filter_param)
631 : {
632 : const struct dma_driver_api *api =
633 : (const struct dma_driver_api *)dev->api;
634 :
635 : if (api->chan_filter) {
636 : return api->chan_filter(dev, channel, filter_param);
637 : }
638 :
639 : return -ENOSYS;
640 : }
641 :
642 : /**
643 : * @brief get current runtime status of DMA transfer
644 : *
645 : * Implementations must check the validity of the channel ID passed in and
646 : * return -EINVAL if it is invalid or -ENOSYS if not supported.
647 : *
648 : * @funcprops \isr_ok
649 : *
650 : * @param dev Pointer to the device structure for the driver instance.
651 : * @param channel Numeric identification of the channel where the transfer was
652 : * being processed
653 : * @param stat a non-NULL dma_status object for storing DMA status
654 : *
655 : * @retval non-negative if successful.
656 : * @retval Negative errno code if failure.
657 : */
658 1 : static inline int dma_get_status(const struct device *dev, uint32_t channel,
659 : struct dma_status *stat)
660 : {
661 : const struct dma_driver_api *api =
662 : (const struct dma_driver_api *)dev->api;
663 :
664 : if (api->get_status) {
665 : return api->get_status(dev, channel, stat);
666 : }
667 :
668 : return -ENOSYS;
669 : }
670 :
671 : /**
672 : * @brief get attribute of a dma controller
673 : *
674 : * This function allows to get a device specific static or runtime attribute like required address
675 : * and size alignment of a buffer.
676 : * Implementations must check the validity of the type passed in and
677 : * return -EINVAL if it is invalid or -ENOSYS if not supported.
678 : *
679 : * @funcprops \isr_ok
680 : *
681 : * @param dev Pointer to the device structure for the driver instance.
682 : * @param type Numeric identification of the attribute
683 : * @param value A non-NULL pointer to the variable where the read value is to be placed
684 : *
685 : * @retval non-negative if successful.
686 : * @retval Negative errno code if failure.
687 : */
688 1 : static inline int dma_get_attribute(const struct device *dev, uint32_t type, uint32_t *value)
689 : {
690 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
691 :
692 : if (api->get_attribute) {
693 : return api->get_attribute(dev, type, value);
694 : }
695 :
696 : return -ENOSYS;
697 : }
698 :
699 : /**
700 : * @brief Look-up generic width index to be used in registers
701 : *
702 : * @warning This look-up works for most controllers, but *may* not work for
703 : * yours. Ensure your controller expects the most common register
704 : * bit values before using this convenience function. If your
705 : * controller does not support these values, you will have to write
706 : * your own look-up inside the controller driver.
707 : *
708 : * @param size: width of bus (in bytes)
709 : *
710 : * @retval common DMA index to be placed into registers.
711 : */
712 1 : static inline uint32_t dma_width_index(uint32_t size)
713 : {
714 : /* Check boundaries (max supported width is 32 Bytes) */
715 : if (size < 1 || size > 32) {
716 : return 0; /* Zero is the default (8 Bytes) */
717 : }
718 :
719 : /* Ensure size is a power of 2 */
720 : if (!is_power_of_two(size)) {
721 : return 0; /* Zero is the default (8 Bytes) */
722 : }
723 :
724 : /* Convert to bit pattern for writing to a register */
725 : return find_msb_set(size);
726 : }
727 :
728 : /**
729 : * @brief Look-up generic burst index to be used in registers
730 : *
731 : * @warning This look-up works for most controllers, but *may* not work for
732 : * yours. Ensure your controller expects the most common register
733 : * bit values before using this convenience function. If your
734 : * controller does not support these values, you will have to write
735 : * your own look-up inside the controller driver.
736 : *
737 : * @param burst: number of bytes to be sent in a single burst
738 : *
739 : * @retval common DMA index to be placed into registers.
740 : */
741 1 : static inline uint32_t dma_burst_index(uint32_t burst)
742 : {
743 : /* Check boundaries (max supported burst length is 256) */
744 : if (burst < 1 || burst > 256) {
745 : return 0; /* Zero is the default (1 burst length) */
746 : }
747 :
748 : /* Ensure burst is a power of 2 */
749 : if (!(burst & (burst - 1))) {
750 : return 0; /* Zero is the default (1 burst length) */
751 : }
752 :
753 : /* Convert to bit pattern for writing to a register */
754 : return find_msb_set(burst);
755 : }
756 :
757 : /**
758 : * @brief Get the device tree property describing the buffer address alignment
759 : *
760 : * Useful when statically defining or allocating buffers for DMA usage where
761 : * memory alignment often matters.
762 : *
763 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
764 : * @return alignment Memory byte alignment required for DMA buffers
765 : */
766 1 : #define DMA_BUF_ADDR_ALIGNMENT(node) DT_PROP(node, dma_buf_addr_alignment)
767 :
768 : /**
769 : * @brief Get the device tree property describing the buffer size alignment
770 : *
771 : * Useful when statically defining or allocating buffers for DMA usage where
772 : * memory alignment often matters.
773 : *
774 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
775 : * @return alignment Memory byte alignment required for DMA buffers
776 : */
777 1 : #define DMA_BUF_SIZE_ALIGNMENT(node) DT_PROP(node, dma_buf_size_alignment)
778 :
779 : /**
780 : * @brief Get the device tree property describing the minimal chunk of data possible to be copied
781 : *
782 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
783 : * @return minimal Minimal chunk of data possible to be copied
784 : */
785 1 : #define DMA_COPY_ALIGNMENT(node) DT_PROP(node, dma_copy_alignment)
786 :
787 : /**
788 : * @}
789 : */
790 :
791 : #ifdef __cplusplus
792 : }
793 : #endif
794 :
795 : #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_H_ */
|