]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
i2c: rcar: ensure Gen3+ reset does not disturb local targets
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Thu, 11 Jul 2024 08:30:44 +0000 (10:30 +0200)
committerAndi Shyti <andi.shyti@kernel.org>
Thu, 11 Jul 2024 23:45:08 +0000 (01:45 +0200)
R-Car Gen3+ needs a reset before every controller transfer. That erases
configuration of a potentially in parallel running local target
instance. To avoid this disruption, avoid controller transfers if a
local target is running. Also, disable SMBusHostNotify because it
requires being a controller and local target at the same time.

Fixes: 3b770017b03a ("i2c: rcar: handle RXDMA HW behaviour on Gen3")
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/busses/i2c-rcar.c

index f0724c8e4b2193e67093d9ebc2b5a278da3de2d8..185a5d60f10192006ffd526a752335145471a7a1 100644 (file)
@@ -883,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;
@@ -1175,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)) {
@@ -1185,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);