rt-thread/bsp/phytium/libraries/standalone/drivers/nand/fnand/fnand_intr.c

205 lines
6.5 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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: fnand_intr.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 08:56:46
* Description:  This file contains functions related to fnand interrupt handling.
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 huanghe 2022/05/10 first release
*/
#include "fnand.h"
#include "fnand_hw.h"
#include "fassert.h"
#include "ferror_code.h"
#include "fdebug.h"
#define FNAND_INTR_DEBUG_TAG "FNAND_INTR"
#define FNAND_INTR_ERROR(format, ...) FT_DEBUG_PRINT_E(FNAND_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define FNAND_INTR_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FNAND_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define FNAND_INTR_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FNAND_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define FNAND_INTR_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FNAND_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
/**
* @name: FNandIsrEnable
* @msg: Enable the corresponding interrupt based on the interrupt mask
* @return {*}
* @note:
* @param {FNand} *instance_p is the pointer to the FNand instance
* @param {u32} int_mask is interrupt mask
*/
void FNandIsrEnable(FNand *instance_p, u32 int_mask)
{
u32 reg_value;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
FNandConfig *config_p;
config_p = &instance_p->config;
FNAND_CLEARBIT(config_p->base_address, FNAND_INTRMASK_OFFSET, int_mask);
}
/**
* @name: FNandIrqDisable
* @msg: Disable the corresponding interrupt based on the interrupt mask
* @note:
* @param {FNand} *instance_p is the pointer to the FNand instance
* @param {u32} int_mask is interrupt mask
* @return {*}
*/
void FNandIrqDisable(FNand *instance_p, u32 int_mask)
{
u32 reg_value;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
FNandConfig *config_p;
config_p = &instance_p->config;
FNAND_SETBIT(config_p->base_address, FNAND_INTRMASK_OFFSET, int_mask);
}
/**
* @name: FNandSetIsrHandler
* @msg: Initializes isr event callback function
* @note:
* @param {FNand} *instance_p is the pointer to the FNand instance.
* @param {FnandIrqEventHandler} event_p is callback function used to respond to the interrupt event
* @param {void} *irq_args is the arguments of event callback
* @return {*}
*/
void FNandSetIsrHandler(FNand *instance_p, FnandIrqEventHandler event_p, void *irq_args)
{
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
instance_p->irq_event_fun_p = event_p;
instance_p->irq_args = irq_args;
}
/**
* @name: FNandIrqHandler
* @msg: Nand driver isr handler
* @note:
* @param {s32} vector is interrupt number
* @param {void} *param is argument
* @return {*}
*/
void FNandIrqHandler(s32 vector, void *param)
{
FNand *instance_p = (FNand *)param;
FNandConfig *config_p;
u32 status;
u32 en_irq;
(void)vector;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
config_p = &instance_p->config;
status = FNAND_READREG(config_p->base_address, FNAND_INTR_OFFSET);
en_irq = (~FNAND_READREG(config_p->base_address, FNAND_INTRMASK_OFFSET)) & FNAND_INTRMASK_ALL_INT_MASK;
if ((status & en_irq) == 0)
{
FNAND_INTR_DEBUG_E("No irq exit");
return;
}
FNandIrqDisable(instance_p, status & FNAND_INTRMASK_ALL_INT_MASK);
FNAND_WRITEREG(config_p->base_address, 0xfd0, 0);
FNAND_WRITEREG(config_p->base_address, FNAND_INTR_OFFSET, status);
if (instance_p->irq_event_fun_p)
{
if (status & FNAND_INTR_BUSY_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_BUSY_EVENT);
}
if (status & FNAND_INTR_DMA_BUSY_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_DMA_BUSY_EVENT);
}
if (status & FNAND_INTR_DMA_PGFINISH_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_DMA_PGFINISH_EVENT);
}
if (status & FNAND_INTR_DMA_FINISH_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_DMA_FINISH_EVENT);
}
if (status & FNAND_INTR_FIFO_EMP_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_FIFO_EMP_EVENT);
}
if (status & FNAND_INTR_FIFO_FULL_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_FIFO_FULL_EVENT);
}
if (status & FNAND_INTR_FIFO_TIMEOUT_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_FIFO_TIMEOUT_EVENT);
}
if (status & FNAND_INTR_CMD_FINISH_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_CMD_FINISH_EVENT);
}
if (status & FNAND_INTR_PGFINISH_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_PGFINISH_EVENT);
}
if (status & FNAND_INTR_RE_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_RE_EVENT);
}
if (status & FNAND_INTR_DQS_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_DQS_EVENT);
}
if (status & FNAND_INTR_RB_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_RB_EVENT);
}
if (status & FNAND_INTR_ECC_FINISH_MASK)
{
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_ECC_FINISH_EVENT);
}
if (status & FNAND_INTR_ECC_ERR_MASK)
{
FNAND_WRITEREG(config_p->base_address, FNAND_ERROR_CLEAR_OFFSET, FNAND_ERROR_CLEAR_ECC_ERR_CLR_MASK);
FNAND_WRITEREG(config_p->base_address, FNAND_FIFO_FREE_OFFSET, FNAND_FIFO_FREE_MASK);
instance_p->irq_event_fun_p(instance_p->irq_args, FNAND_IRQ_ECC_ERR_EVENT);
}
}
}