drivers: i2c: mxc: Add early init
Add early i2c init function with conservative divider when the exact
clock rate is not available.
Signed-off-by: Yuan Yao <yao.yuan@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index 41cc3b8..16b1aba 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -233,6 +233,11 @@
{
}
+/* 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 445fa21..f340208 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -32,6 +32,14 @@
#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
@@ -660,6 +668,25 @@
}
/*
+ * 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
*/
static void mxc_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
diff --git a/include/i2c.h b/include/i2c.h
index 1f5ae45..d500445 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -701,6 +701,9 @@
* 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