Re: [v8 2/3] i2c: muxes: pca954x: Add MAX735x/MAX736x support

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

 



Hi!

2022-04-19 at 14:40, Patrick Rudolph wrote:
Add support for the following Maxim chips using the existing PCA954x
driver:
- MAX7356
- MAX7357
- MAX7358
- MAX7367
- MAX7368
- MAX7369

All added Maxim chips behave like the PCA954x, where a single SMBUS byte
write selects up to 8 channels to be bridged to the primary bus.

The MAX7357 and MAX7358 have 6 additional registers called enhanced mode
in the following paragraphs. While the MAX7357 exposes those registers
without a special sequence, the MAX7358 requires an unlock sequence.
The enhanced mode allows to configure optional features which are nice to
have on a I2C mux, but are not mandatory for it's general operation.

s/on a I2C/on an I2C/


As I don't have a MAX7358 for testing the special unlock sequence the
enhanced mode isn't used on the MAX7358, but it could be added later
if required.

The MAX7357 enhanced mode is used to configure:
  - Disabled interrupts on bus locked up detection
  - Enable bus locked-up clearing
  - Disconnect only locked bus instead of all channels

While the MAX7357/MAX7358 have interrupt support, they don't act as
interrupt controller like the PCA9545 does. Thus don't enable IRQ support
and handle them like the PCA9548.

Tested using the MAX7357 and verified that the stalled bus is disconnected
while the other channels remain operational.

How does recovery work if only one leg be stalled? Does recovery work
differently if the MAX7357_CONF_DISCON_SINGLE_CHAN bit is set? If so,
I'd expect some recovery support, no?

From just reading the patch and not looking up any docs, it looks like
you might need to interact with MAX7357_CONF_LOCK_UP_CLEAR, no? But
that sounds like an operation, so it doesn't really fit in a "CONF"
register. Hmmm, I'm just asking questions and don't know how lock-ups
are handled with preexisting chips, so I'm by no means any expert...


Signed-off-by: Patrick Rudolph <patrick.rudolph@xxxxxxxxxxxxx>
---
  drivers/i2c/muxes/Kconfig           |  4 +-
  drivers/i2c/muxes/i2c-mux-pca954x.c | 92 +++++++++++++++++++++++++++--
  2 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 1708b1a82da2..2ac99d044199 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -65,11 +65,11 @@ config I2C_MUX_PCA9541
  	  will be called i2c-mux-pca9541.
config I2C_MUX_PCA954x
-	tristate "NXP PCA954x and PCA984x I2C Mux/switches"
+	tristate "NXP PCA954x/PCA984x and Maxim MAX735x/MAX736x I2C Mux/switches"
  	depends on GPIOLIB || COMPILE_TEST
  	help
  	  If you say yes here you get support for the NXP PCA954x
-	  and PCA984x I2C mux/switch devices.
+	  and PCA984x and Maxim MAX735x/MAX736x I2C mux/switch devices.

You still have this double-and thing going that I commented on in v6,
including a missing "the" for the Maxim half that is there for the
preexisting NXP half. That makes it unbalanced and difficult to read.

My suggestion then was:

	  If you say yes here you get support for NXP PCA954x/PCA984x
	  and Maxim MAX735x/MAX736x I2C mux/switch devices.

Was there anything wrong with that?

This driver can also be built as a module. If so, the module
  	  will be called i2c-mux-pca954x.
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 4ad665757dd8..122b7a28fc60 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -4,6 +4,7 @@
   *
   * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@xxxxxxxx>
   * Copyright (c) 2008-2009 Eurotech S.p.A. <info@xxxxxxxxxxx>
+ * Copyright (c) 2022 9elements GmbH <patrick.rudolph@xxxxxxxxxxxxx>
   *
   * This module supports the PCA954x and PCA984x series of I2C multiplexer/switch
   * chips made by NXP Semiconductors.
@@ -11,6 +12,12 @@
   *	 PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547,
   *	 PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849.
   *
+ * It's also compatible to Maxims MAX735x I2C switch chips, which are controlled
+ * as the NXP PCA9548 and the MAX736x chips that act like the PCA9544.
+ *
+ * This includes the:
+ *	 MAX7356, MAX7357, MAX7358, MAX7367, MAX7368 and MAX7369
+ *
   * These chips are all controlled via the I2C bus itself, and all have a
   * single 8-bit register. The upstream "parent" bus fans out to two,
   * four, or eight downstream busses or channels; which of these
@@ -50,7 +57,30 @@
#define PCA954X_IRQ_OFFSET 4 +/*
+ * MAX7357 exposes 7 registers without extra commands which allow to configure
+ * additional features. Disable interrupts, enable bus locked-up clearing,
+ * isolate only the locked channel instead of all channels.
+ */

The information from the commit message that describes this as "maxim
enhanced mode" is needed here as well. Also, It makes no sense to talk
about not needing extra commands to open up something unless you also
talk about some case where it is indeed needed to unlock the enhanced
mode. I also miss an explicit description that the below bit definitions
are for one of the mentioned enhanced registers. There could also be
some mention of which register index this "CONF" register has.

