Devicetree
 help / color / mirror / Atom feed
* [PATCH 0/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter
@ 2026-09-08 12:31 Shiv Prakash Gupta
  2026-09-08 12:31 ` [PATCH 1/2] dt-bindings: i2c: " Shiv Prakash Gupta
  2026-09-08 12:31 ` [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver Shiv Prakash Gupta
  0 siblings, 2 replies; 8+ messages in thread
From: Shiv Prakash Gupta @ 2026-09-08 12:31 UTC (permalink / raw)
  To: andi.shyti, robh, krzk+dt, conor+dt, peda, linux-i2c, devicetree,
	linux-kernel
  Cc: vikash.bansal, priyanka.jain, Shiv Prakash Gupta

This series adds support for the NXP PCA9641 2-to-1 I2C bus master arbiter.

The PCA9641 allows two upstream I2C masters to share a single downstream
slave bus using a hardware lock/grant arbitration protocol. It provides
dedicated interrupt outputs (INT0/INT1) per upstream master and a 16-bit
inter-master mailbox.

The driver supports two arbitration modes:
- Interrupt mode: uses INT0/INT1 GPIO interrupt, with automatic fallback
  to polling when no IRQ is configured
- Polling mode: used when no interrupt is configured

Patch 1 adds the devicetree binding schema.
Patch 2 adds the driver with Kconfig, Makefile, and MAINTAINERS entries.

Shiv Prakash Gupta (2):
  dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver

 .../devicetree/bindings/i2c/nxp,pca9641.yaml  | 109 +++++
 MAINTAINERS                                   |   7 +
 drivers/i2c/muxes/Kconfig                     |  15 +
 drivers/i2c/muxes/Makefile                    |   1 +
 drivers/i2c/muxes/i2c-mux-pca9641.c           | 395 ++++++++++++++++++
 5 files changed, 527 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
 create mode 100644 drivers/i2c/muxes/i2c-mux-pca9641.c

-- 
2.34.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  2026-09-08 12:31 [PATCH 0/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter Shiv Prakash Gupta
@ 2026-09-08 12:31 ` Shiv Prakash Gupta
  2026-09-08 12:48   ` sashiko-bot
  2026-09-08 17:47   ` Conor Dooley
  2026-09-08 12:31 ` [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver Shiv Prakash Gupta
  1 sibling, 2 replies; 8+ messages in thread
From: Shiv Prakash Gupta @ 2026-09-08 12:31 UTC (permalink / raw)
  To: andi.shyti, robh, krzk+dt, conor+dt, peda, linux-i2c, devicetree,
	linux-kernel
  Cc: vikash.bansal, priyanka.jain, Shiv Prakash Gupta

Add device tree binding schema for the NXP PCA9641 2-to-1 I2C bus
master arbiter.

The PCA9641 arbitrates between two upstream I2C masters competing for a
single downstream slave bus using a lock/grant ownership model. The
binding supports an optional 'interrupts' property for interrupt-assisted
arbitration.

Signed-off-by: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
---
 .../devicetree/bindings/i2c/nxp,pca9641.yaml  | 109 ++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml

diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
new file mode 100644
index 000000000000..649a3f6d1776
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/nxp,pca9641.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCA9641 2-to-1 I2C bus master arbiter
+
+maintainers:
+  - Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
+
+description: |
+  The PCA9641 is a 2-to-1 I2C bus master arbiter that manages two upstream
+  I2C masters competing for a single downstream slave bus. It uses a
+  lock/grant ownership model: a master requests the downstream bus by setting
+  LOCK_REQ, waits for the arbiter to assert LOCK_GRANT, then explicitly
+  connects to the bus via BUS_CONNECT before issuing transactions.
+
+  Key features compared to the PCA9541:
+    - Lock/grant ownership model (LOCK_REQ + LOCK_GRANT bits in CONTR register)
+    - BUS_CONNECT bit must be set explicitly after receiving LOCK_GRANT
+    - Reserve Time register (RT): guarantees bus ownership for 1-255 ms
+    - INT0 and INT1 interrupt outputs (one per upstream master) and INT_IN
+      interrupt input that propagates downstream slave interrupts upstream
+    - 16-bit shared mailbox (MB_LO + MB_HI) for inter-master communication
+    - ID register (read-only, value 0x38) to distinguish from PCA9541
+    - Four address pins (AD0-AD3) allowing up to 112 unique I2C addresses
+
+properties:
+  compatible:
+    const: nxp,pca9641
+
+  reg:
+    maxItems: 1
+    description:
+      7-bit I2C slave address of the PCA9641 on the upstream bus. The address
+      is set by hardware pins AD0-AD3 at power-on or hardware reset.
+
+  interrupts:
+    maxItems: 1
+    description:
+      Optional interrupt from the INT0 or INT1 output pin. When provided the
+      driver uses interrupt-assisted arbitration (waits on LOCK_GRANT interrupt)
+      instead of polling the CONTR register. Either INT0 or INT1 can be
+      connected depending on which upstream master port is used.
+
+  i2c-arb:
+    type: object
+    $ref: /schemas/i2c/i2c-controller.yaml
+    unevaluatedProperties: false
+    description:
+      I2C bus node representing the downstream slave bus controlled by the
+      PCA9641. Downstream slave devices are declared as child nodes here.
+
+required:
+  - compatible
+  - reg
+  - i2c-arb
+
+additionalProperties: false
+
+examples:
+  - |
+    /* Minimal example: polling mode (no interrupt wiring) */
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        i2c-arbiter@74 {
+            compatible = "nxp,pca9641";
+            reg = <0x74>;
+
+            i2c-arb {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                eeprom@50 {
+                    compatible = "atmel,24c32";
+                    reg = <0x50>;
+                };
+            };
+        };
+    };
+
+  - |
+    /* Interrupt mode: INT0 wired to SoC GPIO */
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        i2c-arbiter@70 {
+            compatible = "nxp,pca9641";
+            reg = <0x70>;
+            interrupt-parent = <&gpio1>;
+            interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+
+            i2c-arb {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                temperature-sensor@48 {
+                    compatible = "national,lm75";
+                    reg = <0x48>;
+                };
+            };
+        };
+    };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver
  2026-09-08 12:31 [PATCH 0/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter Shiv Prakash Gupta
  2026-09-08 12:31 ` [PATCH 1/2] dt-bindings: i2c: " Shiv Prakash Gupta
@ 2026-09-08 12:31 ` Shiv Prakash Gupta
  2026-09-08 12:52   ` sashiko-bot
  1 sibling, 1 reply; 8+ messages in thread
From: Shiv Prakash Gupta @ 2026-09-08 12:31 UTC (permalink / raw)
  To: andi.shyti, robh, krzk+dt, conor+dt, peda, linux-i2c, devicetree,
	linux-kernel
  Cc: vikash.bansal, priyanka.jain, Shiv Prakash Gupta

Add a driver for the NXP PCA9641 2-to-1 I2C bus master arbiter.

The PCA9641 allows two upstream I2C masters to share a single downstream
slave bus using a lock/grant protocol: a master asserts LOCK_REQ, waits
for LOCK_GRANT, sets BUS_CONNECT to open the switch, performs transactions,
then clears LOCK_REQ to release the bus.

The driver supports interrupt-assisted arbitration when INT0/INT1 is
connected to a GPIO. A threaded IRQ handler signals a completion variable
that select_chan() waits on, avoiding busy-polling. Polling mode is used
when no interrupt is configured.

Signed-off-by: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
---
 MAINTAINERS                         |   7 +
 drivers/i2c/muxes/Kconfig           |  15 ++
 drivers/i2c/muxes/Makefile          |   1 +
 drivers/i2c/muxes/i2c-mux-pca9641.c | 395 ++++++++++++++++++++++++++++
 4 files changed, 418 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-pca9641.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6215fcb07770..2b02090edc9e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12250,6 +12250,13 @@ S:	Maintained
 F:	Documentation/i2c/busses/i2c-nvidia-gpu.rst
 F:	drivers/i2c/busses/i2c-nvidia-gpu.c
 
+NXP PCA9641 I2C BUS MASTER ARBITER DRIVER
+M:	Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
+L:	linux-i2c@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
+F:	drivers/i2c/muxes/i2c-mux-pca9641.c
+
 I2C MUXES
 M:	Peter Rosin <peda@lysator.liu.se>
 L:	linux-i2c@vger.kernel.org
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 6d2f66810cdc..0caff9592466 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -64,6 +64,21 @@ config I2C_MUX_PCA9541
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mux-pca9541.
 
+config I2C_MUX_PCA9641
+	tristate "NXP PCA9641 I2C Master Arbiter"
+	help
+	  If you say yes here you get support for the NXP PCA9641
+	  2-to-1 I2C bus master arbiter.
+
+	  The PCA9641 arbitrates between two upstream I2C masters competing
+	  for a single downstream slave bus. It implements a lock/grant
+	  ownership model with an optional reserve time window, hardware
+	  interrupt outputs (INT0/INT1), and a 16-bit shared mailbox for
+	  inter-master communication.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mux-pca9641.
+
 config I2C_MUX_PCA954x
 	tristate "NXP PCA954x/PCA984x and Maxim MAX735x/MAX736x I2C Mux/switches"
 	depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 4b24f49515a7..a50df4013224 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_MUX_LTC4306)	+= i2c-mux-ltc4306.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)	+= i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_MULE)	+= i2c-mux-mule.o
 obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
+obj-$(CONFIG_I2C_MUX_PCA9641)	+= i2c-mux-pca9641.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
 obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
 obj-$(CONFIG_I2C_MUX_REG)	+= i2c-mux-reg.o
diff --git a/drivers/i2c/muxes/i2c-mux-pca9641.c b/drivers/i2c/muxes/i2c-mux-pca9641.c
new file mode 100644
index 000000000000..c12aa88dcf56
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-pca9641.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C multiplexer driver for PCA9641 2-to-1 I2C bus master arbiter
+ *
+ * Copyright (C) 2026 Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
+ *
+ * Based on i2c-mux-pca9541.c by Guenter Roeck <linux@roeck-us.net>
+ *
+ * Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9641.pdf
+ */
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/* Register addresses, selected via the 3 LSBs of the command code byte */
+#define PCA9641_ID          0x00  /* Device ID register (R only, value 0x38) */
+#define PCA9641_CONTR       0x01  /* Control register (R/W) */
+#define PCA9641_STATUS      0x02  /* Status register (R/W) */
+#define PCA9641_RT          0x03  /* Reserve Time register (R/W) */
+#define PCA9641_INT_STATUS  0x04  /* Interrupt Status register (R/W, sticky) */
+#define PCA9641_INT_MSK     0x05  /* Interrupt Mask register (R/W) */
+#define PCA9641_MB_LO       0x06  /* Mailbox low byte (R/W) */
+#define PCA9641_MB_HI       0x07  /* Mailbox high byte (R/W) */
+
+/* CONTR register (0x01) bit definitions */
+#define PCA9641_CTL_LOCK_REQ        BIT(0)  /* Request downstream bus ownership */
+#define PCA9641_CTL_LOCK_GRANT      BIT(1)  /* Downstream bus granted (R only) */
+#define PCA9641_CTL_BUS_CONNECT     BIT(2)  /* Connect master to downstream bus */
+#define PCA9641_CTL_BUS_INIT        BIT(3)  /* Trigger bus init/recovery (9 clocks) */
+#define PCA9641_CTL_SMBUS_SWRST     BIT(4)  /* Assert SCL LOW 35 ms after soft reset */
+#define PCA9641_CTL_IDLE_TIMER_DIS  BIT(5)  /* Disconnect after 100 ms bus idle */
+#define PCA9641_CTL_SMBUS_DIS       BIT(6)  /* Disconnect on SMBus timeout detection */
+#define PCA9641_CTL_PRIORITY        BIT(7)  /* Tie-break priority when both request */
+
+/* STATUS register (0x02) bit definitions (datasheet Section 8.3) */
+#define PCA9641_STA_OTHER_LOCK      BIT(0)  /* Other master currently holds the lock (R only) */
+#define PCA9641_STA_SCL_IO          BIT(6)  /* Manual SCL I/O (LOCK_GRANT=1, BUS_CONNECT=0) */
+#define PCA9641_STA_SDA_IO          BIT(7)  /* Manual SDA I/O (LOCK_GRANT=1, BUS_CONNECT=0) */
+
+/* INT_STATUS register (0x04) bit definitions (sticky, clear by writing 1) */
+#define PCA9641_INTS_INT_IN         BIT(0)  /* Interrupt received on INT_IN pin */
+#define PCA9641_INTS_BUS_LOST       BIT(1)  /* This master involuntarily lost the bus */
+#define PCA9641_INTS_LOCK_GRANT     BIT(2)  /* This master was granted the bus */
+#define PCA9641_INTS_TEST_INT       BIT(3)  /* Self-test interrupt triggered */
+#define PCA9641_INTS_MBOX_EMPTY     BIT(4)  /* Sent mailbox data was read by other master */
+#define PCA9641_INTS_MBOX_FULL      BIT(5)  /* New mailbox data received from other master */
+#define PCA9641_INTS_BUS_HUNG       BIT(6)  /* Bus hung condition detected */
+
+/* INT_MSK register (0x05) bit definitions (1 = masked/disabled, POR = 0x7F) */
+#define PCA9641_MSK_INT_IN          BIT(0)
+#define PCA9641_MSK_BUS_LOST        BIT(1)
+#define PCA9641_MSK_LOCK_GRANT      BIT(2)
+#define PCA9641_MSK_TEST_INT        BIT(3)
+#define PCA9641_MSK_MBOX_EMPTY      BIT(4)
+#define PCA9641_MSK_MBOX_FULL       BIT(5)
+#define PCA9641_MSK_BUS_HUNG        BIT(6)
+
+/* POR value of INT_MSK: all interrupt sources masked */
+#define PCA9641_INT_MSK_ALL         0x7Fu
+
+/*
+ * Interrupt mask value that enables only LOCK_GRANT and BUS_LOST.
+ * All other sources remain masked (bit = 1 means masked).
+ */
+#define PCA9641_INT_MSK_ARB \
+	(PCA9641_INT_MSK_ALL & ~(PCA9641_MSK_LOCK_GRANT | PCA9641_MSK_BUS_LOST))
+
+/* Value in ID register that uniquely identifies PCA9641 (vs. PCA9541) */
+#define PCA9641_ID_MAGIC            0x38u
+
+/* Arbitration retry delays (microseconds) */
+#define PCA9641_DELAY_SHORT         50u
+#define PCA9641_DELAY_LONG          1000u
+
+/**
+ * struct pca9641 - per-device driver state
+ * @client:          I2C client for the arbiter device
+ * @select_timeout:  Current polling retry delay in microseconds
+ * @irq:             Linux IRQ number for INT0/INT1 GPIO, or -1 if not used
+ * @lock_grant_comp: Completion signaled from the IRQ handler on LOCK_GRANT
+ */
+struct pca9641 {
+	struct i2c_client *client;
+	unsigned long select_timeout;
+	int irq;
+	struct completion lock_grant_comp;
+};
+
+static const struct i2c_device_id pca9641_id[] = {
+	{ "pca9641" },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pca9641_id);
+
+static const struct of_device_id pca9641_of_match[] = {
+	{ .compatible = "nxp,pca9641" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pca9641_of_match);
+
+/*
+ * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock the adapter a second time.
+ */
+static int pca9641_reg_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	union i2c_smbus_data data = { .byte = val };
+
+	return __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+				I2C_SMBUS_WRITE, reg,
+				I2C_SMBUS_BYTE_DATA, &data);
+}
+
+/*
+ * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock adapter a second time.
+ */
+static int pca9641_reg_read(struct i2c_client *client, u8 reg)
+{
+	union i2c_smbus_data data;
+	int ret;
+
+	ret = __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+			       I2C_SMBUS_READ, reg,
+			       I2C_SMBUS_BYTE_DATA, &data);
+
+	return ret ? ret : (int)data.byte;
+}
+
+/* Release bus ownership. */
+static void pca9641_release_bus(struct i2c_client *client)
+{
+	pca9641_reg_write(client, PCA9641_CONTR, 0x00);
+}
+
+/*
+ * Threaded IRQ handler for INT0/INT1. Signals the completion waited on by
+ * pca9641_select_chan(). No I2C access here to avoid deadlock on the adapter
+ * mutex held by select_chan().
+ */
+static irqreturn_t pca9641_irq_handler(int irq, void *dev_id)
+{
+	struct pca9641 *data = dev_id;
+
+	complete(&data->lock_grant_comp);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Arbitration management. Asserts LOCK_REQ and checks LOCK_GRANT to acquire
+ * the downstream bus. Returns 1 when acquired, 0 to retry, <0 on error.
+ */
+static int pca9641_arbitrate(struct i2c_client *client)
+{
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca9641 *data = i2c_mux_priv(muxc);
+	int ctrl, status, ret;
+
+	ctrl = pca9641_reg_read(client, PCA9641_CONTR);
+	if (ctrl < 0)
+		return ctrl;
+
+	if (ctrl & PCA9641_CTL_LOCK_GRANT) {
+		if (!(ctrl & PCA9641_CTL_BUS_CONNECT)) {
+			ret = pca9641_reg_write(client, PCA9641_CONTR,
+						(u8)(ctrl | PCA9641_CTL_BUS_CONNECT));
+			if (ret < 0)
+				return ret;
+		}
+		return 1;
+	}
+
+	if (!(ctrl & PCA9641_CTL_LOCK_REQ)) {
+		ret = pca9641_reg_write(client, PCA9641_CONTR,
+					(u8)(ctrl | PCA9641_CTL_LOCK_REQ));
+		if (ret < 0)
+			return ret;
+		data->select_timeout = PCA9641_DELAY_SHORT;
+		return 0;
+	}
+
+	status = pca9641_reg_read(client, PCA9641_STATUS);
+	if (status < 0)
+		return status;
+
+	data->select_timeout = (status & PCA9641_STA_OTHER_LOCK) ?
+				PCA9641_DELAY_LONG : PCA9641_DELAY_SHORT;
+
+	return 0;
+}
+
+/*
+ * Acquire the downstream bus before a transaction. Uses interrupt mode
+ * if IRQ is available, polling otherwise.
+ */
+static int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct pca9641 *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+	unsigned long timeout = jiffies + 2 * client->adapter->timeout;
+	int ctrl, ret;
+
+	if (data->irq > 0) {
+		reinit_completion(&data->lock_grant_comp);
+
+		ctrl = pca9641_reg_read(client, PCA9641_CONTR);
+		if (ctrl < 0)
+			return ctrl;
+
+		if (ctrl & PCA9641_CTL_LOCK_GRANT)
+			goto set_bus_connect;
+
+		ret = pca9641_reg_write(client, PCA9641_CONTR,
+					(u8)((ctrl & ~PCA9641_CTL_BUS_CONNECT) |
+					     PCA9641_CTL_LOCK_REQ));
+		if (ret < 0)
+			return ret;
+
+		if (!wait_for_completion_timeout(&data->lock_grant_comp,
+						 client->adapter->timeout)) {
+			ctrl = pca9641_reg_read(client, PCA9641_CONTR);
+			if (ctrl < 0)
+				return ctrl;
+			if (!(ctrl & PCA9641_CTL_LOCK_GRANT)) {
+				dev_warn(&client->dev,
+					 "Timed out waiting for bus grant\n");
+				return -ETIMEDOUT;
+			}
+			goto set_bus_connect;
+		}
+
+		ctrl = pca9641_reg_read(client, PCA9641_CONTR);
+		if (ctrl < 0)
+			return ctrl;
+
+		if (!(ctrl & PCA9641_CTL_LOCK_GRANT)) {
+			dev_warn(&client->dev,
+				 "Interrupt fired but LOCK_GRANT not set\n");
+			return -ETIMEDOUT;
+		}
+
+set_bus_connect:
+		(void)pca9641_reg_write(client, PCA9641_INT_STATUS,
+					PCA9641_INTS_LOCK_GRANT | PCA9641_INTS_BUS_LOST);
+
+		if (!(ctrl & PCA9641_CTL_BUS_CONNECT)) {
+			ret = pca9641_reg_write(client, PCA9641_CONTR,
+						(u8)(ctrl | PCA9641_CTL_BUS_CONNECT));
+			if (ret < 0)
+				return ret;
+		}
+		return 0;
+	}
+
+	do {
+		ret = pca9641_arbitrate(client);
+		if (ret)
+			return ret < 0 ? ret : 0;
+
+		if (data->select_timeout <= PCA9641_DELAY_SHORT)
+			udelay(data->select_timeout);
+		else
+			msleep(data->select_timeout / 1000);
+	} while (time_is_after_eq_jiffies(timeout));
+
+	dev_warn(&client->dev, "Failed to acquire I2C bus, timed out\n");
+	return -ETIMEDOUT;
+}
+
+/* Release the downstream bus after a transaction completes. */
+static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct pca9641 *data = i2c_mux_priv(muxc);
+
+	pca9641_release_bus(data->client);
+	return 0;
+}
+
+static int pca9641_probe(struct i2c_client *client)
+{
+	struct i2c_adapter *adap = client->adapter;
+	struct i2c_mux_core *muxc;
+	struct pca9641 *data;
+	int id, ret;
+
+	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	id = i2c_smbus_read_byte_data(client, PCA9641_ID);
+	if (id < 0) {
+		dev_err(&client->dev, "Failed to read device ID: %d\n", id);
+		return id;
+	}
+	if ((u8)id != PCA9641_ID_MAGIC) {
+		dev_err(&client->dev,
+			"Unexpected device ID 0x%02x (expected 0x%02x for PCA9641)\n",
+			(u8)id, PCA9641_ID_MAGIC);
+		return -ENODEV;
+	}
+
+	/* Clear any stale bus ownership from a previous crash. */
+	i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+	pca9641_release_bus(client);
+	i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
+
+	muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
+			     I2C_MUX_ARBITRATOR,
+			     pca9641_select_chan, pca9641_release_chan);
+	if (!muxc)
+		return -ENOMEM;
+
+	data = i2c_mux_priv(muxc);
+	data->client = client;
+	data->irq = -1;
+	init_completion(&data->lock_grant_comp);
+
+	i2c_set_clientdata(client, muxc);
+
+	/* Optional interrupt mode; fall back to polling on failure. */
+	if (client->irq > 0) {
+		ret = i2c_smbus_write_byte_data(client, PCA9641_INT_MSK,
+						PCA9641_INT_MSK_ARB);
+		if (ret < 0) {
+			dev_warn(&client->dev,
+				 "Failed to set interrupt mask (%d); using polling\n",
+				 ret);
+			goto add_adapter;
+		}
+
+		ret = devm_request_threaded_irq(&client->dev, client->irq,
+						NULL, pca9641_irq_handler,
+						IRQF_ONESHOT | IRQF_SHARED,
+						dev_name(&client->dev), data);
+		if (ret < 0) {
+			dev_warn(&client->dev,
+				 "Failed to request IRQ %d (%d); using polling\n",
+				 client->irq, ret);
+			i2c_smbus_write_byte_data(client, PCA9641_INT_MSK,
+						  PCA9641_INT_MSK_ALL);
+		} else {
+			data->irq = client->irq;
+			dev_dbg(&client->dev,
+				"Interrupt mode enabled on IRQ %d\n",
+				client->irq);
+		}
+	}
+
+add_adapter:
+	ret = i2c_mux_add_adapter(muxc, 0, 0);
+	if (ret)
+		return ret;
+
+	dev_info(&client->dev,
+		 "PCA9641 I2C master arbiter registered (I2C bus %s, %s mode)\n",
+		 client->name,
+		 data->irq > 0 ? "interrupt" : "polling");
+
+	return 0;
+}
+
+static void pca9641_remove(struct i2c_client *client)
+{
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca9641 *data = i2c_mux_priv(muxc);
+
+	if (data->irq > 0)
+		(void)i2c_smbus_write_byte_data(client, PCA9641_INT_MSK,
+						PCA9641_INT_MSK_ALL);
+
+	i2c_mux_del_adapters(muxc);
+}
+
+static struct i2c_driver pca9641_driver = {
+	.driver = {
+		.name		= "pca9641",
+		.of_match_table	= pca9641_of_match,
+	},
+	.probe		= pca9641_probe,
+	.remove		= pca9641_remove,
+	.id_table	= pca9641_id,
+};
+
+module_i2c_driver(pca9641_driver);
+
+MODULE_AUTHOR("Shiv Prakash Gupta <shivprakash.gupta@nxp.com>");
+MODULE_DESCRIPTION("PCA9641 2-to-1 I2C bus master arbiter driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  2026-09-08 12:31 ` [PATCH 1/2] dt-bindings: i2c: " Shiv Prakash Gupta
@ 2026-09-08 12:48   ` sashiko-bot
  2026-09-08 17:47   ` Conor Dooley
  1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-09-08 12:48 UTC (permalink / raw)
  To: Shiv Prakash Gupta; +Cc: robh, conor+dt, devicetree

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The PCA9641 acts as an interrupt controller for downstream devices by propagating interrupts, but the binding omits the required `interrupt-controller` and `#interrupt-cells` properties.
--

commit f66b0c3d86e4ae950a20caea6a9eb2ad2243149c
Author: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
Subject: dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter

This commit adds a device tree binding schema for the NXP PCA9641 2-to-1 I2C
bus master arbiter. The PCA9641 arbitrates between two upstream I2C masters
using a lock/grant model and supports an optional interrupts property for
interrupt-assisted arbitration.

diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
new file mode 100644
index 0000000000000..649a3f6d1776f
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
[ ... ]
> properties:
>   compatible:
>     const: nxp,pca9641

[Severity: Medium]
Since the commit message notes the PCA9641 has an INT_IN interrupt input that
propagates downstream slave interrupts upstream, it appears to act as an
interrupt controller. 

Should the interrupt-controller and #interrupt-cells properties be defined here
to expose the hardware's capabilities to schema validation?

[ ... ]
> required:
>   - compatible
>   - reg
>   - i2c-arb
> 
> additionalProperties: false

[Severity: Medium]
If a downstream I2C device correctly specifies interrupt-parent = <&i2c_arbiter>
to route its interrupts through the PCA9641, would the device tree fail schema
validation because additionalProperties: false is set and the interrupt
controller properties are omitted?

Should the interrupt-controller and #interrupt-cells properties be included in
this required block to ensure nodes are correctly validated?

> 
> examples:
>   - |
>     /* Minimal example: polling mode (no interrupt wiring) */

[Severity: Medium]
If the interrupt controller properties are added to the required block, would
these examples also need to be updated to include them so the examples can
continue to pass dt_binding_check?

>     i2c {
>         #address-cells = <1>;
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908123146.1839854-1-shivprakash.gupta@nxp.com?part=1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver
  2026-09-08 12:31 ` [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver Shiv Prakash Gupta
@ 2026-09-08 12:52   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-09-08 12:52 UTC (permalink / raw)
  To: Shiv Prakash Gupta; +Cc: robh, devicetree, conor+dt

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] The interrupt implementation is fatally flawed: it requests a shared IRQ with a NULL primary handler (which fails unconditionally), fails to clear the hardware interrupt source (causing an infinite IRQ storm), blindly consumes shared interrupts (stealing from other devices), and instantly aborts I2C transfers upon spurious wakeups.
- [High] Missing clearing of LOCK_REQ on error paths leads to permanent bus lockout.
- [High] pca9641_probe fails to re-mask interrupts if i2c_mux_add_adapter fails, leading to an unhandled IRQ storm.
- [Medium] Incorrect teardown order in `pca9641_remove()` masks hardware interrupts before unregistering child adapters, causing concurrent transactions to stall.
- [Medium] The driver unmasks hardware interrupts before registering the IRQ handler, risking immediate spurious interrupts and disabled IRQ lines.
- [Low] The `i2c_device_id` array fails to use named initializers.
--

commit 2d4a239fba3344246dc50ddca835d1ac1501417b
Author: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>

i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver
    
This patch adds a driver for the NXP PCA9641 2-to-1 I2C bus master arbiter.
It supports interrupt-assisted arbitration when INT0/INT1 is connected to a
GPIO, and falls back to polling mode when an interrupt is not configured.

> diff --git a/drivers/i2c/muxes/i2c-mux-pca9641.c b/drivers/i2c/muxes/i2c-mux-pca9641.c
> new file mode 100644
> index 0000000000000..c12aa88dcf560
> --- /dev/null
> +++ b/drivers/i2c/muxes/i2c-mux-pca9641.c

[ ... ]

> +static const struct i2c_device_id pca9641_id[] = {
> +	{ "pca9641" },
> +	{}
> +};

[Severity: Low]
Is it possible to use named initializers here? I2C subsystem guidelines
typically expect initialized arrays of type struct i2c_device_id to use
named initializers.

[ ... ]

> +static irqreturn_t pca9641_irq_handler(int irq, void *dev_id)
> +{
> +	struct pca9641 *data = dev_id;
> +
> +	complete(&data->lock_grant_comp);
> +	return IRQ_HANDLED;
> +}

[Severity: High]
Does this handler need to clear the hardware interrupt source before
returning IRQ_HANDLED? Since this is a shared interrupt, claiming the
interrupt without checking or clearing the hardware source could lead to
an IRQ storm, and might consume interrupts meant for other devices sharing
the same line.

[ ... ]

> +		if (!wait_for_completion_timeout(&data->lock_grant_comp,
> +						 client->adapter->timeout)) {
> +			ctrl = pca9641_reg_read(client, PCA9641_CONTR);
> +			if (ctrl < 0)
> +				return ctrl;
> +			if (!(ctrl & PCA9641_CTL_LOCK_GRANT)) {
> +				dev_warn(&client->dev,
> +					 "Timed out waiting for bus grant\n");
> +				return -ETIMEDOUT;
> +			}
> +			goto set_bus_connect;
> +		}

[Severity: High]
If this wait times out, do we need to clear the PCA9641_CTL_LOCK_REQ bit in
the control register before returning? Bailing out here without clearing it
seems like it might permanently lock out the downstream I2C bus for the
other master.

> +
> +		ctrl = pca9641_reg_read(client, PCA9641_CONTR);
> +		if (ctrl < 0)
> +			return ctrl;
> +
> +		if (!(ctrl & PCA9641_CTL_LOCK_GRANT)) {
> +			dev_warn(&client->dev,
> +				 "Interrupt fired but LOCK_GRANT not set\n");
> +			return -ETIMEDOUT;
> +		}

[Severity: High]
Since this IRQ is requested as shared, could a spurious wakeup or an
interrupt from another device cause us to take this path? If so, this would
instantly fail the transfer instead of safely resuming the wait.

[ ... ]

> +	do {
> +		ret = pca9641_arbitrate(client);
> +		if (ret)
> +			return ret < 0 ? ret : 0;
> +
> +		if (data->select_timeout <= PCA9641_DELAY_SHORT)
> +			udelay(data->select_timeout);
> +		else
> +			msleep(data->select_timeout / 1000);
> +	} while (time_is_after_eq_jiffies(timeout));
> +
> +	dev_warn(&client->dev, "Failed to acquire I2C bus, timed out\n");
> +	return -ETIMEDOUT;

[Severity: High]
Similar to the interrupt wait timeout, if this polling loop times out,
should we clear the PCA9641_CTL_LOCK_REQ bit before returning -ETIMEDOUT?
Otherwise, the lock might be held indefinitely.

[ ... ]

> +	/* Optional interrupt mode; fall back to polling on failure. */
> +	if (client->irq > 0) {
> +		ret = i2c_smbus_write_byte_data(client, PCA9641_INT_MSK,
> +						PCA9641_INT_MSK_ARB);

[Severity: Medium]
Are hardware interrupts unmasked here before the IRQ handler is successfully
registered? If the device asserts an interrupt before the OS handler is
ready, could the kernel permanently disable the shared IRQ line?

> +		if (ret < 0) {
> +			dev_warn(&client->dev,
> +				 "Failed to set interrupt mask (%d); using polling\n",
> +				 ret);
> +			goto add_adapter;
> +		}
> +
> +		ret = devm_request_threaded_irq(&client->dev, client->irq,
> +						NULL, pca9641_irq_handler,
> +						IRQF_ONESHOT | IRQF_SHARED,
> +						dev_name(&client->dev), data);

[Severity: High]
Will this request succeed? Requesting a threaded IRQ with IRQF_SHARED and a
NULL primary handler usually fails unconditionally with -EINVAL, which would
prevent interrupt mode from working entirely.

[ ... ]

> +add_adapter:
> +	ret = i2c_mux_add_adapter(muxc, 0, 0);
> +	if (ret)
> +		return ret;

[Severity: High]
If i2c_mux_add_adapter fails here, should the error path re-mask the
interrupts? Returning an error while hardware interrupts are left unmasked
could lead to an unhandled IRQ storm.

[ ... ]

> +static void pca9641_remove(struct i2c_client *client)
> +{
> +	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
> +	struct pca9641 *data = i2c_mux_priv(muxc);
> +
> +	if (data->irq > 0)
> +		(void)i2c_smbus_write_byte_data(client, PCA9641_INT_MSK,
> +						PCA9641_INT_MSK_ALL);
> +
> +	i2c_mux_del_adapters(muxc);
> +}

[Severity: Medium]
Could this teardown order stall concurrent transactions? Masking hardware
interrupts before unregistering the child adapters via i2c_mux_del_adapters
means that if a downstream transaction is waiting for a bus grant during
removal, the completion might simply time out instead of finishing.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908123146.1839854-1-shivprakash.gupta@nxp.com?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  2026-09-08 12:31 ` [PATCH 1/2] dt-bindings: i2c: " Shiv Prakash Gupta
  2026-09-08 12:48   ` sashiko-bot
@ 2026-09-08 17:47   ` Conor Dooley
  2026-09-09  5:25     ` Peter Rosin
  1 sibling, 1 reply; 8+ messages in thread
From: Conor Dooley @ 2026-09-08 17:47 UTC (permalink / raw)
  To: Shiv Prakash Gupta
  Cc: andi.shyti, robh, krzk+dt, conor+dt, peda, linux-i2c, devicetree,
	linux-kernel, vikash.bansal, priyanka.jain

[-- Attachment #1: Type: text/plain, Size: 4906 bytes --]

On Tue, Sep 08, 2026 at 06:01:45PM +0530, Shiv Prakash Gupta wrote:
> Add device tree binding schema for the NXP PCA9641 2-to-1 I2C bus
> master arbiter.
> 
> The PCA9641 arbitrates between two upstream I2C masters competing for a
> single downstream slave bus using a lock/grant ownership model. The
> binding supports an optional 'interrupts' property for interrupt-assisted
> arbitration.
> 
> Signed-off-by: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
> ---
>  .../devicetree/bindings/i2c/nxp,pca9641.yaml  | 109 ++++++++++++++++++
>  1 file changed, 109 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
> 
> diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
> new file mode 100644
> index 000000000000..649a3f6d1776
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/nxp,pca9641.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/i2c/nxp,pca9641.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP PCA9641 2-to-1 I2C bus master arbiter
> +
> +maintainers:
> +  - Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
> +
> +description: |
> +  The PCA9641 is a 2-to-1 I2C bus master arbiter that manages two upstream
> +  I2C masters competing for a single downstream slave bus. It uses a
> +  lock/grant ownership model: a master requests the downstream bus by setting
> +  LOCK_REQ, waits for the arbiter to assert LOCK_GRANT, then explicitly
> +  connects to the bus via BUS_CONNECT before issuing transactions.
> +
> +  Key features compared to the PCA9541:
> +    - Lock/grant ownership model (LOCK_REQ + LOCK_GRANT bits in CONTR register)
> +    - BUS_CONNECT bit must be set explicitly after receiving LOCK_GRANT
> +    - Reserve Time register (RT): guarantees bus ownership for 1-255 ms
> +    - INT0 and INT1 interrupt outputs (one per upstream master) and INT_IN
> +      interrupt input that propagates downstream slave interrupts upstream
> +    - 16-bit shared mailbox (MB_LO + MB_HI) for inter-master communication
> +    - ID register (read-only, value 0x38) to distinguish from PCA9541
> +    - Four address pins (AD0-AD3) allowing up to 112 unique I2C addresses
> +
> +properties:
> +  compatible:
> +    const: nxp,pca9641
> +
> +  reg:
> +    maxItems: 1
> +    description:
> +      7-bit I2C slave address of the PCA9641 on the upstream bus. The address
> +      is set by hardware pins AD0-AD3 at power-on or hardware reset.
> +
> +  interrupts:
> +    maxItems: 1
> +    description:
> +      Optional interrupt from the INT0 or INT1 output pin. When provided the
> +      driver uses interrupt-assisted arbitration (waits on LOCK_GRANT interrupt)
> +      instead of polling the CONTR register. Either INT0 or INT1 can be
> +      connected depending on which upstream master port is used.
> +
> +  i2c-arb:
> +    type: object
> +    $ref: /schemas/i2c/i2c-controller.yaml
> +    unevaluatedProperties: false
> +    description:
> +      I2C bus node representing the downstream slave bus controlled by the
> +      PCA9641. Downstream slave devices are declared as child nodes here.

Why does this node need to exist? Can't the i2c-arbiter node itself
contain the child devices?

Thanks,
Conor.

> +
> +required:
> +  - compatible
> +  - reg
> +  - i2c-arb
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    /* Minimal example: polling mode (no interrupt wiring) */
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        i2c-arbiter@74 {
> +            compatible = "nxp,pca9641";
> +            reg = <0x74>;
> +
> +            i2c-arb {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                eeprom@50 {
> +                    compatible = "atmel,24c32";
> +                    reg = <0x50>;
> +                };
> +            };
> +        };
> +    };
> +
> +  - |
> +    /* Interrupt mode: INT0 wired to SoC GPIO */
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        i2c-arbiter@70 {
> +            compatible = "nxp,pca9641";
> +            reg = <0x70>;
> +            interrupt-parent = <&gpio1>;
> +            interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
> +
> +            i2c-arb {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                temperature-sensor@48 {
> +                    compatible = "national,lm75";
> +                    reg = <0x48>;
> +                };
> +            };
> +        };
> +    };
> -- 
> 2.34.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  2026-09-08 17:47   ` Conor Dooley
@ 2026-09-09  5:25     ` Peter Rosin
  2026-09-09 10:00       ` Conor Dooley
  0 siblings, 1 reply; 8+ messages in thread
From: Peter Rosin @ 2026-09-09  5:25 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Shiv Prakash Gupta, andi.shyti, robh, krzk+dt, conor+dt,
	linux-i2c, devicetree, linux-kernel, vikash.bansal, priyanka.jain

Den Tue, Sep 08, 2026 at 06:47:01PM +0100, skrev Conor Dooley:
> On Tue, Sep 08, 2026 at 06:01:45PM +0530, Shiv Prakash Gupta wrote:
> > Add device tree binding schema for the NXP PCA9641 2-to-1 I2C bus
> > master arbiter.
> > 
> > The PCA9641 arbitrates between two upstream I2C masters competing for a
> > single downstream slave bus using a lock/grant ownership model. The
> > binding supports an optional 'interrupts' property for interrupt-assisted
> > arbitration.
> > 
> > Signed-off-by: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
> > ---

...

> > +  i2c-arb:
> > +    type: object
> > +    $ref: /schemas/i2c/i2c-controller.yaml
> > +    unevaluatedProperties: false
> > +    description:
> > +      I2C bus node representing the downstream slave bus controlled by the
> > +      PCA9641. Downstream slave devices are declared as child nodes here.
> 
> Why does this node need to exist? Can't the i2c-arbiter node itself
> contain the child devices?

For symmetry with the pre-existing I2C arbs, which all have the extra
node for historical implementation reasons? I don't know if that's
considered a valid reason? I prefer to have all arbs follow the same
structure...

The "documentation" describing common I2C arbitration details went missing
here:

https://lore.kernel.org/all/20230731163833.319258-1-krzysztof.kozlowski@linaro.org/

Cheers,
Peter

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] dt-bindings: i2c: Add NXP PCA9641 I2C bus master arbiter
  2026-09-09  5:25     ` Peter Rosin
@ 2026-09-09 10:00       ` Conor Dooley
  0 siblings, 0 replies; 8+ messages in thread
From: Conor Dooley @ 2026-09-09 10:00 UTC (permalink / raw)
  To: Peter Rosin
  Cc: Shiv Prakash Gupta, andi.shyti, robh, krzk+dt, conor+dt,
	linux-i2c, devicetree, linux-kernel, vikash.bansal, priyanka.jain

[-- Attachment #1: Type: text/plain, Size: 1775 bytes --]

On Wed, Sep 09, 2026 at 07:25:38AM +0200, Peter Rosin wrote:
> Den Tue, Sep 08, 2026 at 06:47:01PM +0100, skrev Conor Dooley:
> > On Tue, Sep 08, 2026 at 06:01:45PM +0530, Shiv Prakash Gupta wrote:
> > > Add device tree binding schema for the NXP PCA9641 2-to-1 I2C bus
> > > master arbiter.
> > > 
> > > The PCA9641 arbitrates between two upstream I2C masters competing for a
> > > single downstream slave bus using a lock/grant ownership model. The
> > > binding supports an optional 'interrupts' property for interrupt-assisted
> > > arbitration.
> > > 
> > > Signed-off-by: Shiv Prakash Gupta <shivprakash.gupta@nxp.com>
> > > ---
> 
> ...
> 
> > > +  i2c-arb:
> > > +    type: object
> > > +    $ref: /schemas/i2c/i2c-controller.yaml
> > > +    unevaluatedProperties: false
> > > +    description:
> > > +      I2C bus node representing the downstream slave bus controlled by the
> > > +      PCA9641. Downstream slave devices are declared as child nodes here.
> > 
> > Why does this node need to exist? Can't the i2c-arbiter node itself
> > contain the child devices?
> 
> For symmetry with the pre-existing I2C arbs, which all have the extra
> node for historical implementation reasons? I don't know if that's
> considered a valid reason? I prefer to have all arbs follow the same
> structure...

If this is just how these devices are described in general, I think
that's probably fine.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

(Also, good to see you back active)

Cheers.,
Conor.

> 
> The "documentation" describing common I2C arbitration details went missing
> here:
> 
> https://lore.kernel.org/all/20230731163833.319258-1-krzysztof.kozlowski@linaro.org/
> 
> Cheers,
> Peter

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-09-09 10:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 12:31 [PATCH 0/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter Shiv Prakash Gupta
2026-09-08 12:31 ` [PATCH 1/2] dt-bindings: i2c: " Shiv Prakash Gupta
2026-09-08 12:48   ` sashiko-bot
2026-09-08 17:47   ` Conor Dooley
2026-09-09  5:25     ` Peter Rosin
2026-09-09 10:00       ` Conor Dooley
2026-09-08 12:31 ` [PATCH 2/2] i2c: mux: Add NXP PCA9641 I2C bus master arbiter driver Shiv Prakash Gupta
2026-09-08 12:52   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox