rt-thread/bsp/phytium/libraries/standalone/drivers/dma/fgdma/fgdma.h

266 lines
9.6 KiB
C
Raw Normal View History

/*
* Copyright : (C) 2022 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Phytium Public License for more details.
*
*
* FilePath: fgdma.h
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 08:25:35
* Description:  This files is for gdma user api implementation
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 huanghe 2021-11-5 init commit
* 1.1 zhugengyu 2022-5-16 modify according to tech manual.
*/
#ifndef DRIVERS_FGDMA_H
#define DRIVERS_FGDMA_H
#ifdef __cplusplus
extern "C"
{
#endif
/***************************** Include Files *********************************/
#include "ftypes.h"
#include "fassert.h"
#include "ferror_code.h"
#include "fkernel.h"
/************************** Constant Definitions *****************************/
typedef enum
{
FGDMA_CHAN0_INDEX = 0,
FGDMA_CHAN1_INDEX = 1,
FGDMA_CHAN2_INDEX = 2,
FGDMA_CHAN3_INDEX = 3,
FGDMA_CHAN4_INDEX = 4,
FGDMA_CHAN5_INDEX = 5,
FGDMA_CHAN6_INDEX = 6,
FGDMA_CHAN7_INDEX = 7,
FGDMA_CHAN8_INDEX = 8,
FGDMA_CHAN9_INDEX = 9,
FGDMA_CHAN10_INDEX = 10,
FGDMA_CHAN11_INDEX = 11,
FGDMA_CHAN12_INDEX = 12,
FGDMA_CHAN13_INDEX = 13,
FGDMA_CHAN14_INDEX = 14,
FGDMA_CHAN15_INDEX = 15,
FGDMA_NUM_OF_CHAN
} FGdmaChanIndex; /* 16个独立通道, 0 ~ 15 */
typedef enum
{
FGDMA_OPER_NONE_PRIORITY_POLL = -1, /* Priority = -1 表示读写请求仲裁模式为Poll */
FGDMA_OPER_PRIORITY0 = 0, /* Priority >= 0 表示读写请求仲裁模式为Qos */
FGDMA_OPER_PRIORITY1 = 1,
FGDMA_OPER_PRIORITY2 = 2,
FGDMA_OPER_PRIORITY3 = 3,
FGDMA_OPER_PRIORITY4 = 4,
FGDMA_OPER_PRIORITY5 = 5,
FGDMA_OPER_PRIORITY6 = 6,
FGDMA_OPER_PRIORITY7 = 7,
FGDMA_OPER_PRIORITY8 = 8,
FGDMA_OPER_PRIORITY9 = 9,
FGDMA_OPER_PRIORITY10 = 10,
FGDMA_OPER_PRIORITY11 = 11,
FGDMA_OPER_PRIORITY12 = 12,
FGDMA_OPER_PRIORITY13 = 13,
FGDMA_OPER_PRIORITY14 = 14,
FGDMA_OPER_PRIORITY15 = 15
} FGdmaOperPriority; /* Qos配置值越高优先级越高 */
typedef enum
{
FGDMA_OPER_DIRECT = 0, /* 直接操作模式 */
FGDMA_OPER_BDL /* BDL操作模式 */
} FGdmaOperMode; /* 支持的操作模式 */
typedef enum
{
FGDMA_BURST_SIZE_1_BYTE = 0,
FGDMA_BURST_SIZE_2_BYTE = 1,
FGDMA_BURST_SIZE_4_BYTE = 2,
FGDMA_BURST_SIZE_8_BYTE = 3,
FGDMA_BURST_SIZE_16_BYTE = 4
} FGdmaBurstSize; /* 支持的读写请求size大小 */
#define FGDMA_GET_BURST_SIZE(brust_align) (1U << brust_align)
typedef enum
{
FGDMA_CHAN_EVT_FIFO_EMPTY = 0, /* 通道Fifo空事件 */
FGDMA_CHAN_EVT_FIFO_FULL, /* 通道Fifo满事件 */
FGDMA_CHAN_EVT_BDL_END, /* BDL模式下一个BDL条目传输完成 */
FGDMA_CHAN_EVT_TRANS_END, /* 所有传输数据完成 */
FGDMA_CHAN_EVT_BUSY, /* 前一次传输未完成,当前还处于传输中 */
FGDMA_CHAN_NUM_OF_EVT
} FGdmaChanEvtType; /* 通道中断事件 */
#define FGDMA_SUCCESS FT_SUCCESS
#define FGDMA_ERR_NOT_INIT FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 0)
#define FGDMA_ERR_CHAN_IN_USE FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 1)
#define FGDMA_ERR_CHAN_NOT_INIT FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 2)
#define FGDMA_ERR_INVALID_ADDR FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 3)
#define FGDMA_ERR_INVALID_SIZE FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 4)
#define FGDMA_ERR_BDL_NOT_ENOUGH FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 5)
#define FGDMA_ADDR_ALIGMENT 128U /* 直接模式和BDL模式的地址需要按128位对齐 */
/**************************** Type Definitions *******************************/
typedef struct _FGdma FGdma;
typedef struct _FGdmaChan FGdmaChan;
typedef struct
{
u32 instance_id; /* GDMA控制器ID */
u32 irq_num; /* GDMA控制器中断号 */
u32 irq_prority; /* GDMA控制器中断优先级 */
volatile uintptr_t base_addr; /* GDMA控制器基地址 */
FGdmaOperPriority rd_qos; /* 读操作优先级 */
FGdmaOperPriority wr_qos; /* 写操作优先级 */
} FGdmaConfig; /* GDMA控制器配置 */
typedef struct
{
u32 src_addr_l; /* 0x0, 数据源地址低32位 */
u32 src_addr_h; /* 0x4, 数据源地址高32位 */
u32 dst_addr_l; /* 0x8, 数据目的地址低32位 */
u32 dst_addr_h; /* 0xc, 数据目的地址高32位 */
#define FGDMA_SRC_TC_BDL_BURST_SET(x) SET_REG32_BITS((x), 1U, 0U)
#define FGDMA_SRC_TC_BDL_SIZE_SET(x) SET_REG32_BITS((x), 6U, 4U)
#define FGDMA_SRC_TC_BDL_LEN_SET(x) SET_REG32_BITS((x), 15U, 8U)
u32 src_tc; /* 0x10, 源传输控制位 */
#define FGDMA_DST_TC_BDL_BURST_SET(x) SET_REG32_BITS((x), 1U, 0U)
#define FGDMA_DST_TC_BDL_SIZE_SET(x) SET_REG32_BITS((x), 6U, 4U)
#define FGDMA_DST_TC_BDL_LEN_SET(x) SET_REG32_BITS((x), 15U, 8U)
u32 dst_tc; /* 0x14, 目的传输控制 */
u32 total_bytes;/* 0x18, 传输数据总量以Byte为单位 */
u32 ioc; /* 0x1c, 该条目传输完成中断产生控制位 */
} __attribute__((__packed__)) FGdmaBdlDesc; /* BDL描述符 */
FASSERT_STATIC(0x20U == sizeof(FGdmaBdlDesc));
typedef struct
{
FGdmaChanIndex chan_id; /* DMA通道ID */
FGdmaOperPriority rd_qos; /* DMA通道读Qos配置 */
FGdmaOperPriority wr_qos; /* DMA通道写Qos配置 */
FGdmaOperMode trans_mode; /* DMA通道的操作模式直接模式或者BDL模式 */
/* Direct模式有效 */
FGdmaBurstSize rd_align; /* DMA读请求的Burst对齐方式 */
FGdmaBurstSize wr_align; /* DMA写请求的Burst对齐方式 */
/* BDL模式有效 */
boolean roll_back; /* 循环模式TRUE: 当前BDL列表完成后从第一个BDL项从新开始传输 */
FGdmaBdlDesc *descs;
u32 total_desc_num;
u32 valid_desc_num;
} FGdmaChanConfig; /* DMA通道配置 */
typedef void (*FGdmaChanEvtHandler)(FGdmaChan *const chan, void *args);
typedef struct _FGdmaChan
{
FGdmaChanConfig config; /* DMA通道配置 */
FGdma *gdma; /* DMA控制器实例 */
FGdmaChanEvtHandler evt_handlers[FGDMA_CHAN_NUM_OF_EVT]; /* DMA通道事件回调函数 */
void *evt_handler_args[FGDMA_CHAN_NUM_OF_EVT]; /* DMA通道事件回调函数入参 */
} FGdmaChan; /* GDMA通道实例 */
typedef struct _FGdma
{
FGdmaConfig config; /* GDMA控制器配置 */
u32 is_ready; /* GDMA控制器初始化是否完成 */
FGdmaChan *chans[FGDMA_NUM_OF_CHAN]; /* GDMA通道实例如果通道没有分配值为NULL */
} FGdma; /* GDMA控制器实例 */
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/* 获取默认的通道配置 */
#define FGDMA_DEFAULT_DIRECT_CHAN_CONFIG(_chan_id)\
(FGdmaChanConfig){ \
.chan_id = (_chan_id),\
.rd_align = FGDMA_BURST_SIZE_4_BYTE,\
.wr_align = FGDMA_BURST_SIZE_4_BYTE,\
.rd_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
.wr_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
.trans_mode = FGDMA_OPER_DIRECT,\
.roll_back = FALSE\
}
#define FGDMA_DEFAULT_BDL_CHAN_CONFIG(_chan_id, _bdl_descs, _bdl_desc_num)\
(FGdmaChanConfig){ \
.chan_id = (_chan_id),\
.rd_align = FGDMA_BURST_SIZE_4_BYTE,\
.wr_align = FGDMA_BURST_SIZE_4_BYTE,\
.rd_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
.wr_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
.trans_mode = FGDMA_OPER_BDL,\
.roll_back = FALSE,\
.descs = _bdl_descs,\
.total_desc_num = _bdl_desc_num,\
.valid_desc_num = 0U\
}
/************************** Function Prototypes ******************************/
/* 获取GDMA控制器默认配置 */
const FGdmaConfig *FGdmaLookupConfig(u32 instance_id);
/* 初始化GDMA控制器实例 */
FError FGdmaCfgInitialize(FGdma *const instance_p, const FGdmaConfig *config_p);
/* 去初始化GDMA控制器实例 */
void FGdmaDeInitialize(FGdma *const instance_p);
/* 分配指定GDMA通道 */
FError FGdmaAllocateChan(FGdma *const instance_p, FGdmaChan *const chan_p,
const FGdmaChanConfig *config_p);
/* 释放GDMA通道 */
FError FGdmaDellocateChan(FGdmaChan *const chan_p);
/* 直接操作模式下发起DMA传输 */
FError FGdmaDirectTransfer(FGdmaChan *const chan_p, uintptr src_addr, uintptr dst_addr, fsize_t data_len);
/* 设置BDL描述符的一个条目 */
FError FGdmaAppendBDLEntry(FGdmaChan *const chan_p, uintptr src_addr, uintptr dst_addr, fsize_t data_len);
/* BDL操作模式下发起DMA传输 */
FError FGdmaBDLTransfer(FGdmaChan *const chan_p);
/* 使能启动GDMA控制器 */
FError FGdmaStart(FGdma *const instance_p);
/* 停止GDMA控制器 */
FError FGdmaStop(FGdma *const instance_p);
/* GDMA中断处理函数 */
void FGdmaIrqHandler(s32 vector, void *args);
/* 注册GDMA通道事件回调函数 */
void FGdmaChanRegisterEvtHandler(FGdmaChan *const chan_p, FGdmaChanEvtType evt,
FGdmaChanEvtHandler handler, void *handler_arg);
/* 打印当前的GDMA寄存器值, DEBUG模式下有效 */
void FGdmaDumpRegisterVals(uintptr base_addr, u32 max_chan);
#ifdef __cplusplus
}
#endif
#endif