@ -46,6 +46,7 @@ struct i2c_bus {
struct i2c_control * control ;
struct i2c_control * control ;
struct i2c_ctlr * regs ;
struct i2c_ctlr * regs ;
int is_dvc ; /* DVC type, rather than I2C */
int is_dvc ; /* DVC type, rather than I2C */
int is_scs ; /* single clock source (T114+) */
int inited ; /* bus is inited */
int inited ; /* bus is inited */
} ;
} ;
@ -88,7 +89,28 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
* 16 to get the right frequency .
* 16 to get the right frequency .
*/
*/
clock_start_periph_pll ( i2c_bus - > periph_id , CLOCK_ID_PERIPH ,
clock_start_periph_pll ( i2c_bus - > periph_id , CLOCK_ID_PERIPH ,
i2c_bus - > speed * 2 * 8 ) ;
i2c_bus - > speed * 2 * 8 ) ;
if ( i2c_bus - > is_scs ) {
/*
* T114 I2C went to a single clock source for standard / fast and
* HS clock speeds . The new clock rate setting calculation is :
* SCL = CLK_SOURCE . I2C /
* ( CLK_MULT_STD_FAST_MODE * ( I2C_CLK_DIV_STD_FAST_MODE + 1 ) *
* I2C FREQUENCY DIVISOR ) as per the T114 TRM ( sec 30.3 .1 ) .
*
* NOTE : We do this here , after the initial clock / pll start ,
* because if we read the clk_div reg before the controller
* is running , we hang , and we need it for the new calc .
*/
int clk_div_stdfst_mode = readl ( & i2c_bus - > regs - > clk_div ) > > 16 ;
debug ( " %s: CLK_DIV_STD_FAST_MODE setting = %d \n " , __func__ ,
clk_div_stdfst_mode ) ;
clock_start_periph_pll ( i2c_bus - > periph_id , CLOCK_ID_PERIPH ,
CLK_MULT_STD_FAST_MODE * ( clk_div_stdfst_mode + 1 ) *
i2c_bus - > speed * 2 ) ;
}
/* Reset I2C controller. */
/* Reset I2C controller. */
i2c_reset_controller ( i2c_bus ) ;
i2c_reset_controller ( i2c_bus ) ;
@ -352,10 +374,11 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
* @ param node_list list of nodes to process ( any < = 0 are ignored )
* @ param node_list list of nodes to process ( any < = 0 are ignored )
* @ param count number of nodes to process
* @ param count number of nodes to process
* @ param is_dvc 1 if these are DVC ports , 0 if standard I2C
* @ param is_dvc 1 if these are DVC ports , 0 if standard I2C
* @ param is_scs 1 if this HW uses a single clock source ( T114 + )
* @ return 0 if ok , - 1 on error
* @ return 0 if ok , - 1 on error
*/
*/
static int process_nodes ( const void * blob , int node_list [ ] , int count ,
static int process_nodes ( const void * blob , int node_list [ ] , int count ,
int is_dvc )
int is_dvc , int is_scs )
{
{
struct i2c_bus * i2c_bus ;
struct i2c_bus * i2c_bus ;
int i ;
int i ;
@ -375,6 +398,8 @@ static int process_nodes(const void *blob, int node_list[], int count,
return - 1 ;
return - 1 ;
}
}
i2c_bus - > is_scs = is_scs ;
i2c_bus - > is_dvc = is_dvc ;
i2c_bus - > is_dvc = is_dvc ;
if ( is_dvc ) {
if ( is_dvc ) {
i2c_bus - > control =
i2c_bus - > control =
@ -403,18 +428,25 @@ void i2c_init_board(void)
const void * blob = gd - > fdt_blob ;
const void * blob = gd - > fdt_blob ;
int count ;
int count ;
/* First get the normal i2c ports */
/* First check for newer (T114+) I2C ports */
count = fdtdec_find_aliases_for_id ( blob , " i2c " ,
COMPAT_NVIDIA_TEGRA114_I2C , node_list ,
TEGRA_I2C_NUM_CONTROLLERS ) ;
if ( process_nodes ( blob , node_list , count , 0 , 1 ) )
return ;
/* Now get the older (T20/T30) normal I2C ports */
count = fdtdec_find_aliases_for_id ( blob , " i2c " ,
count = fdtdec_find_aliases_for_id ( blob , " i2c " ,
COMPAT_NVIDIA_TEGRA20_I2C , node_list ,
COMPAT_NVIDIA_TEGRA20_I2C , node_list ,
TEGRA_I2C_NUM_CONTROLLERS ) ;
TEGRA_I2C_NUM_CONTROLLERS ) ;
if ( process_nodes ( blob , node_list , count , 0 ) )
if ( process_nodes ( blob , node_list , count , 0 , 0 ) )
return ;
return ;
/* Now look for dvc ports */
/* Now look for dvc ports */
count = fdtdec_add_aliases_for_id ( blob , " i2c " ,
count = fdtdec_add_aliases_for_id ( blob , " i2c " ,
COMPAT_NVIDIA_TEGRA20_DVC , node_list ,
COMPAT_NVIDIA_TEGRA20_DVC , node_list ,
TEGRA_I2C_NUM_CONTROLLERS ) ;
TEGRA_I2C_NUM_CONTROLLERS ) ;
if ( process_nodes ( blob , node_list , count , 1 ) )
if ( process_nodes ( blob , node_list , count , 1 , 0 ) )
return ;
return ;
}
}