/************************************************** * * copyright @ motorola, 1999 * *************************************************/ #include #include #include "epic.h" #define PRINT(format, args...) printf(format , ## args) typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */ struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */ { { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0"}, { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1"}, { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2"}, { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3"}, { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4"}, { EPIC_SR_INT5_VEC_REG, "External Serial Source 5"}, { EPIC_SR_INT6_VEC_REG, "External Serial Source 6"}, { EPIC_SR_INT7_VEC_REG, "External Serial Source 7"}, { EPIC_SR_INT8_VEC_REG, "External Serial Source 8"}, { EPIC_SR_INT9_VEC_REG, "External Serial Source 9"}, { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"}, { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"}, { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"}, { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"}, { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"}, { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"}, { EPIC_I2C_INT_VEC_REG, "Internal I2C Source"}, { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"}, { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"}, { EPIC_MSG_INT_VEC_REG, "Internal Message Source"}, }; VOIDFUNCPTR intVecTbl[MAXVEC]; /* Interrupt vector table */ /**************************************************************************** * epicInit - Initialize the EPIC registers * * This routine resets the Global Configuration Register, thus it: * - Disables all interrupts * - Sets epic registers to reset values * - Sets the value of the Processor Current Task Priority to the * highest priority (0xF). * epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass * Through or 8259 compatible mode). * * If IRQType (input) is Direct IRQs: * - IRQType is written to the SIE bit of the EPIC Interrupt * Configuration register (ICR). * - clkRatio is ignored. * If IRQType is Serial IRQs: * - both IRQType and clkRatio will be written to the ICR register */ void epicInit ( unsigned int IRQType, /* Direct or Serial */ unsigned int clkRatio /* Clk Ratio for Serial IRQs */ ) { ULONG tmp; tmp = sysEUMBBARRead(EPIC_GLOBAL_REG); tmp |= 0xa0000000; /* Set the Global Conf. register */ sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp); /* * Wait for EPIC to reset - CLH */ while( (sysEUMBBARRead(EPIC_GLOBAL_REG) & 0x80000000) == 1); sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000); tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); /* Read interrupt conf. reg */ if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff); else /* Serial mode */ { tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp); } while (epicIntAck() != 0xff) /* Clear all pending interrupts */ epicEOI(); } /**************************************************************************** * epicIntEnable - Enable an interrupt source * * This routine clears the mask bit of an external, an internal or * a Timer register to enable the interrupt. * * RETURNS: None */ void epicIntEnable(int intVec) { ULONG tmp; ULONG srAddr; srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */ tmp = sysEUMBBARRead(srAddr); tmp &= ~EPIC_VEC_PRI_MASK; /* Clear the mask bit */ tmp |= (EPIC_VEC_PRI_DFLT_PRI << 16); /* Set priority to Default - CLH */ tmp |= intVec; /* Set Vector number */ sysEUMBBARWrite(srAddr, tmp); return; } /**************************************************************************** * epicIntDisable - Disable an interrupt source * * This routine sets the mask bit of an external, an internal or * a Timer register to disable the interrupt. * * RETURNS: OK or ERROR * */ void epicIntDisable ( int intVec /* Interrupt vector number */ ) { ULONG tmp, srAddr; srAddr = SrcVecTable[intVec].srcAddr; tmp = sysEUMBBARRead(srAddr); tmp |= 0x80000000; /* Set the mask bit */ sysEUMBBARWrite(srAddr, tmp); return; } /**************************************************************************** * epicIntSourceConfig - Set properties of an interrupt source * * This function sets interrupt properites (Polarity, Sense, Interrupt * Prority, and Interrupt Vector) of an Interrupt Source. The properties * can be set when the current source is not in-request or in-service, * which is determined by the Activity bit. This routine return ERROR * if the the Activity bit is 1 (in-request or in-service). * * This function assumes that the Source Vector/Priority register (input) * is a valid address. * * RETURNS: OK or ERROR */ int epicIntSourceConfig ( int Vect, /* interrupt source vector number */ int Polarity, /* interrupt source polarity */ int Sense, /* interrupt source Sense */ int Prio /* interrupt source priority */ ) { ULONG tmp, newVal; ULONG actBit, srAddr; srAddr = SrcVecTable[Vect].srcAddr; tmp = sysEUMBBARRead(srAddr); actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */ if (actBit == 1) return ERROR; tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */ newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect; sysEUMBBARWrite(srAddr, tmp | newVal ); return (OK); } /**************************************************************************** * epicIntAck - acknowledge an interrupt * * This function reads the Interrupt acknowldge register and return * the vector number of the highest pending interrupt. * * RETURNS: Interrupt Vector number. */ unsigned int epicIntAck(void) { return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG )); } /**************************************************************************** * epicEOI - signal an end of interrupt * * This function writes 0x0 to the EOI register to signal end of interrupt. * It is usually called after an interrupt routine is served. * * RETURNS: None */ void epicEOI(void) { sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0); } /**************************************************************************** * epicCurTaskPrioSet - sets the priority of the Processor Current Task * * This function should be called after epicInit() to lower the priority * of the processor current task. * * RETURNS: OK or ERROR */ int epicCurTaskPrioSet ( int prioNum /* New priority value */ ) { if ( (prioNum < 0) || (prioNum > 0xF)) return ERROR; sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum); return OK; } /************************************************************************ * function: epicIntTaskGet * * description: Get value of processor current interrupt task priority register * * note: ***********************************************************************/ unsigned char epicIntTaskGet() { /* get the interrupt task priority register */ ULONG reg; unsigned char rec; reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG ); rec = ( reg & 0x0F ); return rec; } /************************************************************** * function: epicISR * * description: EPIC service routine called by the core exception * at 0x500 * * note: **************************************************************/ unsigned int epicISR(void) { return 0; } /************************************************************ * function: epicModeGet * * description: query EPIC mode, return 0 if pass through mode * return 1 if mixed mode * * note: *************************************************************/ unsigned int epicModeGet(void) { ULONG val; val = sysEUMBBARRead( EPIC_GLOBAL_REG ); return (( val & 0x20000000 ) >> 29); } /********************************************* * function: epicConfigGet * * description: Get the EPIC interrupt Configuration * return 0 if not error, otherwise return 1 * * note: ********************************************/ void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable) { ULONG val; val = sysEUMBBARRead( EPIC_INT_CONF_REG ); *clkRatio = ( val & 0x70000000 ) >> 28; *serEnable = ( val & 0x8000000 ) >> 27; } /******************************************************************* * sysEUMBBARRead - Read a 32-bit EUMBBAR register * * This routine reads the content of a register in the Embedded * Utilities Memory Block, and swaps to big endian before returning * the value. * * RETURNS: The content of the specified EUMBBAR register. */ ULONG sysEUMBBARRead ( ULONG regNum ) { ULONG temp; temp = *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum); return ( LONGSWAP(temp)); } /******************************************************************* * sysEUMBBARWrite - Write a 32-bit EUMBBAR register * * This routine swaps the value to little endian then writes it to * a register in the Embedded Utilities Memory Block address space. * * RETURNS: N/A */ void sysEUMBBARWrite ( ULONG regNum, /* EUMBBAR register address */ ULONG regVal /* Value to be written */ ) { *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum) = LONGSWAP(regVal); return ; } /******************************************************** * function: epicVendorId * * description: return the EPIC Vendor Identification * register: * * siliccon version, device id, and vendor id * * note: ********************************************************/ void epicVendorId ( unsigned int *step, unsigned int *devId, unsigned int *venId ) { ULONG val; val = sysEUMBBARRead( EPIC_VENDOR_ID_REG ); *step = ( val & 0x00FF0000 ) >> 16; *devId = ( val & 0x0000FF00 ) >> 8; *venId = ( val & 0x000000FF ); } /************************************************** * function: epicFeatures * * description: return the number of IRQ supported, * number of CPU, and the version of the * OpenEPIC * * note: *************************************************/ void epicFeatures ( unsigned int *noIRQs, unsigned int *noCPUs, unsigned int *verId ) { ULONG val; val = sysEUMBBARRead( EPIC_FEATURES_REG ); *noIRQs = ( val & 0x07FF0000 ) >> 16; *noCPUs = ( val & 0x00001F00 ) >> 8; *verId = ( val & 0x000000FF ); } /********************************************************* * function: epciTmFrequncySet * * description: Set the timer frequency reporting register ********************************************************/ void epicTmFrequencySet( unsigned int frq ) { sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq); } /******************************************************* * function: epicTmFrequncyGet * * description: Get the current value of the Timer Frequency * Reporting register * ******************************************************/ unsigned int epicTmFrequencyGet(void) { return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ; } /**************************************************** * function: epicTmBaseSet * * description: Set the #n global timer base count register * return 0 if no error, otherwise return 1. * * note: ****************************************************/ unsigned int epicTmBaseSet ( ULONG srcAddr, /* Address of the Timer Base register */ unsigned int cnt, /* Base count */ unsigned int inhibit /* 1 - count inhibit */ ) { unsigned int val = 0x80000000; /* First inhibit counting the timer */ sysEUMBBARWrite(srcAddr, val) ; /* set the new value */ val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31); sysEUMBBARWrite(srcAddr, val) ; return 0; } /*********************************************************************** * function: epicTmBaseGet * * description: Get the current value of the global timer base count register * return 0 if no error, otherwise return 1. * * note: ***********************************************************************/ unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val ) { *val = sysEUMBBARRead( srcAddr ); *val = *val & 0x7fffffff; return 0; } /*********************************************************** * function: epicTmCountGet * * description: Get the value of a given global timer * current count register * return 0 if no error, otherwise return 1 * note: **********************************************************/ unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ) { *val = sysEUMBBARRead( srcAddr ); *val = *val & 0x7fffffff; return 0; } /*********************************************************** * function: epicTmInhibit * * description: Stop counting of a given global timer * return 0 if no error, otherwise return 1 * * note: ***********************************************************/ unsigned int epicTmInhibit( unsigned int srcAddr ) { ULONG val; val = sysEUMBBARRead( srcAddr ); val |= 0x80000000; sysEUMBBARWrite( srcAddr, val ); return 0; } /****************************************************************** * function: epicTmEnable * * description: Enable counting of a given global timer * return 0 if no error, otherwise return 1 * * note: *****************************************************************/ unsigned int epicTmEnable( ULONG srcAddr ) { ULONG val; val = sysEUMBBARRead( srcAddr ); val &= 0x7fffffff; sysEUMBBARWrite( srcAddr, val ); return 0; } void epicSourcePrint(int Vect) { ULONG srcVal; srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr); PRINT("%s\n", SrcVecTable[Vect].srcName); PRINT("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr); PRINT("Vector = %ld\n", (srcVal & 0x000000FF) ); PRINT("Mask = %ld\n", srcVal >> 31); PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30); PRINT("Polarity = %ld\n", (srcVal & 0x00800000) >> 23); PRINT("Sense = %ld\n", (srcVal & 0x00400000) >> 22); PRINT("Priority = %ld\n", (srcVal & 0x000F0000) >> 16); }