[DM/FEATURE] Support DMA management (#9682)

1. DMA pool management for platform.
2. DMA engine driver API.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GUI
2024-11-22 14:11:40 +08:00
committed by GitHub
parent dd709c1cea
commit c055261177
7 changed files with 1546 additions and 0 deletions
+235
View File
@@ -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__ */
+4
View File
@@ -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