Commit 869c6a3e authored by Lothar Waßmann's avatar Lothar Waßmann Committed by Wolfram Sang

i2c: mxs: fix broken timing calculation

The timing calculation is rather bogus and gives extremely wrong
results for higher frequencies (on an i.MX28). E.g. instead of 400 kHz
I measured 770 kHz.

Implement a calculation that adheres to the I2C spec and gives exact
results for I2C frequencies from 12.56 kHz to 960 kHz.

Also the bus_free and leadin parameters are programmed according to
the I2C spec for standard and fast mode.

This was tested on a Ka-Ro TX28 module with a DS1339, TSC2007, PCA9554
and SGTL5000 client.
Signed-off-by: default avatarLothar Waßmann <LW@KARO-electronics.de>
Acked-by: default avatarMarek Vasut <marex@denx.de>
[wsa: patch fixes whitespace issue, too]
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent b7d12a86
...@@ -114,6 +114,7 @@ struct mxs_i2c_dev { ...@@ -114,6 +114,7 @@ struct mxs_i2c_dev {
uint32_t timing0; uint32_t timing0;
uint32_t timing1; uint32_t timing1;
uint32_t timing2;
/* DMA support components */ /* DMA support components */
struct dma_chan *dmach; struct dma_chan *dmach;
...@@ -138,7 +139,7 @@ static int mxs_i2c_reset(struct mxs_i2c_dev *i2c) ...@@ -138,7 +139,7 @@ static int mxs_i2c_reset(struct mxs_i2c_dev *i2c)
*/ */
writel(i2c->timing0, i2c->regs + MXS_I2C_TIMING0); writel(i2c->timing0, i2c->regs + MXS_I2C_TIMING0);
writel(i2c->timing1, i2c->regs + MXS_I2C_TIMING1); writel(i2c->timing1, i2c->regs + MXS_I2C_TIMING1);
writel(0x00300030, i2c->regs + MXS_I2C_TIMING2); writel(i2c->timing2, i2c->regs + MXS_I2C_TIMING2);
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
...@@ -587,41 +588,79 @@ static const struct i2c_algorithm mxs_i2c_algo = { ...@@ -587,41 +588,79 @@ static const struct i2c_algorithm mxs_i2c_algo = {
.functionality = mxs_i2c_func, .functionality = mxs_i2c_func,
}; };
static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, int speed) static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed)
{ {
/* The I2C block clock run at 24MHz */ /* The I2C block clock runs at 24MHz */
const uint32_t clk = 24000000; const uint32_t clk = 24000000;
uint32_t base; uint32_t divider;
uint16_t high_count, low_count, rcv_count, xmit_count; uint16_t high_count, low_count, rcv_count, xmit_count;
uint32_t bus_free, leadin;
struct device *dev = i2c->dev; struct device *dev = i2c->dev;
if (speed > 540000) { divider = DIV_ROUND_UP(clk, speed);
dev_warn(dev, "Speed too high (%d Hz), using 540 kHz\n", speed);
speed = 540000; if (divider < 25) {
} else if (speed < 12000) { /*
dev_warn(dev, "Speed too low (%d Hz), using 12 kHz\n", speed); * limit the divider, so that min(low_count, high_count)
speed = 12000; * is >= 1
*/
divider = 25;
dev_warn(dev,
"Speed too high (%u.%03u kHz), using %u.%03u kHz\n",
speed / 1000, speed % 1000,
clk / divider / 1000, clk / divider % 1000);
} else if (divider > 1897) {
/*
* limit the divider, so that max(low_count, high_count)
* cannot exceed 1023
*/
divider = 1897;
dev_warn(dev,
"Speed too low (%u.%03u kHz), using %u.%03u kHz\n",
speed / 1000, speed % 1000,
clk / divider / 1000, clk / divider % 1000);
} }
/* /*
* The timing derivation algorithm. There is no documentation for this * The I2C spec specifies the following timing data:
* algorithm available, it was derived by using the scope and fiddling * standard mode fast mode Bitfield name
* with constants until the result observed on the scope was good enough * tLOW (SCL LOW period) 4700 ns 1300 ns
* for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be * tHIGH (SCL HIGH period) 4000 ns 600 ns
* possible to assume the algorithm works for other frequencies as well. * tSU;DAT (data setup time) 250 ns 100 ns
* tHD;STA (START hold time) 4000 ns 600 ns
* tBUF (bus free time) 4700 ns 1300 ns
* *
* Note it was necessary to cap the frequency on both ends as it's not * The hardware (of the i.MX28 at least) seems to add 2 additional
* possible to configure completely arbitrary frequency for the I2C bus * clock cycles to the low_count and 7 cycles to the high_count.
* clock. * This is compensated for by subtracting the respective constants
* from the values written to the timing registers.
*/ */
base = ((clk / speed) - 38) / 2; if (speed > 100000) {
high_count = base + 3; /* fast mode */
low_count = base - 3; low_count = DIV_ROUND_CLOSEST(divider * 13, (13 + 6));
rcv_count = (high_count * 3) / 4; high_count = DIV_ROUND_CLOSEST(divider * 6, (13 + 6));
xmit_count = low_count / 4; leadin = DIV_ROUND_UP(600 * (clk / 1000000), 1000);
bus_free = DIV_ROUND_UP(1300 * (clk / 1000000), 1000);
} else {
/* normal mode */
low_count = DIV_ROUND_CLOSEST(divider * 47, (47 + 40));
high_count = DIV_ROUND_CLOSEST(divider * 40, (47 + 40));
leadin = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
bus_free = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
}
rcv_count = high_count * 3 / 8;
xmit_count = low_count * 3 / 8;
dev_dbg(dev,
"speed=%u(actual %u) divider=%u low=%u high=%u xmit=%u rcv=%u leadin=%u bus_free=%u\n",
speed, clk / divider, divider, low_count, high_count,
xmit_count, rcv_count, leadin, bus_free);
low_count -= 2;
high_count -= 7;
i2c->timing0 = (high_count << 16) | rcv_count; i2c->timing0 = (high_count << 16) | rcv_count;
i2c->timing1 = (low_count << 16) | xmit_count; i2c->timing1 = (low_count << 16) | xmit_count;
i2c->timing2 = (bus_free << 16 | leadin);
} }
static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment