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 <aford...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot