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 | |
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>
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-designware.txt | 15 | ||||
-rw-r--r-- | arch/arc/boot/dts/abilis_tb100_dvk.dts | 10 | ||||
-rw-r--r-- | arch/arc/boot/dts/abilis_tb101_dvk.dts | 10 | ||||
-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 |
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 | ||
13 | Optional 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 | |||
13 | Example : | 17 | Example : |
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 | |