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