Re: [PATCH v2 4/8] i2c: designware: Move SDA hold time configuration to common code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2018-06-01 at 16:47 +0300, Jarkko Nikula wrote:
> SDA hold time configuration is common to both master and slave code.
> It
> is also something that can be done once during probe and do only
> register write when HW needs to be reinitialized.
> 
> Remove duplication and move SDA hold time configuration to common
> code.
> It will be called from slave probe and for master code from a new
> i2c_dw_set_timings_master() to where we will populate more probe time
> timing parameter setting.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>

(Some minor issues / questions below)

> Signed-off-by: Jarkko Nikula <jarkko.nikula@xxxxxxxxxxxxxxx>
> ---
>  drivers/i2c/busses/i2c-designware-common.c | 35
> ++++++++++++++++++++++
>  drivers/i2c/busses/i2c-designware-core.h   |  1 +
>  drivers/i2c/busses/i2c-designware-master.c | 30 ++++++-------------
>  drivers/i2c/busses/i2c-designware-slave.c  | 24 ++-------------
>  4 files changed, 48 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-designware-common.c
> b/drivers/i2c/busses/i2c-designware-common.c
> index c22654cce1df..1b542d3e5a2e 100644
> --- a/drivers/i2c/busses/i2c-designware-common.c
> +++ b/drivers/i2c/busses/i2c-designware-common.c
> @@ -183,6 +183,41 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf,
> int offset)
>  	return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 +
> offset;
>  }
>  
> +void i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
> +{
> +	u32 reg;

> +	int ret = 0;

Redundant assignment.

> +
> +	ret = i2c_dw_acquire_lock(dev);
> +	if (ret)
> +		return;
> +
> +	/* 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;
> +	} else if (dev->sda_hold_time) {
> +		dev_warn(dev->dev,
> +			"Hardware too old to adjust SDA hold
> time.\n");
> +		dev->sda_hold_time = 0;
> +	}
> +
> +	i2c_dw_release_lock(dev);
> +}
> +
>  void __i2c_dw_disable(struct dw_i2c_dev *dev)
>  {
>  	int timeout = 100;
> diff --git a/drivers/i2c/busses/i2c-designware-core.h
> b/drivers/i2c/busses/i2c-designware-core.h
> index 5d54f70710ad..831b3d62b32c 100644
> --- a/drivers/i2c/busses/i2c-designware-core.h
> +++ b/drivers/i2c/busses/i2c-designware-core.h
> @@ -298,6 +298,7 @@ void dw_writel(struct dw_i2c_dev *dev, u32 b, int
> offset);
>  int i2c_dw_set_reg_access(struct dw_i2c_dev *dev);
>  u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int
> offset);
>  u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
> +void i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
>  unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
>  int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
>  int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
> diff --git a/drivers/i2c/busses/i2c-designware-master.c
> b/drivers/i2c/busses/i2c-designware-master.c
> index 3a7c184f24c8..b89bc8a5b0b1 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 void i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
> +{
> +	i2c_dw_set_sda_hold(dev);
> +}
> +

Looking into patch 6 I'm not sure this split is required here and not
there.

Have you checked which one looks better?

>  /**
>   * i2c_dw_init() - Initialize the designware I2C master hardware
>   * @dev: device private data
> @@ -56,7 +61,7 @@ static void i2c_dw_configure_fifo_master(struct
> dw_i2c_dev *dev)
>  static int i2c_dw_init_master(struct dw_i2c_dev *dev)
>  {
>  	u32 hcnt, lcnt;
> -	u32 reg, comp_param1;
> +	u32 comp_param1;
>  	u32 sda_falling_time, scl_falling_time;
>  	int ret;
>  
> @@ -132,27 +137,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);
> @@ -671,6 +658,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
>  	if (ret)
>  		return ret;
>  
> +	i2c_dw_set_timings_master(dev);
>  	ret = dev->init(dev);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/i2c/busses/i2c-designware-slave.c
> b/drivers/i2c/busses/i2c-designware-slave.c
> index a1f802001e1f..6ba265db4eb0 100644
> --- a/drivers/i2c/busses/i2c-designware-slave.c
> +++ b/drivers/i2c/busses/i2c-designware-slave.c
> @@ -51,7 +51,6 @@ static void i2c_dw_configure_fifo_slave(struct
> dw_i2c_dev *dev)
>   */
>  static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
>  {
> -	u32 reg;
>  	int ret;
>  
>  	ret = i2c_dw_acquire_lock(dev);
> @@ -61,27 +60,9 @@ static int i2c_dw_init_slave(struct dw_i2c_dev
> *dev)
>  	/* Disable the adapter. */
>  	__i2c_dw_disable(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 {
> -		dev_warn(dev->dev,
> -			 "Hardware too old to adjust SDA hold
> time.\n");
> -	}
>  
>  	i2c_dw_configure_fifo_slave(dev);
>  	i2c_dw_release_lock(dev);
> @@ -287,6 +268,7 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
>  	if (ret)
>  		return ret;
>  
> +	i2c_dw_set_sda_hold(dev);
>  	ret = dev->init(dev);
>  	if (ret)
>  		return ret;

-- 
Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Intel Finland Oy



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux