| /** |
| * @file |
| * |
| * @brief Public APIs for the DMA drivers. |
| */ |
| |
| /* |
| * Copyright (c) 2016 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_H_ |
| #define ZEPHYR_INCLUDE_DRIVERS_DMA_H_ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/device.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| /** |
| * @brief DMA Interface |
| * @defgroup dma_interface DMA Interface |
| * @since 1.5 |
| * @version 1.0.0 |
| * @ingroup io_interfaces |
| * @{ |
| */ |
| |
| /** |
| * @brief DMA channel direction |
| */ |
| enum dma_channel_direction { |
| /** Memory to memory */ |
| MEMORY_TO_MEMORY = 0x0, |
| /** Memory to peripheral */ |
| MEMORY_TO_PERIPHERAL, |
| /** Peripheral to memory */ |
| PERIPHERAL_TO_MEMORY, |
| /** Peripheral to peripheral */ |
| PERIPHERAL_TO_PERIPHERAL, |
| /** Host to memory */ |
| HOST_TO_MEMORY, |
| /** Memory to host */ |
| MEMORY_TO_HOST, |
| |
| /** |
| * Number of all common channel directions. |
| */ |
| DMA_CHANNEL_DIRECTION_COMMON_COUNT, |
| |
| /** |
| * This and higher values are dma controller or soc specific. |
| * Refer to the specified dma driver header file. |
| */ |
| DMA_CHANNEL_DIRECTION_PRIV_START = DMA_CHANNEL_DIRECTION_COMMON_COUNT, |
| |
| /** |
| * Maximum allowed value (3 bit field!) |
| */ |
| DMA_CHANNEL_DIRECTION_MAX = 0x7 |
| }; |
| |
| /** |
| * @brief DMA address adjustment |
| * |
| * Valid values for @a source_addr_adj and @a dest_addr_adj |
| */ |
| enum dma_addr_adj { |
| /** Increment the address */ |
| DMA_ADDR_ADJ_INCREMENT, |
| /** Decrement the address */ |
| DMA_ADDR_ADJ_DECREMENT, |
| /** No change the address */ |
| DMA_ADDR_ADJ_NO_CHANGE, |
| }; |
| |
| /** |
| * @brief DMA channel attributes |
| */ |
| enum dma_channel_filter { |
| DMA_CHANNEL_NORMAL, /* normal DMA channel */ |
| DMA_CHANNEL_PERIODIC, /* can be triggered by periodic sources */ |
| }; |
| |
| /** |
| * @brief DMA attributes |
| */ |
| enum dma_attribute_type { |
| DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, |
| DMA_ATTR_BUFFER_SIZE_ALIGNMENT, |
| DMA_ATTR_COPY_ALIGNMENT, |
| DMA_ATTR_MAX_BLOCK_COUNT, |
| }; |
| |
| /** |
| * @struct dma_block_config |
| * @brief DMA block configuration structure. |
| * |
| * Aside from source address, destination address, and block size many of these options are hardware |
| * and driver dependent. |
| */ |
| struct dma_block_config { |
| #ifdef CONFIG_DMA_64BIT |
| /** block starting address at source */ |
| uint64_t source_address; |
| /** block starting address at destination */ |
| uint64_t dest_address; |
| #else |
| /** block starting address at source */ |
| uint32_t source_address; |
| /** block starting address at destination */ |
| uint32_t dest_address; |
| #endif |
| /** Address adjustment at gather boundary */ |
| uint32_t source_gather_interval; |
| /** Address adjustment at scatter boundary */ |
| uint32_t dest_scatter_interval; |
| /** Continuous transfer count between scatter boundaries */ |
| uint16_t dest_scatter_count; |
| /** Continuous transfer count between gather boundaries */ |
| uint16_t source_gather_count; |
| /** Number of bytes to be transferred for this block */ |
| uint32_t block_size; |
| /** Pointer to next block in a transfer list */ |
| struct dma_block_config *next_block; |
| /** Enable source gathering when set to 1 */ |
| uint16_t source_gather_en : 1; |
| /** Enable destination scattering when set to 1 */ |
| uint16_t dest_scatter_en : 1; |
| /** |
| * Source address adjustment option |
| * |
| * - 0b00 increment |
| * - 0b01 decrement |
| * - 0b10 no change |
| */ |
| uint16_t source_addr_adj : 2; |
| /** |
| * Destination address adjustment |
| * |
| * - 0b00 increment |
| * - 0b01 decrement |
| * - 0b10 no change |
| */ |
| uint16_t dest_addr_adj : 2; |
| /** Reload source address at the end of block transfer */ |
| uint16_t source_reload_en : 1; |
| /** Reload destination address at the end of block transfer */ |
| uint16_t dest_reload_en : 1; |
| /** FIFO fill before starting transfer, HW specific meaning */ |
| uint16_t fifo_mode_control : 4; |
| /** |
| * Transfer flow control mode |
| * |
| * - 0b0 source request service upon data availability |
| * - 0b1 source request postponed until destination request happens |
| */ |
| uint16_t flow_control_mode : 1; |
| |
| uint16_t _reserved : 3; |
| }; |
| |
| /** The DMA callback event has occurred at the completion of a transfer list */ |
| #define DMA_STATUS_COMPLETE 0 |
| /** The DMA callback has occurred at the completion of a single transfer block in a transfer list */ |
| #define DMA_STATUS_BLOCK 1 |
| |
| /** |
| * @typedef dma_callback_t |
| * @brief Callback function for DMA transfer completion |
| * |
| * If enabled, callback function will be invoked at transfer or block completion, |
| * or when an error happens. |
| * In circular mode, @p status indicates that the DMA device has reached either |
| * the end of the buffer (DMA_STATUS_COMPLETE) or a water mark (DMA_STATUS_BLOCK). |
| * |
| * @param dev Pointer to the DMA device calling the callback. |
| * @param user_data A pointer to some user data or NULL |
| * @param channel The channel number |
| * @param status Status of the transfer |
| * - DMA_STATUS_COMPLETE buffer fully consumed |
| * - DMA_STATUS_BLOCK buffer consumption reached a configured block |
| * or water mark |
| * - A negative errno otherwise |
| */ |
| typedef void (*dma_callback_t)(const struct device *dev, void *user_data, |
| uint32_t channel, int status); |
| |
| /** |
| * @struct dma_config |
| * @brief DMA configuration structure. |
| */ |
| struct dma_config { |
| /** Which peripheral and direction, HW specific */ |
| uint32_t dma_slot : 8; |
| /** |
| * Direction the transfers are occurring |
| * |
| * - 0b000 memory to memory, |
| * - 0b001 memory to peripheral, |
| * - 0b010 peripheral to memory, |
| * - 0b011 peripheral to peripheral, |
| * - 0b100 host to memory |
| * - 0b101 memory to host |
| * - others hardware specific |
| */ |
| uint32_t channel_direction : 3; |
| /** |
| * Completion callback enable |
| * |
| * - 0b0 callback invoked at transfer list completion only |
| * - 0b1 callback invoked at completion of each block |
| */ |
| uint32_t complete_callback_en : 1; |
| /** |
| * Error callback disable |
| * |
| * - 0b0 error callback enabled |
| * - 0b1 error callback disabled |
| */ |
| uint32_t error_callback_dis : 1; |
| /** |
| * Source handshake, HW specific |
| * |
| * - 0b0 HW |
| * - 0b1 SW |
| */ |
| uint32_t source_handshake : 1; |
| /** |
| * Destination handshake, HW specific |
| * |
| * - 0b0 HW |
| * - 0b1 SW |
| */ |
| uint32_t dest_handshake : 1; |
| /** |
| * Channel priority for arbitration, HW specific |
| */ |
| uint32_t channel_priority : 4; |
| /** Source chaining enable, HW specific */ |
| uint32_t source_chaining_en : 1; |
| /** Destination chaining enable, HW specific */ |
| uint32_t dest_chaining_en : 1; |
| /** Linked channel, HW specific */ |
| uint32_t linked_channel : 7; |
| /** Cyclic transfer list, HW specific */ |
| uint32_t cyclic : 1; |
| |
| uint32_t _reserved : 3; |
| /** Width of source data (in bytes) */ |
| uint32_t source_data_size : 16; |
| /** Width of destination data (in bytes) */ |
| uint32_t dest_data_size : 16; |
| /** Source burst length in bytes */ |
| uint32_t source_burst_length : 16; |
| /** Destination burst length in bytes */ |
| uint32_t dest_burst_length : 16; |
| /** Number of blocks in transfer list */ |
| uint32_t block_count; |
| /** Pointer to the first block in the transfer list */ |
| struct dma_block_config *head_block; |
| /** Optional attached user data for callbacks */ |
| void *user_data; |
| /** Optional callback for completion and error events */ |
| dma_callback_t dma_callback; |
| }; |
| |
| /** |
| * DMA runtime status structure |
| */ |
| struct dma_status { |
| /** Is the current DMA transfer busy or idle */ |
| bool busy; |
| /** Direction for the transfer */ |
| enum dma_channel_direction dir; |
| /** Pending length to be transferred in bytes, HW specific */ |
| uint32_t pending_length; |
| /** Available buffers space, HW specific */ |
| uint32_t free; |
| /** Write position in circular DMA buffer, HW specific */ |
| uint32_t write_position; |
| /** Read position in circular DMA buffer, HW specific */ |
| uint32_t read_position; |
| /** Total copied, HW specific */ |
| uint64_t total_copied; |
| }; |
| |
| /** |
| * DMA context structure |
| * Note: the dma_context shall be the first member |
| * of DMA client driver Data, got by dev->data |
| */ |
| struct dma_context { |
| /** magic code to identify the context */ |
| int32_t magic; |
| /** number of dma channels */ |
| int dma_channels; |
| /** atomic holding bit flags for each channel to mark as used/unused */ |
| atomic_t *atomic; |
| }; |
| |
| /** Magic code to identify context content */ |
| #define DMA_MAGIC 0x47494749 |
| |
| /** |
| * @cond INTERNAL_HIDDEN |
| * |
| * These are for internal use only, so skip these in |
| * public documentation. |
| */ |
| typedef int (*dma_api_config)(const struct device *dev, uint32_t channel, |
| struct dma_config *config); |
| |
| #ifdef CONFIG_DMA_64BIT |
| typedef int (*dma_api_reload)(const struct device *dev, uint32_t channel, |
| uint64_t src, uint64_t dst, size_t size); |
| #else |
| typedef int (*dma_api_reload)(const struct device *dev, uint32_t channel, |
| uint32_t src, uint32_t dst, size_t size); |
| #endif |
| |
| typedef int (*dma_api_start)(const struct device *dev, uint32_t channel); |
| |
| typedef int (*dma_api_stop)(const struct device *dev, uint32_t channel); |
| |
| typedef int (*dma_api_suspend)(const struct device *dev, uint32_t channel); |
| |
| typedef int (*dma_api_resume)(const struct device *dev, uint32_t channel); |
| |
| typedef int (*dma_api_get_status)(const struct device *dev, uint32_t channel, |
| struct dma_status *status); |
| |
| typedef int (*dma_api_get_attribute)(const struct device *dev, uint32_t type, uint32_t *value); |
| |
| /** |
| * @typedef dma_chan_filter |
| * @brief channel filter function call |
| * |
| * filter function that is used to find the matched internal dma channel |
| * provide by caller |
| * |
| * @param dev Pointer to the DMA device instance |
| * @param channel the channel id to use |
| * @param filter_param filter function parameter, can be NULL |
| * |
| * @retval True on filter matched otherwise return False. |
| */ |
| typedef bool (*dma_api_chan_filter)(const struct device *dev, |
| int channel, void *filter_param); |
| |
| /** |
| * @typedef dma_chan_release |
| * @brief channel release function call |
| * |
| * used to release channel resources "allocated" during the |
| * request phase. These resources can refer to enabled PDs, IRQs |
| * etc... |
| * |
| * @param dev Pointer to the DMA device instance |
| * @param channel channel id to use |
| */ |
| typedef void (*dma_api_chan_release)(const struct device *dev, |
| uint32_t channel); |
| |
| __subsystem struct dma_driver_api { |
| dma_api_config config; |
| dma_api_reload reload; |
| dma_api_start start; |
| dma_api_stop stop; |
| dma_api_suspend suspend; |
| dma_api_resume resume; |
| dma_api_get_status get_status; |
| dma_api_get_attribute get_attribute; |
| dma_api_chan_filter chan_filter; |
| dma_api_chan_release chan_release; |
| }; |
| /** |
| * @endcond |
| */ |
| |
| /** |
| * @brief Configure individual channel for DMA transfer. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel to configure |
| * @param config Data structure containing the intended configuration for the |
| * selected channel |
| * |
| * @retval 0 if successful. |
| * @retval Negative errno code if failure. |
| */ |
| static inline int dma_config(const struct device *dev, uint32_t channel, |
| struct dma_config *config) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| return api->config(dev, channel, config); |
| } |
| |
| /** |
| * @brief Reload buffer(s) for a DMA channel |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel to configure |
| * selected channel |
| * @param src source address for the DMA transfer |
| * @param dst destination address for the DMA transfer |
| * @param size size of DMA transfer |
| * |
| * @retval 0 if successful. |
| * @retval Negative errno code if failure. |
| */ |
| #ifdef CONFIG_DMA_64BIT |
| static inline int dma_reload(const struct device *dev, uint32_t channel, |
| uint64_t src, uint64_t dst, size_t size) |
| #else |
| static inline int dma_reload(const struct device *dev, uint32_t channel, |
| uint32_t src, uint32_t dst, size_t size) |
| #endif |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| if (api->reload) { |
| return api->reload(dev, channel, src, dst, size); |
| } |
| |
| return -ENOSYS; |
| } |
| |
| /** |
| * @brief Enables DMA channel and starts the transfer, the channel must be |
| * configured beforehand. |
| * |
| * Implementations must check the validity of the channel ID passed in and |
| * return -EINVAL if it is invalid. |
| * |
| * Start is allowed on channels that have already been started and must report |
| * success. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel where the transfer will |
| * be processed |
| * |
| * @retval 0 if successful. |
| * @retval Negative errno code if failure. |
| */ |
| __syscall int dma_start(const struct device *dev, uint32_t channel); |
| |
| static inline int z_impl_dma_start(const struct device *dev, uint32_t channel) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| return api->start(dev, channel); |
| } |
| |
| /** |
| * @brief Stops the DMA transfer and disables the channel. |
| * |
| * Implementations must check the validity of the channel ID passed in and |
| * return -EINVAL if it is invalid. |
| * |
| * Stop is allowed on channels that have already been stopped and must report |
| * success. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel where the transfer was |
| * being processed |
| * |
| * @retval 0 if successful. |
| * @retval Negative errno code if failure. |
| */ |
| __syscall int dma_stop(const struct device *dev, uint32_t channel); |
| |
| static inline int z_impl_dma_stop(const struct device *dev, uint32_t channel) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| return api->stop(dev, channel); |
| } |
| |
| |
| /** |
| * @brief Suspend a DMA channel transfer |
| * |
| * Implementations must check the validity of the channel state and ID passed |
| * in and return -EINVAL if either are invalid. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel to suspend |
| * |
| * @retval 0 If successful. |
| * @retval -ENOSYS If not implemented. |
| * @retval -EINVAL If invalid channel id or state. |
| * @retval -errno Other negative errno code failure. |
| */ |
| __syscall int dma_suspend(const struct device *dev, uint32_t channel); |
| |
| static inline int z_impl_dma_suspend(const struct device *dev, uint32_t channel) |
| { |
| const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api; |
| |
| if (api->suspend == NULL) { |
| return -ENOSYS; |
| } |
| return api->suspend(dev, channel); |
| } |
| |
| /** |
| * @brief Resume a DMA channel transfer |
| * |
| * Implementations must check the validity of the channel state and ID passed |
| * in and return -EINVAL if either are invalid. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel to resume |
| * |
| * @retval 0 If successful. |
| * @retval -ENOSYS If not implemented |
| * @retval -EINVAL If invalid channel id or state. |
| * @retval -errno Other negative errno code failure. |
| */ |
| __syscall int dma_resume(const struct device *dev, uint32_t channel); |
| |
| static inline int z_impl_dma_resume(const struct device *dev, uint32_t channel) |
| { |
| const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api; |
| |
| if (api->resume == NULL) { |
| return -ENOSYS; |
| } |
| return api->resume(dev, channel); |
| } |
| |
| /** |
| * @brief request DMA channel. |
| * |
| * request DMA channel resources |
| * return -EINVAL if there is no valid channel available. |
| * |
| * @note It is safe to use this function in contexts where blocking |
| * is not allowed, e.g. ISR, provided the implementation of the filter |
| * function does not block. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param filter_param filter function parameter |
| * |
| * @retval dma channel if successful. |
| * @retval Negative errno code if failure. |
| */ |
| __syscall int dma_request_channel(const struct device *dev, |
| void *filter_param); |
| |
| static inline int z_impl_dma_request_channel(const struct device *dev, |
| void *filter_param) |
| { |
| int i = 0; |
| int channel = -EINVAL; |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| /* dma_context shall be the first one in dev data */ |
| struct dma_context *dma_ctx = (struct dma_context *)dev->data; |
| |
| if (dma_ctx->magic != DMA_MAGIC) { |
| return channel; |
| } |
| |
| for (i = 0; i < dma_ctx->dma_channels; i++) { |
| if (!atomic_test_and_set_bit(dma_ctx->atomic, i)) { |
| if (api->chan_filter && |
| !api->chan_filter(dev, i, filter_param)) { |
| atomic_clear_bit(dma_ctx->atomic, i); |
| continue; |
| } |
| channel = i; |
| break; |
| } |
| } |
| |
| return channel; |
| } |
| |
| /** |
| * @brief release DMA channel. |
| * |
| * release DMA channel resources |
| * |
| * @note It is safe to use this function in contexts where blocking |
| * is not allowed, e.g. ISR, provided the implementation of the release |
| * function does not block. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel channel number |
| * |
| */ |
| __syscall void dma_release_channel(const struct device *dev, |
| uint32_t channel); |
| |
| static inline void z_impl_dma_release_channel(const struct device *dev, |
| uint32_t channel) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| struct dma_context *dma_ctx = (struct dma_context *)dev->data; |
| |
| if (dma_ctx->magic != DMA_MAGIC) { |
| return; |
| } |
| |
| if ((int)channel < dma_ctx->dma_channels) { |
| if (api->chan_release) { |
| api->chan_release(dev, channel); |
| } |
| |
| atomic_clear_bit(dma_ctx->atomic, channel); |
| } |
| |
| } |
| |
| /** |
| * @brief DMA channel filter. |
| * |
| * filter channel by attribute |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel channel number |
| * @param filter_param filter attribute |
| * |
| * @retval Negative errno code if not support |
| * |
| */ |
| __syscall int dma_chan_filter(const struct device *dev, |
| int channel, void *filter_param); |
| |
| static inline int z_impl_dma_chan_filter(const struct device *dev, |
| int channel, void *filter_param) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| if (api->chan_filter) { |
| return api->chan_filter(dev, channel, filter_param); |
| } |
| |
| return -ENOSYS; |
| } |
| |
| /** |
| * @brief get current runtime status of DMA transfer |
| * |
| * Implementations must check the validity of the channel ID passed in and |
| * return -EINVAL if it is invalid or -ENOSYS if not supported. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param channel Numeric identification of the channel where the transfer was |
| * being processed |
| * @param stat a non-NULL dma_status object for storing DMA status |
| * |
| * @retval non-negative if successful. |
| * @retval Negative errno code if failure. |
| */ |
| static inline int dma_get_status(const struct device *dev, uint32_t channel, |
| struct dma_status *stat) |
| { |
| const struct dma_driver_api *api = |
| (const struct dma_driver_api *)dev->api; |
| |
| if (api->get_status) { |
| return api->get_status(dev, channel, stat); |
| } |
| |
| return -ENOSYS; |
| } |
| |
| /** |
| * @brief get attribute of a dma controller |
| * |
| * This function allows to get a device specific static or runtime attribute like required address |
| * and size alignment of a buffer. |
| * Implementations must check the validity of the type passed in and |
| * return -EINVAL if it is invalid or -ENOSYS if not supported. |
| * |
| * @funcprops \isr_ok |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param type Numeric identification of the attribute |
| * @param value A non-NULL pointer to the variable where the read value is to be placed |
| * |
| * @retval non-negative if successful. |
| * @retval Negative errno code if failure. |
| */ |
| static inline int dma_get_attribute(const struct device *dev, uint32_t type, uint32_t *value) |
| { |
| const struct dma_driver_api *api = (const struct dma_driver_api *)dev->api; |
| |
| if (api->get_attribute) { |
| return api->get_attribute(dev, type, value); |
| } |
| |
| return -ENOSYS; |
| } |
| |
| /** |
| * @brief Look-up generic width index to be used in registers |
| * |
| * @warning This look-up works for most controllers, but *may* not work for |
| * yours. Ensure your controller expects the most common register |
| * bit values before using this convenience function. If your |
| * controller does not support these values, you will have to write |
| * your own look-up inside the controller driver. |
| * |
| * @param size: width of bus (in bytes) |
| * |
| * @retval common DMA index to be placed into registers. |
| */ |
| static inline uint32_t dma_width_index(uint32_t size) |
| { |
| /* Check boundaries (max supported width is 32 Bytes) */ |
| if (size < 1 || size > 32) { |
| return 0; /* Zero is the default (8 Bytes) */ |
| } |
| |
| /* Ensure size is a power of 2 */ |
| if (!is_power_of_two(size)) { |
| return 0; /* Zero is the default (8 Bytes) */ |
| } |
| |
| /* Convert to bit pattern for writing to a register */ |
| return find_msb_set(size); |
| } |
| |
| /** |
| * @brief Look-up generic burst index to be used in registers |
| * |
| * @warning This look-up works for most controllers, but *may* not work for |
| * yours. Ensure your controller expects the most common register |
| * bit values before using this convenience function. If your |
| * controller does not support these values, you will have to write |
| * your own look-up inside the controller driver. |
| * |
| * @param burst: number of bytes to be sent in a single burst |
| * |
| * @retval common DMA index to be placed into registers. |
| */ |
| static inline uint32_t dma_burst_index(uint32_t burst) |
| { |
| /* Check boundaries (max supported burst length is 256) */ |
| if (burst < 1 || burst > 256) { |
| return 0; /* Zero is the default (1 burst length) */ |
| } |
| |
| /* Ensure burst is a power of 2 */ |
| if (!(burst & (burst - 1))) { |
| return 0; /* Zero is the default (1 burst length) */ |
| } |
| |
| /* Convert to bit pattern for writing to a register */ |
| return find_msb_set(burst); |
| } |
| |
| /** |
| * @brief Get the device tree property describing the buffer address alignment |
| * |
| * Useful when statically defining or allocating buffers for DMA usage where |
| * memory alignment often matters. |
| * |
| * @param node Node identifier, e.g. DT_NODELABEL(dma_0) |
| * @return alignment Memory byte alignment required for DMA buffers |
| */ |
| #define DMA_BUF_ADDR_ALIGNMENT(node) DT_PROP(node, dma_buf_addr_alignment) |
| |
| /** |
| * @brief Get the device tree property describing the buffer size alignment |
| * |
| * Useful when statically defining or allocating buffers for DMA usage where |
| * memory alignment often matters. |
| * |
| * @param node Node identifier, e.g. DT_NODELABEL(dma_0) |
| * @return alignment Memory byte alignment required for DMA buffers |
| */ |
| #define DMA_BUF_SIZE_ALIGNMENT(node) DT_PROP(node, dma_buf_size_alignment) |
| |
| /** |
| * @brief Get the device tree property describing the minimal chunk of data possible to be copied |
| * |
| * @param node Node identifier, e.g. DT_NODELABEL(dma_0) |
| * @return minimal Minimal chunk of data possible to be copied |
| */ |
| #define DMA_COPY_ALIGNMENT(node) DT_PROP(node, dma_copy_alignment) |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #include <zephyr/syscalls/dma.h> |
| |
| #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_H_ */ |