Skip to contentSkip to conversation

Improvements for MCP23Sxx chips

PATCH In review Jan Kundrát 6 participants 13 messages Jan 25, 2018 – Feb 9, 2018 6 messages not in the archive

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover Improvements for MCP23Sxx chips

a) Open-Drain output of the IRQ lane (see inside for possible caveats).
b) Improvements for multi-instances on the same SPI CS.

This chip is "special" because it supports several "instances" sharing the same SPI CS lane. Each chip has three HW pins for specifying an internal address. The first byte of each SPI transaction then distinguishes which chip we're talking to. So far, so good -- that's something that the driver already supports.

The actual implementation simply instantiates several regmap and pinctrl instances sharing the same parent (the spi/spiX.Y dev). That leads to clashes as soon as more HW chips are present because of naming clashes within debugfs.

Fixing this for regmap is pretty straightforward. The patch which implements something similar for the pinctrl subsystem is a bit more involved because it touches the pinctrl core. The resulting names are ugly and the strcmp in there is largely a hack in order to not force even more ugliness to the existing chips.

Jan Kundrát (4):
pinctrl: mcp23s08: IRQ behavior for open-drain interrupts
pinctrl: mcp23s08: spi: Fix regmap debugfs entries
pinctrl: mcp23s08: spi: Add HW address to gpio_chip.label
pinctrl: mcp23s08: spi: Fix duplicate pinctrl debugfs entries

 .../bindings/pinctrl/pinctrl-mcp23s08.txt          |   4 +
 drivers/pinctrl/core.c                             |  18 ++-
 drivers/pinctrl/pinctrl-mcp23s08.c                 | 131 +++++++++++++++------
 3 files changed, 114 insertions(+), 39 deletions(-)
Signature · 1 line
2.14.3

A message that is not in the archive (sent off-list or not yet received): cover.1516997103.git.jan.kundrat-xoNZbkdr4U2lVyrhU4qvOw@public.gmane.org

#2 lore raw

PATCH 1/4 pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

The hardware supports three different IRQ modes:
- open drain, i.e., an active-low output which requires an external pull-up and supports IRQ line sharing,
- active low, with push-pull output,
- active high, with push-pull output.

My understanding of electronics is limited, but it is "wrong" to connect different push-pull outpus together. It could sort-of work if the chips/board actually have some resistors there, but it's an ugly thing to do.

In the past, this driver did not touch the ODR bit (for open-drain) operation. During power-on-reset, it is set to zero. Unless some platform code actually set this bit to one, this means that the code never supported open drain operation.

This change makes this handling explicit. If you want sharing of the IRQ line, then use the microchip,irq-open-drain mode and add an external pull-up.

There's some risk here. If, e.g., the bootloader sets the ODR bit for some reason, the HW shares the IRQ lines, and nobody changes the DT, then your HW will suddenly use push-pull driver for the IRQ line. If there is any other chip on the same lane, the HW might suffer (my chip survived this when I "tested" this by accident with no bootloader code to set the ODR bit).

---
 .../bindings/pinctrl/pinctrl-mcp23s08.txt          |  4 ++
 drivers/pinctrl/pinctrl-mcp23s08.c                 | 82 +++++++++++++++-------
 2 files changed, 61 insertions(+), 25 deletions(-)
Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt +4 -0
index 9c451c20dda4..92aa91027c68 100644
@@ -58,6 +58,10 @@ Optional device specific properties:
         On devices with only one interrupt output this property is useless.
 - microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
         configures the IRQ output polarity as active high.
