diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 678460325dd874752186484e7d75d5ee867b956a..1a4c8c9ad2701b550fc1ad0ab2a9fde741902080 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -31,7 +31,69 @@ static void flush_fifo(void);
 
 void i2c_init (int speed, int slaveadd)
 {
-	u16 scl;
+	int psc, fsscll, fssclh;
+	int hsscll = 0, hssclh = 0;
+	u32 scll, sclh;
+
+	/* Only handle standard, fast and high speeds */
+	if ((speed != OMAP_I2C_STANDARD) &&
+	    (speed != OMAP_I2C_FAST_MODE) &&
+	    (speed != OMAP_I2C_HIGH_SPEED)) {
+		printf("Error : I2C unsupported speed %d\n", speed);
+		return;
+	}
+
+	psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+	psc -= 1;
+	if (psc < I2C_PSC_MIN) {
+		printf("Error : I2C unsupported prescalar %d\n", psc);
+		return;
+	}
+
+	if (speed == OMAP_I2C_HIGH_SPEED) {
+		/* High speed */
+
+		/* For first phase of HS mode */
+		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
+			(2 * OMAP_I2C_FAST_MODE);
+
+		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
+		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
+		if (((fsscll < 0) || (fssclh < 0)) ||
+		    ((fsscll > 255) || (fssclh > 255))) {
+			printf("Error : I2C initializing first phase clock\n");
+			return;
+		}
+
+		/* For second phase of HS mode */
+		hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
+
+		hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
+		hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
+		if (((fsscll < 0) || (fssclh < 0)) ||
+		    ((fsscll > 255) || (fssclh > 255))) {
+			printf("Error : I2C initializing second phase clock\n");
+			return;
+		}
+
+		scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
+		sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh;
+
+	} else {
+		/* Standard and fast speed */
+		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
+
+		fsscll -= I2C_FASTSPEED_SCLL_TRIM;
+		fssclh -= I2C_FASTSPEED_SCLH_TRIM;
+		if (((fsscll < 0) || (fssclh < 0)) ||
+		    ((fsscll > 255) || (fssclh > 255))) {
+			printf("Error : I2C initializing clock\n");
+			return;
+		}
+
+		scll = (unsigned int)fsscll;
+		sclh = (unsigned int)fssclh;
+	}
 
 	writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
 	udelay(1000);
@@ -42,12 +104,10 @@ void i2c_init (int speed, int slaveadd)
 		udelay (50000);
 	}
 
-	/* 12MHz I2C module clock */
-	writew (0, I2C_PSC);
-	speed = speed/1000;		    /* 100 or 400 */
-	scl = ((12000/(speed*2)) - 7);	/* use 7 when PSC = 0 */
-	writew (scl, I2C_SCLL);
-	writew (scl, I2C_SCLH);
+	writew(psc, I2C_PSC);
+	writew(scll, I2C_SCLL);
+	writew(sclh, I2C_SCLH);
+
 	/* own address */
 	writew (slaveadd, I2C_OA);
 	writew (I2C_CON_EN, I2C_CON);
diff --git a/include/asm-arm/arch-omap24xx/i2c.h b/include/asm-arm/arch-omap24xx/i2c.h
index 7248950e52fe8f08568bbf5b2725c17746127a79..44db7a2d45efc06dc8f757504331b40ae0484513 100644
--- a/include/asm-arm/arch-omap24xx/i2c.h
+++ b/include/asm-arm/arch-omap24xx/i2c.h
@@ -104,4 +104,48 @@
 #define I2C_SYSTEST_SDA_I       (1 << 1)        /* SDA line sense input value */
 #define I2C_SYSTEST_SDA_O       (1 << 0)        /* SDA line drive output value */
 
