#ifndef __DRV_RFM_INTERFACE_H__
#define __DRV_RFM_INTERFACE_H__

/****************************UCP2.0 Platform start***********************************/
#define STC_LOCAL_TIME_BASE  (0x08568000 +  0x4014)

#define GET_STC_CNT()  (LOAD_EX_V_W(STC_LOCAL_TIME_BASE))

/**************************************************/
/*                  前传接口驱动初始化相关                   */
/**************************************************/

// 前传接口类型
typedef enum _tagProtocolID
{
	PROTOCOL_NULL = 0,
	PROTOCOL_CPRI = 1,
	PROTOCOL_ECPRI,
	PROTOCOL_JESD
}numProtoID;

// cpri option模式，决定接口速率
typedef enum _tagCpriOptionID
{
	CPRI_OPTION_7 = 7,
	CPRI_OPTION_8 = 8,
	CPRI_OPTION_9 = 9,
	CPRI_OPTION_10 = 10
}CpriOptID;

// cpri map模式
typedef enum _tagCpriMapType
{
	OTIC_MAP_FIGURE10 = 0, //option8,双模，4T4R NR小区 + 2T2R LTE小区
	OTIC_MAP_FIGURE12,     //option8,NR 4T4R单小区	
	OTIC_MAP_FIGURE16,     //option10,NR 4T4R的2小区 
    OTIC_MAP_8NR_8LTE      //RJ Mapping(2*4TR NR + 4*2TR LTE)     
}CpriMapType;


// ecpri option模式，决定接口速率
typedef enum _tagEcpriOptionID
{
	ECPRI_OPTION_10G = 10,
	ECPRI_OPTION_25G = 25
}EcpriOptID;

typedef struct _tagFrontHaulDrvPara
{
	uint32_t protocolSel;	// numProtoID
	uint32_t rateOption;	// CpriOptID/EcpriOptID
	uint32_t mapOption;		// CpriMapType
}stFrontHaulDrvPara;

typedef enum _tagScsID
{
	LTE_SCS_ID = 0,
	NR_SCS_30K,
	NR_SCS_60K,
	NR_SCS_120K,
	SCS_NULL	= 0xFFFF
}numScsID;

typedef enum _tagFrameType
{
	FDD_MODE = 0, 
	TDD_MODE = 1,
	TDD_2500US_DOUBLE = 2,
	FRAME_NULL = 0xFFFF
}numFrameType;


/*
    函数名称：fronthaul_drv_cfg
    函数入参：stFrontHaulDrvPara* pFhDrvPara ：前传接口配置参数
    函数功能：前传接口驱动配置
*/
int32_t fronthaul_drv_cfg(stFrontHaulDrvPara* pFhDrvPara);

/*
    函数名称：delay_us
    函数入参：num：微秒
    函数功能：时延函数
*/
void delay_us(uint32_t num);

/**************************************************/
/*                  PORT ID相关                     */
/**************************************************/
/*
    函数名称：get_ucp_port_id
    函数入参：无
    函数功能：获取核的port id
*/
uint32_t get_ucp_port_id();

/**************************************************/
/*                  核ID相关                         */
/**************************************************/
/*
    函数名称：get_core_id
    函数入参：无
    函数功能：获取核id
*/
uint32_t get_core_id(void);

/**************************************************/
/*                  初始化接口                         */
/**************************************************/
/*
    函数名称：ucp_rfm1_init_1
    函数入参：无
    函数功能：RFM模块初始化(print_init + rfm_drv_init)
*/
void ecs_rfm0_drv_init(void);

/*
    函数名称：ucp_rfm1_init_2
    函数入参：无
    函数功能：RFM模块初始化
*/
void ecs_rfm0_app_init(void);

