diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-master.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-master.c | 33 |
1 files changed, 12 insertions, 21 deletions
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index cb3ac1f39cb6..6b64e3d01fd9 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -45,6 +45,11 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg, DW_IC_CON); } +static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) +{ + return i2c_dw_set_sda_hold(dev); +} + /** * i2c_dw_init() - Initialize the designware I2C master hardware * @dev: device private data @@ -57,7 +62,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev) { u32 ic_clk = i2c_dw_clk_rate(dev); u32 hcnt, lcnt; - u32 reg, comp_param1; + u32 comp_param1; u32 sda_falling_time, scl_falling_time; int ret; @@ -133,27 +138,9 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev) } } - /* Configure SDA Hold Time if required */ - reg = dw_readl(dev, DW_IC_COMP_VERSION); - if (reg >= DW_IC_SDA_HOLD_MIN_VERS) { - if (!dev->sda_hold_time) { - /* Keep previous hold time setting if no one set it */ - dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD); - } - /* - * Workaround for avoiding TX arbitration lost in case I2C - * slave pulls SDA down "too quickly" after falling egde of - * SCL by enabling non-zero SDA RX hold. Specification says it - * extends incoming SDA low to high transition while SCL is - * high but it apprears to help also above issue. - */ - if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) - dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; + /* Write SDA hold time if supported */ + if (dev->sda_hold_time) dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD); - } else if (dev->sda_hold_time) { - dev_warn(dev->dev, - "Hardware too old to adjust SDA hold time.\n"); - } i2c_dw_configure_fifo_master(dev); i2c_dw_release_lock(dev); @@ -672,6 +659,10 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) if (ret) return ret; + ret = i2c_dw_set_timings_master(dev); + if (ret) + return ret; + ret = dev->init(dev); if (ret) return ret; |