+/* These values were copied from omap3, include/asm-arm/arch-omap3/i2c.h. */
+#define OMAP_I2C_STANDARD		100000
+#define OMAP_I2C_FAST_MODE		400000
+#define OMAP_I2C_HIGH_SPEED		3400000
+
+#define SYSTEM_CLOCK_12			12000000
+#define SYSTEM_CLOCK_13			13000000
+#define SYSTEM_CLOCK_192		19200000
+#define SYSTEM_CLOCK_96			96000000
+
+#ifndef I2C_IP_CLK
+#define I2C_IP_CLK			SYSTEM_CLOCK_96
+#endif
+
+#ifndef I2C_INTERNAL_SAMPLING_CLK
+#define I2C_INTERNAL_SAMPLING_CLK	19200000
+#endif
+
+/* These are the trim values for standard and fast speed */
+#ifndef I2C_FASTSPEED_SCLL_TRIM
+#define I2C_FASTSPEED_SCLL_TRIM		6
+#endif
+#ifndef I2C_FASTSPEED_SCLH_TRIM
+#define I2C_FASTSPEED_SCLH_TRIM		6
+#endif
+
+/* These are the trim values for high speed */
+#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM
+#define I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM
+#define I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM
+#define I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM
+#define I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM
+#endif
+
+#define I2C_PSC_MAX			0x0f
+#define I2C_PSC_MIN			0x00
+
+
 #endif
diff --git a/include/asm-arm/arch-omap3/i2c.h b/include/asm-arm/arch-omap3/i2c.h
index 3937f3525671cf0742e077a20ff93bb56f30780e..8b339cce9ab553e650282e5fdddcc6252d44aad8 100644
--- a/include/asm-arm/arch-omap3/i2c.h
+++ b/include/asm-arm/arch-omap3/i2c.h
@@ -112,16 +112,72 @@
 #define I2C_SCLH_HSSCLH		8
 #define I2C_SCLH_HSSCLH_M	0xFF
 
-#define OMAP_I2C_STANDARD	100
-#define OMAP_I2C_FAST_MODE	400
-#define OMAP_I2C_HIGH_SPEED	3400
+#define OMAP_I2C_STANDARD	100000
+#define OMAP_I2C_FAST_MODE	400000
+#define OMAP_I2C_HIGH_SPEED	3400000
 
-#define SYSTEM_CLOCK_12		12000
-#define SYSTEM_CLOCK_13		13000
-#define SYSTEM_CLOCK_192	19200
-#define SYSTEM_CLOCK_96		96000
+#define SYSTEM_CLOCK_12		12000000
+#define SYSTEM_CLOCK_13		13000000
+#define SYSTEM_CLOCK_192	19200000
+#define SYSTEM_CLOCK_96		96000000
 
+/* Use the reference value of 96MHz if not explicitly set by the board */
+#ifndef I2C_IP_CLK
 #define I2C_IP_CLK		SYSTEM_CLOCK_96
+#endif
+
+/*
+ * The reference minimum clock for high speed is 19.2MHz.
+ * The linux 2.6.30 kernel uses this value.
+ * The reference minimum clock for fast mode is 9.6MHz
+ * The reference minimum clock for standard mode is 4MHz
+ * In TRM, the value of 12MHz is used.
+ */
+#ifndef I2C_INTERNAL_SAMPLING_CLK
+#define I2C_INTERNAL_SAMPLING_CLK	19200000
+#endif
+
+/*
+ * The equation for the low and high time is
+ * tlow = scll + scll_trim = (sampling clock * tlow_duty) / speed
+ * thigh = sclh + sclh_trim = (sampling clock * (1 - tlow_duty)) / speed
+ *
+ * If the duty cycle is 50%
+ *
+ * tlow = scll + scll_trim = sampling clock / (2 * speed)
+ * thigh = sclh + sclh_trim = sampling clock / (2 * speed)
+ *
+ * In TRM
+ * scll_trim = 7
+ * sclh_trim = 5
+ *
+ * The linux 2.6.30 kernel uses
+ * scll_trim = 6
+ * sclh_trim = 6
+ *
+ * These are the trim values for standard and fast speed
+ */
+#ifndef I2C_FASTSPEED_SCLL_TRIM
+#define I2C_FASTSPEED_SCLL_TRIM		6
+#endif
+#ifndef I2C_FASTSPEED_SCLH_TRIM
+#define I2C_FASTSPEED_SCLH_TRIM		6
+#endif
+
+/* These are the trim values for high speed */
+#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM
+#define I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM
+#define I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM
+#define I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM
+#endif
+#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM
+#define I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM
+#endif
+
 #define I2C_PSC_MAX		0x0f
 #define I2C_PSC_MIN		0x00