Re: [PATCH 3/5] i2c: designware: Separate timing parameter setting from HW initalization

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

 



On Tue, 2018-05-29 at 14:27 +0300, Jarkko Nikula wrote:
> Mixed timing parameter validation, calculation and their debug prints
> with HW initialization in i2c_dw_init_master() and i2c_dw_init_slave()
> has been bothering me some time.
> 
> It makes function a little bit unclear to follow, doesn't show what
> steps
> are needed to do only once during probe and what are needed whenever
> HW
> needs to be reinitialized. Also those debug prints show information
> that
> doesn't change runtime and thus are also needlessly printed multiple
> times
> whenever HW is reinitialized.
> 
> Thus let the i2c_dw_init_master() and i2c_dw_init_slave() to do only
> HW
> initialization and move out one time parameter setting and debug
> prints
> to separate functions which are called only during probe. Since SDA
> hold
> time setting is common to both master and slave code remove this
> duplication and move it to common code.

Just would like you to double check if it possible to split this to
couple or more smaller changes.

> +void i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
> +{
> +	u32 reg;
> +	int ret = 0;
> +
> +	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);
> +		}

Pewrhaps + blank line here ?

> +		/*
> +		 * 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);
> +}

> +static void i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
>  {
> 

> +	u32 comp_param1;
>  	u32 sda_falling_time, scl_falling_time;
> +	int ret = 0;

Redundant assignment.
 
>  	ret = i2c_dw_acquire_lock(dev);
>  	if (ret)
> +		return;

> +	/* Calculate SCL timing parameters for standard mode if not
> set */
> +	if (!dev->ss_hcnt || !dev->ss_lcnt) {
> +		dev->ss_hcnt =
> +			i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),

You can consider to use

dev->ss_hcnt = dev->ss_hcnt ?: instead of conditional
(rationale: smaller indentation level)

> +		dev->ss_lcnt =
> +			i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),

Ditto here and below.

Moreover the question if in all cases the first argument is
i2c_dw_clk_rate(dev)? It might be useful to factor this into the callee.

> +			dev->fs_hcnt = dev->fp_hcnt;
> +			dev->fs_lcnt = dev->fp_lcnt;

Dunno if it makes sense to introduce something like

struct i2c_dw_cnt {
  ... low;
  ... high;
};

...and convert the driver to use it.

> +	dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
> +		dev->clk_freq == 1000000 ? " Plus" : "",
> +		dev->fs_hcnt, dev->fs_lcnt);

I would rather go with switch-case or alike and put full mode name into
string literals. Moreover you may use same literal in the code after
all.

> +	if (dev->sda_hold_time)
>  		dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);

Btw, what happens on older hardware that doesn't support SDA_HOLD
register when you try to write 0 there?

-- 
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