aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2013-08-19 08:07:53 -0400
committerWolfram Sang <wsa@the-dreams.de>2013-08-28 05:11:10 -0400
commitdefc0b2fb5221bca847a9adb8159b88bc3c93904 (patch)
tree345ed01cb257616a5607515dd011ae9c179aca4c /drivers/i2c
parentb3bfce2bc205ff4fdb4ec0b048513557cef459cf (diff)
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 <mika.westerberg@linux.intel.com> Acked-by: Shinya Kuribayashi <skuribay@pobox.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c11
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h12
2 files changed, 23 insertions, 0 deletions
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)
317 47, /* tLOW = 4.7 us */ 317 47, /* tLOW = 4.7 us */
318 3, /* tf = 0.3 us */ 318 3, /* tf = 0.3 us */
319 0); /* No offset */ 319 0); /* No offset */
320
321 /* Allow platforms to specify the ideal HCNT and LCNT values */
322 if (dev->ss_hcnt && dev->ss_lcnt) {
323 hcnt = dev->ss_hcnt;
324 lcnt = dev->ss_lcnt;
325 }
320 dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); 326 dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
321 dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); 327 dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
322 dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); 328 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)
331 13, /* tLOW = 1.3 us */ 337 13, /* tLOW = 1.3 us */
332 3, /* tf = 0.3 us */ 338 3, /* tf = 0.3 us */
333 0); /* No offset */ 339 0); /* No offset */
340
341 if (dev->fs_hcnt && dev->fs_lcnt) {
342 hcnt = dev->fs_hcnt;
343 lcnt = dev->fs_lcnt;
344 }
334 dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); 345 dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
335 dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); 346 dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
336 dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); 347 dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 912aa2262866..e8a756537ed0 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -61,6 +61,14 @@
61 * @tx_fifo_depth: depth of the hardware tx fifo 61 * @tx_fifo_depth: depth of the hardware tx fifo
62 * @rx_fifo_depth: depth of the hardware rx fifo 62 * @rx_fifo_depth: depth of the hardware rx fifo
63 * @rx_outstanding: current master-rx elements in tx fifo 63 * @rx_outstanding: current master-rx elements in tx fifo
64 * @ss_hcnt: standard speed HCNT value
65 * @ss_lcnt: standard speed LCNT value
66 * @fs_hcnt: fast speed HCNT value
67 * @fs_lcnt: fast speed LCNT value
68 *
69 * HCNT and LCNT parameters can be used if the platform knows more accurate
70 * values than the one computed based only on the input clock frequency.
71 * Leave them to be %0 if not used.
64 */ 72 */
65struct dw_i2c_dev { 73struct dw_i2c_dev {
66 struct device *dev; 74 struct device *dev;
@@ -91,6 +99,10 @@ struct dw_i2c_dev {
91 unsigned int rx_fifo_depth; 99 unsigned int rx_fifo_depth;
92 int rx_outstanding; 100 int rx_outstanding;
93 u32 sda_hold_time; 101 u32 sda_hold_time;
102 u16 ss_hcnt;
103 u16 ss_lcnt;
104 u16 fs_hcnt;
105 u16 fs_lcnt;
94}; 106};
95 107
96#define ACCESS_SWAP 0x00000001 108#define ACCESS_SWAP 0x00000001