+- microchip,irq-open-drain: Sets the ODR flag in the IOCON register. This
+        configures the IRQ output as active low open-drain and allows sharing
+	of the IRQ line among several chips. Note that irq-active-high and
+	irq-open-drain are mutually exclusive.
 
 Example I2C (with interrupt):
 gpiom1: gpio@20 {
drivers/pinctrl/pinctrl-mcp23s08.c +57 -25

116 lines not on this page · raw message

Signature · 7 lines
2.14.3


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw

Re: [PATCH 1/4] pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

G'day Jan,

Quoted 38 lines · Jan Kundrát

The hardware supports three different IRQ modes:
- open drain, i.e., an active-low output which requires an external pull-up and supports IRQ line sharing,
- active low, with push-pull output,
- active high, with push-pull output.

My understanding of electronics is limited, but it is "wrong" to connect different push-pull outpus together. It could sort-of work if the chips/board actually have some resistors there, but it's an ugly thing to do.

In the past, this driver did not touch the ODR bit (for open-drain) operation. During power-on-reset, it is set to zero. Unless some platform code actually set this bit to one, this means that the code never supported open drain operation.

This change makes this handling explicit. If you want sharing of the IRQ line, then use the microchip,irq-open-drain mode and add an external pull-up.

There's some risk here. If, e.g., the bootloader sets the ODR bit for some reason, the HW shares the IRQ lines, and nobody changes the DT, then your HW will suddenly use push-pull driver for the IRQ line. If there is any other chip on the same lane, the HW might suffer (my chip survived this when I "tested" this by accident with no bootloader code to set the ODR bit).

---
  .../bindings/pinctrl/pinctrl-mcp23s08.txt          |  4 ++
  drivers/pinctrl/pinctrl-mcp23s08.c                 | 82 +++++++++++++++-------
  2 files changed, 61 insertions(+), 25 deletions(-)
Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt +0 -0
index 9c451c20dda4..92aa91027c68 100644

Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt Optional device specific properties: · line 64

Quoted 7 lines
Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt +4 -0
@@ -58,6 +58,10 @@ Optional device specific properties:
          On devices with only one interrupt output this property is useless.
  - microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
          configures the IRQ output polarity as active high.
+- microchip,irq-open-drain: Sets the ODR flag in the IOCON register. This
+        configures the IRQ output as active low open-drain and allows sharing
+	of the IRQ line among several chips. Note that irq-active-high and
+	irq-open-drain are mutually exclusive.

I submitted a patch for this in November, But haven't followed up on the last review as yet.
See: https://patchwork.ozlabs.org/cover/839923/

I used exactly the same dt in my first propsal. But you'll see form the discussions that series This needs to be the standard 'drive-open-drain' flag

Patch 2/5 has been reviewed by Sebastian acked Rob.

Quoted 32 lines
Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt +0 -0
  Example I2C (with interrupt):
  gpiom1: gpio@20 {
drivers/pinctrl/pinctrl-mcp23s08.c +8 -4
index c017860619d6..186101c575e3 100644
@@ -54,9 +54,15 @@
 
  struct mcp23s08;
 
+enum mcp23s08_irq_regime {
+	MCP_IRQ_PULL_LOW,
+	MCP_IRQ_PUSH_UP,
+	MCP_IRQ_OPEN_DRAIN
+};
+
  struct mcp23s08 {
  	u8			addr;
-	bool			irq_active_high;
+	enum mcp23s08_irq_regime	irq_regime;
  	bool			reg_shift;
 
  	u16			irq_rise;
@@ -625,10 +631,17 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
  	int err;
  	unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
 
-	if (mcp->irq_active_high)
-		irqflags |= IRQF_TRIGGER_HIGH;
-	else
+	switch (mcp->irq_regime) {

drivers/pinctrl/pinctrl-mcp23s08.c static int mcp23s08_irq_setup(struct mcp23s08 *mcp) · line 644

Quoted 10 lines
drivers/pinctrl/pinctrl-mcp23s08.c +9 -0
+	case MCP_IRQ_PULL_LOW:
  		irqflags |= IRQF_TRIGGER_LOW;
+		break;
+	case MCP_IRQ_PUSH_UP:
+		irqflags |= IRQF_TRIGGER_HIGH;
+		break;
+	case MCP_IRQ_OPEN_DRAIN:
+		irqflags |= IRQF_TRIGGER_LOW | IRQF_SHARED;
+		break;
+	}

The original code does the same thing.
open drain is active-low.
Sharing can also be achieved by AND / OR gates with push-pull drivers. So no need to treat that differently.

I'm trying to get ride f this bit of code as it should be needed. see 1/5 of my series.

Quoted 86 lines
drivers/pinctrl/pinctrl-mcp23s08.c +40 -21
  	err = devm_request_threaded_irq(chip->parent, mcp->irq, NULL,
  					mcp23s08_irq,
@@ -780,7 +793,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 
  	mcp->dev = dev;
  	mcp->addr = addr;
-	mcp->irq_active_high = false;
+	mcp->irq_regime = MCP_IRQ_PULL_LOW;
 
  	mcp->chip.direction_input = mcp23s08_direction_input;
  	mcp->chip.get = mcp23s08_get;
@@ -866,33 +879,52 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
  	mcp->irq_controller =
  		device_property_read_bool(dev, "interrupt-controller");
  	if (mcp->irq && mcp->irq_controller) {
-		mcp->irq_active_high =
-			device_property_read_bool(dev,
-					      "microchip,irq-active-high");
+		bool irq_active_high = device_property_read_bool(dev,
+						"microchip,irq-active-high");
+		bool irq_open_drain = device_property_read_bool(dev,
+						"microchip,irq-open-drain");
+		if (irq_active_high && irq_open_drain) {
+			dev_err(dev, "microchip,irq-open-drain and "
+				"microchip,irq-active-high are mutually exclusive\n");
+			ret = -EINVAL;
+			goto fail;
+		} else if (irq_active_high) {
+			mcp->irq_regime = MCP_IRQ_PUSH_UP;
+		} else if (irq_open_drain) {
+			mcp->irq_regime = MCP_IRQ_OPEN_DRAIN;
+		}
 
  		mirror = device_property_read_bool(dev, "microchip,irq-mirror");
  	}
 
-	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror ||
-	     mcp->irq_active_high) {
-		/* mcp23s17 has IOCON twice, make sure they are in sync */
-		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
-		status |= IOCON_HAEN | (IOCON_HAEN << 8);
-		if (mcp->irq_active_high)
-			status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
-		else
-			status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
+	/* mcp23s17 has IOCON twice, make sure they are in sync */
+	status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+	status |= IOCON_HAEN | (IOCON_HAEN << 8);
 
-		if (mirror)
-			status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
+	switch (mcp->irq_regime) {
+	case MCP_IRQ_PUSH_UP:
+		status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
+		status &= ~(IOCON_ODR | (IOCON_ODR << 8));
+		break;
+	case MCP_IRQ_PULL_LOW:
+		status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
+		status &= ~(IOCON_ODR | (IOCON_ODR << 8));
+		break;
+	case MCP_IRQ_OPEN_DRAIN:
+		/* ODR overrides INTPOL */
+		status |= IOCON_ODR | (IOCON_ODR << 8);
+		break;
+	}
 
-		if (type == MCP_TYPE_S18 || type == MCP_TYPE_018)
-			status |= IOCON_INTCC | (IOCON_INTCC << 8);
+	if (mirror)
+		status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
 
-		ret = mcp_write(mcp, MCP_IOCON, status);
-		if (ret < 0)
-			goto fail;
-	}
+	if (type == MCP_TYPE_S18 || type == MCP_TYPE_018)
+		status |= IOCON_INTCC | (IOCON_INTCC << 8);
+
+	ret = mcp_write(mcp, MCP_IOCON, status);
+	if (ret < 0)
+		goto fail;
 
  	ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
  	if (ret < 0)
Signature · 2 lines
Regards
Phil Reid
#4 lore raw

Re: [PATCH 1/4] pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

Quoted 2 lines

I submitted a patch for this in November, But haven't followed up on the last review as yet.
See: https://patchwork.ozlabs.org/cover/839923/

Hi Phil, that looks nice. Sorry for duplicating your work. I would have sworn I haven't seen your patch, but I *think* I actually read that IRQ polarity discussion. Strange, perhaps I just forgot that it was about MCP23xxx.

Quoted 2 lines

I used exactly the same dt in my first propsal. But you'll see form the discussions that series This needs to be the standard 'drive-open-drain' flag

I wasn't aware of that one.

Quoted 4 lines

The original code does the same thing.
open drain is active-low.
Sharing can also be achieved by AND / OR gates with push-pull drivers. So no need to treat that differently.

That's a good point. I agree that decoupling the irq-controller's configuration from this chip's IRQ output lane configuration (and hence moving the IRQ_SHARED etc to the DT) makes sense.

My change also writes to the MCP_IOCON unconditionally. For example, the old code would fail if "something" configured the chip for irq-open-drain before the kernel got a chance to run.

Will you have time to re-spin the series anytime soon? I can help if you'd like to.

Cheers,
Jan

A message that is not in the archive (sent off-list or not yet received): 77ac8e65-1742-4e0e-9f96-8445de92c6c6-xoNZbkdr4U2lVyrhU4qvOw@public.gmane.org

#6 lore raw

Re: [PATCH 1/4] pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

Quoted 10 lines · Jan Kundrát
Quoted 2 lines

I submitted a patch for this in November, But haven't followed up on the last review as yet.
See: https://patchwork.ozlabs.org/cover/839923/

Hi Phil, that looks nice. Sorry for duplicating your work. I would have sworn I haven't seen your patch, but I *think* I actually read that IRQ polarity discussion. Strange, perhaps I just forgot that it was about MCP23xxx.

Quoted 2 lines

I used exactly the same dt in my first propsal. But you'll see form the discussions that series This needs to be the standard 'drive-open-drain' flag

I wasn't aware of that one.

Quoted 8 lines
Quoted 4 lines

The original code does the same thing.
open drain is active-low.
Sharing can also be achieved by AND / OR gates with push-pull drivers. So no need to treat that differently.

That's a good point. I agree that decoupling the irq-controller's configuration from this chip's IRQ output lane configuration (and hence moving the IRQ_SHARED etc to the DT) makes sense.

My change also writes to the MCP_IOCON unconditionally. For example, the old code would fail if "something" configured the chip for irq-open-drain before the kernel got a chance to run.

Yeah I don't like that conditional logic for setting the config.
Tricky to change without potentially breaking something as you say.
But if you don't want mirror set and something is setting it before hand then things are broken.

Quoted 3 lines

Will you have time to re-spin the series anytime soon? I can help if you'd like to.

I'll try and respin the open drain bit in the next week or so. The other part of my series is a little more work I think.

Gives me some motivation to have a look at it.

Signature · 7 lines
Regards
Phil Reid

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 9e78a4a697c8d4d3028ea8780bd925471b49af3c.1516997103.git.jan.kundrat-xoNZbkdr4U2lVyrhU4qvOw@public.gmane.org

#8 lore raw

Re: [PATCH 1/4] pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

Quoted 20 lines · Jan Kundrát

The hardware supports three different IRQ modes:
- open drain, i.e., an active-low output which requires an external pull-up and supports IRQ line sharing,
- active low, with push-pull output,
- active high, with push-pull output.

My understanding of electronics is limited, but it is "wrong" to connect different push-pull outpus together. It could sort-of work if the chips/board actually have some resistors there, but it's an ugly thing to do.

In the past, this driver did not touch the ODR bit (for open-drain) operation. During power-on-reset, it is set to zero. Unless some platform code actually set this bit to one, this means that the code never supported open drain operation.

This change makes this handling explicit. If you want sharing of the IRQ line, then use the microchip,irq-open-drain mode and add an external pull-up.

Quoted 8 lines

There's some risk here. If, e.g., the bootloader sets the ODR bit for some reason, the HW shares the IRQ lines, and nobody changes the DT, then your HW will suddenly use push-pull driver for the IRQ line. If there is any other chip on the same lane, the HW might suffer (my chip survived this when I "tested" this by accident with no bootloader code to set the ODR bit).

I'm holding this patch back pending the discussion with Phil and any alternative approach from him.

Just resend it if nothing happens for a while.

I still try to apply the other patches for now (2-4).

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): CACRpkdYPhkOtfMEZeoSu-Zk8AhzghNUx=ooQk21V6f_f9WtLZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#10 lore raw

Re: [PATCH 1/4] pinctrl: mcp23s08: IRQ behavior for open-drain interrupts

Quoted 29 lines · Linus Walleij
Quoted 27 lines · Jan Kundrát

The hardware supports three different IRQ modes:
- open drain, i.e., an active-low output which requires an external pull-up and supports IRQ line sharing,
- active low, with push-pull output,
- active high, with push-pull output.

My understanding of electronics is limited, but it is "wrong" to connect different push-pull outpus together. It could sort-of work if the chips/board actually have some resistors there, but it's an ugly thing to do.

In the past, this driver did not touch the ODR bit (for open-drain) operation. During power-on-reset, it is set to zero. Unless some platform code actually set this bit to one, this means that the code never supported open drain operation.

This change makes this handling explicit. If you want sharing of the IRQ line, then use the microchip,irq-open-drain mode and add an external pull-up.

There's some risk here. If, e.g., the bootloader sets the ODR bit for some reason, the HW shares the IRQ lines, and nobody changes the DT, then your HW will suddenly use push-pull driver for the IRQ line. If there is any other chip on the same lane, the HW might suffer (my chip survived this when I "tested" this by accident with no bootloader code to set the ODR bit).

Quoted 9 lines
Quoted 1 line

I'm holding this patch back pending the discussion with Phil and any alternative approach from him.

Just resend it if nothing happens for a while.

I still try to apply the other patches for now (2-4).

I tried applying patches 2-4 and a couple of other mcp patches to
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/ for-next before resending mine as for-next is a few days behind by the look, to make sure it'd apply ok but didn't have much success.

But my git skills are not up to figuring out what I'm doing wrong. I'll send once I see those patches on a branch.

Signature · 15 lines
Regards
Phil Reid

ElectroMagnetic Imaging Technology Pty Ltd
Development of Geophysical Instrumentation & Software
www.electromag.com.au

3 The Avenue, Midland WA 6056, AUSTRALIA
Ph: +61 8 9250 8100
Fax: +61 8 9250 7100
Email: preid-qgqNFa1JUf/[email protected]
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#11 lore raw

PATCH 2/4 pinctrl: mcp23s08: spi: Fix regmap debugfs entries

In reply to a message not in the archive

The SPI version of this chip allows several devices to be present on the same SPI bus via a local address. If this is in action and if the kernel has debugfs, however, the code attempts to create duplicate entries for the regmap's debugfs:

mcp23s08 spi1.1: Failed to create debugfs directory

This patch simply assigns a local name matching the device logical address to the struct regmap_config.

No changes are needed for MCP23S18 because that device does not support any logical addressing. Similarly, I2C devices do not need any action, either, because they are already different in their I2C address.

A similar problem is present for the pinctrl debugfs instance, but that one is not addressed by this patch.

---
 drivers/pinctrl/pinctrl-mcp23s08.c | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)
drivers/pinctrl/pinctrl-mcp23s08.c +26 -11
index 186101c575e3..8dc758bacdd1 100644
@@ -788,6 +788,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 {
 	int status, ret;
 	bool mirror = false;
+	struct regmap_config *one_regmap_config = NULL;
 
 	mutex_init(&mcp->lock);
 
@@ -808,22 +809,36 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 	switch (type) {
 #ifdef CONFIG_SPI_MASTER
 	case MCP_TYPE_S08:
-		mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
-					       &mcp23x08_regmap);
-		mcp->reg_shift = 0;
-		mcp->chip.ngpio = 8;
-		mcp->chip.label = "mcp23s08";
-		break;
-
 	case MCP_TYPE_S17:
+		switch (type) {
+		case MCP_TYPE_S08:
+			one_regmap_config =
+				devm_kmemdup(dev, &mcp23x08_regmap,
+					sizeof(struct regmap_config), GFP_KERNEL);
+			mcp->reg_shift = 0;
+			mcp->chip.ngpio = 8;
+			mcp->chip.label = "mcp23s08";
+			break;
+		case MCP_TYPE_S17:
+			one_regmap_config =
+				devm_kmemdup(dev, &mcp23x17_regmap,
+					sizeof(struct regmap_config), GFP_KERNEL);
+			mcp->reg_shift = 1;
+			mcp->chip.ngpio = 16;
+			mcp->chip.label = "mcp23s17";
+			break;
+		}
+		if (!one_regmap_config)
+			return -ENOMEM;
+
+		one_regmap_config->name = devm_kasprintf(dev, GFP_KERNEL, "%d", (addr & ~0x40) >> 1);
 		mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
-					       &mcp23x17_regmap);
-		mcp->reg_shift = 1;
-		mcp->chip.ngpio = 16;
-		mcp->chip.label = "mcp23s17";
+					       one_regmap_config);
 		break;
 
 	case MCP_TYPE_S18:
