diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c')
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c | 517 | 
1 files changed, 517 insertions, 0 deletions
| diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c new file mode 100644 index 000000000..ecbb42d0d --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c @@ -0,0 +1,517 @@ +/************************************************** + * + * copyright @ motorola, 1999 + * + *************************************************/ +#include <mpc824x.h> +#include <common.h> +#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); +    } |