unsigned char * i2c_read(u8 *val, u32 n, u16 addr) { if (!i2c_free()) return NULL; i2c_start(); i2c_sendbyte(ST24C512_ADDR & 0xfe); i2c_waitack(); i2c_sendbyte(addr >> 8); i2c_waitack(); i2c_sendbyte(addr & 0xff); i2c_waitack(); i2c_start(); i2c_sendbyte(ST24C512_ADDR | 1); i2c_waitack(); n--; while (n--) { *val = i2c_recvbyte(); i2c_sendack(); val++; } *val = i2c_recvbyte(); i2c_sendnack(); i2c_stop(); return val; }
unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg) { unsigned char b = 0; int error, cntr = 3; unsigned long flags; spin_lock_irqsave(&i2c_lock, flags); do { error = 0; i2c_start(); i2c_outbyte((theSlave & 0xfe)); if(!i2c_getack()) error = 1; i2c_dir_out(); i2c_outbyte(theReg); if(!i2c_getack()) error |= 2; i2c_delay(CLOCK_LOW_TIME); i2c_start(); i2c_outbyte(theSlave | 0x01); if(!i2c_getack()) error |= 4; b = i2c_inbyte(); i2c_sendnack(); i2c_stop(); } while(error && cntr--); spin_unlock_irqrestore(&i2c_lock, flags); return b; }
int i2c_read(unsigned char theSlave, void *data, size_t nbytes) { unsigned char b = 0; unsigned char bytes_read = 0; int error, cntr = 3; unsigned long flags; spin_lock_irqsave(&i2c_lock, flags); do { error = 0; memset(data, 0, nbytes); i2c_start(); i2c_outbyte((theSlave | 0x01)); if (!i2c_getack()) error = 1; for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { b = i2c_inbyte(); memcpy(data + bytes_read, &b, sizeof b); if (bytes_read < (nbytes - 1)) i2c_sendack(); } i2c_sendnack(); i2c_stop(); } while (error && cntr--); spin_unlock_irqrestore(&i2c_lock, flags); return -error; }
/*#--------------------------------------------------------------------------- *# *# FUNCTION NAME: i2c_read *# *# DESCRIPTION : Reads a value from an I2C device *# *#--------------------------------------------------------------------------*/ int i2c_read(unsigned char theSlave, void *data, size_t nbytes) { unsigned char b = 0; unsigned char bytes_read = 0; int error, cntr = 3; unsigned long flags; spin_lock_irqsave(&i2c_lock, flags); do { error = 0; memset(data, 0, nbytes); /* * generate start condition */ i2c_start(); /* * send slave address */ i2c_outbyte((theSlave | 0x01)); /* * wait for ack */ if (!i2c_getack()) error = 1; /* * fetch data */ for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { b = i2c_inbyte(); memcpy(data + bytes_read, &b, sizeof b); if (bytes_read < (nbytes - 1)) i2c_sendack(); } /* * last received byte needs to be nacked * instead of acked */ i2c_sendnack(); /* * end sequence */ i2c_stop(); } while (error && cntr--); spin_unlock_irqrestore(&i2c_lock, flags); return -error; }
unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg) { unsigned char b = 0; int error, cntr = 3; unsigned long flags; spin_lock(&i2c_lock); do { error = 0; /* * we don't like to be interrupted */ local_irq_save(flags); /* * generate start condition */ i2c_start(); /* * send slave address */ i2c_outbyte((theSlave & 0xfe)); /* * wait for ack */ if(!i2c_getack()) error = 1; /* * now select register */ i2c_dir_out(); i2c_outbyte(theReg); /* * now it's time to wait for ack */ if(!i2c_getack()) error = 1; /* * repeat start condition */ i2c_delay(CLOCK_LOW_TIME); i2c_start(); /* * send slave address */ i2c_outbyte(theSlave | 0x01); /* * wait for ack */ if(!i2c_getack()) error = 1; /* * fetch register */ b = i2c_inbyte(); /* * last received byte needs to be nacked * instead of acked */ i2c_sendnack(); /* * end sequence */ i2c_stop(); /* * enable interrupt again */ local_irq_restore(flags); } while(error && cntr--); spin_unlock(&i2c_lock); return b; }
/*#--------------------------------------------------------------------------- *# *# FUNCTION NAME: i2c_command *# *# DESCRIPTION : general routine to read/write bytes from an I2C device *# *# 'i2c_command()' sends wlen bytes to the I2c bus and receives *# rlen bytes from the I2c bus. *# The data to be send must be placed in wbuf[ 0 ] upto wbuf[ wlen - 1 ). *# The data to be received is assembled in rbuf[ 0 ] upto rbuf[ rlen - 1 ]. *# *# If no data is to be sent or received, put appropriate buffer parameter *# to "NULL" and appropriate length parameter to "0". *# *# PARAMETERS : slave = slave address of the I2C device *# wbuf = address of first element of write buffer (wbuf) *# wlen = number of bytes to be written to slave *# rbuf = address of first element of read buffer (rbuf) *# rlen = number of bytes to be read from slave *# *# RETURN : *# EI2CNOERRORS: I2C communication went fine *# EI2CBUSNFREE: I2C bus is not free *# EI2CWADDRESS: I2C write address failed *# EI2CRADDRESS: I2C read address failed *# EI2CSENDDATA: I2C send data failed *# EI2CRECVDATA: I2C receive data failed *# EI2CSTRTCOND: I2C start condition failed *# EI2CRSTACOND: I2C repeated start condition failed *# EI2CSTOPCOND: I2C stop condition failed *# EI2CNOSNDBYT: I2C no bytes to be sent *# EI2CNOSNDBUF: I2C no send buffer defined *# EI2CNORCVBYT: I2C no bytes to be received *# EI2CNORCVBUF: I2C no receive buffer defined *# EI2CNOACKNLD: I2C no acknowledge received *# *# REMARK : *# First, the send part is completed. *# In the send routine, there is no stop generated. This is because maybe *# a repeated start condition must be generated. *# This happens when we want to receive some data from the I2c bus. If not, *# at the end of the general I2c loop the stopcondition is generated. *# If, on the contrary, there are a number of bytes to be received, a new *# startcondition is generated in the 'if' part of the main I2c routine, *# which controls the receiving part. *# Only when the receiving of data is finished, a final stopcondition is *# generated. *# *#--------------------------------------------------------------------------- */ static int i2c_command( unsigned char slave , unsigned char* wbuf , unsigned char wlen , unsigned char* rbuf , unsigned char rlen ) { /* Check arguments and report error if relevant... */ if ( ( wlen > 0 ) && ( wbuf == NULL ) ) { printk( KERN_DEBUG "I2C: EI2CNOSNDBUF\n" ); return ( EI2CNOSNDBUF ); } else if ( ( wlen == 0 ) && ( wbuf != NULL ) ) { printk( KERN_DEBUG "I2C: EI2CNOSNDBYT\n" ); return ( EI2CNOSNDBYT ); } else if ( ( rlen > 0 ) && ( rbuf == NULL ) ) { printk( KERN_DEBUG "I2C: EI2CNORCVBUF\n" ); return ( EI2CNORCVBUF ); } else if ( ( rlen == 0 ) && ( rbuf != NULL ) ) { printk( KERN_DEBUG "I2C: EI2CNORCVBYT\n" ); return ( EI2CNORCVBYT ); } else if ( EI2CBUSNFREE == i2c_bus_free_check( MAXBUSFREERETRIES ) ) { /* There's no need to try more, since we weren't even * able to start the I2C communication. * So, no IRQ flags are stored yet, no changes to any other * stuff like START, STOP, SENDBYTES... * Result, simply write down the error and return the correct error code. */ printk( KERN_DEBUG "I2C: EI2CBUSNFREE\n" ); return ( EI2CBUSNFREE ); } else { /* Finally... We made it... */ unsigned long irqflags = 0; /* we don't like to be interrupted */ local_irq_save( irqflags ); /* Check if there are bytes to be send, * or if you immediately want to receive data. */ if ( 0 < wlen ) { /* start I2C communication */ if ( EI2CNOERRORS != i2c_start() ) { return ( i2c_finalise( "I2C: EI2CSTRTCOND\n", irqflags ) , EI2CSTRTCOND ); } /* send slave address: xxxxxxx0B (last bit must be zero) */ if ( EI2CNOERRORS != i2c_outbyte( slave & WRITEADDRESS_MASK ) ) { return ( i2c_finalise( "I2C: EI2CWADDRESS\n", irqflags ) , EI2CWADDRESS ); } while ( wlen-- ) { /* send register data */ if ( EI2CNOERRORS != i2c_outbyte( *wbuf ) && wlen ) { return ( i2c_finalise( "I2C: EI2CSENDDATA\n", irqflags ) , EI2CSENDDATA ); } wbuf++; }; i2c_delay( TLOW ); } /* * Receiving data from I2c_bus * If there are bytes to be received, a new start condition is * generated => Repeated Startcondition. * A final stopcondition is generated at the end of the main I2c * routine. */ if ( 0 < rlen ) { /* * Generate start condition if wlen == 0 * or repeated start condition if wlen != 0... */ if ( EI2CNOERRORS != i2c_start() ) { return ( i2c_finalise( ( ( 0 < wlen ) ? "I2C: EI2CRSTACOND\n" : "I2C: EI2CSTRTCOND\n" ) , irqflags ) , ( ( 0 < wlen ) ? EI2CRSTACOND : EI2CSTRTCOND ) ); } /* Send ReadAddress: xxxxxxx1B (last bit must be one) */ if ( EI2CNOERRORS != i2c_outbyte( slave | READADDRESS_MASK ) ) { return ( i2c_finalise( "I2C: EI2CRADDRESS\n", irqflags ) , EI2CRADDRESS ); } while ( rlen-- ) { /* fetch register */ *rbuf = i2c_inbyte(); rbuf++; /* last received byte needs to be NACK-ed instead of ACK-ed */ if ( rlen ) { i2c_sendack(); } else { i2c_sendnack(); } }; } /* Generate final stop condition */ if ( EI2CNOERRORS != i2c_stop() ) { return ( i2c_finalise( "I2C CMD: EI2CSTOPCOND\n", irqflags ) , EI2CSTOPCOND ); } /* enable interrupt again */ local_irq_restore( irqflags ); } return ( EI2CNOERRORS ); } /* i2c_command */
/*#--------------------------------------------------------------------------- *# *# FUNCTION NAME: i2c_readreg *# *# DESCRIPTION : reads the value from a certain register of an I2C device. *# Function first writes the register that it wants to read *# later on. *# *# PARAMETERS : theSlave = slave address of the I2C device *# theReg = register of the I2C device that needs to be written *# *# RETURN : returns OR-ed result of the write action: *# 0 = Ok *# 1 = Slave_NoAck *# 2 = Reg_NoAck *# 4 = Val_NoAck *# *#--------------------------------------------------------------------------- */ unsigned char i2c_readreg( unsigned char theSlave , unsigned char theReg ) { unsigned char b = 0; int error, cntr = 3; unsigned long flags; spin_lock( &i2c_lock ); do { error = 0; /* we don't like to be interrupted */ local_irq_save( flags ); /* generate start condition */ i2c_start(); /* send slave address */ if ( EI2CNOACKNLD == i2c_outbyte( theSlave & 0xfe ) ) { error = 1; } /* now select register */ i2c_sda_dir_out(); if ( EI2CNOACKNLD == i2c_outbyte( theReg ) ) { error |= 2; } /* repeat start condition */ i2c_delay( TLOW ); i2c_start(); /* send slave address */ if ( EI2CNOACKNLD == i2c_outbyte( theSlave | 0x01 ) ) { error |= 1; } /* fetch register */ b = i2c_inbyte(); /* * last received byte needs to be nacked * instead of acked */ i2c_sendnack(); /* end sequence */ i2c_stop(); /* enable interrupt again */ local_irq_restore( flags ); } while ( error && cntr-- ); spin_unlock( &i2c_lock ); return ( b ); } /* i2c_readreg */