+		if (!one_regmap_config)
+			return -ENOMEM;
 		mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
 					       &mcp23x17_regmap);
 		mcp->reg_shift = 1;
Signature · 7 lines
2.14.3


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): de8fbb7902652b5a512f67e2ee0813571e9d2372.1516997103.git.jan.kundrat-xoNZbkdr4U2lVyrhU4qvOw@public.gmane.org

#13 lore raw

Re: [PATCH 2/4] pinctrl: mcp23s08: spi: Fix regmap debugfs entries

Quoted 10 lines · Jan Kundrát

The SPI version of this chip allows several devices to be present on the same SPI bus via a local address. If this is in action and if the kernel has debugfs, however, the code attempts to create duplicate entries for the regmap's debugfs:

mcp23s08 spi1.1: Failed to create debugfs directory

This patch simply assigns a local name matching the device logical address to the struct regmap_config.

Quoted 8 lines

No changes are needed for MCP23S18 because that device does not support any logical addressing. Similarly, I2C devices do not need any action, either, because they are already different in their I2C address.

A similar problem is present for the pinctrl debugfs instance, but that one is not addressed by this patch.

This looks good and straight-forward.

Patch applied for v4.17.

Hope it doesn't clash with Phil et al's parallel developments.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#14 lore raw

PATCH 3/4 pinctrl: mcp23s08: spi: Add HW address to gpio_chip.label

