205 lines
6.5 KiB
C
205 lines
6.5 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: 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);
|
||
}
|
||
}
|
||
}
|