diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c index 41cc3b8fa4..16b1aba32a 100644 --- a/drivers/i2c/i2c_core.c +++ b/drivers/i2c/i2c_core.c @@ -233,6 +233,11 @@ __weak void i2c_init_board(void) { } +/* implement possible for i2c specific early i2c init */ +__weak void i2c_early_init_f(void) +{ +} + /* * i2c_init_all(): * diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 445fa21082..f3402089a8 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -32,6 +32,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMX_I2C_REGSHIFT 2 #define VF610_I2C_REGSHIFT 0 + +#define I2C_EARLY_INIT_INDEX 0 +#ifdef CONFIG_SYS_I2C_IFDR_DIV +#define I2C_IFDR_DIV_CONSERVATIVE CONFIG_SYS_I2C_IFDR_DIV +#else +#define I2C_IFDR_DIV_CONSERVATIVE 0x7e +#endif + /* Register index */ #define IADR 0 #define IFDR 1 @@ -659,6 +667,25 @@ void bus_i2c_init(int index, int speed, int unused, bus_i2c_set_bus_speed(&mxc_i2c_buses[index], speed); } +/* + * Early init I2C for prepare read the clk through I2C. + */ +void i2c_early_init_f(void) +{ + ulong base = mxc_i2c_buses[I2C_EARLY_INIT_INDEX].base; + bool quirk = mxc_i2c_buses[I2C_EARLY_INIT_INDEX].driver_data + & I2C_QUIRK_FLAG ? true : false; + int reg_shift = quirk ? VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT; + + /* Set I2C divider value */ + writeb(I2C_IFDR_DIV_CONSERVATIVE, base + (IFDR << reg_shift)); + /* Reset module */ + writeb(I2CR_IDIS, base + (I2CR << reg_shift)); + writeb(0, base + (I2SR << reg_shift)); + /* Enable I2C */ + writeb(I2CR_IEN, base + (I2CR << reg_shift)); +} + /* * Init I2C Bus */ diff --git a/include/i2c.h b/include/i2c.h index 1f5ae4538a..d500445aaf 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -701,6 +701,9 @@ extern struct i2c_bus_hose i2c_bus[]; * Initialization, must be called once on start up, may be called * repeatedly to change the speed and slave addresses. */ +#ifdef CONFIG_SYS_I2C_EARLY_INIT +void i2c_early_init_f(void); +#endif void i2c_init(int speed, int slaveaddr); void i2c_init_board(void); #ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT