@ -12,13 +12,27 @@
# include <fdtdec.h>
# include <i2c.h>
# include <asm/io.h>
# ifdef CONFIG_TEGRA186
# include <clk.h>
# include <reset.h>
# else
# include <asm/arch/clock.h>
# include <asm/arch/funcmux.h>
# include <asm/arch/gpio.h>
# include <asm/arch/pinmux.h>
# include <asm/arch-tegra/clk_rst.h>
# endif
# include <asm/arch/gpio.h>
# include <asm/arch-tegra/tegra_i2c.h>
/*
* FIXME : TODO : This driver contains a number of ifdef CONFIG_TEGRA186 that
* should not be present . These are needed because newer Tegra SoCs support
* only the standard clock / reset APIs , whereas older Tegra SoCs support only
* a custom Tegra - specific API . ASAP the older Tegra SoCs ' code should be
* fixed to implement the standard APIs , and all drivers converted to solely
* use the new standard APIs , with no ifdefs .
*/
DECLARE_GLOBAL_DATA_PTR ;
enum i2c_type {
@ -30,7 +44,12 @@ enum i2c_type {
/* Information about i2c controller */
struct i2c_bus {
int id ;
# ifdef CONFIG_TEGRA186
struct reset_ctl reset_ctl ;
struct clk clk ;
# else
enum periph_id periph_id ;
# endif
int speed ;
int pinmux_config ;
struct i2c_control * control ;
@ -62,12 +81,41 @@ static void set_packet_mode(struct i2c_bus *i2c_bus)
static void i2c_reset_controller ( struct i2c_bus * i2c_bus )
{
/* Reset I2C controller. */
# ifdef CONFIG_TEGRA186
reset_assert ( & i2c_bus - > reset_ctl ) ;
udelay ( 1 ) ;
reset_deassert ( & i2c_bus - > reset_ctl ) ;
udelay ( 1 ) ;
# else
reset_periph ( i2c_bus - > periph_id , 1 ) ;
# endif
/* re-program config register to packet mode */
set_packet_mode ( i2c_bus ) ;
}
# ifdef CONFIG_TEGRA186
static int i2c_init_clock ( struct i2c_bus * i2c_bus , unsigned rate )
{
int ret ;
ret = reset_assert ( & i2c_bus - > reset_ctl ) ;
if ( ret )
return ret ;
ret = clk_enable ( & i2c_bus - > clk ) ;
if ( ret )
return ret ;
ret = clk_set_rate ( & i2c_bus - > clk , rate ) ;
if ( IS_ERR_VALUE ( ret ) )
return ret ;
ret = reset_deassert ( & i2c_bus - > reset_ctl ) ;
if ( ret )
return ret ;
return 0 ;
}
# endif
static void i2c_init_controller ( struct i2c_bus * i2c_bus )
{
if ( ! i2c_bus - > speed )
@ -78,8 +126,12 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
* here , in section 23.3 .1 , but in fact we seem to need a factor of
* 16 to get the right frequency .
*/
# ifdef CONFIG_TEGRA186
i2c_init_clock ( i2c_bus , i2c_bus - > speed * 2 * 8 ) ;
# else
clock_start_periph_pll ( i2c_bus - > periph_id , CLOCK_ID_PERIPH ,
i2c_bus - > speed * 2 * 8 ) ;
# endif
if ( i2c_bus - > type = = TYPE_114 ) {
/*
@ -94,12 +146,17 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
* is running , we hang , and we need it for the new calc .
*/
int clk_div_stdfst_mode = readl ( & i2c_bus - > regs - > clk_div ) > > 16 ;
unsigned rate = CLK_MULT_STD_FAST_MODE *
( clk_div_stdfst_mode + 1 ) * i2c_bus - > speed * 2 ;
debug ( " %s: CLK_DIV_STD_FAST_MODE setting = %d \n " , __func__ ,
clk_div_stdfst_mode ) ;
# ifdef CONFIG_TEGRA186
i2c_init_clock ( i2c_bus , rate ) ;
# else
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 ) ;
rate ) ;
# endif
}
/* Reset I2C controller. */
@ -112,7 +169,9 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
setbits_le32 ( & dvc - > ctrl3 , DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK ) ;
}
# ifndef CONFIG_TEGRA186
funcmux_select ( i2c_bus - > periph_id , i2c_bus - > pinmux_config ) ;
# endif
}
static void send_packet_headers (
@ -333,8 +392,12 @@ static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
static int tegra_i2c_probe ( struct udevice * dev )
{
struct i2c_bus * i2c_bus = dev_get_priv ( dev ) ;
# ifdef CONFIG_TEGRA186
int ret ;
# else
const void * blob = gd - > fdt_blob ;
int node = dev - > of_offset ;
# endif
bool is_dvc ;
i2c_bus - > id = dev - > seq ;
@ -345,6 +408,18 @@ static int tegra_i2c_probe(struct udevice *dev)
* We don ' t have a binding for pinmux yet . Leave it out for now . So
* far no one needs anything other than the default .
*/
# ifdef CONFIG_TEGRA186
ret = reset_get_by_name ( dev , " i2c " , & i2c_bus - > reset_ctl ) ;
if ( ret ) {
error ( " reset_get_by_name() failed: %d \n " , ret ) ;
return ret ;
}
ret = clk_get_by_name ( dev , " i2c " , & i2c_bus - > clk ) ;
if ( ret ) {
error ( " clk_get_by_name() failed: %d \n " , ret ) ;
return ret ;
}
# else
i2c_bus - > pinmux_config = FUNCMUX_DEFAULT ;
i2c_bus - > periph_id = clock_decode_periph_id ( blob , node ) ;
@ -359,6 +434,7 @@ static int tegra_i2c_probe(struct udevice *dev)
*/
if ( i2c_bus - > periph_id = = - 1 )
return - EINVAL ;
# endif
is_dvc = dev_get_driver_data ( dev ) = = TYPE_DVC ;
if ( is_dvc ) {
@ -370,7 +446,12 @@ static int tegra_i2c_probe(struct udevice *dev)
i2c_init_controller ( i2c_bus ) ;
debug ( " %s: controller bus %d at %p, periph_id %d, speed %d: " ,
is_dvc ? " dvc " : " i2c " , dev - > seq , i2c_bus - > regs ,
i2c_bus - > periph_id , i2c_bus - > speed ) ;
# ifndef CONFIG_TEGRA186
i2c_bus - > periph_id ,
# else
- 1 ,
# endif
i2c_bus - > speed ) ;
return 0 ;
}