636 lines
19 KiB
C
636 lines
19 KiB
C
/* ambaIntrCtl.c - AMBA interrupt controller driver */
|
|
|
|
/* Copyright 1984-2005, Wind River Systems, Inc. */
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01k,01apr05,rec rmove warnings
|
|
01j,09feb05,rec fix manual autogenerate format problems
|
|
01i,03dec01,rec fix compiler warnings
|
|
01h,21sep98,cdp fixed intEnable/Disable(0) (TSR#115062);
|
|
corrected range check in ambaIntLvlEnable/Disable;
|
|
made AMBA_INT_CSR_MASK optional;
|
|
added configurable interrupt priorities.
|
|
01f,10mar98,jpd layout tidying.
|
|
01e,13nov97,cdp include intLib.h and remove things pulled in from it;
|
|
make default I/O access 32 (not 16) bits wide; documentation.
|
|
01d,15aug97,cdp rewritten for new interrupt structure (template 01d).
|
|
01c,14may97,jpd added conditional use of valid interrupts mask.
|
|
01b,18feb97,cdp renamed sysIntEnable/Disable and made global with result.
|
|
Tidyup for mangen. intEnable/Disable now return int.
|
|
01a,13dec96,cdp created from target/config/pid7t/intPid.c.
|
|
*/
|
|
|
|
/*
|
|
This module implements the AMBA interrupt controller driver.
|
|
|
|
The AMBA interrupt controller is a simple, generic interrupt controller
|
|
described in full in the ARM Reference Peripherals Specification. The
|
|
interrupt controller has status and request registers, separate enable
|
|
and disable registers and supports level-sensitive interrupts. This
|
|
library provides the routines to manage interrupts multiplexed by the
|
|
AMBA interrupt controller.
|
|
|
|
The AMBA interrupt controller has a number of registers. Those used by
|
|
this driver are described below under the symbolic names used herein.
|
|
|
|
AMBA_INT_CSR_ENB (write): this is the "Enable Set" register described
|
|
in the ARM Reference Peripherals Specification. When this register is
|
|
written, each data bit that is set (1) causes the corresponding
|
|
interrupt to be enabled. Bits that are clear (0) have no effect.
|
|
|
|
AMBA_INT_CSR_DIS (write): this is the "Enable Clear" register which has
|
|
the opposite effect. When this register is written, each data bit that
|
|
is set (1) causes the corresponding interrupt to be disabled. Bits
|
|
that are clear (0) have no effect.
|
|
|
|
AMBA_INT_CSR_PEND (read): this is the "Interrupt Request" register.
|
|
When this register is read, each data bit that is set (1) indicates an
|
|
interrupt source that is both active and enabled i.e. can interrupt the
|
|
processor. This driver provides a means by which bits in this register
|
|
can be masked if the particular implementation of AMBA returns bits in
|
|
an undefined state. Setting AMBA_INT_CSR_MASK to be a bitwise OR of
|
|
all the valid bits achieves the required effect. If
|
|
AMBA_INT_PRIORITY_MAP is not #defined (see below), the driver also uses
|
|
an external array ambaIntLvlMask[] to determine what should be written
|
|
to AMBA_INT_CSR_ENB to change interrupt levels. This should be defined
|
|
by the BSP such that ambaIntLvlMask[n] has a bit set (1) for each
|
|
interrupt source that should be enabled for interrupt level <n>. For
|
|
example, ambaIntLvlMask[0] should be 0 so that all interrupts are
|
|
disabled when interrupt level 0 is selected.
|
|
|
|
The number of interrupts supported by the device i.e. the number of
|
|
bits in the AMBA_INT_CSR_PEND register, is specified by
|
|
AMBA_INT_NUM_LEVELS.
|
|
|
|
We assume that config.h or <bsp>.h has defined the addresses of the
|
|
controller chips registers: AMBA_INT_CSR_ENB, AMBA_INT_CSR_DIS and
|
|
AMBA_INT_CSR_PEND and also the driver constants AMBA_INT_CSR_MASK (if
|
|
required) and AMBA_INT_NUM_LEVELS.
|
|
|
|
This driver assumes that the chip is memory-mapped and does direct
|
|
memory accesses to the registers which are assumed to be 32 bits wide.
|
|
If a different access method is needed, the BSP can redefine the macros
|
|
AMBA_INT_REG_READ(addr,result) and AMBA_INT_REG_WRITE(addr,data).
|
|
|
|
This driver assumes that interrupt vector numbers are calculated and
|
|
not the result of a special cycle on the bus. Vector numbers are
|
|
generated by adding the current interrupt level number to
|
|
AMBA_INT_VEC_BASE to generate a vector number which the architecture
|
|
level will use to invoke the proper handling routine. If a different
|
|
mapping scheme, or a special hardware routine is needed, then the BSP
|
|
should redefine the macro AMBA_INT_LVL_VEC_MAP(level,vector) to
|
|
override the version defined in this file.
|
|
|
|
This driver was designed to support a single instance of a real
|
|
device. At some point it should be upgraded to operate on an object
|
|
model and to support any number of real devices.
|
|
|
|
Priorities
|
|
==========
|
|
The order of interrupt level priority is undefined at the architecture
|
|
level. In this driver, level 0 is highest and and indicates that all
|
|
levels are disabled; level <AMBA_INT_NUM_LEVELS> is the lowest and
|
|
indicates that all levels are enabled.
|
|
|
|
By default, this driver implements a least-significant bit first
|
|
interrupt priority scheme (this is compatible with earlier versions of
|
|
this driver) which requires a definition of ambaIntLvlMask (see above).
|
|
If required, the driver can be compiled to implement a BSP-configurable
|
|
interrupt priority scheme by #defining AMBA_INT_PRIORITY_MAP. For this
|
|
model, the BSP should define an array of int called ambaIntLvlPriMap,
|
|
each element of which is a bit number to be polled. The list should be
|
|
terminated with an entry containing -1. This list is used in the
|
|
interrupt handler to check bits in the requested order and is also used
|
|
to generate a map of interrupt source to new interrupt level such that
|
|
whilst servicing an interrupt, all interrupts defined by the BSP to be
|
|
of lower priority than that interrupt are disabled. Interrupt sources
|
|
not in the list are serviced after all others in least-significant bit
|
|
first priority. (Note that the list is a list of ints rather than
|
|
bytes because it causes the current compiler to generate faster code.)
|
|
|
|
Note that in this priority system, intLevelSet(n) does not necessarily
|
|
disable interrupt bit n and all lower-priority ones but uses
|
|
ambaIntLvlPriMap to determine which interrupts should be masked e.g.
|
|
if ambaIntLvlPriMap[] contains { 9, 4, 8, 5, -1 }, intLevelSet(0)
|
|
disables all interrupt bits; intLevelSet(1) enables interrupt bit 9 but
|
|
disables interrupts 4, 8, 5 and all others not listed; intLevelSet(3)
|
|
enables interrupt bits 9, 4 and 8 but disables all others. This
|
|
enabling of interrupts only occurs if the interrupt has been explicitly
|
|
enabled via a call to ambaIntLvlEnable().
|
|
|
|
If the list is empty (contains just a terminator) or ambaIntLvlPriMap
|
|
is declared as an int pointer of value 0 (this is more efficient),
|
|
interrupts are handled as least-significant bit is highest priority.
|
|
|
|
The BSP will initialize this driver in sysHwInit2(), after initializing
|
|
the main interrupt library, usually intLibInit(). The initialization
|
|
routine, ambaIntDevInit() will setup the interrupt controller device,
|
|
it will mask off all individual interrupt sources and then set the
|
|
interrupt level to enable all interrupts. See ambaIntDevInit for more
|
|
information.
|
|
|
|
All of the functions in this library are global. This allows them to
|
|
be used by the BSP if it is necessary to create wrapper routines or to
|
|
incorporate several drivers together as one.
|
|
*/
|
|
|
|
#include "vxWorks.h"
|
|
#include "config.h"
|
|
#include "intLib.h"
|
|
|
|
IMPORT int ffsLsb (UINT32);
|
|
|
|
|
|
/* Defines from config.h, or <bsp>.h */
|
|
|
|
#if !defined (AMBA_INT_CSR_PEND) || !defined (AMBA_INT_CSR_ENB) || \
|
|
!defined (AMBA_INT_NUM_LEVELS) || !defined (AMBA_INT_CSR_DIS)
|
|
# error missing AMBA interrupt definitions
|
|
#endif
|
|
|
|
#define AMBA_INT_VEC_BASE (0x0)
|
|
|
|
|
|
/* hardware access methods */
|
|
|
|
#ifndef AMBA_INT_REG_READ
|
|
#define AMBA_INT_REG_READ(reg,result) \
|
|
((result) = *(volatile UINT32 *)(reg))
|
|
#endif /*AMBA_INT_REG_READ*/
|
|
|
|
#ifndef AMBA_INT_REG_WRITE
|
|
#define AMBA_INT_REG_WRITE(reg,data) \
|
|
(*((volatile UINT32 *)(reg)) = (data))
|
|
#endif /*AMBA_INT_REG_WRITE*/
|
|
|
|
|
|
/* Convert level number to vector number */
|
|
|
|
#ifndef AMBA_INT_LVL_VEC_MAP
|
|
#define AMBA_INT_LVL_VEC_MAP(level, vector) \
|
|
((vector) = ((level) + AMBA_INT_VEC_BASE))
|
|
#endif /* AMBA_INT_LVL_VEC_MAP */
|
|
|
|
|
|
#ifndef AMBA_INT_PRIORITY_MAP
|
|
/* Convert pending register value, to a level number */
|
|
|
|
#ifndef AMBA_INT_PEND_LVL_MAP
|
|
#define AMBA_INT_PEND_LVL_MAP(pendReg, level) \
|
|
((level) = (pendReg))
|
|
#endif /* AMBA_INT_PEND_LVL_MAP */
|
|
#endif /* AMBA_INT_PRIORITY_MAP */
|
|
|
|
|
|
/* driver constants */
|
|
|
|
#define AMBA_INT_ALL_ENABLED (AMBA_INT_NUM_LEVELS)
|
|
#define AMBA_INT_ALL_DISABLED 0
|
|
|
|
|
|
/* Local data */
|
|
|
|
/* Current interrupt level setting (ambaIntLvlChg). */
|
|
|
|
LOCAL UINT32 ambaIntLvlCurrent = AMBA_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 ambaIntLvlEnabled;
|
|
|
|
|
|
#ifdef AMBA_INT_PRIORITY_MAP
|
|
/*
|
|
* Controller masks: for each interrupt level, this provides a mask for
|
|
* the controller (see IntLvlChg).
|
|
* Mask is 32 bits * (levels + 1)
|
|
*/
|
|
|
|
LOCAL UINT32 ambaIntLvlMask[(1 + AMBA_INT_NUM_LEVELS) * sizeof(UINT32)];
|
|
|
|
|
|
/*
|
|
* Map of interrupt bit number to level: if bit n is set, ambaIntLvlMap[n]
|
|
* is the interrupt level to change to such that interrupt n and all lower
|
|
* priority ones are disabled.
|
|
*/
|
|
|
|
LOCAL int ambaIntLvlMap[AMBA_INT_NUM_LEVELS * sizeof(int)];
|
|
#endif /* AMBA_INT_PRIORITY_MAP */
|
|
|
|
|
|
/* forward declarations */
|
|
|
|
STATUS ambaIntLvlVecChk (int*, int*);
|
|
STATUS ambaIntLvlVecAck (int, int);
|
|
int ambaIntLvlChg (int);
|
|
STATUS ambaIntLvlEnable (int);
|
|
STATUS ambaIntLvlDisable (int);
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntDevInit - initialize the interrupt controller
|
|
*
|
|
* This routine will initialize the interrupt controller device, disabling all
|
|
* interrupt sources. It will also 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.
|
|
*
|
|
* If used with configurable priorities (#define AMBA_INT_PRIORITY_MAP),
|
|
* before this routine is called, ambaIntLvlPriMap should be initialised
|
|
* as a list of interrupt bits to poll in order of decreasing priority and
|
|
* terminated by an entry containing -1. If ambaIntLvlPriMap is a null
|
|
* pointer (or an empty list), the priority scheme used will be
|
|
* least-significant bit first. This is equivalent to the scheme used if
|
|
* AMBA_INT_PRIORITY_MAP is not defined but slightly less efficient.
|
|
*
|
|
* The return value ERROR indicates that the contents of
|
|
* ambaIntLvlPriMap (if used) were invalid.
|
|
*
|
|
* RETURNS: OK or ERROR if ambaIntLvlPriMap invalid.
|
|
*/
|
|
|
|
int ambaIntDevInit (void)
|
|
{
|
|
#ifdef AMBA_INT_PRIORITY_MAP
|
|
int i, j;
|
|
int level;
|
|
UINT32 bit;
|
|
|
|
/* if priorities are supplied, validate the supplied list */
|
|
|
|
if (ambaIntLvlPriMap != 0)
|
|
{
|
|
/* first check the list is terminated (VecChk requires this) */
|
|
|
|
for (i = 0; i < AMBA_INT_NUM_LEVELS; ++i)
|
|
if (ambaIntLvlPriMap[i] == -1)
|
|
break;
|
|
|
|
if (!(i < AMBA_INT_NUM_LEVELS))
|
|
return ERROR; /* no terminator */
|
|
|
|
|
|
/* now check that all are in range and that there are no duplicates */
|
|
|
|
for (i = 0; ambaIntLvlPriMap[i] != -1; ++i)
|
|
if (ambaIntLvlPriMap[i] < 0 ||
|
|
ambaIntLvlPriMap[i] >= AMBA_INT_NUM_LEVELS)
|
|
{
|
|
return ERROR; /* out of range */
|
|
}
|
|
else
|
|
for (j = i + 1; ambaIntLvlPriMap[j] != -1; ++j)
|
|
if (ambaIntLvlPriMap[j] == ambaIntLvlPriMap[i])
|
|
{
|
|
return ERROR; /* duplicate */
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Now initialise the mask array.
|
|
* For each level (in ascending order), the mask is the mask of the
|
|
* previous level with the bit for the current level set to enable it.
|
|
*/
|
|
|
|
ambaIntLvlMask[0] = 0; /* mask for level 0 = all disabled */
|
|
|
|
|
|
/* do the levels for which priority has been specified */
|
|
|
|
level = 1;
|
|
if (ambaIntLvlPriMap != 0)
|
|
{
|
|
for ( ; level <= AMBA_INT_NUM_LEVELS &&
|
|
(i = ambaIntLvlPriMap[level - 1], i >= 0); ++level)
|
|
{
|
|
/* copy previous level's mask to this one's */
|
|
|
|
ambaIntLvlMask[level] = ambaIntLvlMask[level - 1];
|
|
|
|
|
|
/* OR in the bit indicated by the next entry in PriMap[] */
|
|
|
|
ambaIntLvlMask[level] |= 1 << i;
|
|
|
|
/*
|
|
* set index in level map: to disable this interrupt and all
|
|
* lower-priority ones, select the level one less than this
|
|
*/
|
|
|
|
ambaIntLvlMap[i] = level - 1;
|
|
}
|
|
}
|
|
|
|
|
|
/* do the rest of the levels */
|
|
|
|
i = 0; /* lowest-numbered interrupt bit */
|
|
|
|
for ( ; level <= AMBA_INT_NUM_LEVELS; ++level)
|
|
{
|
|
/* copy previous level's mask to this one's */
|
|
|
|
ambaIntLvlMask[level] = ambaIntLvlMask[level - 1];
|
|
|
|
|
|
/* try to find a bit that has not yet been set */
|
|
|
|
for ( ; ; ++i)
|
|
{
|
|
bit = 1 << i;
|
|
|
|
if ((ambaIntLvlMask[level] & bit) == 0)
|
|
{
|
|
/* this bit not set so put it in the mask */
|
|
|
|
ambaIntLvlMask[level] |= bit;
|
|
|
|
/*
|
|
* set index in level map: to disable this interrupt and all
|
|
* lower-priority ones, select the level one less than this
|
|
*/
|
|
|
|
ambaIntLvlMap[i] = level - 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* install the driver routines in the architecture hooks */
|
|
|
|
sysIntLvlVecChkRtn = ambaIntLvlVecChk;
|
|
sysIntLvlVecAckRtn = ambaIntLvlVecAck;
|
|
sysIntLvlChgRtn = ambaIntLvlChg;
|
|
sysIntLvlEnableRtn = ambaIntLvlEnable;
|
|
sysIntLvlDisableRtn = ambaIntLvlDisable;
|
|
|
|
ambaIntLvlEnabled = 0; /* all sources disabled */
|
|
|
|
ambaIntLvlChg (AMBA_INT_ALL_ENABLED); /* enable all levels */
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntLvlVecChk - 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.
|
|
*
|
|
* This routine must be called with CPU interrupts disabled.
|
|
*
|
|
* 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 ambaIntLvlVecChk
|
|
(
|
|
int* pLevel, /* ptr to receive old interrupt level */
|
|
int* pVector /* ptr to receive current interrupt vector */
|
|
)
|
|
{
|
|
int newLevel;
|
|
UINT32 isr;
|
|
#ifdef AMBA_INT_PRIORITY_MAP
|
|
UINT32 *priPtr;
|
|
int bitNum;
|
|
#endif
|
|
|
|
|
|
/* Read pending interrupt register and mask undefined bits */
|
|
|
|
AMBA_INT_REG_READ (AMBA_INT_CSR_PEND, isr);
|
|
#ifdef AMBA_INT_CSR_MASK
|
|
isr &= AMBA_INT_CSR_MASK;
|
|
#endif
|
|
|
|
/* If no interrupt is pending, return ERROR */
|
|
|
|
if (isr == 0)
|
|
return ERROR;
|
|
|
|
|
|
#ifdef AMBA_INT_PRIORITY_MAP
|
|
priPtr = (UINT32 *)ambaIntLvlPriMap;
|
|
|
|
/* service interrupts according to priority specifed in map */
|
|
|
|
while (bitNum = *priPtr++, bitNum != -1)
|
|
{
|
|
/* bitNum = interrupt bit from priority map */
|
|
|
|
if (isr & (1 << bitNum))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* if priority scan didn't find anything, look for any bit set,
|
|
* starting with the lowest-numbered bit
|
|
*/
|
|
|
|
if (bitNum == -1)
|
|
bitNum = ffsLsb (isr) - 1; /* ffsLsb returns numbers from 1, not 0 */
|
|
|
|
|
|
/* if no interrupt is pending, return ERROR */
|
|
|
|
if (bitNum == -1)
|
|
return ERROR;
|
|
|
|
|
|
/* map the interrupting device to an interrupt level number */
|
|
|
|
newLevel = ambaIntLvlMap[bitNum];
|
|
#else
|
|
/* find first bit set in ISR, starting from lowest-numbered bit */
|
|
|
|
if (newLevel = ffsLsb (isr), newLevel == 0)
|
|
return ERROR;
|
|
|
|
--newLevel; /* ffsLsb returns numbers from 1, not 0 */
|
|
|
|
|
|
/* map the interrupting device to an interrupt level number */
|
|
|
|
AMBA_INT_PEND_LVL_MAP (newLevel, newLevel);
|
|
#endif /* ifdef AMBA_INT_PRIORITY_MAP */
|
|
|
|
|
|
/* change to new interrupt level, returning previous level to caller */
|
|
|
|
*pLevel = ambaIntLvlChg (newLevel);
|
|
|
|
|
|
/* fetch, or compute the interrupt vector number */
|
|
|
|
#ifdef AMBA_INT_PRIORITY_MAP
|
|
AMBA_INT_LVL_VEC_MAP (bitNum, *pVector);
|
|
#else
|
|
AMBA_INT_LVL_VEC_MAP (newLevel, *pVector);
|
|
#endif
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntLvlVecAck - acknowledge the current interrupt
|
|
*
|
|
* Acknowledge the current interrupt cycle. The level and vector values are
|
|
* those generated during the ambaIntLvlVecChk() routine for this interrupt
|
|
* cycle. The basic action is to reset the current interrupt and return
|
|
* the interrupt level to its previous setting. Note that the AMBA interrupt
|
|
* controller does not need an acknowledge cycle.
|
|
*
|
|
* RETURNS: OK or ERROR if a hardware fault is detected.
|
|
*/
|
|
|
|
STATUS ambaIntLvlVecAck
|
|
(
|
|
int level, /* old interrupt level to be restored */
|
|
int vector /* current interrupt vector, if needed */
|
|
)
|
|
{
|
|
/* restore the previous interrupt level */
|
|
|
|
ambaIntLvlChg (level);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntLvlChg - change the interrupt level value
|
|
*
|
|
* This routine implements the overall interrupt setting. All levels
|
|
* up to and including the specifed level are disabled. All levels above
|
|
* the specified level will be enabled, but only if they were specifically
|
|
* enabled by the ambaIntLvlEnable() routine.
|
|
*
|
|
* The specific priority level AMBA_INT_NUM_LEVELS is valid and represents
|
|
* all levels enabled.
|
|
*
|
|
* RETURNS: Previous interrupt level.
|
|
*/
|
|
|
|
int ambaIntLvlChg
|
|
(
|
|
int level /* new interrupt level */
|
|
)
|
|
{
|
|
int oldLevel;
|
|
|
|
oldLevel = ambaIntLvlCurrent;
|
|
|
|
if (level >= 0 &&
|
|
level <= AMBA_INT_NUM_LEVELS)
|
|
{
|
|
/* change current interrupt level */
|
|
|
|
ambaIntLvlCurrent = level;
|
|
}
|
|
|
|
/* Switch off all interrupts */
|
|
|
|
AMBA_INT_REG_WRITE (AMBA_INT_CSR_DIS, (UINT32)-1);
|
|
|
|
/* Activate the enabled interrupts */
|
|
|
|
AMBA_INT_REG_WRITE (AMBA_INT_CSR_ENB,
|
|
(ambaIntLvlMask[ambaIntLvlCurrent] & ambaIntLvlEnabled));
|
|
|
|
return oldLevel;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntLvlEnable - 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 to
|
|
* enable interrupts of this priority (as configured by ambaIntLvlPriMap,
|
|
* if appropriate). 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 ambaIntLvlEnable
|
|
(
|
|
int level /* level to be enabled */
|
|
)
|
|
{
|
|
int key;
|
|
|
|
if (level < 0 ||
|
|
level >= AMBA_INT_NUM_LEVELS)
|
|
return ERROR;
|
|
|
|
|
|
/* set bit in enable mask */
|
|
|
|
key = intLock ();
|
|
ambaIntLvlEnabled |= (1 << level);
|
|
intUnlock (key);
|
|
|
|
ambaIntLvlChg (-1); /* reset current mask */
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ambaIntLvlDisable - 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 to enable interrupts of this priority (as configured by
|
|
* ambaIntLvlPriMap, if appropriate).
|
|
*
|
|
* RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
|
|
*/
|
|
|
|
STATUS ambaIntLvlDisable
|
|
(
|
|
int level /* level to be disabled */
|
|
)
|
|
{
|
|
int key;
|
|
|
|
if (level < 0 ||
|
|
level >= AMBA_INT_NUM_LEVELS)
|
|
return ERROR;
|
|
|
|
|
|
/* clear bit in enable mask */
|
|
|
|
key = intLock ();
|
|
ambaIntLvlEnabled &= ~(1 << level);
|
|
intUnlock (key);
|
|
|
|
ambaIntLvlChg (-1); /* reset current mask */
|
|
|
|
return OK;
|
|
}
|