aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ruppert <christian.ruppert@abilis.com>2013-06-26 04:55:06 -0400
committerWolfram Sang <wsa@the-dreams.de>2013-06-26 10:02:06 -0400
commit9803f868944e879c4623c0d910e81f1ae89ccfb4 (patch)
tree1dc609539e707c857b7a3e38104a6b0063847a41
parent4c730a06c19bb83d2fa4308ee4cbb23abc84c9ca (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>
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-designware.txt15
-rw-r--r--arch/arc/boot/dts/abilis_tb100_dvk.dts10
-rw-r--r--arch/arc/boot/dts/abilis_tb101_dvk.dts10
-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
6 files changed, 49 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-designware.txt b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
index e42a2ee233e6..7fd7fa25e9b0 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-designware.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
@@ -10,6 +10,10 @@ Recommended properties :
10 10
11 - clock-frequency : desired I2C bus clock frequency in Hz. 11 - clock-frequency : desired I2C bus clock frequency in Hz.
12 12
13Optional properties :
14 - i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
15 This option is only supported in hardware blocks version 1.11a or newer.
16
13Example : 17Example :
14 18
15 i2c@f0000 { 19 i2c@f0000 {
@@ -20,3 +24,14 @@ Example :
20 interrupts = <11>; 24 interrupts = <11>;
21 clock-frequency = <400000>; 25 clock-frequency = <400000>;
22 }; 26 };
27
28 i2c@1120000 {
29 #address-cells = <1>;
30 #size-cells = <0>;
31 compatible = "snps,designware-i2c";
32 reg = <0x1120000 0x1000>;
33 interrupt-parent = <&ictl>;
34 interrupts = <12 1>;
35 clock-frequency = <400000>;
36 i2c-sda-hold-time-ns = <300>;
37 };
diff --git a/arch/arc/boot/dts/abilis_tb100_dvk.dts b/arch/arc/boot/dts/abilis_tb100_dvk.dts
index 0fa0d4abe795..ebc313a9f5b2 100644
--- a/arch/arc/boot/dts/abilis_tb100_dvk.dts
+++ b/arch/arc/boot/dts/abilis_tb100_dvk.dts
@@ -45,19 +45,19 @@
45 }; 45 };
46 46
47 i2c0: i2c@FF120000 { 47 i2c0: i2c@FF120000 {
48 sda-hold-time = <432>; 48 i2c-sda-hold-time-ns = <432>;
49 }; 49 };
50 i2c1: i2c@FF121000 { 50 i2c1: i2c@FF121000 {
51 sda-hold-time = <432>; 51 i2c-sda-hold-time-ns = <432>;
52 }; 52 };
53 i2c2: i2c@FF122000 { 53 i2c2: i2c@FF122000 {
54 sda-hold-time = <432>; 54 i2c-sda-hold-time-ns = <432>;
55 }; 55 };
56 i2c3: i2c@FF123000 { 56 i2c3: i2c@FF123000 {
57 sda-hold-time = <432>; 57 i2c-sda-hold-time-ns = <432>;
58 }; 58 };
59 i2c4: i2c@FF124000 { 59 i2c4: i2c@FF124000 {
60 sda-hold-time = <432>; 60 i2c-sda-hold-time-ns = <432>;
61 }; 61 };
62 62
63 leds { 63 leds {
diff --git a/arch/arc/boot/dts/abilis_tb101_dvk.dts b/arch/arc/boot/dts/abilis_tb101_dvk.dts
index a4d80ce283ae..b204657993aa 100644
--- a/arch/arc/boot/dts/abilis_tb101_dvk.dts
+++ b/arch/arc/boot/dts/abilis_tb101_dvk.dts
@@ -45,19 +45,19 @@
45 }; 45 };
46 46
47 i2c0: i2c@FF120000 { 47 i2c0: i2c@FF120000 {
48 sda-hold-time = <432>; 48 i2c-sda-hold-time-ns = <432>;
49 }; 49 };
50 i2c1: i2c@FF121000 { 50 i2c1: i2c@FF121000 {
51 sda-hold-time = <432>; 51 i2c-sda-hold-time-ns = <432>;
52 }; 52 };
53 i2c2: i2c@FF122000 { 53 i2c2: i2c@FF122000 {
54 sda-hold-time = <432>; 54 i2c-sda-hold-time-ns = <432>;
55 }; 55 };
56 i2c3: i2c@FF123000 { 56 i2c3: i2c@FF123000 {
57 sda-hold-time = <432>; 57 i2c-sda-hold-time-ns = <432>;
58 }; 58 };
59 i2c4: i2c@FF124000 { 59 i2c4: i2c@FF124000 {
60 sda-hold-time = <432>; 60 i2c-sda-hold-time-ns = <432>;
61 }; 61 };
62 62
63 leds { 63 leds {
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 |