mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Marcus Folkesson <marcus.folkesson@gmail.com>
To: Wolfram Sang <wsa+renesas@sang-engineering.com>,
	 Michael Hennerich <michael.hennerich@analog.com>,
	 Bartosz Golaszewski <brgl@bgdev.pl>,
	Andi Shyti <andi.shyti@kernel.org>,
	 Andy Shevchenko <andriy.shevchenko@intel.com>,
	 Bartosz Golaszewski <brgl@kernel.org>,
	Peter Rosin <peda@lysator.liu.se>,
	 Peter Rosin <peda@lysator.liu.se>
Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
	 linux-arm-kernel@lists.infradead.org,
	 Marcus Folkesson <marcus.folkesson@gmail.com>
Subject: [PATCH v13 8/8] i2c: mux: pca954x: use idle state from i2c_mux_core
Date: Thu, 15 Oct 2026 13:01:55 +0200	[thread overview]
Message-ID: <20261015-i2c-mux-v13-8-778a12cfe93b@gmail.com> (raw)
In-Reply-To: <20261015-i2c-mux-v13-0-778a12cfe93b@gmail.com>

The core now have support for keeping the track of the idle state.
Make use of that instead of handle this on our own.

Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 76 ++++++++++++++++++++++++-------------
 1 file changed, 50 insertions(+), 26 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 8fca709ed279..87bde07374d2 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -52,7 +52,6 @@
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <dt-bindings/mux/mux.h>
 
 #define PCA954X_MAX_NCHANS 8
 