In reply to Jan Kundrát

When several devices are sharing one hardware SPI CS, there is no visual clue in lsgpio or in /sys/kernel/debug/gpio about which one is which one. Stuff depends on the enumeration order, and therefore lower chip addresses always go first, but that's just an implementation detail. This change includes the device-specific address in the debug output:

gpiochip4: GPIOs 464-479, parent: spi/spi1.1, mcp23s17.2, can sleep:
gpiochip3: GPIOs 480-495, parent: spi/spi1.1, mcp23s17.1, can sleep:

---
 drivers/pinctrl/pinctrl-mcp23s08.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/pinctrl/pinctrl-mcp23s08.c +6 -3
index 8dc758bacdd1..c76c9d4b26c9 100644
@@ -789,6 +789,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 	int status, ret;
 	bool mirror = false;
 	struct regmap_config *one_regmap_config = NULL;
+	int raw_chip_address = (addr & ~0x40) >> 1;
 
 	mutex_init(&mcp->lock);
 
@@ -817,7 +818,8 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 					sizeof(struct regmap_config), GFP_KERNEL);
 			mcp->reg_shift = 0;
 			mcp->chip.ngpio = 8;
-			mcp->chip.label = "mcp23s08";
+			mcp->chip.label = devm_kasprintf(dev, GFP_KERNEL,
+					"mcp23s08.%d", raw_chip_address);
 			break;
 		case MCP_TYPE_S17:
 			one_regmap_config =
