diff options
author | Christian Ruppert <christian.ruppert@abilis.com> | 2013-06-26 04:55:06 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2013-06-26 10:02:06 -0400 |
commit | 9803f868944e879c4623c0d910e81f1ae89ccfb4 (patch) | |
tree | 1dc609539e707c857b7a3e38104a6b0063847a41 /drivers/i2c/busses | |
parent | 4c730a06c19bb83d2fa4308ee4cbb23abc84c9ca (diff) |
i2c-designware: make SDA hold time configurable
This patch makes the SDA hold time configurable through device tree.
Signed-off-by: Christian Ruppert <christian.ruppert@abilis.com>
Signed-off-by: Pierrick Hascoet <pierrick.hascoet@abilis.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com> for arch/arc bits
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-platdrv.c | 10 |
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 | |