aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c13
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h1
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c10
3 files changed, 24 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 3de549436992..ad46616de29e 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -67,9 +67,12 @@
67#define DW_IC_STATUS 0x70 67#define DW_IC_STATUS 0x70
68#define DW_IC_TXFLR 0x74 68#define DW_IC_TXFLR 0x74
69#define DW_IC_RXFLR 0x78 69#define DW_IC_RXFLR 0x78
70#define DW_IC_SDA_HOLD 0x7c
70#define DW_IC_TX_ABRT_SOURCE 0x80 71#define DW_IC_TX_ABRT_SOURCE 0x80
71#define DW_IC_ENABLE_STATUS 0x9c 72#define DW_IC_ENABLE_STATUS 0x9c
72#define DW_IC_COMP_PARAM_1 0xf4 73#define DW_IC_COMP_PARAM_1 0xf4
74#define DW_IC_COMP_VERSION 0xf8
75#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A
73#define DW_IC_COMP_TYPE 0xfc 76#define DW_IC_COMP_TYPE 0xfc
74#define DW_IC_COMP_TYPE_VALUE 0x44570140 77#define DW_IC_COMP_TYPE_VALUE 0x44570140
75 78
@@ -332,6 +335,16 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
332 dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); 335 dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
333 dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); 336 dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
334 337
338 /* Configure SDA Hold Time if required */
339 if (dev->sda_hold_time) {
340 reg = dw_readl(dev, DW_IC_COMP_VERSION);
341 if (reg >= DW_IC_SDA_HOLD_MIN_VERS)
342 dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
343 else
344 dev_warn(dev->dev,
345 "Hardware too old to adjust SDA hold time.");
346 }
347
335 /* Configure Tx/Rx FIFO threshold levels */ 348 /* Configure Tx/Rx FIFO threshold levels */
336 dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); 349 dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
337 dw_writel(dev, 0, DW_IC_RX_TL); 350 dw_writel(dev, 0, DW_IC_RX_TL);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index e761ad18dd61..912aa2262866 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -90,6 +90,7 @@ struct dw_i2c_dev {
90 unsigned int tx_fifo_depth; 90 unsigned int tx_fifo_depth;
91 unsigned int rx_fifo_depth; 91 unsigned int rx_fifo_depth;
92 int rx_outstanding; 92 int rx_outstanding;
93 u32 sda_hold_time;
93}; 94};
94 95
95#define ACCESS_SWAP 0x00000001 96#define ACCESS_SWAP 0x00000001
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index ee46c92d7e3c..def79b5fd4c8 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -34,6 +34,7 @@
34#include <linux/sched.h> 34#include <linux/sched.h>
35#include <linux/err.h> 35#include <linux/err.h>
36#include <linux/interrupt.h> 36#include <linux/interrupt.h>
37#include <linux/of.h>
37#include <linux/of_i2c.h> 38#include <linux/of_i2c.h>
38#include <linux/platform_device.h> 39#include <linux/platform_device.h>
39#include <linux/pm.h> 40#include <linux/pm.h>
@@ -115,6 +116,15 @@ static int dw_i2c_probe(struct platform_device *pdev)
115 return PTR_ERR(dev->clk); 116 return PTR_ERR(dev->clk);
116 clk_prepare_enable(dev->clk); 117 clk_prepare_enable(dev->clk);
117 118
119 if (pdev->dev.of_node) {
120 u32 ht = 0;
121 u32 ic_clk = dev->get_clk_rate_khz(dev);
122
123 of_property_read_u32(pdev->dev.of_node,
124 "i2c-sda-hold-time-ns", &ht);
125 dev->sda_hold_time = ((u64)ic_clk * ht + 500000) / 1000000;
126 }
127
118 dev->functionality = 128 dev->functionality =
119 I2C_FUNC_I2C | 129 I2C_FUNC_I2C |
120 I2C_FUNC_10BIT_ADDR | 130 I2C_FUNC_10BIT_ADDR |