[U-Boot] [RFC] i2c, omap24xx: Fixup High Speed Initialization

Adam Ford aford173 at gmail.com
Fri Jan 26 18:14:24 UTC 2018


For devices running I2C over 400KHz, this needs to be in HS mode.
Currently, the code is only running in HS mode when the speed is
equal or greater than 3.4MHz.

Using the Linux kernel setup as a reference, I used much of their
calculation for fsscll, fssclh, hsscll, and hssclh.  However, Linux
uses fclk = clk_get(omap->dev, "fck") and fclk_rate = clk_get_rate(fclk)
to setup psc.  I wasn't sure how to do that in U-Boot since the structures
are different, so I assumed fclk = I2C_IP_CLK (48000000).  I don't think
this is correct, so I am hoping someone might have a suggestion.

As it stands, attempts to initialize I2C1 @ 2.6MHz fail, but this RFC doesn't
appear to give me issues.  As of this writing, I don't have a scope to
look at the actual clock speed.

Signed-off-by: Adam Ford <aford173 at gmail.com>

diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 5d33815..4c1aa5d 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -205,9 +205,12 @@ static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
 	int hsscll = 0, hssclh = 0;
 	u32 scll = 0, sclh = 0;
 
-	if (speed >= OMAP_I2C_HIGH_SPEED) {
+	if (speed > OMAP_I2C_FAST_MODE) {
 		/* High speed */
-		psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+		int scl;
+		int internal_clk = 19200000;
+
+		psc = I2C_IP_CLK / internal_clk;
 		psc -= 1;
 		if (psc < I2C_PSC_MIN) {
 			printf("Error : I2C unsupported prescaler %d\n", psc);
@@ -215,12 +218,10 @@ static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
 		}
 
 		/* For first phase of HS mode */
-		fsscll = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
-
-		fssclh = fsscll;
+		scl = internal_clk / (400000);
+		fsscll = scl - (scl / 3) - 7;
+		fssclh = (scl / 3) - 5;
 
-		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
-		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
 		if (((fsscll < 0) || (fssclh < 0)) ||
 		    ((fsscll > 255) || (fssclh > 255))) {
 			puts("Error : I2C initializing first phase clock\n");
@@ -228,10 +229,11 @@ static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
 		}
 
 		/* For second phase of HS mode */
-		hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
+		scl = I2C_INTERNAL_SAMPLING_CLK / speed;
+
+		hsscll = scl - (scl / 3) - 7;
+		hssclh = (scl / 3) - 5;
 
-		hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
-		hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
 		if (((fsscll < 0) || (fssclh < 0)) ||
 		    ((fsscll > 255) || (fssclh > 255))) {
 			puts("Error : I2C initializing second phase clock\n");
-- 
2.7.4



More information about the U-Boot mailing list