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
prev 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®