diff options
| author | GUI <[email protected]> | 2024-11-22 14:11:40 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-11-22 14:11:40 +0800 |
| commit | c05526117770a45a1450eef2140d1107b349e499 (patch) | |
| tree | d5e5dd9d23bd044f091b76fe556af326bab44153 /components/drivers/include | |
| parent | dd709c1cea4289d841dda413c60e90dbc5ec6193 (diff) | |
[DM/FEATURE] Support DMA management (#9682)
1. DMA pool management for platform.
2. DMA engine driver API.
Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'components/drivers/include')
| -rw-r--r-- | components/drivers/include/drivers/dma.h | 235 | ||||
| -rw-r--r-- | components/drivers/include/rtdevice.h | 4 |
2 files changed, 239 insertions, 0 deletions
diff --git a/components/drivers/include/drivers/dma.h b/components/drivers/include/drivers/dma.h new file mode 100644 index 0000000000..16f02c3df7 --- /dev/null +++ b/components/drivers/include/drivers/dma.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI the first version + */ + +#ifndef __DMA_H__ +#define __DMA_H__ + +#include <rtthread.h> +#include <drivers/ofw.h> +#include <drivers/misc.h> +#include <drivers/core/dm.h> + +#include <mmu.h> +#include <mm_page.h> +#include <bitmap.h> + +struct rt_dma_chan; +struct rt_dma_controller_ops; + +enum rt_dma_transfer_direction +{ + RT_DMA_MEM_TO_MEM, + RT_DMA_MEM_TO_DEV, + RT_DMA_DEV_TO_MEM, + RT_DMA_DEV_TO_DEV, + + RT_DMA_DIR_MAX, +}; + +enum rt_dma_slave_buswidth +{ + RT_DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, + RT_DMA_SLAVE_BUSWIDTH_1_BYTE = 1, + RT_DMA_SLAVE_BUSWIDTH_2_BYTES = 2, + RT_DMA_SLAVE_BUSWIDTH_3_BYTES = 3, + RT_DMA_SLAVE_BUSWIDTH_4_BYTES = 4, + RT_DMA_SLAVE_BUSWIDTH_8_BYTES = 8, + RT_DMA_SLAVE_BUSWIDTH_16_BYTES = 16, + RT_DMA_SLAVE_BUSWIDTH_32_BYTES = 32, + RT_DMA_SLAVE_BUSWIDTH_64_BYTES = 64, + RT_DMA_SLAVE_BUSWIDTH_128_BYTES = 128, + + RT_DMA_SLAVE_BUSWIDTH_BYTES_MAX, +}; + +struct rt_dma_slave_config +{ + enum rt_dma_transfer_direction direction; + enum rt_dma_slave_buswidth src_addr_width; + enum rt_dma_slave_buswidth dst_addr_width; + + rt_ubase_t src_addr; + rt_ubase_t dst_addr; + + rt_uint32_t src_maxburst; + rt_uint32_t dst_maxburst; + rt_uint32_t src_port_window_size; + rt_uint32_t dst_port_window_size; +}; + +struct rt_dma_slave_transfer +{ + rt_ubase_t src_addr; + rt_ubase_t dst_addr; + + void *buffer; + rt_ubase_t dma_handle; + rt_size_t buffer_len; + rt_size_t period_len; +}; + +struct rt_dma_controller +{ + rt_list_t list; + + struct rt_device *dev; + + RT_BITMAP_DECLARE(dir_cap, RT_DMA_DIR_MAX); + const struct rt_dma_controller_ops *ops; + + rt_list_t channels_nodes; + struct rt_mutex mutex; +}; + +struct rt_dma_controller_ops +{ + struct rt_dma_chan *(*request_chan)(struct rt_dma_controller *ctrl, struct rt_device *slave); + rt_err_t (*release_chan)(struct rt_dma_chan *chan); + + rt_err_t (*start)(struct rt_dma_chan *chan); + rt_err_t (*stop)(struct rt_dma_chan *chan); + rt_err_t (*config)(struct rt_dma_chan *chan, struct rt_dma_slave_config *conf); + + rt_err_t (*prep_memcpy)(struct rt_dma_chan *chan, + rt_ubase_t dma_addr_src, rt_ubase_t dma_addr_dst, rt_size_t len); + + rt_err_t (*prep_cyclic)(struct rt_dma_chan *chan, + rt_ubase_t dma_buf_addr, rt_size_t buf_len, rt_size_t period_len, + enum rt_dma_transfer_direction dir); + + rt_err_t (*prep_single)(struct rt_dma_chan *chan, + rt_ubase_t dma_buf_addr, rt_size_t buf_len, + enum rt_dma_transfer_direction dir); + + rt_err_t (*ofw_parse)(struct rt_dma_controller *ctrl, struct rt_ofw_cell_args *dma_args); +}; + +struct rt_dma_chan +{ + const char *name; + + struct rt_dma_controller *ctrl; + struct rt_device *slave; + + rt_list_t list; + rt_err_t conf_err; + rt_err_t prep_err; + struct rt_dma_slave_config conf; + struct rt_dma_slave_transfer transfer; + + void (*callback)(struct rt_dma_chan *chan, rt_size_t size); + + void *priv; +}; + +struct rt_dma_pool +{ + rt_region_t region; + + rt_list_t list; + + rt_ubase_t flags; + + rt_bitmap_t *map; + rt_size_t bits; + rt_ubase_t start; + + struct rt_device *dev; +}; + +struct rt_dma_map_ops +{ + void *(*alloc)(struct rt_device *dev, rt_size_t size, + rt_ubase_t *dma_handle, rt_ubase_t flags); + void (*free)(struct rt_device *dev, rt_size_t size, + void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags); + rt_err_t (*sync_out_data)(struct rt_device *dev, void *data, rt_size_t size, + rt_ubase_t *dma_handle, rt_ubase_t flags); + rt_err_t (*sync_in_data)(struct rt_device *dev, void *out_data, rt_size_t size, + rt_ubase_t dma_handle, rt_ubase_t flags); +}; + +rt_inline void rt_dma_controller_add_direction(struct rt_dma_controller *ctrl, + enum rt_dma_transfer_direction dir) +{ + RT_ASSERT(ctrl != RT_NULL); + RT_ASSERT(dir < RT_DMA_DIR_MAX); + + rt_bitmap_set_bit(ctrl->dir_cap, dir); +} + +rt_err_t rt_dma_controller_register(struct rt_dma_controller *ctrl); +rt_err_t rt_dma_controller_unregister(struct rt_dma_controller *ctrl); + +rt_err_t rt_dma_chan_start(struct rt_dma_chan *chan); +rt_err_t rt_dma_chan_stop(struct rt_dma_chan *chan); +rt_err_t rt_dma_chan_config(struct rt_dma_chan *chan, + struct rt_dma_slave_config *conf); +rt_err_t rt_dma_chan_done(struct rt_dma_chan *chan, rt_size_t size); + +rt_err_t rt_dma_prep_memcpy(struct rt_dma_chan *chan, + struct rt_dma_slave_transfer *transfer); +rt_err_t rt_dma_prep_cyclic(struct rt_dma_chan *chan, + struct rt_dma_slave_transfer *transfer); +rt_err_t rt_dma_prep_single(struct rt_dma_chan *chan, + struct rt_dma_slave_transfer *transfer); + +struct rt_dma_chan *rt_dma_chan_request(struct rt_device *dev, const char *name); +rt_err_t rt_dma_chan_release(struct rt_dma_chan *chan); + +#define RT_DMA_F_LINEAR RT_BIT(0) +#define RT_DMA_F_32BITS RT_BIT(1) +#define RT_DMA_F_NOCACHE RT_BIT(2) +#define RT_DMA_F_DEVICE RT_BIT(3) +#define RT_DMA_F_NOMAP RT_BIT(4) + +#define RT_DMA_PAGE_SIZE ARCH_PAGE_SIZE + +void *rt_dma_alloc(struct rt_device *dev, rt_size_t size, + rt_ubase_t *dma_handle, rt_ubase_t flags); + +void rt_dma_free(struct rt_device *dev, rt_size_t size, + void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags); + +rt_inline void *rt_dma_alloc_coherent(struct rt_device *dev, rt_size_t size, + rt_ubase_t *dma_handle) +{ + return rt_dma_alloc(dev, size, dma_handle, + RT_DMA_F_NOCACHE | RT_DMA_F_LINEAR); +} + +rt_inline void rt_dma_free_coherent(struct rt_device *dev, rt_size_t size, + void *cpu_addr, rt_ubase_t dma_handle) +{ + rt_dma_free(dev, size, cpu_addr, dma_handle, + RT_DMA_F_NOCACHE | RT_DMA_F_LINEAR); +} + +rt_err_t rt_dma_sync_out_data(struct rt_device *dev, void *data, rt_size_t size, + rt_ubase_t *dma_handle, rt_ubase_t flags); +rt_err_t rt_dma_sync_in_data(struct rt_device *dev, void *out_data, rt_size_t size, + rt_ubase_t dma_handle, rt_ubase_t flags); + +rt_inline rt_bool_t rt_dma_device_is_coherent(struct rt_device *dev) +{ + return rt_dm_dev_prop_read_bool(dev, "dma-coherent"); +} + +rt_inline void rt_dma_device_set_ops(struct rt_device *dev, + const struct rt_dma_map_ops *ops) +{ + dev->dma_ops = ops; +} + +struct rt_dma_pool *rt_dma_pool_install(rt_region_t *region); +rt_err_t rt_dma_pool_extract(rt_region_t *region_list, rt_size_t list_len, + rt_size_t cma_size, rt_size_t coherent_pool_size); + +#endif /* __DMA_H__ */ diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index ff7a17734f..f6a3cfb9cf 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -49,6 +49,10 @@ extern "C" { #include "drivers/blk.h" #endif +#ifdef RT_USING_DMA +#include "drivers/dma.h" +#endif + #include "drivers/iio.h" #ifdef RT_USING_OFW |