@@ -825,13 +827,14 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 					sizeof(struct regmap_config), GFP_KERNEL);
 			mcp->reg_shift = 1;
 			mcp->chip.ngpio = 16;
-			mcp->chip.label = "mcp23s17";
+			mcp->chip.label = devm_kasprintf(dev, GFP_KERNEL,
+					"mcp23s17.%d", raw_chip_address);
 			break;
 		}
 		if (!one_regmap_config)
 			return -ENOMEM;
 
-		one_regmap_config->name = devm_kasprintf(dev, GFP_KERNEL, "%d", (addr & ~0x40) >> 1);
+		one_regmap_config->name = devm_kasprintf(dev, GFP_KERNEL, "%d", raw_chip_address);
 		mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
 					       one_regmap_config);
 		break;
Signature · 1 line
2.14.3
#15 lore raw

Re: [PATCH 3/4] pinctrl: mcp23s08: spi: Add HW address to gpio_chip.label

Quoted 10 lines · Jan Kundrát

When several devices are sharing one hardware SPI CS, there is no visual clue in lsgpio or in /sys/kernel/debug/gpio about which one is which one. Stuff depends on the enumeration order, and therefore lower chip addresses always go first, but that's just an implementation detail. This change includes the device-specific address in the debug output:

gpiochip4: GPIOs 464-479, parent: spi/spi1.1, mcp23s17.2, can sleep:
gpiochip3: GPIOs 480-495, parent: spi/spi1.1, mcp23s17.1, can sleep:

