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

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. At least on the OMAP3630/3730, this fails when trying to configure at 2.6MHz
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)
When dumping the data of fck, I got 96000000. The U-Boot omap24xx I2C driver sets the I2C_IP_CLK to SYSTEM_CLOCK_96 and I2C_INTERNAL_SAMPLING_CLK to 19200000 except for arch/arm/include/asm/arch-am33xx/i2c.h which defines I2C_INTERNAL_SAMPLING_CLK to 12000000 and I2C_IP_CLK 48000000.
I do not have this hardware, so I cannot test, but I compared the values of psc=4, scll=4377, sclh=1803 for both U-Boot and Linux and they match on an OMAP630/3730.
Signed-off-by: Adam Ford aford173@gmail.com
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 5d33815..eace748 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -205,8 +205,10 @@ 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 */ + unsigned long scl; + psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; psc -= 1; if (psc < I2C_PSC_MIN) { @@ -215,12 +217,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); + scl = I2C_INTERNAL_SAMPLING_CLK / 400000; + fsscll = scl - (scl / 3) - 7; + fssclh = (scl / 3) - 5;
- fssclh = fsscll; - - 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 +228,10 @@ 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_IP_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"); @@ -240,7 +240,6 @@ static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; - } else { /* Standard and fast speed */ psc = omap24_i2c_findpsc(&scll, &sclh, speed);
participants (1)
-
Adam Ford