From a60d57586f5d5c7dbf7e0bd94cf7bf5f3b91c293 Mon Sep 17 00:00:00 2001
From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
Date: Wed, 13 Jun 2018 14:06:59 +0300
Subject: [PATCH 114/115] i2c: mux: pca954x: reset mux in case of error during
 bus deselect

Also reset device on probe to workaround reset errata at low
supply rise rate.

Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 7b992db..b26d6a0 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -35,6 +35,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
@@ -78,6 +79,7 @@ struct chip_desc {
 struct pca954x {
 	const struct chip_desc *chip;
 
+	struct gpio_desc *gpio;	/* reset gpio */
 	u8 last_chan;		/* last register value */
 	u8 deselect;
 	struct i2c_client *client;
@@ -217,13 +219,24 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
 {
 	struct pca954x *data = i2c_mux_priv(muxc);
 	struct i2c_client *client = data->client;
+	int ret;
 
 	if (!(data->deselect & (1 << chan)))
 		return 0;
 
 	/* Deselect active channel */
 	data->last_chan = 0;
-	return pca954x_reg_write(muxc->parent, client, data->last_chan);
+	ret = pca954x_reg_write(muxc->parent, client, data->last_chan);
+	if ((ret < 0) && (data->gpio)) {
+		gpiod_set_value(data->gpio, GPIOD_OUT_HIGH);
+		udelay(5);
+		gpiod_set_value(data->gpio, GPIOD_OUT_LOW);
+		/* retry */
+		ret = pca954x_reg_write(muxc->parent, client, data->last_chan);
+		if (ret < 0)
+			dev_err(&data->client->dev, "error deselecting channed %d: %d\n", chan, ret);
+	}
+	return ret;
 }
 
 static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
@@ -344,7 +357,6 @@ static int pca954x_probe(struct i2c_client *client,
 	struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct device_node *of_node = client->dev.of_node;
 	bool idle_disconnect_dt;
-	struct gpio_desc *gpio;
 	int num, force, class;
 	struct i2c_mux_core *muxc;
 	struct pca954x *data;
@@ -365,9 +377,16 @@ static int pca954x_probe(struct i2c_client *client,
 	data->client = client;
 
 	/* Get the mux out of reset if a reset GPIO is specified. */
-	gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
-		return PTR_ERR(gpio);
+	data->gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(data->gpio))
+		return PTR_ERR(data->gpio);
+
+	if (data->gpio) {
+		/* delay and release reset */
+		udelay(1);
+		gpiod_set_value(data->gpio, 0);
+		udelay(1);
+	}
 
 	/* Write the mux register at addr to verify
 	 * that the mux is in fact present. This also
-- 
1.9.1

