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 : __syscall int dma_start(const struct device *dev, uint32_t channel);
455 :
456 : static inline int z_impl_dma_start(const struct device *dev, uint32_t channel)
457 : {
458 : const struct dma_driver_api *api =
459 : (const struct dma_driver_api *)dev->api;
460 :
461 : return api->start(dev, channel);
462 : }
463 :
464 : /**
465 : * @brief Stops the DMA transfer and disables the channel.
466 : *
467 : * Implementations must check the validity of the channel ID passed in and
468 : * return -EINVAL if it is invalid.
469 : *
470 : * Stop is allowed on channels that have already been stopped and must report
471 : * success.
472 : *
473 : * @funcprops \isr_ok
474 : *
475 : * @param dev Pointer to the device structure for the driver instance.
476 : * @param channel Numeric identification of the channel where the transfer was
477 : * being processed
478 : *
479 : * @retval 0 if successful.
480 : * @retval Negative errno code if failure.
481 : */
482 1 : __syscall int dma_stop(const struct device *dev, uint32_t channel);
483 :
484 : static inline int z_impl_dma_stop(const struct device *dev, uint32_t channel)
485 : {
486 : const struct dma_driver_api *api =
487 : (const struct dma_driver_api *)dev->api;
488 :
489 : return api->stop(dev, channel);
490 : }
491 :
492 :
493 : /**
494 : * @brief Suspend a DMA channel transfer
495 : *
496 : * Implementations must check the validity of the channel state and ID passed
497 : * in and return -EINVAL if either are invalid.
498 : *
499 : * @funcprops \isr_ok
500 : *
501 : * @param dev Pointer to the device structure for the driver instance.
502 : * @param channel Numeric identification of the channel to suspend
503 : *
504 : * @retval 0 If successful.
505 : * @retval -ENOSYS If not implemented.
506 : * @retval -EINVAL If invalid channel id or state.
507 : * @retval -errno Other negative errno code failure.
508 : */
509 1 : __syscall int dma_suspend(const struct device *dev, uint32_t channel);
510 :
511 : static inline int z_impl_dma_suspend(const struct device *dev, uint32_t channel)
512 : {
513 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
514 :
515 : if (api->suspend == NULL) {
516 : return -ENOSYS;
517 : }
518 : return api->suspend(dev, channel);
519 : }
520 :
521 : /**
522 : * @brief Resume a DMA channel transfer
523 : *
524 : * Implementations must check the validity of the channel state and ID passed
525 : * in and return -EINVAL if either are invalid.
526 : *
527 : * @funcprops \isr_ok
528 : *
529 : * @param dev Pointer to the device structure for the driver instance.
530 : * @param channel Numeric identification of the channel to resume
531 : *
532 : * @retval 0 If successful.
533 : * @retval -ENOSYS If not implemented
534 : * @retval -EINVAL If invalid channel id or state.
535 : * @retval -errno Other negative errno code failure.
536 : */
537 1 : __syscall int dma_resume(const struct device *dev, uint32_t channel);
538 :
539 : static inline int z_impl_dma_resume(const struct device *dev, uint32_t channel)
540 : {
541 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
542 :
543 : if (api->resume == NULL) {
544 : return -ENOSYS;
545 : }
546 : return api->resume(dev, channel);
547 : }
548 :
549 : /**
550 : * @brief request DMA channel.
551 : *
552 : * request DMA channel resources
553 : * return -EINVAL if there is no valid channel available.
554 : *
555 : * @note It is safe to use this function in contexts where blocking
556 : * is not allowed, e.g. ISR, provided the implementation of the filter
557 : * function does not block.
558 : *
559 : * @param dev Pointer to the device structure for the driver instance.
560 : * @param filter_param filter function parameter
561 : *
562 : * @retval dma channel if successful.
563 : * @retval Negative errno code if failure.
564 : */
565 1 : __syscall int dma_request_channel(const struct device *dev,
566 : void *filter_param);
567 :
568 : static inline int z_impl_dma_request_channel(const struct device *dev,
569 : void *filter_param)
570 : {
571 : int i = 0;
572 : int channel = -EINVAL;
573 : const struct dma_driver_api *api =
574 : (const struct dma_driver_api *)dev->api;
575 : /* dma_context shall be the first one in dev data */
576 : struct dma_context *dma_ctx = (struct dma_context *)dev->data;
577 :
578 : if (dma_ctx->magic != DMA_MAGIC) {
579 : return channel;
580 : }
581 :
582 : for (i = 0; i < dma_ctx->dma_channels; i++) {
583 : if (!atomic_test_and_set_bit(dma_ctx->atomic, i)) {
584 : if (api->chan_filter &&
585 : !api->chan_filter(dev, i, filter_param)) {
586 : atomic_clear_bit(dma_ctx->atomic, i);
587 : continue;
588 : }
589 : channel = i;
590 : break;
591 : }
592 : }
593 :
594 : return channel;
595 : }
596 :
597 : /**
598 : * @brief release DMA channel.
599 : *
600 : * release DMA channel resources
601 : *
602 : * @note It is safe to use this function in contexts where blocking
603 : * is not allowed, e.g. ISR, provided the implementation of the release
604 : * function does not block.
605 : *
606 : * @param dev Pointer to the device structure for the driver instance.
607 : * @param channel channel number
608 : *
609 : */
610 1 : __syscall void dma_release_channel(const struct device *dev,
611 : uint32_t channel);
612 :
613 : static inline void z_impl_dma_release_channel(const struct device *dev,
614 : uint32_t channel)
615 : {
616 : const struct dma_driver_api *api =
617 : (const struct dma_driver_api *)dev->api;
618 : struct dma_context *dma_ctx = (struct dma_context *)dev->data;
619 :
620 : if (dma_ctx->magic != DMA_MAGIC) {
621 : return;
622 : }
623 :
624 : if ((int)channel < dma_ctx->dma_channels) {
625 : if (api->chan_release) {
626 : api->chan_release(dev, channel);
627 : }
628 :
629 : atomic_clear_bit(dma_ctx->atomic, channel);
630 : }
631 :
632 : }
633 :
634 : /**
635 : * @brief DMA channel filter.
636 : *
637 : * filter channel by attribute
638 : *
639 : * @param dev Pointer to the device structure for the driver instance.
640 : * @param channel channel number
641 : * @param filter_param filter attribute
642 : *
643 : * @retval Negative errno code if not support
644 : *
645 : */
646 1 : __syscall int dma_chan_filter(const struct device *dev,
647 : int channel, void *filter_param);
648 :
649 : static inline int z_impl_dma_chan_filter(const struct device *dev,
650 : int channel, void *filter_param)
651 : {
652 : const struct dma_driver_api *api =
653 : (const struct dma_driver_api *)dev->api;
654 :
655 : if (api->chan_filter) {
656 : return api->chan_filter(dev, channel, filter_param);
657 : }
658 :
659 : return -ENOSYS;
660 : }
661 :
662 : /**
663 : * @brief get current runtime status of DMA transfer
664 : *
665 : * Implementations must check the validity of the channel ID passed in and
666 : * return -EINVAL if it is invalid or -ENOSYS if not supported.
667 : *
668 : * @funcprops \isr_ok
669 : *
670 : * @param dev Pointer to the device structure for the driver instance.
671 : * @param channel Numeric identification of the channel where the transfer was
672 : * being processed
673 : * @param stat a non-NULL dma_status object for storing DMA status
674 : *
675 : * @retval non-negative if successful.
676 : * @retval Negative errno code if failure.
677 : */
678 1 : static inline int dma_get_status(const struct device *dev, uint32_t channel,
679 : struct dma_status *stat)
680 : {
681 : const struct dma_driver_api *api =
682 : (const struct dma_driver_api *)dev->api;
683 :
684 : if (api->get_status) {
685 : return api->get_status(dev, channel, stat);
686 : }
687 :
688 : return -ENOSYS;
689 : }
690 :
691 : /**
692 : * @brief get attribute of a dma controller
693 : *
694 : * This function allows to get a device specific static or runtime attribute like required address
695 : * and size alignment of a buffer.
696 : * Implementations must check the validity of the type passed in and
697 : * return -EINVAL if it is invalid or -ENOSYS if not supported.
698 : *
699 : * @funcprops \isr_ok
700 : *
701 : * @param dev Pointer to the device structure for the driver instance.
702 : * @param type Numeric identification of the attribute
703 : * @param value A non-NULL pointer to the variable where the read value is to be placed
704 : *
705 : * @retval non-negative if successful.
706 : * @retval Negative errno code if failure.
707 : */
708 1 : static inline int dma_get_attribute(const struct device *dev, uint32_t type, uint32_t *value)
709 : {
710 : const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api;
711 :
712 : if (api->get_attribute) {
713 : return api->get_attribute(dev, type, value);
714 : }
715 :
716 : return -ENOSYS;
717 : }
718 :
719 : /**
720 : * @brief Look-up generic width index to be used in registers
721 : *
722 : * @warning This look-up works for most controllers, but *may* not work for
723 : * yours. Ensure your controller expects the most common register
724 : * bit values before using this convenience function. If your
725 : * controller does not support these values, you will have to write
726 : * your own look-up inside the controller driver.
727 : *
728 : * @param size: width of bus (in bytes)
729 : *
730 : * @retval common DMA index to be placed into registers.
731 : */
732 1 : static inline uint32_t dma_width_index(uint32_t size)
733 : {
734 : /* Check boundaries (max supported width is 32 Bytes) */
735 : if (size < 1 || size > 32) {
736 : return 0; /* Zero is the default (8 Bytes) */
737 : }
738 :
739 : /* Ensure size is a power of 2 */
740 : if (!is_power_of_two(size)) {
741 : return 0; /* Zero is the default (8 Bytes) */
742 : }
743 :
744 : /* Convert to bit pattern for writing to a register */
745 : return find_msb_set(size);
746 : }
747 :
748 : /**
749 : * @brief Look-up generic burst index to be used in registers
750 : *
751 : * @warning This look-up works for most controllers, but *may* not work for
752 : * yours. Ensure your controller expects the most common register
753 : * bit values before using this convenience function. If your
754 : * controller does not support these values, you will have to write
755 : * your own look-up inside the controller driver.
756 : *
757 : * @param burst: number of bytes to be sent in a single burst
758 : *
759 : * @retval common DMA index to be placed into registers.
760 : */
761 1 : static inline uint32_t dma_burst_index(uint32_t burst)
762 : {
763 : /* Check boundaries (max supported burst length is 256) */
764 : if (burst < 1 || burst > 256) {
765 : return 0; /* Zero is the default (1 burst length) */
766 : }
767 :
768 : /* Ensure burst is a power of 2 */
769 : if (!(burst & (burst - 1))) {
770 : return 0; /* Zero is the default (1 burst length) */
771 : }
772 :
773 : /* Convert to bit pattern for writing to a register */
774 : return find_msb_set(burst);
775 : }
776 :
777 : /**
778 : * @brief Get the device tree property describing the buffer address alignment
779 : *
780 : * Useful when statically defining or allocating buffers for DMA usage where
781 : * memory alignment often matters.
782 : *
783 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
784 : * @return alignment Memory byte alignment required for DMA buffers
785 : */
786 1 : #define DMA_BUF_ADDR_ALIGNMENT(node) DT_PROP(node, dma_buf_addr_alignment)
787 :
788 : /**
789 : * @brief Get the device tree property describing the buffer size alignment
790 : *
791 : * Useful when statically defining or allocating buffers for DMA usage where
792 : * memory alignment often matters.
793 : *
794 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
795 : * @return alignment Memory byte alignment required for DMA buffers
796 : */
797 1 : #define DMA_BUF_SIZE_ALIGNMENT(node) DT_PROP(node, dma_buf_size_alignment)
798 :
799 : /**
800 : * @brief Get the device tree property describing the minimal chunk of data possible to be copied
801 : *
802 : * @param node Node identifier, e.g. DT_NODELABEL(dma_0)
803 : * @return minimal Minimal chunk of data possible to be copied
804 : */
805 1 : #define DMA_COPY_ALIGNMENT(node) DT_PROP(node, dma_copy_alignment)
806 :
807 : /**
808 : * @}
809 : */
810 :
811 : #ifdef __cplusplus
812 : }
813 : #endif
814 :
815 : #include <zephyr/syscalls/dma.h>
816 :
817 : #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_H_ */
|