/**************************************************/
/*                   其他接口                         */
/**************************************************/
/*
    函数名称：set_tx_slot_intflag
    函数入参：scs: 子载波ID号
    		  flag, 1: 设置中断标志； 0：清空中断标志
    函数功能：设置发送时隙中断标志
    备注		：该标志位在SM上，rfm1负责在中断中置位，清零操作交给物理层，只有一个核可清零，否则可能有冲突，导致读出的时隙号有误。
*/
void set_tx_slot_intflag(uint8_t scs, int flag);
/*
    函数名称：get_tx_slot_intflag
    函数入参：scs: 子载波ID号
    函数功能：获取接收时隙中断标志
*/
int get_tx_slot_intflag(uint8_t scs);

/*
    函数名称：set_rx_slot_intflag
    函数入参：scs: 子载波ID号
    		  flag, 1: 设置中断标志； 0：清空中断标志
    函数功能：设置接收时隙中断标志
	备注		：该标志位在SM上，rfm1负责在中断中置位，清零操作交给物理层，只有一个核可清零，否则可能有冲突，导致读出的时隙号有误。
*/
void set_rx_slot_intflag(uint8_t scs, int flag);

/*
    函数名称：get_rx_slot_intflag
    函数入参：scs: 子载波ID号
    函数功能：获取接收时隙中断标志
*/
int get_rx_slot_intflag(uint8_t scs);


typedef struct phy_timer_config_ind_t
{
    uint32_t frameType;		//0:FDD, 1:TDD, 2:TDD(双周期DDDSUDDSUU)
    uint32_t scsId;
	uint32_t runCoreId;		// 此次需要建小区的ape core id，bitmap方式，bit0对应ape0，bit1对应ape1，。。。
    uint16_t bandWidth;     //带宽:5M,10M,15M,20M,25M,30M,40M,50M,60M,80M,100M
    uint16_t t_period;      //timer周期=t_us*num_tti, 500us, 625us, 1000us, 1250us, 2500us, 5000us, 10000us, 20000us


    uint16_t t_us;          //物理层时隙定时长度, 125us, 250us, 500us, 1000us
    uint8_t  num_tti;         //timer周期内时隙的个数5,10,20,40,80
    uint8_t  num_tti_per_sfn; //一个SFN内的时隙个数


    uint8_t num_t_dl[2];       //下行时隙个数
    uint8_t num_t_dl_symb[2];  //S时隙内下行符号个数
    uint8_t num_t_ul_symb[2];  //S时隙内上行符号个数
    uint8_t num_ants[2];       //天线个数
}phy_timer_config_ind_t;

typedef struct _tagPhyDelCell
{
    uint32_t scsId;
	uint32_t delCoreId;		// 此次需要删除小区的ape core id，bitmap方式，bit0对应ape0，bit1对应ape1，。。。
}stPhyDelCell;

typedef struct CpriRruMsg
{
    uint32_t msg_addr;
	uint32_t msg_len;
}CpriRruMsg_t;

/*
    函数名称：mtimer_init4phy
    函数入参：my_cpritmr：小区参数
    函数功能：小区创建时，定时器参数配置接口，先走ecs rfm1的建小区流程，再通知APE建小区
*/
int32_t mtimer_init4phy(phy_timer_config_ind_t *my_mtmr);

/*
    函数名称：mtimer_del_cell_cfg
    函数入参：delCell：待删除的小区参数
    函数功能：删小区，先通知APE删除任务和定时点，再走ecs rfm1的删小区流程
*/
int32_t mtimer_del_cell_cfg(stPhyDelCell* delCell);


/*
    函数名称：get_cpri_delay
    函数入参：
    *delay: cpri的接收延迟量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的接收延迟量，如果oam或phy脚本配置的延迟量不足6us，
              驱动实际取6us做接收延迟量（考虑到中断处理延迟及最小光纤延迟）
*/
void get_cpri_delay(uint32_t* delay);

/*
    函数名称：get_cpri_advance
    函数入参：
    *advance: cpri的发送提前量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的发送提前量，如果oam或phy脚本配置的延迟量不足6us，
              驱动实际取6us做发送提前量（考虑到中断处理延迟及最小光纤延迟）
*/
void get_cpri_advance(uint32_t* advance);

/*
    函数名称：get_cpri_frame_data_offset
    函数入参：
    *offset: cpri的上行帧头与上行数据直接的偏移量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的上行帧头与上行数据直接的偏移量
*/
void get_cpri_frame_data_offset(uint32_t* offset);

