diff --git a/cpu/mpc824x/drivers/i2c/i2c.h b/cpu/mpc824x/drivers/i2c/i2c.h new file mode 100644 index 0000000000..3209bfed2d --- /dev/null +++ b/cpu/mpc824x/drivers/i2c/i2c.h @@ -0,0 +1,309 @@ +#ifndef I2C_H +#define I2C_H + +/**************************************************** + * + * Copyright Motrola 1999 + * + ****************************************************/ +#define get_eumbbar() CFG_EUMB_ADDR + +#define I2CADR 0x00003000 +#define I2CFDR 0x00003004 +#define I2CCR 0x00003008 +#define I2CSR 0x0000300C +#define I2CDR 0x00003010 + +typedef enum _i2cstatus +{ + I2CSUCCESS = 0x3000, + I2CADDRESS, + I2CERROR, + I2CBUFFFULL, + I2CBUFFEMPTY, + I2CXMITERROR, + I2CRCVERROR, + I2CBUSBUSY, + I2CALOSS, + I2CNOEVENT, +} I2CStatus; + +typedef enum i2c_control +{ + MEN = 0x00000080, + MIEN = 0x00000040, + MSTA = 0x00000020, + MTX = 0x00000010, + TXAK = 0x00000008, + RSTA = 0x00000004, +} I2C_CONTROL; + +typedef enum i2c_status +{ + MCF = 0x00000080, + MAAS = 0x00000040, + MBB = 0x00000020, + MAL = 0x00000010, + SRW = 0x00000004, + MIF = 0x00000002, + RXAK = 0x00000001, +} I2C_STATUS; + +typedef struct _i2c_ctrl +{ + unsigned int reserved0 : 24; + unsigned int men : 1; + unsigned int mien : 1; + unsigned int msta : 1; + unsigned int mtx : 1; + unsigned int txak : 1; + unsigned int rsta : 1; + unsigned int reserved1 : 2; +} I2C_CTRL; + +typedef struct _i2c_stat +{ + unsigned int rsrv0 : 24; + unsigned int mcf : 1; + unsigned int maas : 1; + unsigned int mbb : 1; + unsigned int mal : 1; + unsigned int rsrv1 : 1; + unsigned int srw : 1; + unsigned int mif : 1; + unsigned int rxak : 1; +} I2C_STAT; + +typedef enum _i2c_mode +{ + RCV = 0, + XMIT = 1, +} I2C_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the funcitonality provided by I2C driver + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we just transfer whatever + * we are given + **************************************************/ +/** + * Note: + * + * In all following functions, + * the caller shall pass the configured embedded utility memory + * block base, EUMBBAR. + **/ + +/* Send a buffer of data to the intended rcv_addr. + * If stop_flag is set, after the whole buffer + * is sent, generate a STOP signal provided that the + * receiver doesn't signal the STOP in the middle. + * I2C is the master performing transmitting. If + * no STOP signal is generated at the end of current + * transaction, the master can generate a START signal + * to another slave addr. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_put( unsigned int eumbbar, + unsigned char rcv_addr, /* receiver's address */ + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +/* Receive a buffer of data from the desired sender_addr + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the master performing receiving. If no STOP signal + * is generated, the master can generate a START signal + * to another slave addr. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_get( unsigned int eumbbar, + unsigned char sender_addr, /* sender's address */ + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +#if 0 /* the I2C_write and I2C_read functions are not active */ +/* Send a buffer of data to the requiring master. + * If stop_flag is set, after the whole buffer is sent, + * generate a STOP signal provided that the requiring + * receiver doesn't signal the STOP in the middle. + * I2C is the slave performing transmitting. + * + * return I2CSUCCESS if no error. + * + * Note: due to the Kahlua design, slave transmitter + * shall not signal STOP since there is no way + * for master to detect it, causing I2C bus hung. + * + * For the above reason, the stop_flag is always + * set, i.e., 1. + * + * programmer shall use the timer on Kahlua to + * control the interval of data byte at the + * master side. + */ +static I2CStatus I2C_write( unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag ); /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + + /* Receive a buffer of data from the sending master. + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the slave performing receiving. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_read(unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag ); /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ +#endif /* of if0 for turning off I2C_read & I2C_write */ + +/* if interrupt is not used, this is the timer event handler. + * After each fixed time interval, this function can be called + * to check the I2C status and call appropriate function to + * handle the status event. + */ +static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) ); + +/********************* Kernel API ************************ + * Kernel APIs are functions I2C driver provides to the + * O.S. + *********************************************************/ + +/******************* device I/O function ***************/ + +/* Generate a START signal in the desired mode. + * I2C is the master. + * + * return I2CSUCCESS if no error. + * I2CERROR if i2c unit is not enabled. + * I2CBUSBUSY if bus cannot be granted + */ +static I2CStatus I2C_Start( unsigned int eumbbar, + unsigned char slave_addr, /* address of the receiver */ + I2C_MODE mode, /* XMIT(1) - put (write) + * RCV(0) - get (read) + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +/* Generate a STOP signal to terminate the transaction. */ +static I2CStatus I2C_Stop( unsigned int eumbbar ); + +/* Do a one-byte master transmit. + * + * return I2CBUFFEMPTY if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Master_Xmit( unsigned int eumbbar ); + +/* Do a one-byte master receive. + * + * return I2CBUFFFULL if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Master_Rcv( unsigned int eumbbar ); + +/* Do a one-byte slave transmit. + * + * return I2CBUFFEMPTY if this is the last byte. + * Otherwise return I2CSUCCESS + * + */ +static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar ); + +/* Do a one-byte slave receive. + * + * return I2CBUFFFULL if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Slave_Rcv( unsigned int eumbbar ); + +/* Process slave address phase. + * + * return I2CADDRESS if this is slave receiver's address phase + * Otherwise return the result of slave xmit one byte. + */ +static I2CStatus I2C_Slave_Addr( unsigned int eumbbar ); + +/******************* Device Control Fucntion ****************/ +/* Initialize I2C unit with desired frequency divider, + * driver's slave address w/o interrupt enabled. + * + * This function must be called before I2C unit can + * be used. + */ +static I2CStatus I2C_Init( unsigned int eumbbar, + unsigned char fdr, /* frequency divider */ + unsigned char addr, /* driver's address used for receiving */ + unsigned int en_int); /* 1 - enable I2C interrupt + * 0 - disable I2C interrup + */ + +/* I2C interrupt service routine. + * + * return I2CADDRESS if it is receiver's (either master or slave) address phase. + * return the result of xmit or receive one byte + */ +static I2CStatus I2C_ISR(unsigned int eumbbar ); + +/* Set I2C Status, i.e., write to I2CSR */ +static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat ); + +/* Query I2C Status, i.e., read I2CSR */ +static I2C_STAT I2C_Get_Stat( unsigned int eumbbar ); + +/* Change I2C Control bits, i.e., write to I2CCR */ +static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ); /* new control value */ + +/* Query I2C Control bits, i.e., read I2CCR */ +static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar ); + +/* This function performs the work for I2C_do_transaction. The work is + * split into this function to enable I2C_do_transaction to first transmit + * the data address to the I2C slave device without putting the data address + * into the first byte of the buffer. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_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 + */ +static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + int len, + unsigned char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta); +#endif