2022-11-10 22:22:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* 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_intr.c
|
|
|
|
|
* Date: 2022-05-16 17:01:48
|
|
|
|
|
* LastEditTime: 2022-05-16 17:01:49
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Description: This file is for interrupt api implmentation
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* 1.0 huanghe 2021/11/5 init commit
|
|
|
|
|
* 1.1 zhugengyu 2022/5/16 modify according to tech manual.
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "fdebug.h"
|
|
|
|
|
#include "fassert.h"
|
|
|
|
|
|
|
|
|
|
#include "fgdma_hw.h"
|
|
|
|
|
#include "fgdma.h"
|
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
#define FGDMA_DEBUG_TAG "GDMA-INTR"
|
|
|
|
|
#define FGDMA_ERROR(format, ...) FT_DEBUG_PRINT_E(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FGDMA_WARN(format, ...) FT_DEBUG_PRINT_W(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FGDMA_INFO(format, ...) FT_DEBUG_PRINT_I(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FGDMA_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
#define FGDMA_CALL_EVT_HANDLER(express, dma_chan, args) \
|
|
|
|
|
do \
|
|
|
|
|
{ \
|
|
|
|
|
if (express) \
|
|
|
|
|
{ \
|
|
|
|
|
express(dma_chan, args); \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
|
/**
|
|
|
|
|
* @name: FGdmaChanIrqHandler
|
|
|
|
|
* @msg: GDMA通道中断处理函数
|
|
|
|
|
* @return {void} 无
|
|
|
|
|
* @param {FGdmaChan} *chan_p, GDMA通道实例
|
|
|
|
|
*/
|
|
|
|
|
static void FGdmaChanIrqHandler(FGdmaChan *const chan_p)
|
|
|
|
|
{
|
|
|
|
|
FGdma *const instance_p = chan_p->gdma;
|
|
|
|
|
FASSERT(instance_p);
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
u32 chan_status = FGdmaReadChanStatus(base_addr, chan_p->config.chan_id);
|
|
|
|
|
|
|
|
|
|
if (FGDMA_CHX_INT_STATE_BUSY & chan_status)
|
|
|
|
|
{
|
|
|
|
|
FGDMA_CALL_EVT_HANDLER(chan_p->evt_handlers[FGDMA_CHAN_EVT_BUSY],
|
|
|
|
|
chan_p, chan_p->evt_handler_args[FGDMA_CHAN_EVT_BUSY]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FGDMA_CHX_INT_STATE_TRANS_END & chan_status)
|
|
|
|
|
{
|
|
|
|
|
FGDMA_CALL_EVT_HANDLER(chan_p->evt_handlers[FGDMA_CHAN_EVT_TRANS_END],
|
|
|
|
|
chan_p, chan_p->evt_handler_args[FGDMA_CHAN_EVT_TRANS_END]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FGDMA_CHX_INT_STATE_BDL_END & chan_status)
|
|
|
|
|
{
|
|
|
|
|
FGDMA_CALL_EVT_HANDLER(chan_p->evt_handlers[FGDMA_CHAN_EVT_BDL_END],
|
|
|
|
|
chan_p, chan_p->evt_handler_args[FGDMA_CHAN_EVT_BDL_END]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FGDMA_CHX_INT_STATE_FIFO_FULL & chan_status)
|
|
|
|
|
{
|
|
|
|
|
FGDMA_CALL_EVT_HANDLER(chan_p->evt_handlers[FGDMA_CHAN_EVT_FIFO_FULL],
|
|
|
|
|
chan_p, chan_p->evt_handler_args[FGDMA_CHAN_EVT_FIFO_FULL]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FGDMA_CHX_INT_STATE_FIFO_EMPTY & chan_status)
|
|
|
|
|
{
|
|
|
|
|
FGDMA_CALL_EVT_HANDLER(chan_p->evt_handlers[FGDMA_CHAN_EVT_FIFO_EMPTY],
|
|
|
|
|
chan_p, chan_p->evt_handler_args[FGDMA_CHAN_EVT_FIFO_EMPTY]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGdmaClearChanStatus(base_addr, chan_p->config.chan_id, chan_status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FGdmaIrqHandler
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* @msg: 当instance_p->config.caps 具有FGDMA_IRQ1_MASK特性时,此函数作为GDMA中断处理函数
|
2022-11-10 22:22:48 +08:00
|
|
|
|
* @return {void} 无
|
|
|
|
|
* @param {s32} vector, 中断号
|
|
|
|
|
* @param {void} *args, 中断参数
|
|
|
|
|
*/
|
|
|
|
|
void FGdmaIrqHandler(s32 vector, void *args)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(args);
|
|
|
|
|
FGdma *const instance_p = (FGdma * const)args;
|
|
|
|
|
FASSERT(FT_COMPONENT_IS_READY == instance_p->is_ready);
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FASSERT(FGDMA_IRQ1_MASK & instance_p->config.caps);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
u32 chan_id;
|
|
|
|
|
|
|
|
|
|
u32 status = FGdmaReadStatus(base_addr);
|
|
|
|
|
FGDMA_INFO("status: 0x%x", status);
|
|
|
|
|
|
|
|
|
|
FGdmaIrqDisable(base_addr);
|
2023-05-11 10:25:21 +08:00
|
|
|
|
for (chan_id = 0; chan_id < FGDMA_NUM_OF_CHAN; chan_id++)
|
2022-11-10 22:22:48 +08:00
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
if (!(FGDMA_CHX_INTR_STATE(chan_id) & status))
|
|
|
|
|
{
|
2022-11-10 22:22:48 +08:00
|
|
|
|
continue;
|
2023-05-11 10:25:21 +08:00
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
|
|
|
|
/* channel interrupt happens */
|
|
|
|
|
FASSERT_MSG((NULL != instance_p->chans[chan_id]), "invalid chan interrupt event !!!");
|
|
|
|
|
FGdmaChanIrqHandler(instance_p->chans[chan_id]);
|
|
|
|
|
}
|
|
|
|
|
FGdmaIrqEnable(base_addr);
|
2023-05-11 10:25:21 +08:00
|
|
|
|
status = FGdmaReadStatus(base_addr);
|
|
|
|
|
FGDMA_INFO("after status: 0x%x", status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
2023-05-11 10:25:21 +08:00
|
|
|
|
/**
|
|
|
|
|
* @name: FGdmaIrqHandlerPrivateChannel
|
|
|
|
|
* @msg: 当instance_p->config.caps 具有FGDMA_IRQ2_MASK特性时,此函数作为GDMA中断处理函数
|
|
|
|
|
* @return {void} 无
|
|
|
|
|
* @param {s32} vector, 中断号
|
|
|
|
|
* @param {void} *args, 中断参数
|
|
|
|
|
*/
|
|
|
|
|
void FGdmaIrqHandlerPrivateChannel(s32 vector, void *args)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(args);
|
|
|
|
|
FGdmaChan *gdma_chan = (FGdmaChan *)args;
|
|
|
|
|
FASSERT(gdma_chan);
|
|
|
|
|
FGdma *const instance_p = (FGdma *const)gdma_chan->gdma;
|
|
|
|
|
FASSERT(FT_COMPONENT_IS_READY == instance_p->is_ready);
|
|
|
|
|
FASSERT(FGDMA_IRQ2_MASK & instance_p->config.caps);
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
u32 chan_id;
|
|
|
|
|
FGDMA_INFO("FGdmaIrqHandlerPrivateChannel is here %d \r\n",vector);
|
|
|
|
|
chan_id = gdma_chan->config.chan_id ;
|
|
|
|
|
FASSERT(chan_id <= FGDMA_NUM_OF_CHAN);
|
|
|
|
|
u32 status = FGdmaReadStatus(base_addr);
|
|
|
|
|
FGDMA_INFO("status: 0x%x", status);
|
|
|
|
|
if(!(FGDMA_CHX_INTR_STATE(chan_id) & status))
|
|
|
|
|
{
|
|
|
|
|
FGDMA_WARN("The interrupt state does not match the interrupt chan_id ,chan_id is %d, interrupt state is 0x%x ",chan_id,status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FASSERT_MSG((NULL != instance_p->chans[chan_id]), "invalid chan interrupt event !!!");
|
|
|
|
|
FGdmaChanIrqHandler(instance_p->chans[chan_id]);
|
|
|
|
|
status = FGdmaReadStatus(base_addr);
|
|
|
|
|
FGDMA_INFO("after status: 0x%x", status);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 10:25:21 +08:00
|
|
|
|
|
2022-11-10 22:22:48 +08:00
|
|
|
|
/**
|
|
|
|
|
* @name: FGdmaChanRegisterEvtHandler
|
|
|
|
|
* @msg: 注册GDMA通道事件回调函数
|
|
|
|
|
* @return {void} 无
|
|
|
|
|
* @param {FGdmaChan} *chan_p, GDMA通道实例
|
|
|
|
|
* @param {FGdmaChanEvtType} evt, 通道事件
|
|
|
|
|
* @param {FGdmaChanEvtHandler} handler, 事件回调函数
|
|
|
|
|
* @param {void} *handler_arg, 事件回调函数输入参数
|
|
|
|
|
*/
|
|
|
|
|
void FGdmaChanRegisterEvtHandler(FGdmaChan *const chan_p, FGdmaChanEvtType evt,
|
|
|
|
|
FGdmaChanEvtHandler handler, void *handler_arg)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(chan_p);
|
|
|
|
|
FASSERT(FGDMA_CHAN_NUM_OF_EVT > evt);
|
|
|
|
|
|
|
|
|
|
chan_p->evt_handlers[evt] = handler;
|
|
|
|
|
chan_p->evt_handler_args[evt] = handler_arg;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|