/*
    函数名称：set_cpri_rru_msg
    函数入参：
    CpriRruMsg_t rru_msg: 透传的消息信息结构体
    函数功能：物理层通过cpri headerram向rru透传消息的接口
*/
int32_t set_cpri_rru_msg(CpriRruMsg_t rru_msg);

/*
    函数名称：phy_sniffer_start
    函数入参：
        uint32_t nOffsetUs:测量时偏移pp1s的us数
    函数返回：0：正常；
    		 -1：异常
    函数功能：物理层通知平台，进行orx数据搬移
*/
int32_t phy_sniffer_start(uint32_t nOffsetUs);

/*
    函数名称：spu_ddr_monitor_start
    函数入参：uint32_t monitorCnt: 本次启动需要监控的次数
    函数返回：无
    函数功能：物理层通知平台，启动ddr监控功能，且配置需要监控的次数
*/
void spu_ddr_monitor_start(uint32_t monitorCnt);


/**************************************************/
/*                  ape csu相关                         */
/**************************************************/
#define APC_DMA_REG_NUM		16

#define DMA_DIR_L2G		0
#define DMA_DIR_G2L 	1
#define DMA_DIR_G2G 	1


#define DMA_REG_GROUP0  0
#define DMA_REG_GROUP1 	1
#define DMA_REG_GROUP2 	2
#define DMA_REG_GROUP3 	3

//ape-csu dma chain define
#define MAX_CHAIN_LEN                                               (16)
#define APC_DMA_CHAIN_L2_SIZE_WORD                                  (4)
#define APC_DMA_CHAIN_L1_3D_SIZE_WORD                               (8)
#define APC_DMA_CHAIN_L1_1D_SIZE_WORD                               (4)

/* apc-dma chain level2 info */
// word0
// cmdData Low 32bit
#define APC_DMA_CHAIN_L2_CMDDATAL_WORD_OFFSET                       (0)
#define APC_DMA_CHAIN_L2_CMDDATAL_BIT_OFFSET                        (0)
// word1
// bit26:24: next node address High 3bit
// bit17:16: base address for level1 chain High 2bit
// bit15:0:  number of nodes for level1 chain 16bit
#define APC_DMA_CHAIN_L2_NXTADDRH_L1_BASEADDRH_NUMNODES_WORD_OFFSET (1)
#define APC_DMA_CHAIN_L2_L1_NUMNODES_BIT_OFFSET                     (0)
#define APC_DMA_CHAIN_L2_L1_BASEADDRH_BIT_OFFSET                    (16)
#define APC_DMA_CHAIN_L2_NXTADDRH_BIT_OFFSET                        (24)
// word2
// base address for level1 chain Low 32bit
#define APC_DMA_CHAIN_LEVEL2_L1_BASEADDR_L32_WORD_OFFSET            (2)
#define APC_DMA_CHAIN_LEVEL2_L1_BASEADDR_L32_BIT_OFFSET             (0)
// word3
// bit31:   node address mode 1bit
// bit30:0: next node address Low 31bit
#define APC_DMA_CHAIN_L2_ADDRMODE_NXTADDRL_WORD_OFFSET              (3)
#define APC_DMA_CHAIN_L2_NXTADDR_L31_BIT_OFFSET                     (0)
#define APC_DMA_CHAIN_L2_ADDRMODE_BIT_OFFSET                        (31)

