@ -6,17 +6,33 @@
*/
# include <common.h>
# include <i2c.h>
# include <asm/io.h>
# include "designware_i2c.h"
# include <i2c.h>
# ifdef CONFIG_I2C_MULTI_BUS
static unsigned int bus_initialized [ CONFIG_SYS_I2C_BUS_MAX ] ;
static unsigned int current_bus = 0 ;
static struct i2c_regs * i2c_get_base ( struct i2c_adapter * adap )
{
switch ( adap - > hwadapnr ) {
# if CONFIG_SYS_I2C_BUS_MAX >= 4
case 3 :
return ( struct i2c_regs * ) CONFIG_SYS_I2C_BASE3 ;
# endif
# if CONFIG_SYS_I2C_BUS_MAX >= 3
case 2 :
return ( struct i2c_regs * ) CONFIG_SYS_I2C_BASE2 ;
# endif
# if CONFIG_SYS_I2C_BUS_MAX >= 2
case 1 :
return ( struct i2c_regs * ) CONFIG_SYS_I2C_BASE1 ;
# endif
case 0 :
return ( struct i2c_regs * ) CONFIG_SYS_I2C_BASE ;
default :
printf ( " Wrong I2C-adapter number %d \n " , adap - > hwadapnr ) ;
}
static struct i2c_regs * i2c_regs_p =
( struct i2c_regs * ) CONFIG_SYS_I2C_BASE ;
return NULL ;
}
/*
* set_speed - Set the i2c speed mode ( standard , high , fast )
@ -24,51 +40,52 @@ static struct i2c_regs *i2c_regs_p =
*
* Set the i2c speed mode ( standard , high , fast )
*/
static void set_speed ( int i2c_spd )
static void set_speed ( struct i2c_adapter * adap , int i2c_spd )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
unsigned int cntl ;
unsigned int hcnt , lcnt ;
unsigned int enbl ;
/* to set speed cltr must be disabled */
enbl = readl ( & i2c_regs_p - > ic_enable ) ;
enbl = readl ( & i2c_base - > ic_enable ) ;
enbl & = ~ IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
writel ( enbl , & i2c_base - > ic_enable ) ;
cntl = ( readl ( & i2c_regs_p - > ic_con ) & ( ~ IC_CON_SPD_MSK ) ) ;
cntl = ( readl ( & i2c_base - > ic_con ) & ( ~ IC_CON_SPD_MSK ) ) ;
switch ( i2c_spd ) {
case IC_SPEED_MODE_MAX :
cntl | = IC_CON_SPD_HS ;
hcnt = ( IC_CLK * MIN_HS_SCL_HIGHTIME ) / NANO_TO_MICRO ;
writel ( hcnt , & i2c_regs_p - > ic_hs_scl_hcnt ) ;
writel ( hcnt , & i2c_base - > ic_hs_scl_hcnt ) ;
lcnt = ( IC_CLK * MIN_HS_SCL_LOWTIME ) / NANO_TO_MICRO ;
writel ( lcnt , & i2c_regs_p - > ic_hs_scl_lcnt ) ;
writel ( lcnt , & i2c_base - > ic_hs_scl_lcnt ) ;
break ;
case IC_SPEED_MODE_STANDARD :
cntl | = IC_CON_SPD_SS ;
hcnt = ( IC_CLK * MIN_SS_SCL_HIGHTIME ) / NANO_TO_MICRO ;
writel ( hcnt , & i2c_regs_p - > ic_ss_scl_hcnt ) ;
writel ( hcnt , & i2c_base - > ic_ss_scl_hcnt ) ;
lcnt = ( IC_CLK * MIN_SS_SCL_LOWTIME ) / NANO_TO_MICRO ;
writel ( lcnt , & i2c_regs_p - > ic_ss_scl_lcnt ) ;
writel ( lcnt , & i2c_base - > ic_ss_scl_lcnt ) ;
break ;
case IC_SPEED_MODE_FAST :
default :
cntl | = IC_CON_SPD_FS ;
hcnt = ( IC_CLK * MIN_FS_SCL_HIGHTIME ) / NANO_TO_MICRO ;
writel ( hcnt , & i2c_regs_p - > ic_fs_scl_hcnt ) ;
writel ( hcnt , & i2c_base - > ic_fs_scl_hcnt ) ;
lcnt = ( IC_CLK * MIN_FS_SCL_LOWTIME ) / NANO_TO_MICRO ;
writel ( lcnt , & i2c_regs_p - > ic_fs_scl_lcnt ) ;
writel ( lcnt , & i2c_base - > ic_fs_scl_lcnt ) ;
break ;
}
writel ( cntl , & i2c_regs_p - > ic_con ) ;
writel ( cntl , & i2c_base - > ic_con ) ;
/* Enable back i2c now speed set */
enbl | = IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
writel ( enbl , & i2c_base - > ic_enable ) ;
}
/*
@ -77,7 +94,8 @@ static void set_speed(int i2c_spd)
*
* Set the i2c speed .
*/
int i2c_set_bus_speed ( unsigned int speed )
static unsigned int dw_i2c_set_bus_speed ( struct i2c_adapter * adap ,
unsigned int speed )
{
int i2c_spd ;
@ -88,28 +106,8 @@ int i2c_set_bus_speed(unsigned int speed)
else
i2c_spd = IC_SPEED_MODE_STANDARD ;
set_speed ( i2c_spd ) ;
return i2c_spd ;
}
/*
* i2c_get_bus_speed - Gets the i2c speed
*
* Gets the i2c speed .
*/
unsigned int i2c_get_bus_speed ( void )
{
u32 cntl ;
cntl = ( readl ( & i2c_regs_p - > ic_con ) & IC_CON_SPD_MSK ) ;
if ( cntl = = IC_CON_SPD_HS )
return I2C_MAX_SPEED ;
else if ( cntl = = IC_CON_SPD_FS )
return I2C_FAST_SPEED ;
else if ( cntl = = IC_CON_SPD_SS )
return I2C_STANDARD_SPEED ;
set_speed ( adap , i2c_spd ) ;
adap - > speed = speed ;
return 0 ;
}
@ -117,34 +115,32 @@ unsigned int i2c_get_bus_speed(void)
/*
* i2c_init - Init function
* @ speed : required i2c speed
* @ slaveadd : slave address for the device
* @ slaveaddr : slave address for the device
*
* Initialization function .
*/
void i2c_init ( int speed , int slaveadd )
static void dw_i2c_init ( struct i2c_adapter * adap , int speed ,
int slaveaddr )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
unsigned int enbl ;
/* Disable i2c */
enbl = readl ( & i2c_regs_p - > ic_enable ) ;
enbl = readl ( & i2c_base - > ic_enable ) ;
enbl & = ~ IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
writel ( enbl , & i2c_base - > ic_enable ) ;
writel ( ( IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM ) , & i2c_regs_p - > ic_con ) ;
writel ( IC_RX_TL , & i2c_regs_p - > ic_rx_tl ) ;
writel ( IC_TX_TL , & i2c_regs_p - > ic_tx_tl ) ;
i2c_set_bus_speed ( speed ) ;
writel ( IC_STOP_DET , & i2c_regs_p - > ic_intr_mask ) ;
writel ( slaveadd , & i2c_regs_p - > ic_sar ) ;
writel ( ( IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM ) , & i2c_base - > ic_con ) ;
writel ( IC_RX_TL , & i2c_base - > ic_rx_tl ) ;
writel ( IC_TX_TL , & i2c_base - > ic_tx_tl ) ;
dw_ i2c_set_bus_speed( adap , speed ) ;
writel ( IC_STOP_DET , & i2c_base - > ic_intr_mask ) ;
writel ( slaveaddr , & i2c_base - > ic_sar ) ;
/* Enable i2c */
enbl = readl ( & i2c_regs_p - > ic_enable ) ;
enbl = readl ( & i2c_base - > ic_enable ) ;
enbl | = IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
# ifdef CONFIG_I2C_MULTI_BUS
bus_initialized [ current_bus ] = 1 ;
# endif
writel ( enbl , & i2c_base - > ic_enable ) ;
}
/*
@ -153,21 +149,22 @@ void i2c_init(int speed, int slaveadd)
*
* Sets the target slave address .
*/
static void i2c_setaddress ( unsigned int i2c_addr )
static void i2c_setaddress ( struct i2c_adapter * adap , unsigned int i2c_addr )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
unsigned int enbl ;
/* Disable i2c */
enbl = readl ( & i2c_regs_p - > ic_enable ) ;
enbl = readl ( & i2c_base - > ic_enable ) ;
enbl & = ~ IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
writel ( enbl , & i2c_base - > ic_enable ) ;
writel ( i2c_addr , & i2c_regs_p - > ic_tar ) ;
writel ( i2c_addr , & i2c_base - > ic_tar ) ;
/* Enable i2c */
enbl = readl ( & i2c_regs_p - > ic_enable ) ;
enbl = readl ( & i2c_base - > ic_enable ) ;
enbl | = IC_ENABLE_0B ;
writel ( enbl , & i2c_regs_p - > ic_enable ) ;
writel ( enbl , & i2c_base - > ic_enable ) ;
}
/*
@ -175,10 +172,12 @@ static void i2c_setaddress(unsigned int i2c_addr)
*
* Flushes the i2c RX FIFO
*/
static void i2c_flush_rxfifo ( vo id)
static void i2c_flush_rxfifo ( struct i2c_a dapter * adap )
{
while ( readl ( & i2c_regs_p - > ic_status ) & IC_STATUS_RFNE )
readl ( & i2c_regs_p - > ic_cmd_data ) ;
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
while ( readl ( & i2c_base - > ic_status ) & IC_STATUS_RFNE )
readl ( & i2c_base - > ic_cmd_data ) ;
}
/*
@ -186,12 +185,13 @@ static void i2c_flush_rxfifo(void)
*
* Waits for bus busy
*/
static int i2c_wait_for_bb ( vo id)
static int i2c_wait_for_bb ( struct i2c_a dapter * adap )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
unsigned long start_time_bb = get_timer ( 0 ) ;
while ( ( readl ( & i2c_regs_p - > ic_status ) & IC_STATUS_MA ) | |
! ( readl ( & i2c_regs_p - > ic_status ) & IC_STATUS_TFE ) ) {
while ( ( readl ( & i2c_base - > ic_status ) & IC_STATUS_MA ) | |
! ( readl ( & i2c_base - > ic_status ) & IC_STATUS_TFE ) ) {
/* Evaluate timeout */
if ( get_timer ( start_time_bb ) > ( unsigned long ) ( I2C_BYTE_TO_BB ) )
@ -201,40 +201,44 @@ static int i2c_wait_for_bb(void)
return 0 ;
}
static int i2c_xfer_init ( uchar chip , uint addr , int alen )
static int i2c_xfer_init ( struct i2c_adapter * adap , uchar chip , uint addr ,
int alen )
{
if ( i2c_wait_for_bb ( ) )
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
if ( i2c_wait_for_bb ( adap ) )
return 1 ;
i2c_setaddress ( chip ) ;
i2c_setaddress ( adap , chip ) ;
while ( alen ) {
alen - - ;
/* high byte address going out first */
writel ( ( addr > > ( alen * 8 ) ) & 0xff ,
& i2c_regs_p - > ic_cmd_data ) ;
& i2c_base - > ic_cmd_data ) ;
}
return 0 ;
}
static int i2c_xfer_finish ( vo id)
static int i2c_xfer_finish ( struct i2c_a dapter * adap )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
ulong start_stop_det = get_timer ( 0 ) ;
while ( 1 ) {
if ( ( readl ( & i2c_regs_p - > ic_raw_intr_stat ) & IC_STOP_DET ) ) {
readl ( & i2c_regs_p - > ic_clr_stop_det ) ;
if ( ( readl ( & i2c_base - > ic_raw_intr_stat ) & IC_STOP_DET ) ) {
readl ( & i2c_base - > ic_clr_stop_det ) ;
break ;
} else if ( get_timer ( start_stop_det ) > I2C_STOPDET_TO ) {
break ;
}
}
if ( i2c_wait_for_bb ( ) ) {
if ( i2c_wait_for_bb ( adap ) ) {
printf ( " Timed out waiting for bus \n " ) ;
return 1 ;
}
i2c_flush_rxfifo ( ) ;
i2c_flush_rxfifo ( adap ) ;
return 0 ;
}
@ -249,8 +253,10 @@ static int i2c_xfer_finish(void)
*
* Read from i2c memory .
*/
int i2c_read ( uchar chip , uint addr , int alen , uchar * buffer , int len )
static int dw_i2c_read ( struct i2c_adapter * adap , u8 dev , uint addr ,
int alen , u8 * buffer , int len )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
unsigned long start_time_rx ;
# ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
@ -265,25 +271,25 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address .
*/
chip | = ( ( addr > > ( alen * 8 ) ) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW ) ;
dev | = ( ( addr > > ( alen * 8 ) ) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW ) ;
addr & = ~ ( CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW < < ( alen * 8 ) ) ;
debug ( " %s: fix addr_overflow: chip %02x addr %02x \n " , __func__ , chip ,
debug ( " %s: fix addr_overflow: dev %02x addr %02x \n " , __func__ , dev ,
addr ) ;
# endif
if ( i2c_xfer_init ( chip , addr , alen ) )
if ( i2c_xfer_init ( adap , dev , addr , alen ) )
return 1 ;
start_time_rx = get_timer ( 0 ) ;
while ( len ) {
if ( len = = 1 )
writel ( IC_CMD | IC_STOP , & i2c_regs_p - > ic_cmd_data ) ;
writel ( IC_CMD | IC_STOP , & i2c_base - > ic_cmd_data ) ;
else
writel ( IC_CMD , & i2c_regs_p - > ic_cmd_data ) ;
writel ( IC_CMD , & i2c_base - > ic_cmd_data ) ;
if ( readl ( & i2c_regs_p - > ic_status ) & IC_STATUS_RFNE ) {
* buffer + + = ( uchar ) readl ( & i2c_regs_p - > ic_cmd_data ) ;
if ( readl ( & i2c_base - > ic_status ) & IC_STATUS_RFNE ) {
* buffer + + = ( uchar ) readl ( & i2c_base - > ic_cmd_data ) ;
len - - ;
start_time_rx = get_timer ( 0 ) ;
@ -292,7 +298,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
}
}
return i2c_xfer_finish ( ) ;
return i2c_xfer_finish ( adap ) ;
}
/*
@ -305,8 +311,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
*
* Write to i2c memory .
*/
int i2c_write ( uchar chip , uint addr , int alen , uchar * buffer , int len )
static int dw_i2c_write ( struct i2c_adapter * adap , u8 dev , uint addr ,
int alen , u8 * buffer , int len )
{
struct i2c_regs * i2c_base = i2c_get_base ( adap ) ;
int nb = len ;
unsigned long start_time_tx ;
@ -322,23 +330,25 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address .
*/
chip | = ( ( addr > > ( alen * 8 ) ) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW ) ;
dev | = ( ( addr > > ( alen * 8 ) ) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW ) ;
addr & = ~ ( CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW < < ( alen * 8 ) ) ;
debug ( " %s: fix addr_overflow: chip %02x addr %02x \n " , __func__ , chip ,
debug ( " %s: fix addr_overflow: dev %02x addr %02x \n " , __func__ , dev ,
addr ) ;
# endif
if ( i2c_xfer_init ( chip , addr , alen ) )
if ( i2c_xfer_init ( adap , dev , addr , alen ) )
return 1 ;
start_time_tx = get_timer ( 0 ) ;
while ( len ) {
if ( readl ( & i2c_regs_p - > ic_status ) & IC_STATUS_TFNF ) {
if ( - - len = = 0 )
writel ( * buffer | IC_STOP , & i2c_regs_p - > ic_cmd_data ) ;
else
writel ( * buffer , & i2c_regs_p - > ic_cmd_data ) ;
if ( readl ( & i2c_base - > ic_status ) & IC_STATUS_TFNF ) {
if ( - - len = = 0 ) {
writel ( * buffer | IC_STOP ,
& i2c_base - > ic_cmd_data ) ;
} else {
writel ( * buffer , & i2c_base - > ic_cmd_data ) ;
}
buffer + + ;
start_time_tx = get_timer ( 0 ) ;
@ -348,13 +358,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
}
}
return i2c_xfer_finish ( ) ;
return i2c_xfer_finish ( adap ) ;
}
/*
* i2c_probe - Probe the i2c chip
*/
int i2c_probe ( uchar chip )
static int dw_ i2c_probe( struct i2c_adapter * adap , u8 dev )
{
u32 tmp ;
int ret ;
@ -362,80 +372,31 @@ int i2c_probe(uchar chip)
/*
* Try to read the first location of the chip .
*/
ret = i2c_read ( chip , 0 , 1 , ( uchar * ) & tmp , 1 ) ;
ret = dw_ i2c_read( adap , dev , 0 , 1 , ( uchar * ) & tmp , 1 ) ;
if ( ret )
i2c_init ( CONFIG_SYS_I2C_SPEED , CONFIG_SYS_I2C_SLAVE ) ;
dw_ i2c_init( adap , adap - > speed , adap - > slaveaddr ) ;
return ret ;
}
# ifdef CONFIG_I2C_MULTI_BUS
int i2c_set_bus_num ( unsigned int bus )
{
switch ( bus ) {
case 0 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE ;
break ;
# ifdef CONFIG_SYS_I2C_BASE1
case 1 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE1 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE2
case 2 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE2 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE3
case 3 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE3 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE4
case 4 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE4 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE5
case 5 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE5 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE6
case 6 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE6 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE7
case 7 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE7 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE8
case 8 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE8 ;
break ;
# endif
# ifdef CONFIG_SYS_I2C_BASE9
case 9 :
i2c_regs_p = ( void * ) CONFIG_SYS_I2C_BASE9 ;
break ;
# endif
default :
printf ( " Bad bus: %d \n " , bus ) ;
return - 1 ;
}
current_bus = bus ;
U_BOOT_I2C_ADAP_COMPLETE ( dw_0 , dw_i2c_init , dw_i2c_probe , dw_i2c_read ,
dw_i2c_write , dw_i2c_set_bus_speed ,
CONFIG_SYS_I2C_SPEED , CONFIG_SYS_I2C_SLAVE , 0 )
if ( ! bus_initialized [ current_bus ] )
i2c_init ( CONFIG_SYS_I2C_SPEED , CONFIG_SYS_I2C_SLAVE ) ;
# if CONFIG_SYS_I2C_BUS_MAX >= 2
U_BOOT_I2C_ADAP_COMPLETE ( dw_1 , dw_i2c_init , dw_i2c_probe , dw_i2c_read ,
dw_i2c_write , dw_i2c_set_bus_speed ,
CONFIG_SYS_I2C_SPEED1 , CONFIG_SYS_I2C_SLAVE1 , 1 )
# endif
return 0 ;
}
# if CONFIG_SYS_I2C_BUS_MAX >= 3
U_BOOT_I2C_ADAP_COMPLETE ( dw_2 , dw_i2c_init , dw_i2c_probe , dw_i2c_read ,
dw_i2c_write , dw_i2c_set_bus_speed ,
CONFIG_SYS_I2C_SPEED2 , CONFIG_SYS_I2C_SLAVE2 , 2 )
# endif
unsigned int i2c_get_bus_num ( void )
{
return current_bus ;
}
# if CONFIG_SYS_I2C_BUS_MAX >= 4
U_BOOT_I2C_ADAP_COMPLETE ( dw_3 , dw_i2c_init , dw_i2c_probe , dw_i2c_read ,
dw_i2c_write , dw_i2c_set_bus_speed ,
CONFIG_SYS_I2C_SPEED3 , CONFIG_SYS_I2C_SLAVE3 , 3 )
# endif