1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-01 16:52:14 +02:00

i2c: designware_i2c: Use an accurate bus clock instead of MHz

At present the driver uses an approximation for the bus clock, e.g. 166MHz
instead of 166 2/3 MHz.

This can result in small errors in the resulting I2C speed, perhaps 0.5%
or so.

Adjust the existing code to start from the accurate figure, even if later
rounding reduces this accuracy.

Update the bus speed code to work in KHz instead of MHz, which removes
most of the error.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
Simon Glass
2020-01-23 11:48:09 -07:00
committed by Heiko Schocher
parent 65190d15ef
commit dd3c1602cf
2 changed files with 10 additions and 12 deletions

View File

@@ -55,8 +55,9 @@ static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
struct dw_scl_sda_cfg *scl_sda_cfg,
unsigned int speed,
unsigned int bus_mhz)
unsigned int bus_clk)
{
ulong bus_khz = bus_clk / 1000;
enum i2c_speed_mode i2c_spd;
unsigned int cntl;
unsigned int hcnt, lcnt;
@@ -86,8 +87,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
hcnt = scl_sda_cfg->fs_hcnt;
lcnt = scl_sda_cfg->fs_lcnt;
} else {
hcnt = (bus_mhz * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
lcnt = (bus_mhz * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
hcnt = (bus_khz * MIN_HS_SCL_HIGHTIME) / NANO_TO_KILO;
lcnt = (bus_khz * MIN_HS_SCL_LOWTIME) / NANO_TO_KILO;
}
writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
@@ -99,8 +100,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
hcnt = scl_sda_cfg->ss_hcnt;
lcnt = scl_sda_cfg->ss_lcnt;
} else {
hcnt = (bus_mhz * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
lcnt = (bus_mhz * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
hcnt = (bus_khz * MIN_SS_SCL_HIGHTIME) / NANO_TO_KILO;
lcnt = (bus_khz * MIN_SS_SCL_LOWTIME) / NANO_TO_KILO;
}
writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
@@ -113,8 +114,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
hcnt = scl_sda_cfg->fs_hcnt;
lcnt = scl_sda_cfg->fs_lcnt;
} else {
hcnt = (bus_mhz * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
lcnt = (bus_mhz * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
hcnt = (bus_khz * MIN_FS_SCL_HIGHTIME) / NANO_TO_KILO;
lcnt = (bus_khz * MIN_FS_SCL_LOWTIME) / NANO_TO_KILO;
}
writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
@@ -511,9 +512,6 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
rate = clk_get_rate(&i2c->clk);
if (IS_ERR_VALUE(rate))
return -EINVAL;
/* Convert to MHz */
rate /= 1000000;
#else
rate = IC_CLK;
#endif