/* apc-dma chain level1 2-3d info */
// word0
// cmdData Low 32bit
#define APC_DMA_CHAIN_L1_3D_CMDDATAL_WORD_OFFSET                    (0)
#define APC_DMA_CHAIN_L1_3D_CMDDATAL_BIT_OFFSET                     (0)
// word1
// xAddr Low 32bit
#define APC_DMA_CHAIN_L1_3D_XADDRL_WORD_OFFSET                      (1)
#define APC_DMA_CHAIN_L1_3D_XADDRL_BIT_OFFSET                       (0)
// word2
// bit29:16: cmdData High 14bit
// bit15:0:  xNum 16bit
#define APC_DMA_CHAIN_L1_3D_CMDDATAH_XNUM_WORD_OFFSET               (2)
#define APC_DMA_CHAIN_L1_3D_XNUM_BIT_OFFSET                         (0)
#define APC_DMA_CHAIN_L1_3D_CMDDATAH_BIT_OFFSET                     (16)
// word3
// yStep 32bit
#define APC_DMA_CHAIN_L1_3D_YSTEP_WORD_OFFSET                       (3)
#define APC_DMA_CHAIN_L1_3D_YSTEP_BIT_OFFSET                        (0)
// word4
// bit30:28: next node address High 3bit
// bit25:24: xAddr High 2bit
// bit23:20: GRAN
// bit19:16: SIZE
// bit15:0:  YNum
#define APC_DMA_CHAIN_L1_3D_NXTADDRH_XADDRH_GRANSIZE_YNUM_WORD_OFFSET (4)
#define APC_DMA_CHAIN_L1_3D_YNUM_BIT_OFFSET                         (0)
#define APC_DMA_CHAIN_L1_3D_SIZE_BIT_OFFSET                         (16)
#define APC_DMA_CHAIN_L1_3D_GRAN_BIT_OFFSET                         (20)
#define APC_DMA_CHAIN_L1_3D_XADDRH_BIT_OFFSET                       (24)
#define APC_DMA_CHAIN_L1_3D_NXTADDRH_BIT_OFFSET                     (28)
// word5
// zStep 32bit
#define APC_DMA_CHAIN_L1_3D_ZSTEP_WORD_OFFSET                       (5)
#define APC_DMA_CHAIN_L1_3D_ZSTEP_BIT_OFFSET                        (0)
// word6
// AllNum 32bit (valid field is bit23:0)
#define APC_DMA_CHAIN_L1_3D_ALLNUM_WORD_OFFSET                      (6)
#define APC_DMA_CHAIN_L1_3D_ALLNUM_BIT_OFFSET                       (0)
// word7
// bit31:   node address mode 1bit
// bit30:0: next node address Low 31bit
#define APC_DMA_CHAIN_L1_3D_ADDRMODE_NXTADDRL_WORD_OFFSET           (7)
#define APC_DMA_CHAIN_L1_3D_NXTADDRL_BIT_OFFSET                     (0)
#define APC_DMA_CHAIN_L1_3D_ADDRMODE_BIT_OFFSET                     (31)

/* apc-dma chain level1 1d info */
// word0
// cmdData Low 32bit
#define APC_DMA_CHAIN_L1_1D_CMDDATAL_WORD_OFFSET                    (0)
#define APC_DMA_CHAIN_L1_1D_CMDDATAL_BIT_OFFSET                     (0)
// word1
// xAddr Low 32bit
#define APC_DMA_CHAIN_L1_1D_XADDRL_WORD_OFFSET                      (1)
#define APC_DMA_CHAIN_L1_1D_XADDRL_BIT_OFFSET                       (0)
// word2
// bit31:30: xAddr High 2bit
// bit29:16: cmdData High 14bit
// bit15:0:  AllNum 16bit (MaxBytes 65535)
#define APC_DMA_CHAIN_L1_1D_XADDRH_CMDDATAH_ALLNUM_WORD_OFFSET      (2)
#define APC_DMA_CHAIN_L1_1D_ALLNUM_BIT_OFFSET                       (0)
#define APC_DMA_CHAIN_L1_1D_CMDDATAH_BIT_OFFSET                     (16)
#define APC_DMA_CHAIN_L1_1D_XADDRH_BIT_OFFSET                       (30)
// word3
// bit31:   node address mode 1bit
// bit30:0: next node address Low 31bit
#define APC_DMA_CHAIN_L1_1D_ADDRMODE_NXTADDRL_WORD_OFFSET           (3)
#define APC_DMA_CHAIN_L1_1D_NXTADDRL_BIT_OFFSET                     (0)
#define APC_DMA_CHAIN_L1_1D_ADDRMODE_BIT_OFFSET                     (31)

