@ -83,7 +83,9 @@
# include <common.h>
# include <command.h>
# include <environment.h>
# include <i2c.h>
# include <malloc.h>
# include <asm/byteorder.h>
/* Display values from last command.
@ -125,6 +127,14 @@ static uchar i2c_no_probes[] = CFG_I2C_NOPROBES;
# define NUM_ELEMENTS_NOPROBE (sizeof(i2c_no_probes) / sizeof(i2c_no_probes[0]))
# endif
# if defined(CONFIG_I2C_MUX)
static I2C_MUX_DEVICE * i2c_mux_devices = NULL ;
static int i2c_mux_busid = CFG_MAX_I2C_BUS ;
DECLARE_GLOBAL_DATA_PTR ;
# endif
static int
mod_i2c_mem ( cmd_tbl_t * cmdtp , int incrflag , int flag , int argc , char * argv [ ] ) ;
@ -1188,6 +1198,37 @@ int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
return 0 ;
}
# if defined(CONFIG_I2C_MUX)
int do_i2c_add_bus ( cmd_tbl_t * cmdtp , int flag , int argc , char * argv [ ] )
{
int ret = 0 ;
if ( argc = = 1 ) {
/* show all busses */
I2C_MUX * mux ;
I2C_MUX_DEVICE * device = i2c_mux_devices ;
printf ( " Busses reached over muxes: \n " ) ;
while ( device ! = NULL ) {
printf ( " Bus ID: %x \n " , device - > busid ) ;
printf ( " reached over Mux(es): \n " ) ;
mux = device - > mux ;
while ( mux ! = NULL ) {
printf ( " %s@%x ch: %x \n " , mux - > name , mux - > chip , mux - > channel ) ;
mux = mux - > next ;
}
device = device - > next ;
}
} else {
I2C_MUX_DEVICE * dev ;
dev = i2c_mux_ident_muxstring ( ( uchar * ) argv [ 1 ] ) ;
ret = 0 ;
}
return ret ;
}
# endif /* CONFIG_I2C_MUX */
# if defined(CONFIG_I2C_MULTI_BUS)
int do_i2c_bus_num ( cmd_tbl_t * cmdtp , int flag , int argc , char * argv [ ] )
{
@ -1226,6 +1267,10 @@ int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
int do_i2c ( cmd_tbl_t * cmdtp , int flag , int argc , char * argv [ ] )
{
# if defined(CONFIG_I2C_MUX)
if ( ! strncmp ( argv [ 1 ] , " bu " , 2 ) )
return do_i2c_add_bus ( cmdtp , flag , - - argc , + + argv ) ;
# endif /* CONFIG_I2C_MUX */
if ( ! strncmp ( argv [ 1 ] , " sp " , 2 ) )
return do_i2c_bus_speed ( cmdtp , flag , - - argc , + + argv ) ;
# if defined(CONFIG_I2C_MULTI_BUS)
@ -1264,6 +1309,9 @@ int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
U_BOOT_CMD (
i2c , 6 , 1 , do_i2c ,
" i2c - I2C sub-system \n " ,
# if defined(CONFIG_I2C_MUX)
" bus [muxtype:muxaddr:muxchannel] - add a new bus reached over muxes. \n "
# endif /* CONFIG_I2C_MUX */
" speed [speed] - show or set I2C bus speed \n "
# if defined(CONFIG_I2C_MULTI_BUS)
" i2c dev [dev] - show or set current I2C bus \n "
@ -1335,3 +1383,222 @@ U_BOOT_CMD(
" (valid chip values 50..57) \n "
) ;
# endif
# if defined(CONFIG_I2C_MUX)
int i2c_mux_add_device ( I2C_MUX_DEVICE * dev )
{
I2C_MUX_DEVICE * devtmp = i2c_mux_devices ;
if ( i2c_mux_devices = = NULL ) {
i2c_mux_devices = dev ;
return 0 ;
}
while ( devtmp - > next ! = NULL )
devtmp = devtmp - > next ;
devtmp - > next = dev ;
return 0 ;
}
I2C_MUX_DEVICE * i2c_mux_search_device ( int id )
{
I2C_MUX_DEVICE * device = i2c_mux_devices ;
while ( device ! = NULL ) {
if ( device - > busid = = id )
return device ;
device = device - > next ;
}
return NULL ;
}
/* searches in the buf from *pos the next ':'.
* returns :
* 0 if found ( with * pos = where )
* < 0 if an error occured
* > 0 if the end of buf is reached
*/
static int i2c_mux_search_next ( int * pos , uchar * buf , int len )
{
while ( ( buf [ * pos ] ! = ' : ' ) & & ( * pos < len ) ) {
* pos + = 1 ;
}
if ( * pos > = len )
return 1 ;
if ( buf [ * pos ] ! = ' : ' )
return - 1 ;
return 0 ;
}
static int i2c_mux_get_busid ( void )
{
int tmp = i2c_mux_busid ;
i2c_mux_busid + + ;
return tmp ;
}
/* Analyses a Muxstring and sends immediately the
Commands to the Muxes . Runs from Flash .
*/
int i2c_mux_ident_muxstring_f ( uchar * buf )
{
int pos = 0 ;
int oldpos ;
int ret = 0 ;
int len = strlen ( ( char * ) buf ) ;
int chip ;
uchar channel ;
int was = 0 ;
while ( ret = = 0 ) {
oldpos = pos ;
/* search name */
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret ! = 0 )
printf ( " ERROR \n " ) ;
/* search address */
pos + + ;
oldpos = pos ;
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret ! = 0 )
printf ( " ERROR \n " ) ;
buf [ pos ] = 0 ;
chip = simple_strtoul ( ( char * ) & buf [ oldpos ] , NULL , 16 ) ;
buf [ pos ] = ' : ' ;
/* search channel */
pos + + ;
oldpos = pos ;
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret < 0 )
printf ( " ERROR \n " ) ;
was = 0 ;
if ( buf [ pos ] ! = 0 ) {
buf [ pos ] = 0 ;
was = 1 ;
}
channel = simple_strtoul ( ( char * ) & buf [ oldpos ] , NULL , 16 ) ;
if ( was )
buf [ pos ] = ' : ' ;
if ( i2c_write ( chip , 0 , 0 , & channel , 1 ) ! = 0 ) {
printf ( " Error setting Mux: chip:%x channel: \
% x \ n " , chip, channel);
return - 1 ;
}
pos + + ;
oldpos = pos ;
}
return 0 ;
}
/* Analyses a Muxstring and if this String is correct
* adds a new I2C Bus .
*/
I2C_MUX_DEVICE * i2c_mux_ident_muxstring ( uchar * buf )
{
I2C_MUX_DEVICE * device ;
I2C_MUX * mux ;
int pos = 0 ;
int oldpos ;
int ret = 0 ;
int len = strlen ( ( char * ) buf ) ;
int was = 0 ;
device = ( I2C_MUX_DEVICE * ) malloc ( sizeof ( I2C_MUX_DEVICE ) ) ;
device - > mux = NULL ;
device - > busid = i2c_mux_get_busid ( ) ;
device - > next = NULL ;
while ( ret = = 0 ) {
mux = ( I2C_MUX * ) malloc ( sizeof ( I2C_MUX ) ) ;
mux - > next = NULL ;
/* search name of mux */
oldpos = pos ;
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret ! = 0 )
printf ( " %s no name. \n " , __FUNCTION__ ) ;
mux - > name = ( char * ) malloc ( pos - oldpos + 1 ) ;
memcpy ( mux - > name , & buf [ oldpos ] , pos - oldpos ) ;
mux - > name [ pos - oldpos ] = 0 ;
/* search address */
pos + + ;
oldpos = pos ;
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret ! = 0 )
printf ( " %s no mux address. \n " , __FUNCTION__ ) ;
buf [ pos ] = 0 ;
mux - > chip = simple_strtoul ( ( char * ) & buf [ oldpos ] , NULL , 16 ) ;
buf [ pos ] = ' : ' ;
/* search channel */
pos + + ;
oldpos = pos ;
ret = i2c_mux_search_next ( & pos , buf , len ) ;
if ( ret < 0 )
printf ( " %s no mux channel. \n " , __FUNCTION__ ) ;
was = 0 ;
if ( buf [ pos ] ! = 0 ) {
buf [ pos ] = 0 ;
was = 1 ;
}
mux - > channel = simple_strtoul ( ( char * ) & buf [ oldpos ] , NULL , 16 ) ;
if ( was )
buf [ pos ] = ' : ' ;
if ( device - > mux = = NULL )
device - > mux = mux ;
else {
I2C_MUX * muxtmp = device - > mux ;
while ( muxtmp - > next ! = NULL ) {
muxtmp = muxtmp - > next ;
}
muxtmp - > next = mux ;
}
pos + + ;
oldpos = pos ;
}
if ( ret > 0 ) {
/* Add Device */
i2c_mux_add_device ( device ) ;
return device ;
}
return NULL ;
}
int i2x_mux_select_mux ( int bus )
{
I2C_MUX_DEVICE * dev ;
I2C_MUX * mux ;
if ( ( gd - > flags & GD_FLG_RELOC ) ! = GD_FLG_RELOC ) {
/* select Default Mux Bus */
# if defined(CFG_I2C_IVM_BUS)
i2c_mux_ident_muxstring_f ( ( uchar * ) CFG_I2C_IVM_BUS ) ;
# else
{
unsigned char * buf ;
buf = ( unsigned char * ) getenv ( " EEprom_ivm " ) ;
if ( buf ! = NULL )
i2c_mux_ident_muxstring_f ( buf ) ;
}
# endif
return 0 ;
}
dev = i2c_mux_search_device ( bus ) ;
if ( dev = = NULL )
return - 1 ;
mux = dev - > mux ;
while ( mux ! = NULL ) {
if ( i2c_write ( mux - > chip , 0 , 0 , & mux - > channel , 1 ) ! = 0 ) {
printf ( " Error setting Mux: chip:%x channel: \
% x \ n " , mux->chip, mux->channel);
return - 1 ;
}
mux = mux - > next ;
}
return 0 ;
}
# endif /* CONFIG_I2C_MUX */