@ -6,6 +6,7 @@
*/
# include <common.h>
# include <i2c.h>
# include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR ;
@ -22,8 +23,6 @@ struct sh_i2c {
} ;
# undef ureg
static struct sh_i2c * base ;
/* ICCR */
# define SH_I2C_ICCR_ICE (1 << 7)
# define SH_I2C_ICCR_RACK (1 << 6)
@ -43,202 +42,165 @@ static struct sh_i2c *base;
# define SH_I2C_ICIC_ICCHB8 (1 << 6)
# endif
static const struct sh_i2c * i2c_dev [ CONFIG_SYS_I2C_SH_NUM_CONTROLLERS ] = {
( struct sh_i2c * ) CONFIG_SYS_I2C_SH_BASE0 ,
# ifdef CONFIG_SYS_I2C_SH_BASE1
( struct sh_i2c * ) CONFIG_SYS_I2C_SH_BASE1 ,
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE2
( struct sh_i2c * ) CONFIG_SYS_I2C_SH_BASE2 ,
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE3
( struct sh_i2c * ) CONFIG_SYS_I2C_SH_BASE3 ,
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE4
( struct sh_i2c * ) CONFIG_SYS_I2C_SH_BASE4 ,
# endif
} ;
static u16 iccl , icch ;
# define IRQ_WAIT 1000
static void irq_dte ( struct sh_i2c * base )
static void sh_ irq_dte( struct sh_i2c * dev )
{
int i ;
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( SH_IC_DTE & readb ( & base - > icsr ) )
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( SH_IC_DTE & readb ( & dev - > icsr ) )
break ;
udelay ( 10 ) ;
}
}
static int irq_dte_with_tack ( struct sh_i2c * base )
static int sh_ irq_dte_with_tack( struct sh_i2c * dev )
{
int i ;
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( SH_IC_DTE & readb ( & base - > icsr ) )
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( SH_IC_DTE & readb ( & dev - > icsr ) )
break ;
if ( SH_IC_TACK & readb ( & base - > icsr ) )
if ( SH_IC_TACK & readb ( & dev - > icsr ) )
return - 1 ;
udelay ( 10 ) ;
}
return 0 ;
}
static void irq_busy ( struct sh_i2c * base )
static void sh_ irq_busy( struct sh_i2c * dev )
{
int i ;
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( ! ( SH_IC_BUSY & readb ( & base - > icsr ) ) )
for ( i = 0 ; i < IRQ_WAIT ; i + + ) {
if ( ! ( SH_IC_BUSY & readb ( & dev - > icsr ) ) )
break ;
udelay ( 10 ) ;
}
}
static int i2c_set_addr ( struct sh_i2c * base , u8 id , u8 reg , int stop )
static int sh_ i2c_set_addr( struct sh_i2c * dev , u8 chip , u8 add r, int stop )
{
u8 icic = SH_IC_TACK ;
clrbits_8 ( & base - > iccr , SH_I2C_ICCR_ICE ) ;
setbits_8 ( & base - > iccr , SH_I2C_ICCR_ICE ) ;
debug ( " %s: chip: %x, addr: %x iccl: %x, icch %x \n " ,
__func__ , chip , addr , iccl , icch ) ;
clrbits_8 ( & dev - > iccr , SH_I2C_ICCR_ICE ) ;
setbits_8 ( & dev - > iccr , SH_I2C_ICCR_ICE ) ;
writeb ( iccl & 0xff , & base - > iccl ) ;
writeb ( icch & 0xff , & base - > icch ) ;
writeb ( iccl & 0xff , & dev - > iccl ) ;
writeb ( icch & 0xff , & dev - > icch ) ;
# ifdef CONFIG_SH_I2C_8BIT
if ( iccl > 0xff )
icic | = SH_I2C_ICIC_ICCLB8 ;
if ( icch > 0xff )
icic | = SH_I2C_ICIC_ICCHB8 ;
# endif
writeb ( icic , & base - > icic ) ;
writeb ( icic , & dev - > icic ) ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS | SH_I2C_ICCR_BUSY ) , & base - > iccr ) ;
irq_dte ( base ) ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS | SH_I2C_ICCR_BUSY ) , & dev - > iccr ) ;
sh_ irq_dte( dev ) ;
clrbits_8 ( & base - > icsr , SH_IC_TACK ) ;
writeb ( id < < 1 , & base - > icdr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
clrbits_8 ( & dev - > icsr , SH_IC_TACK ) ;
writeb ( chip < < 1 , & dev - > icdr ) ;
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
return - 1 ;
writeb ( reg , & base - > icdr ) ;
writeb ( add r, & dev - > icdr ) ;
if ( stop )
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS ) , & base - > iccr ) ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS ) , & dev - > iccr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
return - 1 ;
return 0 ;
}
static void i2c_finish ( struct sh_i2c * base )
static void sh_ i2c_finish( struct sh_i2c * dev )
{
writeb ( 0 , & base - > icsr ) ;
clrbits_8 ( & base - > iccr , SH_I2C_ICCR_ICE ) ;
writeb ( 0 , & dev - > icsr ) ;
clrbits_8 ( & dev - > iccr , SH_I2C_ICCR_ICE ) ;
}
static int i2c_raw_write ( struct sh_i2c * base , u8 id , u8 reg , u8 val )
static int
sh_i2c_raw_write ( struct sh_i2c * dev , u8 chip , uint addr , u8 val )
{
int ret = - 1 ;
if ( i2c_set_addr ( base , id , reg , 0 ) ! = 0 )
if ( sh_ i2c_set_addr( dev , chip , addr , 0 ) ! = 0 )
goto exit0 ;
udelay ( 10 ) ;
writeb ( val , & base - > icdr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
writeb ( val , & dev - > icdr ) ;
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
goto exit0 ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS ) , & base - > iccr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS ) , & dev - > iccr ) ;
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
goto exit0 ;
irq_busy ( base ) ;
sh_ irq_busy( dev ) ;
ret = 0 ;
exit0 :
i2c_finish ( base ) ;
sh_ i2c_finish( dev ) ;
return ret ;
}
static int i2c_raw_read ( struct sh_i2c * base , u8 id , u8 reg )
static int sh_ i2c_raw_read( struct sh_i2c * dev , u8 chip , u8 add r)
{
int ret = - 1 ;
# if defined(CONFIG_SH73A0)
if ( i2c_set_addr ( base , id , reg , 0 ) ! = 0 )
if ( sh_ i2c_set_addr( dev , chip , addr , 0 ) ! = 0 )
goto exit0 ;
# else
if ( i2c_set_addr ( base , id , reg , 1 ) ! = 0 )
if ( sh_ i2c_set_addr( dev , chip , addr , 1 ) ! = 0 )
goto exit0 ;
udelay ( 100 ) ;
# endif
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS | SH_I2C_ICCR_BUSY ) , & base - > iccr ) ;
irq_dte ( base ) ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS | SH_I2C_ICCR_BUSY ) , & dev - > iccr ) ;
sh_ irq_dte( dev ) ;
writeb ( id < < 1 | 0x01 , & base - > icdr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
writeb ( chip < < 1 | 0x01 , & dev - > icdr ) ;
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
goto exit0 ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_SCP ) , & base - > iccr ) ;
if ( irq_dte_with_tack ( base ) ! = 0 )
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_SCP ) , & dev - > iccr ) ;
if ( sh_ irq_dte_with_tack( dev ) ! = 0 )
goto exit0 ;
ret = readb ( & base - > icdr ) & 0xff ;
ret = readb ( & dev - > icdr ) & 0xff ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RACK ) , & dev - > iccr ) ;
readb ( & dev - > icdr ) ; /* Dummy read */
sh_irq_busy ( dev ) ;
writeb ( ( SH_I2C_ICCR_ICE | SH_I2C_ICCR_RACK ) , & base - > iccr ) ;
readb ( & base - > icdr ) ; /* Dummy read */
irq_busy ( base ) ;
exit0 :
i2c_finish ( base ) ;
sh_i2c_finish ( dev ) ;
return ret ;
}
# ifdef CONFIG_I2C_MULTI_BUS
static unsigned int current_bus ;
/**
* i2c_set_bus_num - change active I2C bus
* @ bus : bus index , zero based
* @ returns : 0 on success , non - 0 on failure
*/
int i2c_set_bus_num ( unsigned int bus )
{
if ( ( bus < 0 ) | | ( bus > = CONFIG_SYS_MAX_I2C_BUS ) ) {
printf ( " Bad bus: %d \n " , bus ) ;
return - 1 ;
}
switch ( bus ) {
case 0 :
base = ( void * ) CONFIG_SH_I2C_BASE0 ;
break ;
case 1 :
base = ( void * ) CONFIG_SH_I2C_BASE1 ;
break ;
# ifdef CONFIG_SH_I2C_BASE2
case 2 :
base = ( void * ) CONFIG_SH_I2C_BASE2 ;
break ;
# endif
# ifdef CONFIG_SH_I2C_BASE3
case 3 :
base = ( void * ) CONFIG_SH_I2C_BASE3 ;
break ;
# endif
# ifdef CONFIG_SH_I2C_BASE4
case 4 :
base = ( void * ) CONFIG_SH_I2C_BASE4 ;
break ;
# endif
default :
return - 1 ;
}
current_bus = bus ;
return 0 ;
}
/**
* i2c_get_bus_num - returns index of active I2C bus
*/
unsigned int i2c_get_bus_num ( void )
{
return current_bus ;
}
# endif
# define SH_I2C_ICCL_CALC(clk, date, t_low, t_high) \
( ( clk / rate ) * ( t_low / t_low + t_high ) )
# define SH_I2C_ICCH_CALC(clk, date, t_low, t_high) \
( ( clk / rate ) * ( t_high / t_low + t_high ) )
void i2c_init ( int speed , int slaveaddr )
static void
sh_i2c_init ( struct i2c_adapter * adap , int speed , int slaveadd )
{
int num , denom , tmp ;
@ -246,11 +208,6 @@ void i2c_init(int speed, int slaveaddr)
if ( ! ( gd - > flags & GD_FLG_RELOC ) )
return ;
# ifdef CONFIG_I2C_MULTI_BUS
current_bus = 0 ;
# endif
base = ( struct sh_i2c * ) CONFIG_SH_I2C_BASE0 ;
/*
* Calculate the value for iccl . From the data sheet :
* iccl = ( p - clock / transfer - rate ) * ( L / ( L + H ) )
@ -272,67 +229,78 @@ void i2c_init(int speed, int slaveaddr)
icch = ( u16 ) ( ( num / denom ) + 1 ) ;
else
icch = ( u16 ) ( num / denom ) ;
debug ( " clock: %d, speed %d, iccl: %x, icch: %x \n " ,
CONFIG_SH_I2C_CLOCK , speed , iccl , icch ) ;
}
/*
* i2c_read : - Read multiple bytes from an i2c device
*
* The higher level routines take into account that this function is only
* called with len < page length of the device ( see configuration file )
*
* @ chip : address of the chip which is to be read
* @ addr : i2c data address within the chip
* @ alen : length of the i2c data address ( 1. .2 bytes )
* @ buffer : where to write the data
* @ len : how much byte do we want to read
* @ return : 0 in case of success
*/
int i2c_read ( u8 chip , u32 addr , int alen , u8 * buffer , int len )
static int sh_i2c_read ( struct i2c_adapter * adap , uint8_t chip ,
uint addr , int alen , u8 * data , int len )
{
int ret ;
int i = 0 ;
for ( i = 0 ; i < len ; i + + ) {
ret = i2c_raw_read ( base , chip , addr + i ) ;
int ret , i ;
struct sh_i2c * dev = ( struct sh_i2c * ) i2c_dev [ adap - > hwadapnr ] ;
for ( i = 0 ; i < len ; i + + ) {
ret = sh_i2c_raw_read ( dev , chip , addr + i ) ;
if ( ret < 0 )
return - 1 ;
buffer [ i ] = ret & 0xff ;
data [ i ] = ret & 0xff ;
debug ( " %s: data[%d]: %02x \n " , __func__ , i , data [ i ] ) ;
}
return 0 ;
}
/*
* i2c_write : - Write multiple bytes to an i2c device
*
* The higher level routines take into account that this function is only
* called with len < page length of the device ( see configuration file )
*
* @ chip : address of the chip which is to be written
* @ addr : i2c data address within the chip
* @ alen : length of the i2c data address ( 1. .2 bytes )
* @ buffer : where to find the data to be written
* @ len : how much byte do we want to read
* @ return : 0 in case of success
*/
int i2c_write ( u8 chip , u32 addr , int alen , u8 * buffer , int len )
static int sh_i2c_write ( struct i2c_adapter * adap , uint8_t chip , uint addr ,
int alen , u8 * data , int len )
{
int i = 0 ;
for ( i = 0 ; i < len ; i + + )
if ( i2c_raw_write ( base , chip , addr + i , buffer [ i ] ) ! = 0 )
struct sh_i2c * dev = ( struct sh_i2c * ) i2c_dev [ adap - > hwadapnr ] ;
int i ;
for ( i = 0 ; i < len ; i + + ) {
debug ( " %s: data[%d]: %02x \n " , __func__ , i , data [ i ] ) ;
if ( sh_i2c_raw_write ( dev , chip , addr + i , data [ i ] ) ! = 0 )
return - 1 ;
}
return 0 ;
}
/*
* i2c_probe : - Test if a chip answers for a given i2c address
*
* @ chip : address of the chip which is searched for
* @ return : 0 if a chip was found , - 1 otherwhise
*/
int i2c_probe ( u8 chip )
static int
sh_i2c_probe ( struct i2c_adapter * adap , u8 dev )
{
int ret ;
return sh_i2c_read ( adap , dev , 0 , 0 , NULL , 0 ) ;
}
ret = i2c_set_addr ( base , chip , 0 , 1 ) ;
i2c_finish ( base ) ;
return ret ;
static unsigned int sh_i2c_set_bus_speed ( struct i2c_adapter * adap ,
unsigned int speed )
{
struct sh_i2c * dev = ( struct sh_i2c * ) i2c_dev [ adap - > hwadapnr ] ;
sh_i2c_finish ( dev ) ;
sh_i2c_init ( adap , speed , 0 ) ;
return 0 ;
}
/*
* Register RCAR i2c adapters
*/
U_BOOT_I2C_ADAP_COMPLETE ( sh_0 , sh_i2c_init , sh_i2c_probe , sh_i2c_read ,
sh_i2c_write , sh_i2c_set_bus_speed , CONFIG_SYS_I2C_SH_SPEED0 , 0 , 0 )
# ifdef CONFIG_SYS_I2C_SH_BASE1
U_BOOT_I2C_ADAP_COMPLETE ( sh_1 , sh_i2c_init , sh_i2c_probe , sh_i2c_read ,
sh_i2c_write , sh_i2c_set_bus_speed , CONFIG_SYS_I2C_SH_SPEED1 , 0 , 1 )
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE2
U_BOOT_I2C_ADAP_COMPLETE ( sh_2 , sh_i2c_init , sh_i2c_probe , sh_i2c_read ,
sh_i2c_write , sh_i2c_set_bus_speed , CONFIG_SYS_I2C_SH_SPEED2 , 0 , 2 )
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE3
U_BOOT_I2C_ADAP_COMPLETE ( sh_3 , sh_i2c_init , sh_i2c_probe , sh_i2c_read ,
sh_i2c_write , sh_i2c_set_bus_speed , CONFIG_SYS_I2C_SH_SPEED3 , 0 , 3 )
# endif
# ifdef CONFIG_SYS_I2C_SH_BASE4
U_BOOT_I2C_ADAP_COMPLETE ( sh_4 , sh_i2c_init , sh_i2c_probe , sh_i2c_read ,
sh_i2c_write , sh_i2c_set_bus_speed , CONFIG_SYS_I2C_SH_SPEED4 , 0 , 4 )
# endif