//-------------------------------------------------------------
//struct define
//------------------------------------------------------------- 
// cus dma 寄存器方式，结构体参数
typedef struct _tagCsuDmaReg
{
	uint32_t dmaAddrL;
	uint32_t dmaAddrH;
	uint32_t dmaYStepL;
	uint32_t dmaYStepH;
	uint32_t dmaZStepL;
	uint32_t dmaZStepH;
	uint16_t dmaXNum;
	uint16_t dmaYNum;
	uint32_t dmaAllNum	: 24;
	uint32_t dmaGran		: 4;
	uint32_t dmaSize		: 4;
}stCsuDmaReg;

typedef struct _tagCsuDmaCmdL
{  
    uint32_t rCmd			: 2; // 0:普通DMA，1:一级DMA，2:一级DMA并等待ActNum，3:二级DMA
    uint32_t wCmd			: 2;
    uint32_t dmaType		: 1; // 0:一维，1:多维
    uint32_t cacheMode	: 1; // 0:common mode, 1:cache mode
    uint32_t continueNext	: 1; // continue the next dma
	uint32_t continueLast	: 1; // continue the last dma
    uint32_t idSrc		: 5; // src buffer id
    uint32_t idDst		: 5; // dst buffer id
    uint32_t dmaTag		: 5; // tag
    uint32_t flush		: 1;
	uint32_t ecpriEnd		: 3;
	uint32_t zNumValid	: 1;
	uint32_t allOrYNum	: 2;
	uint32_t allNumSel	: 1;
    uint32_t stall		: 1; // stall信号，是否在传输之前触发stall中断
}stCsuDmaCmdL;

typedef struct _tagCsuDmaCmdH
{
	uint32_t rXNumNextDma		: 1; // 读操作完成一个XNum后，换下一个DMA
	uint32_t rYNumNextDma 	: 1; // 读操作完成一个YNum后，换下一个DMA
	uint32_t wXNumNextDma 	: 1; // 写操作完成一个XNum后，换下一个DMA
	uint32_t wYNumNextDma 	: 1; // 写操作完成一个YNum后，换下一个DMA
	uint32_t rRfpFirstDma 	: 1; // 读操作位对应AxC的rfp后第一组DMA请求
	uint32_t reserved1    	: 6; 
	uint32_t wLinkCycleMode	: 1; // 写操作为链表循环模式
	uint32_t reserved2		: 1;
	uint32_t rLinkCycleMode	: 1; // 读操作为链表循环模式
	uint32_t reserved3		: 18;
}stCsuDmaCmdH;

// 一级链表，多维DMA
typedef struct _tagCsuLinkDesc1L3D
{
	uint32_t cmdFifoL;			// [31:0]		// fifo[31:0]
	uint32_t dmaAddrL;			// [63:32]		// addr[31:0]
	uint32_t dmaXNum		: 16;	// [79:64]		// XNum
	uint32_t cmdFifoH		: 14;	// [93:80]		// fifo[45:32]
	uint32_t reserved1 		: 2;	// [95:94]
	uint32_t dmaYStep;			// [127:96]		// YStep[31:0]
	uint32_t dmaYNum		: 16;	// [143:128]	// YNum
	uint32_t dmaSize		: 4;	// [147:144]	// dmaSize
	uint32_t dmaGran		: 3;	// [150:148]	// gran
	uint32_t dmaCGran		: 1;	// [151]		// cgran
	uint32_t dmaAddrH		: 2;	// [153:152]	// addr[33:32]
	uint32_t reserved2	: 2;	// [155:154]
	uint32_t nextAddrH	: 3;	// [158:156]	// next addr[33:31]
	uint32_t reserved3	: 1;	// [159]
	uint32_t dmaZStep;			// [191:160]	// ZStep[31:0]
	uint32_t dmaAllNum;			// [223:192]	// all num
	uint32_t nextAddrL	: 31;	// [254:224]	// next addr[30:0]
	uint32_t nAddrMode	: 1;	// [255]		// 1：使用nextAddr，0：地址自动加0x20/0x40
}stCsuLinkDesc1L3D;