@@ -108,8 +107,6 @@ struct pca954x {
 	const struct chip_desc *chip;
 
 	u8 last_chan;		/* last register value */
-	/* MUX_IDLE_AS_IS, MUX_IDLE_DISCONNECT or >= 0 for channel */
-	s32 idle_state;
 
 	struct i2c_client *client;
 
@@ -337,14 +334,14 @@ 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;
-	s32 idle_state;
+	int idle_state;
 
-	idle_state = READ_ONCE(data->idle_state);
+	idle_state = i2c_mux_idle_state(muxc);
 	if (idle_state >= 0)
 		/* Set the mux back to a predetermined channel */
 		return pca954x_select_chan(muxc, idle_state);
 
-	if (idle_state == MUX_IDLE_DISCONNECT) {
+	if (idle_state == I2C_MUX_IDLE_DISCONNECT) {
 		/* Deselect active channel */
 		data->last_chan = 0;
 		return pca954x_reg_write(muxc->parent, client,
@@ -356,15 +353,30 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
 	return 0;
 }
 
+/*
+ * The mux core only knows the maximum number of channels the driver may
+ * register, so range-check against the actual channel count of this chip
+ * before handing the state over.
+ */
+static int pca954x_set_idle_state(struct i2c_mux_core *muxc, int state)
+{
+	struct pca954x *data = i2c_mux_priv(muxc);
+
+	/* I2C_MUX_IDLE_UNKNOWN is internal to the mux core. */
+	if (state == I2C_MUX_IDLE_UNKNOWN || state >= data->chip->nchans)
+		return -EINVAL;
+
+	return i2c_mux_set_idle_state(muxc, state);
+}
+
 static ssize_t idle_state_show(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
-	struct pca954x *data = i2c_mux_priv(muxc);
 
-	return sprintf(buf, "%d\n", READ_ONCE(data->idle_state));
+	return sprintf(buf, "%d\n", i2c_mux_idle_state(muxc));
 }
 
 static ssize_t idle_state_store(struct device *dev,
@@ -381,18 +393,19 @@ static ssize_t idle_state_store(struct device *dev,
 	if (ret < 0)
 		return ret;
 
-	if (val != MUX_IDLE_AS_IS && val != MUX_IDLE_DISCONNECT &&
-	    (val < 0 || val >= data->chip->nchans))
-		return -EINVAL;
-
 	i2c_lock_bus(muxc->parent, I2C_LOCK_SEGMENT);
 
-	WRITE_ONCE(data->idle_state, val);
+	ret = pca954x_set_idle_state(muxc, val);
+	if (ret) {
+		i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT);
+		return ret;
+	}
+
 	/*
 	 * Set the mux into a state consistent with the new
 	 * idle_state.
 	 */
-	if (data->last_chan || val != MUX_IDLE_DISCONNECT)
+	if (data->last_chan || val != I2C_MUX_IDLE_DISCONNECT)
 		ret = pca954x_deselect_mux(muxc, 0);
 
 	i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT);
@@ -478,12 +491,15 @@ static void pca954x_cleanup(struct i2c_mux_core *muxc)
 	i2c_mux_del_adapters(muxc);
 }
 
-static int pca954x_init(struct i2c_client *client, struct pca954x *data)
+static int pca954x_init(struct i2c_mux_core *muxc)
 {
+	struct pca954x *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+	int idle_state = i2c_mux_idle_state(muxc);
 	int ret;
 
-	if (data->idle_state >= 0)
-		data->last_chan = pca954x_regval(data, data->idle_state);
+	if (idle_state >= 0)
+		data->last_chan = pca954x_regval(data, idle_state);
 	else
 		data->last_chan = 0; /* Disconnect multiplexer */
 
@@ -560,6 +576,8 @@ static int pca954x_probe(struct i2c_client *client)
 	struct device *dev = &client->dev;
 	struct i2c_mux_core *muxc;
 	struct pca954x *data;
+	int idle_state;
+	u32 prop;
 	int num;
 	int ret;
 
@@ -618,25 +636,32 @@ static int pca954x_probe(struct i2c_client *client)
 		}
 	}
 
-	data->idle_state = MUX_IDLE_AS_IS;
-	if (device_property_read_u32(dev, "idle-state", &data->idle_state)) {
-		if (device_property_read_bool(dev, "i2c-mux-idle-disconnect"))
-			data->idle_state = MUX_IDLE_DISCONNECT;
-	}
-
 	/*
 	 * Write the mux register at addr to verify
 	 * that the mux is in fact present. This also
 	 * initializes the mux to a channel
 	 * or disconnected state.
 	 */
-	ret = pca954x_init(client, data);
+	ret = pca954x_init(muxc);
 	if (ret < 0) {
 		dev_warn(dev, "probe failed\n");
 		ret = -ENODEV;
 		goto fail_cleanup;
 	}
 
+	/* Set idle state to the default value, or to the value specified in the device tree */
+	idle_state = I2C_MUX_IDLE_AS_IS;
+	if (!device_property_read_u32(dev, "idle-state", &prop))
+		idle_state = (int)prop;
+	else if (device_property_read_bool(dev, "i2c-mux-idle-disconnect"))
+		idle_state = I2C_MUX_IDLE_DISCONNECT;
+
+	ret = pca954x_set_idle_state(muxc, idle_state);
+	if (ret) {
+		dev_err(dev, "invalid idle state %d\n", idle_state);
+		goto fail_cleanup;
+	}
+
 	ret = pca954x_irq_setup(muxc);
 	if (ret)
 		goto fail_cleanup;
@@ -687,10 +712,9 @@ static int pca954x_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
-	struct pca954x *data = i2c_mux_priv(muxc);
 	int ret;
 
-	ret = pca954x_init(client, data);
+	ret = pca954x_init(muxc);
 	if (ret < 0)
 		dev_err(&client->dev, "failed to verify mux presence\n");
 

-- 
2.55.0


      parent reply	other threads:[~2026-10-15 11:02 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 11:01 [PATCH v13 0/8] I2C Mux per channel bus speed Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 1/8] i2c: core: add callback to change bus frequency Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 2/8] i2c: mux: add idle_state property to i2c_mux_core Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 3/8] i2c: mux: add support for per channel bus frequency Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 4/8] i2c: davinci: calculate bus freq from Hz instead of kHz Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 5/8] i2c: davinci: add support for setting bus frequency Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 6/8] i2c: mux: ltc4306: set correct idle_state in i2c_mux_core Marcus Folkesson
2026-10-15 11:01 ` [PATCH v13 7/8] docs: i2c: i2c-topology: add section about bus speed Marcus Folkesson
2026-10-15 11:01 ` Marcus Folkesson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261015-i2c-mux-v13-8-778a12cfe93b@gmail.com \
    --to=marcus.folkesson@gmail.com \
    --cc=andi.shyti@kernel.org \
    --cc=andriy.shevchenko@intel.com \
    --cc=brgl@bgdev.pl \
    --cc=brgl@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.hennerich@analog.com \
    --cc=peda@lysator.liu.se \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®