diff mbox series

[v2,06/19] i2c: designware_i2c: Use an accurate bus clock instead of MHz

Message ID 20200103222650.32592-5-sjg@chromium.org
State Superseded
Headers show
Series i2c: designware_ic2: Improvements to timing and general cleanup | expand

Commit Message

Simon Glass Jan. 3, 2020, 10:26 p.m. UTC
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 at chromium.org>
---

Changes in v2: None

 drivers/i2c/designware_i2c.c | 18 ++++++++----------
 drivers/i2c/designware_i2c.h |  4 ++--
 2 files changed, 10 insertions(+), 12 deletions(-)

Comments

Heiko Schocher Jan. 16, 2020, 6:45 a.m. UTC | #1
Hello Simon,

Am 03.01.2020 um 23:26 schrieb Simon Glass:
> 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 at chromium.org>
> ---
> 
> Changes in v2: None
> 
>   drivers/i2c/designware_i2c.c | 18 ++++++++----------
>   drivers/i2c/designware_i2c.h |  4 ++--
>   2 files changed, 10 insertions(+), 12 deletions(-)

Reviewed-by: Heiko Schocher <hs at denx.de>

bye,
Heiko
diff mbox series

Patch

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 2416ef32f9..0a1df8015f 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -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
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 06d794ca64..1f9940c2ba 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -59,8 +59,8 @@  struct i2c_regs {
 	u32 comp_type;
 };
 
-#define IC_CLK			166
-#define NANO_TO_MICRO		1000
+#define IC_CLK			166666666
+#define NANO_TO_KILO		1000000
 
 /* High and low times in different speed modes (in ns) */
 #define MIN_SS_SCL_HIGHTIME	4000