diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc824x/drivers')
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/README | 102 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/epic.h | 163 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c | 517 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S | 196 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S | 57 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/errors.h | 212 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c | 270 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc824x/drivers/i2c_export.h | 103 | 
9 files changed, 1621 insertions, 0 deletions
| diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic.h new file mode 100644 index 000000000..2803f631c --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic.h @@ -0,0 +1 @@ +#include "epic/epic.h" diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/README b/arch/powerpc/cpu/mpc824x/drivers/epic/README new file mode 100644 index 000000000..57989969b --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic/README @@ -0,0 +1,102 @@ +CONTENT: + +   epic.h +   epic1.c +   epic2.s + +WHAT ARE THESE FILES: + +These files contain MPC8240 (Kahlua) EPIC +driver routines. The driver routines are not +written for any specific operating system. +They serves the purpose of code sample, and +jump-start for using the MPC8240 EPIC unit. + +For the reason of correctness of C language +syntax, these files are compiled by Metaware +C compiler and assembler. + +ENDIAN NOTATION: + +The algorithm is designed for big-endian mode, +software is responsible for byte swapping. + +USAGE: + +1. The host system that is running on MPC8240 +   shall link the files listed here. The memory +   location of driver routines shall take into +   account of that driver routines need to run +   in supervisor mode and they process external +   interrupts. + +   The routine epic_exception shall be called by +   exception vector at location 0x500, i.e., +   603e core external exception vector. + +2. The host system is responsible for configuring +   the MPC8240 including Embedded Utilities Memory +   Block. All EPIC driver functions require the +   content of Embedded Utilities Memory Block +   Base Address Register, EUMBBAR, as the first +   parameter. + +3. Before EPIC unit of MPC8240 can be used, +   initialize EPIC unit by calling epicInit +   with the corresponding parameters. + +   The initialization shall disable the 603e +   core External Exception by calling CoreExtIntDisable( ). +   Next, call epicInit( ). Last, enable the 603e core +   External Exception by calling CoreExtIntEnable( ). + +4. After EPIC unit has been successfully initialized, +   epicIntSourceSet( ) shall be used to register each +   external interrupt source. Anytime, an external +   interrupt source can be disabled or enabled by +   calling corresponding function, epicIntDisable( ), +   or epicIntEnable( ). + +   Global Timers' resource, base count and frequency, +   can be changed by calling epicTmFrequencySet( ) +   and epicTmBaseSet( ). + +   To stop counting a specific global timer, use +   the function, epicTmInhibit while epicTmEnable +   can be used to start counting a timer. + +5. To mask a set of external interrupts that are +   are certain level below, epicIntPrioritySet( ) +   can be used. For example, if the processor's +   current task priority register is set to 0x7, +   only interrupts of priority 0x8 or higher will +   be passed to the processor. + +   Be careful when using this function. It may +   corrupt the current interrupt pending, selector, +   and request registers, resulting an invalid vetor. + +   After enabling an interrupt, disable it may also +   cause an invalid vector. User may consider using +   the spurious vector interrupt service routine to +   handle this case. + +6. The EPIC driver routines contains a set +   of utilities, Set and Get, for host system +   to query and modify the desired EPIC source +   registers. + +7. Each external interrupt source shall register +   its interrupt service routine. The routine +   shall contain all interrupt source specific +   processes and keep as short as possible. + +   Special customized end of interrupt routine +   is optional. If it is needed, it shall contain +   the external interrupt source specific end of +   interrupt process. + +   External interrupt exception vector at 0x500 +   shall always call the epicEOI just before +   rfi instruction. Refer to the routine, +   epic_exception, for a code sample. diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h new file mode 100644 index 000000000..58f81c5df --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h @@ -0,0 +1,163 @@ +/********************************************************************* + * mpc8240epic.h - EPIC module of the MPC8240 micro-controller + * + * Copyrigh 1999  Motorola Inc. + * + * Modification History: + * ===================== + * 01a,04Feb99,My  Created. + * 15Nov200, robt -modified to use in U-Boot + * +*/ + +#ifndef __INCEPICh +#define __INCEPICh + +#define ULONG unsigned long +#define MAXVEC             20 +#define MAXIRQ        5 /* IRQs */ +#define EPIC_DIRECT_IRQ     0 /* Direct interrupt type */ + +/* EPIC register addresses */ + +#define EPIC_EUMBBAR      0x40000     /* EUMBBAR of EPIC  */ +#define EPIC_FEATURES_REG (EPIC_EUMBBAR + 0x01000)/* Feature reporting */ +#define EPIC_GLOBAL_REG   (EPIC_EUMBBAR + 0x01020)/* Global config.  */ +#define EPIC_INT_CONF_REG (EPIC_EUMBBAR + 0x01030)/* Interrupt config. */ +#define EPIC_VENDOR_ID_REG  (EPIC_EUMBBAR + 0x01080)/* Vendor id */ +#define EPIC_PROC_INIT_REG  (EPIC_EUMBBAR + 0x01090)/* Processor init. */ +#define EPIC_SPUR_VEC_REG (EPIC_EUMBBAR + 0x010e0)/* Spurious vector */ +#define EPIC_TM_FREQ_REG  (EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */ + +#define EPIC_TM0_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/ +#define EPIC_TM0_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/ +#define EPIC_TM0_VEC_REG  (EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/ +#define EPIC_TM0_DES_REG  (EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */ + +#define EPIC_TM1_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/ +#define EPIC_TM1_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/ +#define EPIC_TM1_VEC_REG  (EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/ +#define EPIC_TM1_DES_REG  (EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */ + +#define EPIC_TM2_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/ +#define EPIC_TM2_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/ +#define EPIC_TM2_VEC_REG  (EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/ +#define EPIC_TM2_DES_REG  (EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */ + +#define EPIC_TM3_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/ +#define EPIC_TM3_BASE_COUNT_REG (EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/ +#define EPIC_TM3_VEC_REG  (EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/ +#define EPIC_TM3_DES_REG  (EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */ + +#define EPIC_EX_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */ +#define EPIC_EX_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/ +#define EPIC_EX_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */ +#define EPIC_EX_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/ +#define EPIC_EX_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */ +#define EPIC_EX_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/ +#define EPIC_EX_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */ +#define EPIC_EX_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/ +#define EPIC_EX_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */ +#define EPIC_EX_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/ + +#define EPIC_SR_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */ +#define EPIC_SR_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */ +#define EPIC_SR_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */ +#define EPIC_SR_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/ +#define EPIC_SR_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */ +#define EPIC_SR_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/ +#define EPIC_SR_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */ +#define EPIC_SR_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/ +#define EPIC_SR_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */ +#define EPIC_SR_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/ + +#define EPIC_SR_INT5_VEC_REG  (EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */ +#define EPIC_SR_INT5_DES_REG  (EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/ +#define EPIC_SR_INT6_VEC_REG  (EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */ +#define EPIC_SR_INT6_DES_REG  (EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/ +#define EPIC_SR_INT7_VEC_REG  (EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */ +#define EPIC_SR_INT7_DES_REG  (EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/ +#define EPIC_SR_INT8_VEC_REG  (EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */ +#define EPIC_SR_INT8_DES_REG  (EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/ +#define EPIC_SR_INT9_VEC_REG  (EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */ +#define EPIC_SR_INT9_DES_REG  (EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/ + +#define EPIC_SR_INT10_VEC_REG (EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */ +#define EPIC_SR_INT10_DES_REG (EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/ +#define EPIC_SR_INT11_VEC_REG (EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */ +#define EPIC_SR_INT11_DES_REG (EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/ +#define EPIC_SR_INT12_VEC_REG (EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */ +#define EPIC_SR_INT12_DES_REG (EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/ +#define EPIC_SR_INT13_VEC_REG (EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */ +#define EPIC_SR_INT13_DES_REG (EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/ +#define EPIC_SR_INT14_VEC_REG (EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */ +#define EPIC_SR_INT14_DES_REG (EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/ +#define EPIC_SR_INT15_VEC_REG (EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */ +#define EPIC_SR_INT15_DES_REG (EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/ + +#define EPIC_I2C_INT_VEC_REG  (EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/ +#define EPIC_I2C_INT_DES_REG  (EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */ +#define EPIC_DMA0_INT_VEC_REG (EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/ +#define EPIC_DMA0_INT_DES_REG (EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */ +#define EPIC_DMA1_INT_VEC_REG (EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/ +#define EPIC_DMA1_INT_DES_REG (EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */ +#define EPIC_MSG_INT_VEC_REG  (EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/ +#define EPIC_MSG_INT_DES_REG  (EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest  */ + +#define EPIC_PROC_CTASK_PRI_REG (EPIC_EUMBBAR + 0x20080)/* Proc. current task*/ +#define EPIC_PROC_INT_ACK_REG (EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */ +#define EPIC_PROC_EOI_REG (EPIC_EUMBBAR + 0x200b0)/* End of interrupt */ + +#define EPIC_VEC_PRI_MASK      0x80000000 /* Mask Interrupt bit in IVPR */ +#define EPIC_VEC_PRI_DFLT_PRI  8          /* Interrupt Priority in IVPR */ + +/* Error code */ + +#define OK       0 +#define ERROR    -1 + +/* function prototypes */ + +void epicVendorId( unsigned int *step, +       unsigned int *devId, +       unsigned int *venId +     ); +void epicFeatures( unsigned int *noIRQs, +	     unsigned int *noCPUs, +       unsigned int *VerId ); +extern void epicInit( unsigned int IRQType, unsigned int clkRatio); +ULONG sysEUMBBARRead ( ULONG regNum ); +void sysEUMBBARWrite ( ULONG regNum, ULONG regVal); +extern void epicTmFrequencySet( unsigned int frq ); +extern unsigned int epicTmFrequencyGet(void); +extern unsigned int epicTmBaseSet( ULONG srcAddr, +		 unsigned int cnt, +		 unsigned int inhibit ); +extern unsigned int epicTmBaseGet ( ULONG srcAddr, unsigned int *val ); +extern unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ); +extern unsigned int epicTmInhibit( unsigned int timer ); +extern unsigned int epicTmEnable( ULONG srcAdr ); +extern void CoreExtIntEnable(void);  /* Enable 603e external interrupts */ +extern void CoreExtIntDisable(void); /* Disable 603e external interrupts */ +extern unsigned char epicIntTaskGet(void); +extern void epicIntTaskSet( unsigned char val ); +extern unsigned int epicIntAck(void); +extern void epicSprSet( unsigned int eumbbar, unsigned char ); +extern void epicConfigGet( unsigned int *clkRatio, +	       unsigned int *serEnable ); +extern void SrcVecTableInit(void); +extern unsigned int  epicModeGet(void); +extern void epicIntEnable(int Vect); +extern void epicIntDisable(int Vect); +extern int epicIntSourceConfig(int Vect, int Polarity, int Sense, int Prio); +extern unsigned int epicIntAck(void); +extern void epicEOI(void); +extern int epicCurTaskPrioSet(int Vect); + +struct SrcVecTable +    { +     ULONG srcAddr; +     char  srcName[40]; +    }; + +#endif   /*  EPIC_H */ 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); +    } diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S new file mode 100644 index 000000000..52d19aae8 --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S @@ -0,0 +1,196 @@ +/************************************** + * + * copyright @ Motorola, 1999 + * + **************************************/ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/processor.h> + +/********************************************* + * function: CoreExtIntEnable + * + * description: Enable 603e core external interrupt + * + * note: mtmsr is context-synchronization + **********************************************/ +		.text +		.align 2 +	.global CoreExtIntEnable +CoreExtIntEnable: +	 mfmsr    r3 + +	 ori      r3,r3,0x8000         /* enable external interrupt */ +	 mtmsr    r3 + +	 bclr 20, 0 + +/******************************************* + * function: CoreExtIntDisable + * + * description: Disable 603e core external interrupt + * + * note: + *******************************************/ +		.text +		.align 2 +	.global CoreExtIntDisable +CoreExtIntDisable: +	mfmsr    r4 + +	xor	r3,r3,r3 +	or      r3,r3,r4 + +	andis.	r4,r4,0xffff +	andi.   r3,r3,0x7fff         /* disable external interrupt */ + +	or      r3,r3,r4 +	mtmsr    r3 + +	bclr 20, 0 + +/********************************************************* + * function: epicEOI + * + * description: signal the EOI and restore machine status + *       Input: r3 - value of eumbbar + *       Output: r3 - value of eumbbar + *               r4 - ISR vector value + * note: + ********************************************************/ +		.text +		.align 2 +	.global epicEOI +epicEOI: +	lis	r5,0x0006	        /* Build End Of Interrupt Register offset */ +	ori	r5,r5,0x00b0 +	xor	r7,r7,r7	        /* Clear r7 */ +	stwbrx	r7,r5,r3	    /* Save r7, writing to this register will +					     * intidate the end of processing the +					     * highest interrupt. +			     */ +	sync + +	/* ---RESTORE MACHINE STATE */ +	mfmsr	r13		        /* Clear Recoverable Interrupt bit in MSR */ +	or      r7,r7,r13 + +	andis.  r7,r7,0xffff +	andi.	r13,r13,0x7ffd	/* (and disable interrupts) */ +	or      r13,r13,r7 +	mtmsr	r13 + +	lwz   r13,0x1c(r1)      /* pull ctr */ +	mtctr r13 + +	lwz   r13,0x18(r1)      /* pull xer */ +	mtctr r13 + +	lwz   r13,0x14(r1)      /* pull lr */ +	mtctr r13 + +	lwz	    r13,0x10(r1)	/* Pull SRR1 from stack */ +	mtspr   SRR1,r13	    /* Restore SRR1 */ + +	lwz	    r13,0xc(r1)	    /* Pull SRR0 from stack */ +	mtspr   SRR0,r13	    /* Restore SRR0 */ + +	lwz	    r13,0x8(r1)	    /* Pull User stack pointer from stack */ +	mtspr   SPRG1,r13	    /* Restore SPRG1 */ + +	lwz	r4,0x4(r1)          /* vector value */ +	lwz	r3,0x0(r1)          /* eumbbar */ +	sync + +	addi	r1,r1,0x20	/* Deallocate stack */ +	mtspr   SPRG0,r1	/* Save updated Supervisor stack pointer */ +	mfspr   r1,SPRG1	/* Restore User stack pointer */ + +	bclr     20,0 + +/*********************************************************** + * function: exception routine called by exception vector + *           at 0x500, external interrupt + * + * description: Kahlua EPIC controller + * + * input:  r3 - content of eumbbar + * output: r3 - ISR return value + *         r4 - Interrupt vector number + * note: + ***********************************************************/ + +       .text +	   .align 2 +       .global epic_exception + +epic_exception: + +	/*---SAVE MACHINE STATE TO A STACK */ +	mtspr   SPRG1,r1	/* Save User stack pointer to SPRG1 */ +	mfspr	r1,SPRG0	/* Load Supervisor stack pointer into r1 */ + +	stwu	r3,-0x20(r1)	/* Push the value of eumbbar onto stack */ + +	mfspr	r3,SPRG1	/* Push User stack pointer onto stack */ +	stw	    r3,0x8(r1) +	mfspr	r3,SRR0	    /* Push SRR0 onto stack */ +	stw	    r1,0xc(r1) +	mfspr	r3,SRR1	    /* Push SRR1 onto stack */ +	stw	    r3,0x10(r1) +	mflr    r3 +	stw     r3,0x14(r1) /* Push LR */ +	mfxer   r3 +	stw     r3,0x18(r1) /* Push Xer */ +	mfctr   r3 +	stw     r3,0x1c(r1) /* Push CTR */ + +	mtspr	SPRG0,r1	/* Save updated Supervisor stack pointer +					 * value to SPRG0 +			 */ +	mfmsr	r3 +	ori	    r3,r3,0x0002	/* Set Recoverable Interrupt bit in MSR */ +	mtmsr	r3 + +	/* ---READ IN THE EUMBAR REGISTER */ +    lwz     r6,0(r1)       /* this is eumbbar */ +    sync + +	/* ---READ EPIC REGISTER:	PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */ +	lis	r5,0x0006	        /* Build Interrupt Acknowledge Register +					     * offset +			     */ +	ori	r5,r5,0x00a0 +	lwbrx	r7,r5,r6    /* Load interrupt vector into r7 */ +	sync + +	/* --MASK OFF ALL BITS EXCEPT THE VECTOR */ +	xor	r3,r3,r3 +    xor r4,r4,r4 +	or    r3, r3, r6        /*  eumbbar in r3 */ +	andi. r4,r7,0x00ff	/* Mask off bits, vector in r4 */ + +    stw     r4,0x04(r1)     /* save the vector value */ + +    lis     r5,epicISR@ha +	ori     r5,r5,epicISR@l +	mtlr    r5 +	blrl + +    xor   r30,r30,r30 +	or    r30,r30,r3        /* save the r3 which containts the return value from epicISR */ + +	/* ---READ IN THE EUMBAR REGISTER */ +    lwz     r3,0(r1) +    sync + +    lis     r5,epicEOI@ha +	ori     r5,r5,epicEOI@l +	mtlr    r5 +	blrl + +    xor  r3,r3,r3 +	or   r3,r3,r30           /* restore the ISR return value  */ + +	bclr     20,0 diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S new file mode 100644 index 000000000..4877050ba --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S @@ -0,0 +1,57 @@ +/************************************** + * + * copyright @ Motorola, 1999 + * + * + * This file contains two commonly used + * lower level utility routines. + * + * The utility routines are also in other + * Kahlua device driver libraries. The + * need to be linked in only once. + **************************************/ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +/********************************************************** + * function: load_runtime_reg + * + * input:  r3 - value of eumbbar + *         r4 - register offset in embedded utility space + * + * output: r3 - register content + **********************************************************/ +      .text +      .align 2 +      .global load_runtime_reg + +load_runtime_reg: + +		  xor r5,r5,r5 +	  or  r5,r5,r3       /* save eumbbar */ + +	      lwbrx	r3,r4,r5 +	      sync + +	      bclr 20, 0 + +/**************************************************************** + * function: store_runtime_reg + * + * input: r3 - value of eumbbar + *        r4 - register offset in embedded utility space + *        r5 - new value to be stored + * + ****************************************************************/ +	   .text +	   .align 2 +	   .global store_runtime_reg +store_runtime_reg: + +		  xor r0,r0,r0 + +	      stwbrx r5,  r4, r3 +	      sync + +		  bclr   20,0 diff --git a/arch/powerpc/cpu/mpc824x/drivers/errors.h b/arch/powerpc/cpu/mpc824x/drivers/errors.h new file mode 100644 index 000000000..20794a2e8 --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/errors.h @@ -0,0 +1,212 @@ +/*	Copyright Motorola, Inc. 1993, 1994 +	ALL RIGHTS RESERVED + +	You are hereby granted a copyright license to use, modify, and +	distribute the SOFTWARE so long as this entire notice is retained +	without alteration in any modified and/or redistributed versions, +	and that such modified versions are clearly identified as such. +	No licenses are granted by implication, estoppel or otherwise under +	any patents or trademarks of Motorola, Inc. + +	The SOFTWARE is provided on an "AS IS" basis and without warranty. +	To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +	ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +	WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +	PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +	REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +	THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. + +	To the maximum extent permitted by applicable law, IN NO EVENT SHALL +	MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +	BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +	INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +	INABILITY TO USE THE SOFTWARE.   Motorola assumes no responsibility +	for the maintenance and support of the SOFTWARE. + +*/ + + +#include "config.h" + +/* +	 1         2         3         4         5         6         7         8 +01234567890123456789012345678901234567890123456789012345678901234567890123456789 +*/ +/* List define statements here */ + +/* These are for all the toolboxes and functions to use. These will help +to standardize the error handling in the current project */ + +				/* this is the "data type" for the error +				messages in the system */ +#define STATUS unsigned int + +				/* this is a success status code */ +#define SUCCESS 1 + +				/* likewise this is failure */ +#define FAILURE 0 + +#define NUM_ERRORS 47 + +/* This first section of "defines" are for error codes ONLY.  The called +   routine will return one of these error codes to the caller.  If the final +   returned code is "VALID", then everything is a-okay.  However, if one +   of the functions returns a non-valid status, that error code should be +   propogated back to all the callers.  At the end, the last caller will +   call an error_processing function, and send in the status which was +   returned.  It's up to the error_processing function to determine which +   error occured (as indicated by the status), and print an appropriate +   message back to the user. +*/ +/*----------------------------------------------------------------------*/ +/* these are specifically for the parser routines			*/ + +#define UNKNOWN_COMMAND		0xfb00 /* "unrecognized command " */ +#define UNKNOWN_REGISTER	0xfb01 /* "unknown register "*/ +#define ILLEGAL_RD_STAGE	0xfb02 /* cannot specify reg. family in range*/ +#define ILLEGAL_REG_FAMILY	0xfb03 /* "cannot specify a range of special +					or miscellaneous registers"*/ +#define RANGE_CROSS_FAMILY	0xfb04 /* "cannot specify a range across +					register families" */ +#define UNIMPLEMENTED_STAGE	0xfb05 /* invalid rd or rmm parameter format */ +#define REG_NOT_WRITEABLE	0xfb06 /* "unknown operator in arguements"*/ +#define INVALID_FILENAME	0xfb07 /* "invalid download filename" */ +#define INVALID_BAUD_RATE	0xfb08	/* invalid baud rate from sb command */ +#define UNSUPPORTED_REGISTER	0xfb09	/* Special register is not supported */ +#define FOR_BOARD_ONLY		0xfb0a  /* "Not available for Unix." */ + + +/*----------------------------------------------------------------------*/ +/* these are for the error checking toolbox				*/ + +#define INVALID			0xfd00 /* NOT valid */ +#define VALID			0xfd01 /* valid */ + +					/* This error is found in the fcn: +					is_right_size_input() to indicate +					that the input was not 8 characters +					long.  */ +#define INVALID_SIZE		0xfd02 + +					/* This error is found in the fcn: +					is_valid_address_range() to indicate +					that the address given falls outside +					of valid memory defined by MEM_START +					to MEM_END. +					*/ +#define OUT_OF_BOUNDS_ADDRESS	0xfd03 + +					/* This error is found in the fcn: +					is_valid_hex_input() to indicate that +					one of more of the characters entered +					are not valid hex characters.  Valid +					hex characters are 0-9, A-F, a-f. +					*/ +#define INVALID_HEX_INPUT	0xfd04 + +					/* This error is found in the fcn: +					is_valid_register_number() to indicate +					that a given register does not exist. +					*/ +#define REG_NOT_READABLE	0xfd05 + +					/* This error is found in the fcn: +					is_word_aligned_address() to indicate +					that the given address is not word- +					aligned.  A word-aligned address ends +					in 0x0,0x4,0x8,0xc. +					*/ +#define	NOT_WORD_ALIGNED	0xfd07 + +					/* This error is found in the fcn: +					is_valid_address_range() to indicate +					that the starting address is greater +					than the ending address. +					*/ +#define REVERSED_ADDRESS	0xfd08 + +					/* this error tells us that the address +					specified as the destination is within +					the source addresses  */ +#define RANGE_OVERLAP		0xfd09 + + +#define	ERROR			0xfd0a /* An error occured */ +#define INVALID_PARAM		0xfd0b /* "invalid input parameter " */ + + +#define INVALID_FLAG		0xfd0c	/* invalid flag */ + +/*----------------------------------------------------------------------*/ +/* these are for the getarg toolbox					*/ + +#define INVALID_NUMBER_ARGS	0xFE00 /* invalid number of commd arguements */ +#define UNKNOWN_PARAMETER	0xFE01 /* "unknown type of parameter "*/ + + +/*----------------------------------------------------------------------*/ +/* these are for the tokenizer toolbox					*/ + +#define ILLEGAL_CHARACTER	0xFF00 /* unrecognized char. in input stream*/ +#define TTL_NOT_SORTED		0xFF01 /* token translation list not sorted */ +#define TTL_NOT_DEFINED		0xFF02 /* token translation list not assigned*/ +#define INVALID_STRING		0xFF03 /* unable to extract string from input */ +#define BUFFER_EMPTY		0xFF04 /* "input buffer is empty" */ +#define INVALID_MODE		0xFF05 /* input buf is in an unrecognized mode*/ +#define TOK_INTERNAL_ERROR	0xFF06 /* "internal tokenizer error" */ +#define TOO_MANY_IBS		0xFF07 /* "too many open input buffers" */ +#define NO_OPEN_IBS		0xFF08 /* "no open input buffers" */ + + +/* these are for the read from screen toolbox */ + +#define RESERVED_WORD		0xFC00 /* used a reserved word as an arguement*/ + + +/* these are for the breakpoint routines */ + +#define FULL_BPDS		0xFA00 /* breakpoint data structure is full */ + + +/* THESE are for the downloader */ + +#define NOT_IN_S_RECORD_FORMAT	0xf900 /* "not in S-Record Format" */ +#define UNREC_RECORD_TYPE	0xf901 /* "unrecognized record type" */ +#define CONVERSION_ERROR	0xf902 /* "ascii to int conversion error" */ +#define INVALID_MEMORY		0xf903 /* "bad s-record memory address " */ + + +/* these are for the compression and decompression stuff */ + +#define COMP_UNK_CHARACTER	0xf800 /* "unknown compressed character " */ + +#define COMP_UNKNOWN_STATE	0xf801 /* "unknown binary state" */ + +#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */ + + +/* these are for the DUART handling things */ + +					/* "unrecognized serial port configuration" */ +#define UNKNOWN_PORT_STATE	0xf700 + + +/* these are for the register toolbox */ + +					/* "cannot find register in special +					 purpose register file " */ +#define SPR_NOT_FOUND		0xf600 + + +/* these are for the duart specific stuff */ + +					/* "transparent mode needs access to +						two serial ports" */ +#define TM_NEEDS_BOTH_PORTS	0xf500 + + +/*----------------------------------------------------------------------*/ +/* these are specifically for the flash routines			*/ +#define FLASH_ERROR		0xf100		/* general flash error */ diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c new file mode 100644 index 000000000..637ae4c1b --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c @@ -0,0 +1,270 @@ +/* + * (C) Copyright 2003 + * Gleb Natapov <gnatapov@mrv.com> + * Some bits are taken from linux driver writen by adrian@humboldt.co.uk + * + * Hardware I2C driver for MPC107 PCI bridge. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#undef I2CDBG + +#ifdef CONFIG_HARD_I2C +#include <i2c.h> + +#define TIMEOUT (CONFIG_SYS_HZ/4) + +#define I2C_Addr ((unsigned *)(CONFIG_SYS_EUMB_ADDR + 0x3000)) + +#define I2CADR &I2C_Addr[0] +#define I2CFDR  &I2C_Addr[1] +#define I2CCCR  &I2C_Addr[2] +#define I2CCSR  &I2C_Addr[3] +#define I2CCDR  &I2C_Addr[4] + +#define MPC107_CCR_MEN  0x80 +#define MPC107_CCR_MIEN 0x40 +#define MPC107_CCR_MSTA 0x20 +#define MPC107_CCR_MTX  0x10 +#define MPC107_CCR_TXAK 0x08 +#define MPC107_CCR_RSTA 0x04 + +#define MPC107_CSR_MCF  0x80 +#define MPC107_CSR_MAAS 0x40 +#define MPC107_CSR_MBB  0x20 +#define MPC107_CSR_MAL  0x10 +#define MPC107_CSR_SRW  0x04 +#define MPC107_CSR_MIF  0x02 +#define MPC107_CSR_RXAK 0x01 + +#define I2C_READ  1 +#define I2C_WRITE 0 + +/* taken from linux include/asm-ppc/io.h */ +inline unsigned in_le32 (volatile unsigned *addr) +{ +	unsigned ret; + +	__asm__ __volatile__ ("lwbrx %0,0,%1;\n" +			      "twi 0,%0,0;\n" +			      "isync":"=r" (ret): "r" (addr), "m" (*addr)); +	return ret; +} + +inline void out_le32 (volatile unsigned *addr, int val) +{ +	__asm__ __volatile__ ("stwbrx %1,0,%2; eieio":"=m" (*addr):"r" (val), +			      "r" (addr)); +} + +#define writel(val, addr) out_le32(addr, val) +#define readl(addr) in_le32(addr) + +void i2c_init (int speed, int slaveadd) +{ +	/* stop I2C controller */ +	writel (0x0, I2CCCR); +	/* set clock */ +	writel (0x1020, I2CFDR); +	/* write slave address */ +	writel (slaveadd, I2CADR); +	/* clear status register */ +	writel (0x0, I2CCSR); +	/* start I2C controller */ +	writel (MPC107_CCR_MEN, I2CCCR); + +	return; +} + +static __inline__ int i2c_wait4bus (void) +{ +	ulong timeval = get_timer (0); + +	while (readl (I2CCSR) & MPC107_CSR_MBB) +		if (get_timer (timeval) > TIMEOUT) +			return -1; + +	return 0; +} + +static __inline__ int i2c_wait (int write) +{ +	u32 csr; +	ulong timeval = get_timer (0); + +	do { +		csr = readl (I2CCSR); + +		if (!(csr & MPC107_CSR_MIF)) +			continue; + +		writel (0x0, I2CCSR); + +		if (csr & MPC107_CSR_MAL) { +#ifdef I2CDBG +			printf ("i2c_wait: MAL\n"); +#endif +			return -1; +		} + +		if (!(csr & MPC107_CSR_MCF)) { +#ifdef I2CDBG +			printf ("i2c_wait: unfinished\n"); +#endif +			return -1; +		} + +		if (write == I2C_WRITE && (csr & MPC107_CSR_RXAK)) { +#ifdef I2CDBG +			printf ("i2c_wait: No RXACK\n"); +#endif +			return -1; +		} + +		return 0; +	} while (get_timer (timeval) < TIMEOUT); + +#ifdef I2CDBG +	printf ("i2c_wait: timed out\n"); +#endif +	return -1; +} + +static __inline__ int i2c_write_addr (u8 dev, u8 dir, int rsta) +{ +	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX | +		(rsta ? MPC107_CCR_RSTA : 0), I2CCCR); + +	writel ((dev << 1) | dir, I2CCDR); + +	if (i2c_wait (I2C_WRITE) < 0) +		return 0; + +	return 1; +} + +static __inline__ int __i2c_write (u8 * data, int length) +{ +	int i; + +	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, I2CCCR); + +	for (i = 0; i < length; i++) { +		writel (data[i], I2CCDR); + +		if (i2c_wait (I2C_WRITE) < 0) +			break; +	} + +	return i; +} + +static __inline__ int __i2c_read (u8 * data, int length) +{ +	int i; + +	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | +		((length == 1) ? MPC107_CCR_TXAK : 0), I2CCCR); + +	/* dummy read */ +	readl (I2CCDR); + +	for (i = 0; i < length; i++) { +		if (i2c_wait (I2C_READ) < 0) +			break; + +		/* Generate ack on last next to last byte */ +		if (i == length - 2) +			writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | +				MPC107_CCR_TXAK, I2CCCR); + +		/* Generate stop on last byte */ +		if (i == length - 1) +			writel (MPC107_CCR_MEN | MPC107_CCR_TXAK, I2CCCR); + +		data[i] = readl (I2CCDR); +	} + +	return i; +} + +int i2c_read (u8 dev, uint addr, int alen, u8 * data, int length) +{ +	int i = 0; +	u8 *a = (u8 *) & addr; + +	if (i2c_wait4bus () < 0) +		goto exit; + +	if (i2c_write_addr (dev, I2C_WRITE, 0) == 0) +		goto exit; + +	if (__i2c_write (&a[4 - alen], alen) != alen) +		goto exit; + +	if (i2c_write_addr (dev, I2C_READ, 1) == 0) +		goto exit; + +	i = __i2c_read (data, length); + +exit: +	writel (MPC107_CCR_MEN, I2CCCR); + +	return !(i == length); +} + +int i2c_write (u8 dev, uint addr, int alen, u8 * data, int length) +{ +	int i = 0; +	u8 *a = (u8 *) & addr; + +	if (i2c_wait4bus () < 0) +		goto exit; + +	if (i2c_write_addr (dev, I2C_WRITE, 0) == 0) +		goto exit; + +	if (__i2c_write (&a[4 - alen], alen) != alen) +		goto exit; + +	i = __i2c_write (data, length); + +exit: +	writel (MPC107_CCR_MEN, I2CCCR); + +	return !(i == length); +} + +int i2c_probe (uchar chip) +{ +	int tmp; + +	/* +	 * Try to read the first location of the chip.  The underlying +	 * driver doesn't appear to support sending just the chip address +	 * and looking for an <ACK> back. +	 */ +	udelay (10000); +	return i2c_read (chip, 0, 1, (uchar *) &tmp, 1); +} + +#endif /* CONFIG_HARD_I2C */ diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h new file mode 100644 index 000000000..6264d189b --- /dev/null +++ b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h @@ -0,0 +1,103 @@ +#ifndef I2C_EXPORT_H +#define I2C_EXPORT_H + +/**************************************************** + * + * Copyright Motrola 1999 + * + ****************************************************/ + +/* These are the defined return values for the I2C_do_transaction function. + * Any non-zero value indicates failure.  Failure modes can be added for + * more detailed error reporting. + */ +typedef enum _i2c_status +{ + I2C_SUCCESS     = 0, + I2C_ERROR, +} I2C_Status; + +/* These are the defined tasks for I2C_do_transaction. + * Modes for SLAVE_RCV and SLAVE_XMIT will be added. + */ +typedef enum _i2c_transaction_mode +{ +	I2C_MASTER_RCV =  0, +	I2C_MASTER_XMIT = 1, +} I2C_TRANSACTION_MODE; + +typedef enum _i2c_interrupt_mode +{ +	I2C_INT_DISABLE =  0, +	I2C_INT_ENABLE = 1, +} I2C_INTERRUPT_MODE; + +typedef enum _i2c_stop +{ +	I2C_NO_STOP =  0, +	I2C_STOP = 1, +} I2C_STOP_MODE; + +typedef enum _i2c_restart +{ +	I2C_NO_RESTART =  0, +	I2C_RESTART = 1, +} I2C_RESTART_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the functionality provided by I2C driver. + * This is a "generic" I2C interface, it should contain + * nothing specific to the Kahlua implementation. + * Only the generic functions are exported by the library. + * + * Note: Its App.s responsibility to swap the data + *       byte. In our API, we just transfer whatever + *       we are given + **************************************************/ + + +/*  Initialize I2C unit with the following: + *  driver's slave address + *  interrupt enabled + *  optional pointer to application layer print function + * + *  These parameters may be added: + *  desired clock rate + *  digital filter frequency sampling rate + * + *  This function must be called before I2C unit can be used. + */ +extern I2C_Status I2C_Initialize( +	unsigned char addr,            /* driver's I2C slave address */ +	I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt +					* 0 - disable I2C interrupt +					*/ +	int (*app_print_function)(char *,...)); /* pointer to optional "printf" +						 * provided by application +						 */ + +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV + * are implemented.  Both are only in polling mode. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + *        I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + *        I2C_RESTART, this is a continuation of existing transaction + */ +extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, +				      I2C_TRANSACTION_MODE act, +				      unsigned char i2c_addr, +				      unsigned char data_addr, +				      int len, +				      char *buffer, +				      I2C_STOP_MODE stop, +				      int retry, +				      I2C_RESTART_MODE rsta); +#endif |