//extern __attribute__((always_inline)) uint8_t os_get_apeid();

//-------------------------------------------------------------
//api
//------------------------------------------------------------- 
/*!
* @brief:  查看tag号对应的dma任务是否完成，未完成返回0，完成返回1
*  		   如果isWait==1，则等待该tag对应的任务完成，再返回，返回1
* @author:  xinxin.li
* @Date:  2022年6月1日
* @param: task_tag :         [DMA Tag: 0~31用于查询是否完成 ]
* @param: isWait :           [是否等DMA结束函数返回0:不等待,1:等待 ]
* @return: 1：已完成，0：未完成
*/
int ape_csu_task_lookup(uint8_t task_tag, uint8_t isWait);

/*!
* @brief:  一维搬移到一维，使用寄存器组0和组1实现L2G的Dma搬移
* @author:  xinxin.li
* @Date:  2022年6月1日
* @param: addrSrc :          [源地址 ]
* @param: addrDst :          [目的地址 ]
* @param: dataLen :          [搬移总字节数 ]
* @param: tag :              [DMA Tag: 0~31用于查询是否完成 ]
* @param: isWait :           [是否等DMA结束函数返回0:不等待,1:等待 ]
* @return: 0：搬移完成
*/
int ape_csu_dma_1D_L2G_ch0ch1_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen, uint8_t tag, uint8_t isWait);

/*!
* @brief:  一维搬移到一维，使用寄存器组2和组3实现L2G的Dma搬移
* @author:  xinxin.li
* @Date:  2022年6月1日
* @param: addrSrc :          [源地址 ]
* @param: addrDst :          [目的地址 ]
* @param: dataLen :          [搬移总字节数 ]
* @param: tag :              [DMA Tag: 0~31用于查询是否完成 ]
* @param: isWait :           [是否等DMA结束函数返回0:不等待,1:等待 ]
* @return: 0：搬移完成
*/
int ape_csu_dma_1D_L2G_ch2ch3_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen, uint8_t tag, uint8_t isWait);

/*!
* @brief:  一维搬移到一维，使用寄存器组0和组1实现G2L的Dma搬移
* @author:  xinxin.li
* @Date:  2022年6月1日
* @param: addrSrc :          [源地址 ]
* @param: addrDst :          [目的地址 ]
* @param: dataLen :          [搬移总字节数 ]
* @param: tag :              [DMA Tag: 0~31用于查询是否完成 ]
* @param: isWait :           [是否等DMA结束函数返回0:不等待,1:等待 ]
* @return: 0：搬移完成
*/
int ape_csu_dma_1D_G2L_ch0ch1_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen, uint8_t tag, uint8_t isWait);

/*!
* @brief:  一维搬移到一维，使用寄存器组2和组3实现G2L的Dma搬移
* @author:  xinxin.li
* @Date:  2022年6月1日
* @param: addrSrc :          [源地址 ]
* @param: addrDst :          [目的地址 ]
* @param: dataLen :          [搬移总字节数 ]
* @param: tag :              [DMA Tag: 0~31用于查询是否完成 ]
* @param: isWait :           [是否等DMA结束函数返回0:不等待,1:等待 ]
* @return: 0：搬移完成
*/
int ape_csu_dma_1D_G2L_ch2ch3_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen, uint8_t tag, uint8_t isWait);

/*!
* @brief:  一维搬移到一维，如果目前没有可用的DMA资源，会一直等待，直至获取到可用资源才配置，配置完即退出，不会等待搬移完成
* @author:  xinxin.li
* @Date:  2023年3月15日
* @param: addrSrc :          [源地址 ]
* @param: addrDst :          [目的地址 ]
* @param: dataLen :          [搬移总字节数 ]
* @return: 本次DMA搬移，用的tag号
*/
uint32_t spu_csu_dma_1D_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen);



/****************************UCP2.0 Platform end*************************************/

#endif /* __RFM_INTERFACE_H__ */

