[PATCH] i2c: mux: pca954x: Disable cacheing of the last channel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx>

In case of multimaster configuration the last channel cached value is
not reliable. Basically the first processor/master does a write to the
mux and then to the intended slave, it caches the value.
Now the second processor/processor does a write to mux on another
channel and writes to another slave.
The first processor/master when it attempts to write the slave
skips the mux as it relies on the mux channel being the same as the
intended. This causes an issue.

To fix that write always to the mux address.

Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx>
---
 Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt | 1 +
 drivers/i2c/muxes/i2c-mux-pca954x.c                       | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
index 30ac6a6..fc4c0b0 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
@@ -34,6 +34,7 @@ Optional Properties:
     - first cell is the pin number
     - second cell is used to specify flags.
     See also Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+  - no-channel-cache: Write the mux channel always.
 
 Example:
 
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 923aa3a..37d32b0 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -85,6 +85,7 @@ struct pca954x {
 	const struct chip_desc *chip;
 
 	u8 last_chan;		/* last register value */
+	u8 last_chan_unchached;	/* write channel register always */
 	/* MUX_IDLE_AS_IS, MUX_IDLE_DISCONNECT or >= 0 for channel */
 	s8 idle_state;
 
@@ -244,7 +245,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
 		regval = 1 << chan;
 
 	/* Only select the channel if its different from the last channel */
-	if (data->last_chan != regval) {
+	if (last_chan_unchached && data->last_chan != regval) {
 		ret = pca954x_reg_write(muxc->parent, client, regval);
 		data->last_chan = ret < 0 ? 0 : regval;
 	}
@@ -479,6 +480,9 @@ static int pca954x_probe(struct i2c_client *client,
 	if (idle_disconnect_dt)
 		data->idle_state = MUX_IDLE_DISCONNECT;
 
+	data->last_chan_unchached = np &&
+		of_property_read_bool(np, "no-channel-cache");
+
 	ret = pca954x_irq_setup(muxc);
 	if (ret)
 		goto fail_cleanup;
-- 
2.1.1




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux