[PATCH 3/3] i2c: xiic: Support forcing single-master in DT

Michal Simek michal.simek at xilinx.com
Thu Aug 27 11:57:03 EDT 2020



On 27. 08. 20 16:48, ext-jaakko.laine at vaisala.com wrote:
> From: Jaakko Laine <ext-jaakko.laine at vaisala.com>
> 
> I2C master operating in multimaster mode can get stuck
> indefinitely if I2C start is detected on bus, but no master
> has a transaction going.
> 
> This is a weakness in I2C standard, which defines no way
> to recover, since all masters are indefinitely disallowed
> from interrupting the currently operating master. A start
> condition can be created for example by an electromagnetic
> discharge applied near physical I2C lines. Or a already
> operating master could get reset immediately after sending
> a start.
> 
> If it is known during device tree creation that only a single
> I2C master will be present on the bus, this deadlock of the
> I2C bus could be avoided in the driver by ignoring the
> bus_is_busy register of the xiic, since bus can never be
> reserved by any other master.
> 
> This patch adds this support for detecting single-master flag
> in device tree and when provided, improves I2C reliability by
> ignoring the therefore unnecessary xiic bus_is_busy register.
> 
> Error can be reproduced by pulling I2C SDA -line temporarily low
> by shorting it to ground, while linux I2C master is operating on
> it using the xiic driver. The application using the bus will
> start receiving linux error code 16: "Device or resource busy"
> indefinitely:
> 
> kernel: pca953x 0-0020: failed writing register
> app: Error writing file, error: 16
> 
> With multi-master disabled device will instead receive error
> code 5: "I/O error" while SDA is grounded, but recover normal
> operation once short is removed.
> 
> kernel: pca953x 0-0020: failed reading register
> app: Error reading file, error: 5
> 
> Signed-off-by: Jaakko Laine <ext-jaakko.laine at vaisala.com>
> ---
>  drivers/i2c/busses/i2c-xiic.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
> index 1453d82bb664..087b2951942e 100644
> --- a/drivers/i2c/busses/i2c-xiic.c
> +++ b/drivers/i2c/busses/i2c-xiic.c
> @@ -59,6 +59,7 @@ enum xiic_endian {
>   * @endianness: big/little-endian byte order
>   * @clk: Pointer to AXI4-lite input clock
>   * @state: See STATE_
> + * @singlemaster: Indicates bus is single master
>   */
>  struct xiic_i2c {
>  	struct device *dev;
> @@ -74,6 +75,7 @@ struct xiic_i2c {
>  	enum xiic_endian endianness;
>  	struct clk *clk;
>  	enum xilinx_i2c_state state;
> +	bool singlemaster;
>  };
>  
>  
> @@ -526,6 +528,15 @@ static int xiic_busy(struct xiic_i2c *i2c)
>  	if (i2c->tx_msg)
>  		return -EBUSY;
>  
> +	/* In single master mode bus can only be busy, when in use by this
> +	 * driver. If the register indicates bus being busy for some reason we
> +	 * should ignore it, since bus will never be released and i2c will be
> +	 * stuck forever.
> +	 */
> +	if (i2c->singlemaster) {
> +		return 0;
> +	}
> +
>  	/* for instance if previous transfer was terminated due to TX error
>  	 * it might be that the bus is on it's way to become available
>  	 * give it at most 3 ms to wake
> @@ -811,6 +822,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
>  		goto err_clk_dis;
>  	}
>  
> +	i2c->singlemaster =
> +		of_property_read_bool(pdev->dev.of_node, "single-master");
> +
>  	/*
>  	 * Detect endianness
>  	 * Try to reset the TX FIFO. Then check the EMPTY flag. If it is not
> 

Acked-by: Michal Simek <michal.simek at xilinx.com>

Thanks,
Michal



More information about the linux-arm-kernel mailing list