@ -206,9 +206,50 @@ static unsigned int get_i2c_clock(int bus)
return gd - > arch . i2c1_clk ; /* I2C1 clock */
}
static int fsl_i2c_fixup ( const struct fsl_i2c * dev )
{
const unsigned long long timeout = usec2ticks ( CONFIG_I2C_MBB_TIMEOUT ) ;
unsigned long long timeval = 0 ;
int ret = - 1 ;
writeb ( I2C_CR_MEN | I2C_CR_MSTA , & dev - > cr ) ;
timeval = get_ticks ( ) ;
while ( ! ( readb ( & dev - > sr ) & I2C_SR_MBB ) ) {
if ( ( get_ticks ( ) - timeval ) > timeout )
goto err ;
}
if ( readb ( & dev - > sr ) & I2C_SR_MAL ) {
/* SDA is stuck low */
writeb ( 0 , & dev - > cr ) ;
udelay ( 100 ) ;
writeb ( I2C_CR_MSTA , & dev - > cr ) ;
writeb ( I2C_CR_MEN | I2C_CR_MSTA , & dev - > cr ) ;
}
readb ( & dev - > dr ) ;
timeval = get_ticks ( ) ;
while ( ! ( readb ( & dev - > sr ) & I2C_SR_MIF ) ) {
if ( ( get_ticks ( ) - timeval ) > timeout )
goto err ;
}
ret = 0 ;
err :
writeb ( I2C_CR_MEN , & dev - > cr ) ;
writeb ( 0 , & dev - > sr ) ;
udelay ( 100 ) ;
return ret ;
}
static void fsl_i2c_init ( struct i2c_adapter * adap , int speed , int slaveadd )
{
const struct fsl_i2c * dev ;
const unsigned long long timeout = usec2ticks ( CONFIG_I2C_MBB_TIMEOUT ) ;
unsigned long long timeval ;
# ifdef CONFIG_SYS_I2C_INIT_BOARD
/* Call board specific i2c bus reset routine before accessing the
@ -226,6 +267,18 @@ static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
writeb ( 0x0 , & dev - > sr ) ; /* clear status register */
writeb ( I2C_CR_MEN , & dev - > cr ) ; /* start I2C controller */
timeval = get_ticks ( ) ;
while ( readb ( & dev - > sr ) & I2C_SR_MBB ) {
if ( ( get_ticks ( ) - timeval ) < timeout )
continue ;
if ( fsl_i2c_fixup ( dev ) )
debug ( " i2c_init: BUS#%d failed to init \n " ,
adap - > hwadapnr ) ;
break ;
}
# ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT
/* Call board specific i2c bus reset routine AFTER the bus has been
* initialized . Use either this callpoint or i2c_init_board ;
@ -394,8 +447,10 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen,
int i = - 1 ; /* signal error */
u8 * a = ( u8 * ) & addr ;
if ( i2c_wait4bus ( adap ) > = 0 & &
i2c_write_addr ( adap , dev , I2C_WRITE_BIT , 0 ) ! = 0 & &
if ( i2c_wait4bus ( adap ) < 0 )
return - 1 ;
if ( i2c_write_addr ( adap , dev , I2C_WRITE_BIT , 0 ) ! = 0 & &
__i2c_write ( adap , & a [ 4 - alen ] , alen ) = = alen ) {
i = __i2c_write ( adap , data , length ) ;
}