Patch applied.

Yours,
Linus Walleij

#16 lore raw

PATCH 4/4 pinctrl: mcp23s08: spi: Fix duplicate pinctrl debugfs entries

In reply to Jan Kundrát

This is a bit more involved because the pinctrl core so far always assumed that one device (with a unique dev_name) only contains a single pinctrl thing. This is not true for the mcp23s08 driver for chips connected over SPI. They have a "logical address" which means that several chips can share one physical CS signal.

A downside of this patch are some possibly ugly names for the debugfs entries, such as "spi1.1-mcp23xxx-pinctrl.2", etc.

---
 drivers/pinctrl/core.c             | 18 ++++++++++++++++--
 drivers/pinctrl/pinctrl-mcp23s08.c |  9 ++++++++-
 2 files changed, 24 insertions(+), 3 deletions(-)
drivers/pinctrl/core.c +16 -2
index 4c8d5b23e4d0..dc7a77f2f9fe 100644
@@ -1856,9 +1856,23 @@ static struct dentry *debugfs_root;
 static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
 {
 	struct dentry *device_root;
+	const char *debugfs_name;
+
+	if (pctldev->desc->name &&
+			strcmp(dev_name(pctldev->dev), pctldev->desc->name)) {
+		debugfs_name = devm_kasprintf(pctldev->dev, GFP_KERNEL,
+				"%s-%s", dev_name(pctldev->dev),
+				pctldev->desc->name);
+		if (!debugfs_name) {
+			pr_warn("failed to determine debugfs dir name for %s\n",
+				dev_name(pctldev->dev));
+			return;
+		}
+	} else {
+		debugfs_name = dev_name(pctldev->dev);
+	}
 
-	device_root = debugfs_create_dir(dev_name(pctldev->dev),
-					 debugfs_root);
+	device_root = debugfs_create_dir(debugfs_name, debugfs_root);
 	pctldev->device_root = device_root;
 
 	if (IS_ERR(device_root) || !device_root) {
drivers/pinctrl/pinctrl-mcp23s08.c +8 -1
index c76c9d4b26c9..1f3971d02084 100644
@@ -954,7 +954,14 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 			goto fail;
 	}
 
-	mcp->pinctrl_desc.name = "mcp23xxx-pinctrl";
+	if (one_regmap_config) {
+		mcp->pinctrl_desc.name = devm_kasprintf(dev, GFP_KERNEL,
+				"mcp23xxx-pinctrl.%d", raw_chip_address);
+		if (!mcp->pinctrl_desc.name)
+			return -ENOMEM;
+	} else {
+		mcp->pinctrl_desc.name = "mcp23xxx-pinctrl";
+	}
 	mcp->pinctrl_desc.pctlops = &mcp_pinctrl_ops;
 	mcp->pinctrl_desc.confops = &mcp_pinconf_ops;
 	mcp->pinctrl_desc.npins = mcp->chip.ngpio;
Signature · 1 line
2.14.3

A message that is not in the archive (sent off-list or not yet received): e3a251cf48ad518ce4205cfdf2e866e6b3bb76f8.1516997103.git.jan.kundrat-xoNZbkdr4U2lVyrhU4qvOw@public.gmane.org

#18 lore raw

Re: [PATCH 4/4] pinctrl: mcp23s08: spi: Fix duplicate pinctrl debugfs entries

Quoted 10 lines · Jan Kundrát

This is a bit more involved because the pinctrl core so far always assumed that one device (with a unique dev_name) only contains a single pinctrl thing. This is not true for the mcp23s08 driver for chips connected over SPI. They have a "logical address" which means that several chips can share one physical CS signal.

A downside of this patch are some possibly ugly names for the debugfs entries, such as "spi1.1-mcp23xxx-pinctrl.2", etc.

Patch applied with some fuzzing.

I don't know any better approach, it is definately better than what we have today. If people think it is too ugly they can patch it.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html