Commit 3fdd2d21 authored by Wolfram Sang's avatar Wolfram Sang
Browse files

Merge tag 'i2c-host-fixes-6.10-rc8' of...

Merge tag 'i2c-host-fixes-6.10-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-current

This tag includes three fixes for the Renesas R-Car driver:

 1. Ensures the device is in a known state after probing.
 2. Allows clearing the NO_RXDMA flag after a reset.
 3. Forces a reset before any transfer on Gen3+ platforms to
    prevent disruption of the configuration during parallel
    transfers.
parents 119736c7 ea5ea84c
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -257,6 +257,14 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
	}
}

static void rcar_i2c_reset_slave(struct rcar_i2c_priv *priv)
{
	rcar_i2c_write(priv, ICSIER, 0);
	rcar_i2c_write(priv, ICSSR, 0);
	rcar_i2c_write(priv, ICSCR, SDBS);
	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
}

static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{
	int ret;
@@ -875,6 +883,10 @@ static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv)
{
	int ret;

	/* Don't reset if a slave instance is currently running */
	if (priv->slave)
		return -EISCONN;

	ret = reset_control_reset(priv->rstc);
	if (ret)
		return ret;
@@ -903,10 +915,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,

	/* Gen3+ needs a reset. That also allows RXDMA once */
	if (priv->devtype >= I2C_RCAR_GEN3) {
		priv->flags &= ~ID_P_NO_RXDMA;
		ret = rcar_i2c_do_reset(priv);
		if (ret)
			goto out;
		priv->flags &= ~ID_P_NO_RXDMA;
	}

	rcar_i2c_init(priv);
@@ -1033,11 +1045,8 @@ static int rcar_unreg_slave(struct i2c_client *slave)

	/* ensure no irq is running before clearing ptr */
	disable_irq(priv->irq);
	rcar_i2c_write(priv, ICSIER, 0);
	rcar_i2c_write(priv, ICSSR, 0);
	rcar_i2c_reset_slave(priv);
	enable_irq(priv->irq);
	rcar_i2c_write(priv, ICSCR, SDBS);
	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */

	priv->slave = NULL;

@@ -1152,7 +1161,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
		goto out_pm_disable;
	}

	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
	/* Bring hardware to known state */
	rcar_i2c_init(priv);
	rcar_i2c_reset_slave(priv);

	if (priv->devtype < I2C_RCAR_GEN3) {
		irqflags |= IRQF_NO_THREAD;
@@ -1168,6 +1179,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
	if (of_property_read_bool(dev->of_node, "smbus"))
		priv->flags |= ID_P_HOST_NOTIFY;

	/* R-Car Gen3+ needs a reset before every transfer */
	if (priv->devtype >= I2C_RCAR_GEN3) {
		priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
		if (IS_ERR(priv->rstc)) {
@@ -1178,6 +1190,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
		ret = reset_control_status(priv->rstc);
		if (ret < 0)
			goto out_pm_put;

		/* hard reset disturbs HostNotify local target, so disable it */
		priv->flags &= ~ID_P_HOST_NOTIFY;
	}

	ret = platform_get_irq(pdev, 0);