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>
This commit is contained in:
Родитель
4c730a06c1
Коммит
9803f86894
|
@ -10,6 +10,10 @@ Recommended properties :
|
||||||
|
|
||||||
- clock-frequency : desired I2C bus clock frequency in Hz.
|
- clock-frequency : desired I2C bus clock frequency in Hz.
|
||||||
|
|
||||||
|
Optional properties :
|
||||||
|
- i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
|
||||||
|
This option is only supported in hardware blocks version 1.11a or newer.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
i2c@f0000 {
|
i2c@f0000 {
|
||||||
|
@ -20,3 +24,14 @@ Example :
|
||||||
interrupts = <11>;
|
interrupts = <11>;
|
||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
i2c@1120000 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "snps,designware-i2c";
|
||||||
|
reg = <0x1120000 0x1000>;
|
||||||
|
interrupt-parent = <&ictl>;
|
||||||
|
interrupts = <12 1>;
|
||||||
|
clock-frequency = <400000>;
|
||||||
|
i2c-sda-hold-time-ns = <300>;
|
||||||
|
};
|
||||||
|
|
|
@ -45,19 +45,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c0: i2c@FF120000 {
|
i2c0: i2c@FF120000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c1: i2c@FF121000 {
|
i2c1: i2c@FF121000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c2: i2c@FF122000 {
|
i2c2: i2c@FF122000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c3: i2c@FF123000 {
|
i2c3: i2c@FF123000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c4: i2c@FF124000 {
|
i2c4: i2c@FF124000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
|
|
||||||
leds {
|
leds {
|
||||||
|
|
|
@ -45,19 +45,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c0: i2c@FF120000 {
|
i2c0: i2c@FF120000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c1: i2c@FF121000 {
|
i2c1: i2c@FF121000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c2: i2c@FF122000 {
|
i2c2: i2c@FF122000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c3: i2c@FF123000 {
|
i2c3: i2c@FF123000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
i2c4: i2c@FF124000 {
|
i2c4: i2c@FF124000 {
|
||||||
sda-hold-time = <432>;
|
i2c-sda-hold-time-ns = <432>;
|
||||||
};
|
};
|
||||||
|
|
||||||
leds {
|
leds {
|
||||||
|
|
|
@ -67,9 +67,12 @@
|
||||||
#define DW_IC_STATUS 0x70
|
#define DW_IC_STATUS 0x70
|
||||||
#define DW_IC_TXFLR 0x74
|
#define DW_IC_TXFLR 0x74
|
||||||
#define DW_IC_RXFLR 0x78
|
#define DW_IC_RXFLR 0x78
|
||||||
|
#define DW_IC_SDA_HOLD 0x7c
|
||||||
#define DW_IC_TX_ABRT_SOURCE 0x80
|
#define DW_IC_TX_ABRT_SOURCE 0x80
|
||||||
#define DW_IC_ENABLE_STATUS 0x9c
|
#define DW_IC_ENABLE_STATUS 0x9c
|
||||||
#define DW_IC_COMP_PARAM_1 0xf4
|
#define DW_IC_COMP_PARAM_1 0xf4
|
||||||
|
#define DW_IC_COMP_VERSION 0xf8
|
||||||
|
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A
|
||||||
#define DW_IC_COMP_TYPE 0xfc
|
#define DW_IC_COMP_TYPE 0xfc
|
||||||
#define DW_IC_COMP_TYPE_VALUE 0x44570140
|
#define DW_IC_COMP_TYPE_VALUE 0x44570140
|
||||||
|
|
||||||
|
@ -332,6 +335,16 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
|
||||||
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
|
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
|
||||||
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
|
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
|
||||||
|
|
||||||
|
/* Configure SDA Hold Time if required */
|
||||||
|
if (dev->sda_hold_time) {
|
||||||
|
reg = dw_readl(dev, DW_IC_COMP_VERSION);
|
||||||
|
if (reg >= DW_IC_SDA_HOLD_MIN_VERS)
|
||||||
|
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
|
||||||
|
else
|
||||||
|
dev_warn(dev->dev,
|
||||||
|
"Hardware too old to adjust SDA hold time.");
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure Tx/Rx FIFO threshold levels */
|
/* Configure Tx/Rx FIFO threshold levels */
|
||||||
dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
|
dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
|
||||||
dw_writel(dev, 0, DW_IC_RX_TL);
|
dw_writel(dev, 0, DW_IC_RX_TL);
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct dw_i2c_dev {
|
||||||
unsigned int tx_fifo_depth;
|
unsigned int tx_fifo_depth;
|
||||||
unsigned int rx_fifo_depth;
|
unsigned int rx_fifo_depth;
|
||||||
int rx_outstanding;
|
int rx_outstanding;
|
||||||
|
u32 sda_hold_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ACCESS_SWAP 0x00000001
|
#define ACCESS_SWAP 0x00000001
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/of_i2c.h>
|
#include <linux/of_i2c.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
@ -115,6 +116,15 @@ static int dw_i2c_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(dev->clk);
|
return PTR_ERR(dev->clk);
|
||||||
clk_prepare_enable(dev->clk);
|
clk_prepare_enable(dev->clk);
|
||||||
|
|
||||||
|
if (pdev->dev.of_node) {
|
||||||
|
u32 ht = 0;
|
||||||
|
u32 ic_clk = dev->get_clk_rate_khz(dev);
|
||||||
|
|
||||||
|
of_property_read_u32(pdev->dev.of_node,
|
||||||
|
"i2c-sda-hold-time-ns", &ht);
|
||||||
|
dev->sda_hold_time = ((u64)ic_clk * ht + 500000) / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
dev->functionality =
|
dev->functionality =
|
||||||
I2C_FUNC_I2C |
|
I2C_FUNC_I2C |
|
||||||
I2C_FUNC_10BIT_ADDR |
|
I2C_FUNC_10BIT_ADDR |
|
||||||
|
|
Загрузка…
Ссылка в новой задаче