+#define MAX7357_CONF_INT_ENABLE			BIT(0)
+#define MAX7357_CONF_FLUSH_OUT			BIT(1)
+#define MAX7357_CONF_RELEASE_INT		BIT(2)
+#define MAX7357_CONF_LOCK_UP_CLEAR		BIT(3)
+#define MAX7357_CONF_DISCON_SINGLE_CHAN		BIT(4)
+#define MAX7357_CONF_BUS_LOCKUP_DETECTION	BIT(5)
+#define MAX7357_CONF_ENABLE_BASIC_MODE		BIT(6)
+#define MAX7357_CONF_PRECONNECT_TEST		BIT(7)
+
+#define MAX7357_CONF_DEFAULTS (MAX7357_CONF_FLUSH_OUT | \
+	 MAX7357_CONF_DISCON_SINGLE_CHAN)
+
  enum pca_type {
+	max_7367,
+	max_7368,
+	max_7369,
+	max_7356,
+	max_7357,
+	max_7358,
  	pca_9540,
  	pca_9542,
  	pca_9543,
@@ -69,6 +99,7 @@ struct chip_desc {
  	u8 nchans;
  	u8 enable;	/* used for muxes only */
  	u8 has_irq;
+	u8 maxim_enhanced_mode;
  	enum muxtype {
  		pca954x_ismux = 0,
  		pca954x_isswi
@@ -90,8 +121,42 @@ struct pca954x {
  	raw_spinlock_t lock;
  };
-/* Provide specs for the PCA954x types we know about */
+/* Provide specs for the PCA954x and MAX735x types we know about */

Not really your fault, but specs are also provided for some PCA984x
parts that "we know about". However, arguably all of these are
PCA954x "types".

So, either drop the change to this comment or also add PCA984x to the
mix. I vote for the latter.

  static const struct chip_desc chips[] = {
+	[max_7356] = {
+		.nchans = 8,
+		.muxtype = pca954x_isswi,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
+	[max_7357] = {
+		.nchans = 8,
+		.muxtype = pca954x_isswi,
+		.maxim_enhanced_mode = 1,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
+	[max_7358] = {
+		.nchans = 8,
+		.muxtype = pca954x_isswi,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
+	[max_7367] = {
+		.nchans = 4,
+		.muxtype = pca954x_isswi,
+		.has_irq = 1,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
+	[max_7368] = {
+		.nchans = 4,
+		.muxtype = pca954x_isswi,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
+	[max_7369] = {
+		.nchans = 4,
+		.enable = 0x4,
+		.muxtype = pca954x_ismux,
+		.has_irq = 1,
+		.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+	},
  	[pca_9540] = {
  		.nchans = 2,
  		.enable = 0x4,
@@ -177,6 +242,12 @@ static const struct chip_desc chips[] = {
  };
static const struct i2c_device_id pca954x_id[] = {
+	{ "max7356", max_7356 },
+	{ "max7357", max_7357 },
+	{ "max7358", max_7358 },
+	{ "max7367", max_7367 },
+	{ "max7368", max_7368 },
+	{ "max7369", max_7369 },
  	{ "pca9540", pca_9540 },
  	{ "pca9542", pca_9542 },
  	{ "pca9543", pca_9543 },
@@ -194,6 +265,12 @@ static const struct i2c_device_id pca954x_id[] = {
  MODULE_DEVICE_TABLE(i2c, pca954x_id);
static const struct of_device_id pca954x_of_match[] = {
+	{ .compatible = "maxim,max7356", .data = &chips[max_7356] },
+	{ .compatible = "maxim,max7357", .data = &chips[max_7357] },
+	{ .compatible = "maxim,max7358", .data = &chips[max_7358] },
+	{ .compatible = "maxim,max7367", .data = &chips[max_7367] },
+	{ .compatible = "maxim,max7368", .data = &chips[max_7368] },
+	{ .compatible = "maxim,max7369", .data = &chips[max_7369] },
  	{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },
  	{ .compatible = "nxp,pca9542", .data = &chips[pca_9542] },
  	{ .compatible = "nxp,pca9543", .data = &chips[pca_9543] },
@@ -401,9 +478,16 @@ static int pca954x_init(struct i2c_client *client, struct pca954x *data)
  	else
  		data->last_chan = 0; /* Disconnect multiplexer */
- ret = i2c_smbus_write_byte(client, data->last_chan);
-	if (ret < 0)
-		data->last_chan = 0;
+	if (data->chip->maxim_enhanced_mode) {
+		ret = i2c_smbus_write_byte_data(client, data->last_chan,
+						MAX7357_CONF_DEFAULTS);

You are using i2c_smbus_write_byte_data() without first checking if
the adapter supports I2C_FUNC_SMBUS_WRITE_BYTE_DATA. I managed to
overlook that in the previous review, sorry about that. Anyway, see the
call to i2c_check_functionality() at the very top of pca954x_probe().
Probably not a big problem since i2c_smbus_write_byte_data() will
hopefully fail nicely if/when support is unexpectedly lacking causing
the probe to fail anyway, but it's better to fail early...

One could also perhaps fall back to not using enhanced mode if the
adapter does not support I2C_FUNC_SMBUS_WRITE_BYTE_DATA? Don't know
if it's worth it though -- probably not.

There is no support for programming anything other than the defaults
you have selected. If those defaults are the only thing that is ever
going to be needed, why are the chips not hard-wired by maxim like
that in the first place? How are we going to add support for other
values in the enhanced registers? Do we need to have a plan for that
up front, or should we let the person that is eventually going to need
that worry about those details?

Cheers,
Peter

+		if (ret < 0)
+			data->last_chan = 0;
+	} else {
+		ret = i2c_smbus_write_byte(client, data->last_chan);
+		if (ret < 0)
+			data->last_chan = 0;
+	}
return ret;
  }



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux