📄 mpc8240epic.c
字号:
/* mpc8240Epic.c - EPIC Interrupt Controller driver */
/* Copyright 1984-2000 Wind River Systems, Inc. */
/* Copyright 1996-2000 Motorola, Inc., All Rights Reserved */
#include "copyright_wrs.h"
/*
modification history
--------------------
01a,28feb00,rhk created from version 01d, MV2100 BSP.
*/
/*
DESCRIPTION
This module implements the EPIC interrupt controller functionality.
*/
/* includes */
#include "mpc8240.h"
#include "mpc8240Epic.h"
/* defines */
/* globals */
IMPORT STATUS (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);
IMPORT int (*_func_intEnableRtn) (int);
IMPORT int (*_func_intDisableRtn) (int);
IMPORT UINT32 sysPciInLong (UINT32);
IMPORT void sysPciOutLong (UINT32, UINT32);
IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
IMPORT UINT sysGetMpuSpd(void);
IMPORT void sysDecDelay (UINT usDelay);
void sysEpicIntHandler (void);
/* system interrupt table */
#define SYSTEM_INTERRUPT_TABLE_SIZE 256
INT_HANDLER_DESC * sysIntTbl [SYSTEM_INTERRUPT_TABLE_SIZE];
#ifdef INCLUDE_INSTRUMENTATION
IMPORT int evtTimeStamp;
#endif
/* forward declarations */
LOCAL int getEpicVecAddr (int);
LOCAL STATUS sysEpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine,
int parameter);
LOCAL int sysEpicIntEnable (int);
LOCAL int sysEpicIntDisable (int);
LOCAL int getEpicPrio(UINT32 vecRegAddr);
#ifndef CPU_INT_LOCK
# define CPU_INT_LOCK(x) \
(*x = intLock ())
#endif
#ifndef CPU_INT_UNLOCK
# define CPU_INT_UNLOCK(data) \
(intUnlock (data))
#endif
/*******************************************************************************
*
* epicCurTaskPrioSet - set the priority of the current task.
*
* NOTES
*
* epicCurTaskPrioSet sets the priority of the Processor Current Task
* Priority register to the value of the prioNum parameter. This function
* should be called after sysEpicInit() to lower the priority of the processor
* current task. Note that valid priority values are 0 through 15 (15 being
* the highest priority)
*
* NOMANUAL
*
* RETURNS: previous priority of the task.
*
* This function added by xdg, 00.10.13
*/
ULONG epicCurTaskPrioSet
(
int prioNum
)
{
ULONG oldPrio;
if ((prioNum < 0) || (prioNum > 15))
{
return (EPIC_INV_PRIO_ERROR);
}
oldPrio = sysPciInLong ((UINT32)EPIC_CUR_TASK_PRI_REG);
sysPciOutLong ((UINT32)EPIC_CUR_TASK_PRI_REG, (UINT32)prioNum);
return (oldPrio);
}
/******************************************************************************
*
* sysEpicInit - initialize the EPIC
*
* This function initializes the Embedded Programmable Interrupt Controller
* (EPIC) contained in the Mpc8240 chip.
*
* It first initializes the system vector table, connects the EPIC interrupt
* handler to the PPC external interrupt and attaches the local EPIC routines
* for interrupt connecting, enabling and disabling to the corresponding system
* routine pointers.
*
* It then initializes the EPIC registers, clears any pending EPIC interrupts,
* and enables interrupt handling by the EPIC.
*
* RETURNS: OK always
*/
STATUS sysEpicInit (void)
{
int i;
UINT32 temp = 0;
/* Initialize the interrupt table */
for (i = 0; i < SYSTEM_INTERRUPT_TABLE_SIZE; i++)
sysIntTbl[i] = NULL;
/*reset the EPIC unit*/
sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, 0x80000000);
/* wait for the reset sequence to be completed */
while(sysPciInLong((UINT32)EPIC_GLOBAL_CONFIG_REG)&0x80000000)
{
;
}
/* Initialze the global timer frequency to the MPU speed. */
#if(0)
sysPciOutLong((UINT32)EPIC_TIMER_FREQ_REG, sysGetMpuSpd());
#endif
/* Initialze the 4 global timer interrupt sources */
sysPciOutLong((UINT32)EPIC_TIMER0_VEC_PRI_REG, INIT_TMR_SRC0);
sysPciOutLong((UINT32)EPIC_TIMER1_VEC_PRI_REG, INIT_TMR_SRC0);
sysPciOutLong((UINT32)EPIC_TIMER2_VEC_PRI_REG, INIT_TMR_SRC0);
sysPciOutLong((UINT32)EPIC_TIMER3_VEC_PRI_REG, INIT_TMR_SRC0);
#if(0)
/* Initialize the 16 serial interrupt sources */
sysPciOutLong((UINT32)EPIC_SER_SRC0_VEC_PRI_REG, INIT_SER_SRC0);
sysPciOutLong((UINT32)EPIC_SER_SRC1_VEC_PRI_REG, INIT_SER_SRC1);
sysPciOutLong((UINT32)EPIC_SER_SRC2_VEC_PRI_REG, INIT_SER_SRC2);
sysPciOutLong((UINT32)EPIC_SER_SRC3_VEC_PRI_REG, INIT_SER_SRC3);
sysPciOutLong((UINT32)EPIC_SER_SRC4_VEC_PRI_REG, INIT_SER_SRC4);
sysPciOutLong((UINT32)EPIC_SER_SRC5_VEC_PRI_REG, INIT_SER_SRC5);
sysPciOutLong((UINT32)EPIC_SER_SRC6_VEC_PRI_REG, INIT_SER_SRC6);
sysPciOutLong((UINT32)EPIC_SER_SRC7_VEC_PRI_REG, INIT_SER_SRC7);
sysPciOutLong((UINT32)EPIC_SER_SRC8_VEC_PRI_REG, INIT_SER_SRC8);
sysPciOutLong((UINT32)EPIC_SER_SRC9_VEC_PRI_REG, INIT_SER_SRC9);
sysPciOutLong((UINT32)EPIC_SER_SRC10_VEC_PRI_REG, INIT_SER_SRC10);
sysPciOutLong((UINT32)EPIC_SER_SRC11_VEC_PRI_REG, INIT_SER_SRC11);
sysPciOutLong((UINT32)EPIC_SER_SRC12_VEC_PRI_REG, INIT_SER_SRC12);
sysPciOutLong((UINT32)EPIC_SER_SRC13_VEC_PRI_REG, INIT_SER_SRC13);
sysPciOutLong((UINT32)EPIC_SER_SRC14_VEC_PRI_REG, INIT_SER_SRC14);
sysPciOutLong((UINT32)EPIC_SER_SRC15_VEC_PRI_REG, INIT_SER_SRC15);
#else
/* Initialize the 4 external interrupt sources */
sysPciOutLong((UINT32)EPIC_EXT_SRC0_VEC_PRI_REG, INIT_EXT_SRC0);
sysPciOutLong((UINT32)EPIC_EXT_SRC1_VEC_PRI_REG, INIT_EXT_SRC1);
sysPciOutLong((UINT32)EPIC_EXT_SRC2_VEC_PRI_REG, INIT_EXT_SRC2);
sysPciOutLong((UINT32)EPIC_EXT_SRC3_VEC_PRI_REG, INIT_EXT_SRC3);
sysPciOutLong((UINT32)EPIC_EXT_SRC4_VEC_PRI_REG, INIT_EXT_SRC4);
#endif
/* Initialize the 2 DMA interrupt sources */
sysPciOutLong((UINT32)EPIC_DMA_CHAN0_INTR_VEC_SRC, INIT_DMA_SRC0);
sysPciOutLong((UINT32)EPIC_DMA_CHAN1_INTR_VEC_SRC, INIT_DMA_SRC1);
/* Initialize the I2C unit interrupt source */
sysPciOutLong((UINT32)EPIC_I2C_INTR_VEC_SRC, INIT_I2C_SRC);
/* Initialize the message unit interrupt source. */
sysPciOutLong((UINT32)EPIC_MSG_UNIT_INTR_VEC_SRC, INIT_MSGUNIT_SRC);
sysPciOutLong((UINT32)EPIC_DUART_CHAN1_INTR_VEC_SRC, INIT_DUART_SRC1);
sysPciOutLong((UINT32)EPIC_DUART_CHAN2_INTR_VEC_SRC, INIT_DUART_SRC2);
/* Setup the EPIC to mixed mode. */
temp = sysPciInLong((UINT32)EPIC_GLOBAL_CONFIG_REG );
sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, (temp | EPIC_GC_MIXED));
/* Set to direct-interrupt mode (5 extern int sources) and clock ratio to 4. */
temp = sysPciInLong((UINT32)EPIC_INTR_CONFIG_REG);
temp = temp & (~EPIC_IC_R_MASK);
sysPciOutLong((UINT32)EPIC_INTR_CONFIG_REG, (temp |
(EPIC_IC_R_VALUE << EPIC_IC_R_SHFT)));
/* Clear all pending interrupt */
while(sysPciInLong((UINT32)EPIC_IACK_REG)!=0xff)
{
;
}
/* connect the interrupt demultiplexer to the PowerPC external interrupt */
#if(1)
excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysEpicIntHandler);
/* attach the BSP specific routines to the operating system. */
_func_intConnectRtn = sysEpicIntConnect;
_func_intEnableRtn = sysEpicIntEnable;
_func_intDisableRtn = sysEpicIntDisable;
#endif
/* Enable interrupts for this processor (1 and above). */
epicCurTaskPrioSet( EPIC_TASK_PRI_0 );
return(OK);
}
/******************************************************************************
*
* sysEpicIntConnect - connect an interrupt handler to the system vector table
*
* This function connects an interrupt handler to the system vector table.
*
* RETURNS: OK/ERROR.
*/
LOCAL STATUS sysEpicIntConnect
(
VOIDFUNCPTR * vector, /* interrupt vector to attach */
VOIDFUNCPTR routine, /* routine to be called */
int parameter /* parameter to be passed to routine */
)
{
INT_HANDLER_DESC * newHandler;
INT_HANDLER_DESC * currHandler;
LOCAL_INT_DATA connect;
BOOL sharing = FALSE;
/* validate the vector */
if (((int)vector < 0) || ((int)vector > (SYSTEM_INTERRUPT_TABLE_SIZE - 1)))
return (ERROR);
/* create a new interrupt handler */
if ((newHandler = (INT_HANDLER_DESC *)calloc (1, sizeof (INT_HANDLER_DESC)))
== NULL)
return (ERROR);
/* initialize the new handler */
newHandler->vec = routine;
newHandler->arg = parameter;
newHandler->next = NULL;
/* install the handler in the system interrupt table */
if (sysIntTbl[(int)vector] == NULL)
{
sysIntTbl[(int)vector] = newHandler; /* single int. handler case */
}
else
{
currHandler = sysIntTbl[(int)vector]; /* multiple int. handler case */
while (currHandler->next != NULL)
{
currHandler = currHandler->next;
}
currHandler->next = newHandler;
sharing = TRUE;
}
/*
* if the connect is for an EPIC interrupt,
* then store the vector into the appropriate EPIC vector register
*/
if (!sharing)
{
connect.regAddr = getEpicVecAddr((int)vector);
if (connect.regAddr > 0)
{
/* read the vector register */
connect.regVal = sysPciInLong((UINT32)(connect.regAddr));
/* store the interrupt vector number */
connect.regVal |= (int)vector;
/* write the contents of the vector register back */
sysPciOutLong((UINT32)(connect.regAddr), connect.regVal);
}
else
{
return ERROR;
}
}
return (OK);
}
/******************************************************************************
*
* sysEpicIntEnable - enable an Epic interrupt level
*
* This routine enables a specified Epic interrupt level.
*
* RETURNS: OK or ERROR if interrupt level not supported
*/
LOCAL int sysEpicIntEnable
(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -