📄 s3c2410intrctl.c
字号:
/* s3c2410IntrCtl.c - S2410 interrupt controller driver */
/* Copyright 1999 ARM Limited */
/*
modification history
--------------------
01b,27aug99,jpd add use of Protect Mode and Spurious Vector; doc'n updated.
01a,29jun99,jpd created.
*/
/*
This module implements the S2410 interrupt controller driver.
The S2410 interrupt controller is an 8-level priority, individually
maskable vectored interrupt controller, described in full in the
S2410M40400 Data Sheet. The interrupt controller has status and request
registers, separate enable and disable registers and supports edge- and
level-sensitive interrupts. This library provides the routines to
manage interrupts multiplexed by the S2410 interrupt controller.
The hardware supports controlling of the priority of interrupts in
hardware, and also supports hardware interrupt vectoring. The latter
feature cannot be supported by this driver, as the interrupts must, in
the first case be handled by the (hardware-independent) architecture
code, before being handled by this driver. This driver does not
currently support hardware control of interrupt priority, but
(conditionally) supports software control of interrupt priority if the
symbol S2410_INT_SOFT_PRIORITY_MAP is defined. This is done in a manner
compatible with the standard AMBA interrupt controller driver.
The S2410 interrupt controller has a number of registers. Those used by
this driver are described below under the symbolic names used herein.
S2410_INT_CSR_MODE (read/write): these are the source mode registers. They
configure the hardware priority (if used, zero otherwise) and the type
of interrupt (level, edge, high, low etc).
S2410_INT_CSR_SVEC (read/write): these are the source vector registers.
If hardware vectoring were used, the address of the interrupt handling
routine for each interrupt source would be written to the register for
each source. This driver puts the interrupt level into the source
vector register for each source so that when the interrupt vector
register is read when an interrupt occurs, we have the level.
S2410_INT_CSR_ENB (write): this is the "Enable Set" register. 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.
S2410_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.
S2410_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 active but not necessarily enabled i.e. can
interrupt the processor. If S2410_INT_SOFT_PRIORITY_MAP is not #defined
(see below), the driver also uses an external array s3c2410IntLvlMask[] to
determine what should be written to S2410_INT_CSR_ENB to change
interrupt levels. This should be defined by the BSP such that
s3c2410IntLvlMask[n] has a bit set (1) for each interrupt source that
should be enabled for interrupt level <n>. For example,
s3c2410IntLvlMask[0] should be 0 so that all interrupts are disabled when
interrupt level 0 is selected.
S2410_INT_CSR_IMR (read): this is the interrupt mask register. Each data
bit that is set (1) indicates an interrupt source that is enabled. When
the contents of S2410_INT_CSR_PEND are 'and'ed together with the
contents of this register, the value obtained shows the interrupt
sources that are active and enabled.
S2410_INT_CSR_VECT (read): this contains the interrupt "vector": a value
that was placed into the hardware when configuring a particular
interrupt source. If software priority control is used, then the value
read is discarded, but otherwise is used as the current interrupt
level. When this register is read, the current interrupt level (in
hardware terms) is placed on a hardware stack, NIRQ is deasserted, the
interrupt is cleared (if edge-triggered) and sets the current interrupt
level to be the highest priority pending source.
S2410_INT_CSR_EOIC (write): any value written to this register performs
an End-of-Interrupt command. This unstacks the current interrupt level
(if any) from the hardware stack, and allows any pending interrupts to
be serviced.
The number of interrupts supported by the device i.e. the number of
bits in the S2410_INT_CSR_PEND register, is specified by
S2410_INT_NUM_LEVELS.
We assume that config.h or <bsp>.h has defined the addresses of the
controller chips registers: S2410_INT_CSR_ENB, S2410_INT_CSR_DIS,
S2410_INT_CSR_VECT, S2410_INT_CSR_IMR and S2410_INT_CSR_PEND and also the
driver constant S2410_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
S2410_INT_REG_READ(addr,result) and S2410_INT_REG_WRITE(addr,data).
This driver assumes that interrupt vector numbers (in VxWorks terms)
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 S2410_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 S2410_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.
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"
/* Defines from config.h, or <bsp>.h */
#if !defined (S2410_INT_NUM_LEVELS)
# error missing S2410 interrupt definitions
#endif
#ifndef S2410_INT_REG_READ
#define S2410_INT_REG_READ(x,result) \
((result) = (x))
#endif
#ifndef S2410_INT_REG_WRITE
#define S2410_INT_REG_WRITE(x,data) \
(x= (data))
#endif
/* Local data */
/*
* 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 S2410IntLvlEnabled;
/* forward declarations */
STATUS s2410IntLvlVecChk (int*, int*);
STATUS s2410IntLvlVecAck (int, int);
/*int s2410IntLvlChg (int);*/
STATUS s2410IntLvlEnable (int);
STATUS s2410IntLvlDisable (int);
void S2410_UndefHandler()
{
printf("-F- Undef detected\n\r");
while (1);
}
/*******************************************************************************
*
* s2410IntDevInit - 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 architecture level routines, it
* should install the pointer to the wrapper routine after calling this
* routine.
*
* By default, the driver is compiled to implement a software-
* controlled, BSP-configurable interrupt priority scheme by #defining
* S2410_INT_SOFT_PRIORITY_MAP. The order of interrupt level priority is
* undefined at the architecture level: when using software priorities in
* this driver, level 0 is highest and and indicates that all levels are
* disabled; level S2410_INT_NUM_LEVELS is the lowest and indicates that
* all levels are enabled.
*
* Alternatively, if required, this driver can be configured to
* implement a least-significant bit first interrupt priority scheme by
* undefining the symbol S2410_INT_SOFT_PRIORITY_MAP (this is then
* compatible with earlier versions of the AMBA interrupt driver). The
* driver then requires a definition of s2410IntLvlMask[].
*
* If compiled to implement software configurable interrupt
* priorities, the hardware priority scheme is currently unused by this
* driver. For this model, before this routine is called, the BSP
* should define an array of int called s2410IntLvlPriMap[], 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -