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>
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 2416ef3..0a1df80 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -55,8 +55,9 @@
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 @@
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 @@
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 @@
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 @@
rate = clk_get_rate(&i2c->clk);
if (IS_ERR_VALUE(rate))
return -EINVAL;
-
- /* Convert to MHz */
- rate /= 1000000;
#else
rate = IC_CLK;
#endif