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: fsdmmc_intr.c
|
|
|
|
|
* Date: 2022-02-10 14:53:42
|
|
|
|
|
* LastEditTime: 2022-02-18 08:54:53
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Description: This file contains the functions that are related to interrupt processing
|
|
|
|
|
* for the fsdmmc device.
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
|
|
|
|
* 1.0 zhugengyu 2021/12/2 init
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
|
#include "fassert.h"
|
|
|
|
|
#include "fio.h"
|
|
|
|
|
#include "fdebug.h"
|
|
|
|
|
|
|
|
|
|
#include "fsdmmc_hw.h"
|
|
|
|
|
#include "fsdmmc.h"
|
|
|
|
|
|
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
#define FSDMMC_DEBUG_TAG "FSDMMC-INTR"
|
|
|
|
|
#define FSDMMC_ERROR(format, ...) FT_DEBUG_PRINT_E(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FSDMMC_WARN(format, ...) FT_DEBUG_PRINT_W(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FSDMMC_INFO(format, ...) FT_DEBUG_PRINT_I(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FSDMMC_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
2023-05-11 10:25:21 +08:00
|
|
|
|
static void FSdmmcCallEvtHandler(FSdmmcEventHandler handler, void *arg)
|
2022-11-10 22:22:48 +08:00
|
|
|
|
{
|
|
|
|
|
if (NULL != handler)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
handler(arg);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
|
extern u32 FSdmmcMakeRawCmd(FSdmmcCmd *cmd_p);
|
|
|
|
|
extern void FSdmmcSendCmd(uintptr base_addr, FSdmmcCmd *cmd_p);
|
|
|
|
|
extern FError FSdmmcSendData(uintptr base_addr, boolean read, FSdmmcCmd *cmd_p);
|
|
|
|
|
|
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcGetInterruptMask
|
|
|
|
|
* @msg: 获取FSDMMC的中断掩码
|
|
|
|
|
* @return {u32} 中断掩码
|
|
|
|
|
* @param {uintptr} base_addr FSDMMC控制器基地址
|
|
|
|
|
* @param {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
|
|
|
|
|
* @note FSDMMC控制器初始化后才能调用此函数
|
|
|
|
|
*/
|
|
|
|
|
u32 FSdmmcGetInterruptMask(uintptr base_addr, u32 intr_type)
|
|
|
|
|
{
|
|
|
|
|
u32 mask;
|
|
|
|
|
|
|
|
|
|
switch (intr_type)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
case FSDMMC_CMD_INTR:
|
|
|
|
|
mask = FSDMMC_READ_REG(base_addr, FSDMMC_NORMAL_INT_EN_REG_OFFSET);
|
|
|
|
|
break;
|
|
|
|
|
case FSDMMC_ERROR_INTR:
|
|
|
|
|
mask = FSDMMC_READ_REG(base_addr, FSDMMC_ERROR_INT_EN_REG_OFFSET);
|
|
|
|
|
break;
|
|
|
|
|
case FSDMMC_DMA_BD_INTR:
|
|
|
|
|
mask = FSDMMC_READ_REG(base_addr, FSDMMC_BD_ISR_EN_REG_OFFSET);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
FASSERT(0);
|
|
|
|
|
break;
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcSetInterruptMask
|
|
|
|
|
* @msg: 设置FSDMMC的中断掩码
|
|
|
|
|
* @param {uintptr} base_addr FSDMMC控制器基地址
|
|
|
|
|
* @param {u32} intr_type FSDMMC中断类型, 参考FSDMMC_INTR_NUM
|
|
|
|
|
* @param {u32} mask 中断掩码
|
|
|
|
|
* @param {boolean} enable TRUE:打开中断, FALSE:关闭中断
|
|
|
|
|
* @note FSDMMC控制器初始化后才能调用此函数
|
|
|
|
|
*/
|
|
|
|
|
void FSdmmcSetInterruptMask(uintptr base_addr, u32 intr_type, u32 mask, boolean enable)
|
|
|
|
|
{
|
|
|
|
|
u32 old_mask = FSdmmcGetInterruptMask(base_addr, intr_type);
|
|
|
|
|
u32 new_mask = 0;
|
|
|
|
|
|
|
|
|
|
if (TRUE == enable)
|
2023-05-11 10:25:21 +08:00
|
|
|
|
{
|
2022-11-10 22:22:48 +08:00
|
|
|
|
new_mask = old_mask | mask;
|
2023-05-11 10:25:21 +08:00
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
else
|
2023-05-11 10:25:21 +08:00
|
|
|
|
{
|
2022-11-10 22:22:48 +08:00
|
|
|
|
new_mask = old_mask & (~mask);
|
2023-05-11 10:25:21 +08:00
|
|
|
|
}
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
|
|
|
|
switch (intr_type)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
case FSDMMC_CMD_INTR:
|
|
|
|
|
FSDMMC_WRITE_REG(base_addr, FSDMMC_NORMAL_INT_EN_REG_OFFSET, new_mask);
|
|
|
|
|
break;
|
|
|
|
|
case FSDMMC_ERROR_INTR:
|
|
|
|
|
FSDMMC_WRITE_REG(base_addr, FSDMMC_ERROR_INT_EN_REG_OFFSET, new_mask);
|
|
|
|
|
break;
|
|
|
|
|
case FSDMMC_DMA_BD_INTR:
|
|
|
|
|
FSDMMC_WRITE_REG(base_addr, FSDMMC_BD_ISR_EN_REG_OFFSET, new_mask);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
FASSERT(0);
|
|
|
|
|
break;
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcCmdInterrupHandler
|
|
|
|
|
* @msg: 命令中断响应函数
|
|
|
|
|
* @return {*} 无
|
|
|
|
|
* @param {s32} vector 中断向量号
|
|
|
|
|
* @param {void} *param 中断响应输入参数
|
|
|
|
|
* @note 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
*/
|
|
|
|
|
void FSdmmcCmdInterrupHandler(s32 vector, void *param)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(param);
|
|
|
|
|
u32 status;
|
|
|
|
|
FSdmmc *instance_p = (FSdmmc *)param;
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
|
|
|
|
|
/* clear interrupts */
|
|
|
|
|
status = FSDMMC_READ_REG(base_addr, FSDMMC_NORMAL_INT_STATUS_REG_OFFSET);
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_NORMAL_INT_STATUS_CR) /* 卡移除中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_CARD_REMOVED],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_CARD_REMOVED]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_NORMAL_INT_STATUS_CC) /* 命令完成中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_CMD_DONE],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_CMD_DONE]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_NORMAL_INT_STATUS_EI) /* 命令错误中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_CMD_ERROR],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_CMD_ERROR]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSdmmcClearNormalInterruptStatus(base_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcDmaInterrupHandler
|
|
|
|
|
* @msg: DMA中断响应函数
|
|
|
|
|
* @return {*}
|
|
|
|
|
* @param {s32} vector 中断向量号
|
|
|
|
|
* @param {void} *param 中断响应输入参数
|
|
|
|
|
* @note 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
*/
|
|
|
|
|
void FSdmmcDmaInterrupHandler(s32 vector, void *param)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(param);
|
|
|
|
|
u32 status;
|
|
|
|
|
FSdmmc *instance_p = (FSdmmc *)param;
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
|
|
|
|
|
/* clear interrupts */
|
|
|
|
|
status = FSDMMC_READ_REG(base_addr, FSDMMC_BD_ISR_REG_OFFSET);
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_DAIS) /* DMA 错误中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_DATA_ERROR],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_DATA_ERROR]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_RESPE) /* 读 SD 卡操作,AXI BR 通道完成中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_DATA_READ_DONE],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_DATA_READ_DONE]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_DATFRAX) /* AXI 总线强制释放中断*/
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_BD_ISR_REG_DATFRAX");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_NRCRC) /* 无 CRC 响应中断*/
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_BD_ISR_REG_NRCRC");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_TRE) /* CRC 响应错误中断*/
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_BD_ISR_REG_TRE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_CMDE) /* 命令响应错误中断*/
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_BD_ISR_REG_CMDE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_DTE) /* 超时中断*/
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_BD_ISR_REG_DTE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_BD_ISR_REG_TRS) /* DMA 传输完成中断*/
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_DATA_WRITE_DONE],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_DATA_WRITE_DONE]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSdmmcClearBDInterruptStatus(base_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcErrInterrupHandler
|
|
|
|
|
* @msg: 错误中断响应函数
|
|
|
|
|
* @return {*}
|
|
|
|
|
* @param {s32} vector 中断向量号
|
|
|
|
|
* @param {void} *param 中断响应输入参数
|
|
|
|
|
* @note 此函数用于设置FSDMMC中断时注册,用户可以自定义一个中断响应函数替换此函数
|
|
|
|
|
*/
|
|
|
|
|
void FSdmmcErrInterrupHandler(s32 vector, void *param)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(param);
|
|
|
|
|
u32 status;
|
|
|
|
|
FSdmmc *instance_p = (FSdmmc *)param;
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
|
|
|
|
|
status = FSDMMC_READ_REG(base_addr, FSDMMC_ERROR_INT_STATUS_REG_OFFSET);
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_ERROR_INT_STATUS_CNR) /* 命令响应错误中断 */
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSdmmcCallEvtHandler(instance_p->evt_handler[FSDMMC_EVT_CMD_RESP_ERROR],
|
|
|
|
|
instance_p->evt_args[FSDMMC_EVT_CMD_RESP_ERROR]);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_ERROR_INT_STATUS_CIR) /* 命令索引错误中断 */
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_ERROR_INT_STATUS_CIR");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_ERROR_INT_STATUS_CCRCE) /* 命令 CRC 错误中断 */
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_ERROR_INT_STATUS_CCRCE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status & FSDMMC_ERROR_INT_STATUS_CTE) /* 命令超时错误中断 */
|
|
|
|
|
{
|
|
|
|
|
FSDMMC_ERROR("FSDMMC_ERROR_INT_STATUS_CTE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* clear command error status */
|
|
|
|
|
FSdmmcClearErrorInterruptStatus(base_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcRegisterInterruptHandler
|
|
|
|
|
* @msg: 注册中断事件响应函数
|
|
|
|
|
* @return {*}
|
|
|
|
|
* @param {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
* @param {u32} event FSDMMC中断事件类型,参考FSDMMC_EVT_NUM
|
|
|
|
|
* @param {FSdmmcEventHandler} handler, FSDMMC中断事件响应函数
|
|
|
|
|
* @note 此函数用于设置FSDMMC中断时注册,被注册的函数被FSdmmcCmdInterrupHandler、FSdmmcErrInterrupHandler
|
|
|
|
|
* 和FSdmmcDmaInterrupHandler调用
|
|
|
|
|
*/
|
2023-05-11 10:25:21 +08:00
|
|
|
|
void FSdmmcRegisterInterruptHandler(FSdmmc *instance_p, u32 event, FSdmmcEventHandler handler, void *args)
|
2022-11-10 22:22:48 +08:00
|
|
|
|
{
|
|
|
|
|
FASSERT(instance_p);
|
|
|
|
|
instance_p->evt_handler[event] = handler;
|
2023-05-11 10:25:21 +08:00
|
|
|
|
instance_p->evt_args[event] = args;
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FSdmmcInterruptTransfer
|
|
|
|
|
* @msg: 通过FSDMMC中断方式发送/接收数据和命令
|
|
|
|
|
* @return {FError} 驱动初始化的错误码信息,FSDMMC_SUCCESS 表示发送/接收成功,其它返回值表示发送/接收失败
|
|
|
|
|
* @param {FSdmmc} *instance_p FSDMMC驱动控制数据
|
|
|
|
|
* @param {FSdmmcCmd} *cmd_data_p FSDMMC数据和命令
|
|
|
|
|
* @note FSDMMC控制器初始化后才能调用此函数,使用前需要确保FSDMMC中断设置完成
|
|
|
|
|
*/
|
|
|
|
|
FError FSdmmcInterruptTransfer(FSdmmc *instance_p, FSdmmcCmd *cmd_data_p)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(instance_p && cmd_data_p);
|
|
|
|
|
uintptr base_addr = instance_p->config.base_addr;
|
|
|
|
|
FError ret = FSDMMC_SUCCESS;
|
|
|
|
|
|
|
|
|
|
if (FALSE == FSdmmcCheckIfCardExists(base_addr))
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FSDMMC_ERROR("Card not found !!! fsdio ctrl base 0x%x", base_addr);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
return FSDMMC_ERR_CARD_NO_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cmd_data_p->flag & FSDMMC_CMD_FLAG_EXP_DATA)
|
|
|
|
|
{
|
|
|
|
|
/* transfer data */
|
|
|
|
|
FSDMMC_INFO("====DATA [%d] START: buf: %p=====", cmd_data_p->cmdidx, cmd_data_p->data_p);
|
|
|
|
|
ret = FSdmmcSendData(base_addr,
|
|
|
|
|
(FSDMMC_CMD_FLAG_READ_DATA == (cmd_data_p->flag & FSDMMC_CMD_FLAG_READ_DATA)),
|
|
|
|
|
cmd_data_p);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* transfer command */
|
|
|
|
|
FSDMMC_INFO("=====CMD [%d] START=====", cmd_data_p->cmdidx);
|
|
|
|
|
FSdmmcSendCmd(base_addr, cmd_data_p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|