LCOV - code coverage report
Current view: top level - zephyr/drivers - dma.h Coverage Total Hit
Test: new.info Lines: 97.3 % 74 72
Test Date: 2025-09-05 16:43:28

            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_ */
        

Generated by: LCOV version 2.0-1