258 lines
9.6 KiB
C
258 lines
9.6 KiB
C
/*
|
||
* 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 file 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 FGDMA_H
|
||
#define FGDMA_H
|
||
|
||
#include "ftypes.h"
|
||
#include "fassert.h"
|
||
#include "ferror_code.h"
|
||
#include "fkernel.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C"
|
||
{
|
||
#endif
|
||
|
||
/***************************** Include Files *********************************/
|
||
|
||
|
||
|
||
/************************** Constant Definitions *****************************/
|
||
|
||
/* gdma capacity mask */
|
||
|
||
#define FGDMA_IRQ1_MASK BIT(0) /* All Gdma channel share a single interrupt */
|
||
#define FGDMA_IRQ2_MASK BIT(1) /* Each gdma channel owns an independent interrupt */
|
||
#define FGDMA_TRANS_NEED_RESET_MASK BIT(2) /* Gdma needs to be reset before transmission */
|
||
|
||
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[FGDMA_NUM_OF_CHAN]; /* GDMA控制器中断号 */
|
||
u32 irq_prority; /* GDMA控制器中断优先级 */
|
||
volatile uintptr_t base_addr; /* GDMA控制器基地址 */
|
||
FGdmaOperPriority rd_qos; /* 读操作优先级 */
|
||
FGdmaOperPriority wr_qos; /* 写操作优先级 */
|
||
u32 caps; /* driver capacity */
|
||
} 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 u32 FGdmaChanIndex;
|
||
|
||
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);
|
||
void FGdmaIrqHandlerPrivateChannel(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
|