📄 s3c2410xintrctl.c
字号:
/* s3c2410xIntrCtl.c - s3c2410x interrupt controller driver */
/* Copyright 2004, HITSAT, Inc. */
#include "vxWorks.h"
#include "config.h"
IMPORT FUNCPTR sysIntLvlVecChkRtn;
IMPORT FUNCPTR sysIntLvlEnableRtn;
IMPORT FUNCPTR sysIntLvlDisableRtn;
/* hardware access methods */
#ifndef s3c2410x_INT_REG_READ
#define s3c2410x_INT_REG_READ(reg,result) \
((result) = *(volatile UINT32 *)(reg))
#endif
#ifndef s3c2410x_INT_REG_WRITE
#define s3c2410x_INT_REG_WRITE(reg,data) \
(*((volatile UINT32 *)(reg)) = (data))
#endif
/* Local data
#define s3c2410x_INT_ALL_ENABLED (s3c2410x_INT_NUM_LEVELS)
#define s3c2410x_INT_ALL_DISABLED (s3c2410x_INT_NUM_LEVELS-1)
*/
/* Current interrupt level setting (s3c2410xIntLvlChg). */
/*LOCAL UINT32 s3c2410xIntLvlCurrent = s3c2410x_INT_ALL_DISABLED; all levels disabled */
/*
* A mask word. Bits are set in this word when a specific level
* is enabled. It is used to mask off individual levels that have
* not been explicitly enabled.
*/
LOCAL UINT32 s3c2410xIntLvlEnabled;
/* forward declarations */
STATUS s3c2410xIntLvlVecChk (int*, int*);
STATUS s3c2410xIntLvlEnable (int);
STATUS s3c2410xIntLvlDisable (int);
/*
* s3c2410xIntDevInit - initialize the interrupt controller
*
* This routine will:
* <1> Initialize the interrupt controller device;
* <2> Disabling all interrupt sources;
* <3> Connect the device driver specific routines into the architecture level hooks.
*
* If the BSP needs to create a wrapper routine around any of the arhitecture level routines,
* it should install the pointer to the wrapper routine after calling this routine.
*
* RETURNS: N/A.
*/
int s3c2410xIntDevInit (void)
{
UINT32 tempUINT32 = 0;
/* <1> Initialize the interrupt controller device; */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTMSK,0xfeffffbf); /* Mask all Interrupt. */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTSUBMSK,0x7ff); /* Mask all subInterrupt. */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_SUBSRCPND,tempUINT32);
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SUBSRCPND,tempUINT32); /* Clear SUBSRCPND */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_SRCPND,tempUINT32);
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SRCPND,tempUINT32); /* Clear SRCPND */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_INTPND,tempUINT32);
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTPND,tempUINT32); /* Clear INTPND. */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTMOD,0); /* Select IRQ mode. */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_PRIORITY,0); /* Set priority. */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_EINTSTYLE,EINT0_7_STYLE);
/* <3> Install the driver routines in the architecture hooks */
sysIntLvlVecChkRtn = s3c2410xIntLvlVecChk;
sysIntLvlEnableRtn = s3c2410xIntLvlEnable;
sysIntLvlDisableRtn = s3c2410xIntLvlDisable;
/* all sources disabled */
s3c2410xIntLvlEnabled = 0;
return OK;
}
/*
* s3c2410xIntLvlVecChk - check for and return any pending interrupts
*
* This routine interrogates the hardware to determine the highest priority
* interrupt pending. It returns the vector associated with that interrupt, and
* also the interrupt priority level prior to the interrupt (not the
* level of the interrupt). The current interrupt priority level is then
* raised to the level of the current interrupt so that only higher priority
* interrupts will be accepted until this interrupt is finished.
*
* The return value ERROR indicates that no pending interrupt was found and
* that the level and vector values were not returned.
*
* RETURNS: OK or ERROR if no interrupt is pending.
*/
STATUS s3c2410xIntLvlVecChk
(
int* pLevel, /* ptr to receive old interrupt level */
int* pVector /* ptr to receive current interrupt vector */
)
{
UINT32 tempUINT32;
/* Read pending interrupt register and mask undefined bits */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_INTPND, tempUINT32);
/* If no interrupt is pending, return ERROR */
if((tempUINT32 & s3c2410x_INT_CSR_MASK_VAL) == 0) return ERROR;
/* get the number of the pending interrupt */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_INTOFFSET, tempUINT32);
*pVector = tempUINT32;
/* Ack interrupt for this level. */
if((1<<tempUINT32)&((1<<INT_LVL_ADC)|(1<<INT_LVL_UART_0)|(1<<INT_LVL_UART_1)|(1<<INT_LVL_UART_2)))
{
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTSUBMSK, 0x7ff);
}
/* s3c2410xIntLvlDisable(tempUINT32); */
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SRCPND, (1<<tempUINT32));
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTPND, (1<<tempUINT32));
return OK;
}
/*
* s3c2410xIntLvlEnable - enable a single interrupt level
*
* Enable a specific interrupt level. The enabled level will be allowed to
* generate an interrupt, when the overall interrupt level is set below the
* specified level. Without being enabled, the interrupt is blocked regardless
* of the overall interrupt level setting.
*
* RETURNS: OK or ERROR if the specified level cannot be enabled.
*/
STATUS s3c2410xIntLvlEnable
(
int level /* level to be enabled */
)
{
int key;
if(level < 0 || level >= s3c2410x_INT_NUM_LEVELS) return ERROR;
/* set bit in enable mask */
key = intLock();
s3c2410xIntLvlEnabled |= (1 << level);
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTMSK, ((~s3c2410xIntLvlEnabled) & s3c2410x_INT_CSR_MASK_VAL));
intUnlock(key);
return OK;
}
/*
* s3c2410xIntLvlDisable - disable a single interrupt level
*
* Disable a specific interrupt level. The disabled level is prevented
* from generating an interrupt even if the overall interrupt level is set
* below the specified level.
*
* RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
*/
STATUS s3c2410xIntLvlDisable
(
int level /* level to be disabled */
)
{
int key;
if(level < 0 || level >= s3c2410x_INT_NUM_LEVELS) return ERROR;
/* clear bit in enable mask */
key = intLock();
s3c2410xIntLvlEnabled &= ~(1 << level);
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTMSK, ((~s3c2410xIntLvlEnabled) & s3c2410x_INT_CSR_MASK_VAL));
intUnlock(key);
return OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -