From defc0b2fb5221bca847a9adb8159b88bc3c93904 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 19 Aug 2013 15:07:53 +0300 Subject: i2c: designware: make HCNT/LCNT values configurable The DesignWare I2C controller has high count (HCNT) and low count (LCNT) registers for each of the I2C speed modes (standard and fast). These registers are programmed based on the input clock speed in the driver. The current code calculates these values based on the input clock speed and tries hard to meet the I2C bus timing requirements. This could result non-optimal values with regarding to the bus speed. For example on Intel BayTrail we get bus speed of 315.41kHz which is ~20% slower than we would expect (400kHz) in fast mode (even though the timing requirements are met). This patch makes it possible for the platform code to pass more optimal HCNT/LCNT values to the core driver if they are known beforehand. If these are not set we use the calculated and more conservative values. Signed-off-by: Mika Westerberg Acked-by: Shinya Kuribayashi Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/i2c/busses/i2c-designware-core.c') diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index f325ec7abfb1..dbecf08399f8 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -317,6 +317,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev) 47, /* tLOW = 4.7 us */ 3, /* tf = 0.3 us */ 0); /* No offset */ + + /* Allow platforms to specify the ideal HCNT and LCNT values */ + if (dev->ss_hcnt && dev->ss_lcnt) { + hcnt = dev->ss_hcnt; + lcnt = dev->ss_lcnt; + } dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); @@ -331,6 +337,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev) 13, /* tLOW = 1.3 us */ 3, /* tf = 0.3 us */ 0); /* No offset */ + + if (dev->fs_hcnt && dev->fs_lcnt) { + hcnt = dev->fs_hcnt; + lcnt = dev->fs_lcnt; + } dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); -- cgit v1.2.3