[PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios

Bartosz Golaszewski posted 2 patches 1 week, 5 days ago
[PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Bartosz Golaszewski 1 week, 5 days ago
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Currently the SPI driver sets up a software node referencing the GPIO
controller exposing the chip-select GPIO but this node never gets
attached to the actual GPIO provider. The lookup uses the weird way GPIO
core performs the software node lookup by the swnode's name. We want to
switch to a true firmware node lookup in GPIO core but without the true
link, this driver will break.

We can't use software nodes as only one software node per device is
allowed and the ACPI node the MFD device uses has a secondary node
already attached.

Let's switch to GPIO machine lookup instead.

Fixes: 439fbc97502a ("spi: cs42l43: Add bridged cs35l56 amplifiers")
Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Closes: https://lore.kernel.org/all/aRyf7qDdHKABppP8@opensource.cirrus.com/
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/mfd/cs42l43.c     | 23 +++++++++++++++++++++++
 drivers/spi/spi-cs42l43.c | 35 -----------------------------------
 2 files changed, 23 insertions(+), 35 deletions(-)

diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c
index 107cfb983fec416bbdd31caa1e6a569026467735..098b95a21b38158b5ea765ad55fdcf703a2454c0 100644
--- a/drivers/mfd/cs42l43.c
+++ b/drivers/mfd/cs42l43.c
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/firmware.h>
 #include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
 #include <linux/jiffies.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/cs42l43.h>
@@ -522,6 +523,15 @@ static const struct mfd_cell cs42l43_devs[] = {
 	},
 };
 
+static struct gpiod_lookup_table cs42l43_gpio_lookup = {
+	.dev_id = "cs42l43-spi",
+	.table = {
+		GPIO_LOOKUP("cs42l43-pinctrl", 0, "cs", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP(INIT_ERR_PTR(-ENOENT), 0, "cs", 0),
+		{ }
+	},
+};
+
 /*
  * If the device is connected over Soundwire, as well as soft resetting the
  * device, this function will also way for the device to detach from the bus
@@ -900,6 +910,11 @@ static int cs42l43_irq_config(struct cs42l43 *cs42l43)
 	return 0;
 }
 
+static void cs42l43_remove_gpio_lookup(void *data)
+{
+	gpiod_remove_lookup_table(&cs42l43_gpio_lookup);
+}
+
 static void cs42l43_boot_work(struct work_struct *work)
 {
 	struct cs42l43 *cs42l43 = container_of(work, struct cs42l43, boot_work);
@@ -954,6 +969,14 @@ static void cs42l43_boot_work(struct work_struct *work)
 	if (ret)
 		goto err;
 
+	gpiod_add_lookup_table(&cs42l43_gpio_lookup);
+
+	ret = devm_add_action_or_reset(cs42l43->dev, cs42l43_remove_gpio_lookup, NULL);
+	if (ret) {
+		dev_err(cs42l43->dev, "Failed to schedule a devres action: %d\n", ret);
+		goto err;
+	}
+
 	ret = devm_mfd_add_devices(cs42l43->dev, PLATFORM_DEVID_NONE,
 				   cs42l43_devs, ARRAY_SIZE(cs42l43_devs),
 				   NULL, 0, NULL);
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c
index 14307dd800b744fee17edd864688a68c65666c68..7430a1ba829cbd68d4bfdb1cf9cf8fa7a1cf23a6 100644
--- a/drivers/spi/spi-cs42l43.c
+++ b/drivers/spi/spi-cs42l43.c
@@ -13,8 +13,6 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
-#include <linux/gpio/property.h>
 #include <linux/mfd/cs42l43.h>
 #include <linux/mfd/cs42l43-regs.h>
 #include <linux/mod_devicetable.h>
@@ -52,20 +50,6 @@ static struct spi_board_info amp_info_template = {
 	.mode			= SPI_MODE_0,
 };
 
-static const struct software_node cs42l43_gpiochip_swnode = {
-	.name			= "cs42l43-pinctrl",
-};
-
-static const struct software_node_ref_args cs42l43_cs_refs[] = {
-	SOFTWARE_NODE_REFERENCE(&cs42l43_gpiochip_swnode, 0, GPIO_ACTIVE_LOW),
-	SOFTWARE_NODE_REFERENCE(&swnode_gpio_undefined),
-};
-
-static const struct property_entry cs42l43_cs_props[] = {
-	PROPERTY_ENTRY_REF_ARRAY("cs-gpios", cs42l43_cs_refs),
-	{}
-};
-
 static int cs42l43_spi_tx(struct regmap *regmap, const u8 *buf, unsigned int len)
 {
 	const u8 *end = buf + len;
@@ -324,11 +308,6 @@ static void cs42l43_release_of_node(void *data)
 	fwnode_handle_put(data);
 }
 
-static void cs42l43_release_sw_node(void *data)
-{
-	software_node_unregister(&cs42l43_gpiochip_swnode);
-}
-
 static int cs42l43_spi_probe(struct platform_device *pdev)
 {
 	struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
@@ -402,20 +381,6 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
 				return dev_err_probe(priv->dev, ret,
 						     "Failed to get spk-id-gpios\n");
 		}
-
-		ret = software_node_register(&cs42l43_gpiochip_swnode);
-		if (ret)
-			return dev_err_probe(priv->dev, ret,
-					     "Failed to register gpio swnode\n");
-
-		ret = devm_add_action_or_reset(priv->dev, cs42l43_release_sw_node, NULL);
-		if (ret)
-			return ret;
-
-		ret = device_create_managed_software_node(&priv->ctlr->dev,
-							  cs42l43_cs_props, NULL);
-		if (ret)
-			return dev_err_probe(priv->dev, ret, "Failed to add swnode\n");
 	} else {
 		device_set_node(&priv->ctlr->dev, fwnode);
 	}

-- 
2.51.0
Re: [PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Bartosz Golaszewski 1 week, 5 days ago
On Wed, Nov 19, 2025 at 4:21 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Currently the SPI driver sets up a software node referencing the GPIO
> controller exposing the chip-select GPIO but this node never gets
> attached to the actual GPIO provider. The lookup uses the weird way GPIO
> core performs the software node lookup by the swnode's name. We want to
> switch to a true firmware node lookup in GPIO core but without the true
> link, this driver will break.
>
> We can't use software nodes as only one software node per device is
> allowed and the ACPI node the MFD device uses has a secondary node
> already attached.
>
> Let's switch to GPIO machine lookup instead.
>
> Fixes: 439fbc97502a ("spi: cs42l43: Add bridged cs35l56 amplifiers")
> Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> Closes: https://lore.kernel.org/all/aRyf7qDdHKABppP8@opensource.cirrus.com/
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
>
> +static struct gpiod_lookup_table cs42l43_gpio_lookup = {
> +       .dev_id = "cs42l43-spi",
> +       .table = {
> +               GPIO_LOOKUP("cs42l43-pinctrl", 0, "cs", GPIO_ACTIVE_LOW),
> +               GPIO_LOOKUP(INIT_ERR_PTR(-ENOENT), 0, "cs", 0),

I sent the wrong version, sorry. This should have been:

GPIO_LOOKUP_IDX("cs42l43-pinctrl", 0, "cs", 0, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(INIT_ERR_PTR(-ENOENT), 0, "cs", 1, 0),

Charles: Can you fix it up yourself before testing?

Bart
Re: [PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Charles Keepax 1 week, 5 days ago
On Wed, Nov 19, 2025 at 04:35:07PM +0100, Bartosz Golaszewski wrote:
> On Wed, Nov 19, 2025 at 4:21 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> >
> > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> >
> > Currently the SPI driver sets up a software node referencing the GPIO
> > controller exposing the chip-select GPIO but this node never gets
> > attached to the actual GPIO provider. The lookup uses the weird way GPIO
> > core performs the software node lookup by the swnode's name. We want to
> > switch to a true firmware node lookup in GPIO core but without the true
> > link, this driver will break.
> >
> > We can't use software nodes as only one software node per device is
> > allowed and the ACPI node the MFD device uses has a secondary node
> > already attached.
> >
> > Let's switch to GPIO machine lookup instead.
> >
> > Fixes: 439fbc97502a ("spi: cs42l43: Add bridged cs35l56 amplifiers")
> > Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> > Closes: https://lore.kernel.org/all/aRyf7qDdHKABppP8@opensource.cirrus.com/
> > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> > ---
> >
> > +static struct gpiod_lookup_table cs42l43_gpio_lookup = {
> > +       .dev_id = "cs42l43-spi",
> > +       .table = {
> > +               GPIO_LOOKUP("cs42l43-pinctrl", 0, "cs", GPIO_ACTIVE_LOW),
> > +               GPIO_LOOKUP(INIT_ERR_PTR(-ENOENT), 0, "cs", 0),
> 
> I sent the wrong version, sorry. This should have been:
> 
> GPIO_LOOKUP_IDX("cs42l43-pinctrl", 0, "cs", 0, GPIO_ACTIVE_LOW),
> GPIO_LOOKUP_IDX(INIT_ERR_PTR(-ENOENT), 0, "cs", 1, 0),
> 
> Charles: Can you fix it up yourself before testing?

Yeah can do, but I am still very nervous about how this approach
interacts with device tree and ACPI systems doing things
normally. Is this also ignored if the firmware specifies the
properties correctly? I feel like if we go this route I am going
to have to bring up a few extra things to test on as its quite a
big change.

Apologies for the delay on my suggestion but something weird is
happening deep in the swnode stuff and its taking me ages to peel
back all the layers of in abstraction there. It seems something
copies all the properties and somehow the fwnode I want doesn't
make it through that process. But the basic idea is like:

props = devm_kmemdup(priv->dev, cs42l43_cs_props,
		     sizeof(cs42l43_cs_props), GFP_KERNEL);
if (!props)
	return -ENOMEM;

args = devm_kmemdup(priv->dev, cs42l43_cs_refs,
		    sizeof(cs42l43_cs_refs), GFP_KERNEL);
if (!args)
	return -ENOMEM;

args[0].fwnode = fwnode;
props->pointer = props;

ie. As your patches add support for using the geniune firmware
node just do so.

Thanks,
Charles
Re: [PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Bartosz Golaszewski 1 week, 5 days ago
On Wed, Nov 19, 2025 at 4:52 PM Charles Keepax
<ckeepax@opensource.cirrus.com> wrote:
>
> On Wed, Nov 19, 2025 at 04:35:07PM +0100, Bartosz Golaszewski wrote:
> > On Wed, Nov 19, 2025 at 4:21 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > >
> > > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> > >
> > > Currently the SPI driver sets up a software node referencing the GPIO
> > > controller exposing the chip-select GPIO but this node never gets
> > > attached to the actual GPIO provider. The lookup uses the weird way GPIO
> > > core performs the software node lookup by the swnode's name. We want to
> > > switch to a true firmware node lookup in GPIO core but without the true
> > > link, this driver will break.
> > >
> > > We can't use software nodes as only one software node per device is
> > > allowed and the ACPI node the MFD device uses has a secondary node
> > > already attached.
> > >
> > > Let's switch to GPIO machine lookup instead.
> > >
> > > Fixes: 439fbc97502a ("spi: cs42l43: Add bridged cs35l56 amplifiers")
> > > Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> > > Closes: https://lore.kernel.org/all/aRyf7qDdHKABppP8@opensource.cirrus.com/
> > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> > > ---
> > >
> > > +static struct gpiod_lookup_table cs42l43_gpio_lookup = {
> > > +       .dev_id = "cs42l43-spi",
> > > +       .table = {
> > > +               GPIO_LOOKUP("cs42l43-pinctrl", 0, "cs", GPIO_ACTIVE_LOW),
> > > +               GPIO_LOOKUP(INIT_ERR_PTR(-ENOENT), 0, "cs", 0),
> >
> > I sent the wrong version, sorry. This should have been:
> >
> > GPIO_LOOKUP_IDX("cs42l43-pinctrl", 0, "cs", 0, GPIO_ACTIVE_LOW),
> > GPIO_LOOKUP_IDX(INIT_ERR_PTR(-ENOENT), 0, "cs", 1, 0),
> >
> > Charles: Can you fix it up yourself before testing?
>
> Yeah can do, but I am still very nervous about how this approach
> interacts with device tree and ACPI systems doing things
> normally. Is this also ignored if the firmware specifies the
> properties correctly? I feel like if we go this route I am going
> to have to bring up a few extra things to test on as its quite a
> big change.
>

The machine lookup always comes after the firmware node lookup. Even
after the secondary node. It's the last-ditch effort to find a match
actually.

> Apologies for the delay on my suggestion but something weird is
> happening deep in the swnode stuff and its taking me ages to peel
> back all the layers of in abstraction there. It seems something
> copies all the properties and somehow the fwnode I want doesn't
> make it through that process. But the basic idea is like:
>
> props = devm_kmemdup(priv->dev, cs42l43_cs_props,
>                      sizeof(cs42l43_cs_props), GFP_KERNEL);
> if (!props)
>         return -ENOMEM;
>
> args = devm_kmemdup(priv->dev, cs42l43_cs_refs,
>                     sizeof(cs42l43_cs_refs), GFP_KERNEL);
> if (!args)
>         return -ENOMEM;
>
> args[0].fwnode = fwnode;
> props->pointer = props;
>
> ie. As your patches add support for using the geniune firmware
> node just do so.
>

But do you have the firmware node at the time of doing the above? The
software node must first be registered with the swnode subsystem to
become an actual firmware node. Only then can you reference it by its
firmware node address.

Bart
Re: [PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Charles Keepax 1 week, 5 days ago
On Wed, Nov 19, 2025 at 05:28:54PM +0100, Bartosz Golaszewski wrote:
> On Wed, Nov 19, 2025 at 4:52 PM Charles Keepax
> <ckeepax@opensource.cirrus.com> wrote:
> > On Wed, Nov 19, 2025 at 04:35:07PM +0100, Bartosz Golaszewski wrote:
> > > On Wed, Nov 19, 2025 at 4:21 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > props = devm_kmemdup(priv->dev, cs42l43_cs_props,
> >                      sizeof(cs42l43_cs_props), GFP_KERNEL);
> > if (!props)
> >         return -ENOMEM;
> >
> > args = devm_kmemdup(priv->dev, cs42l43_cs_refs,
> >                     sizeof(cs42l43_cs_refs), GFP_KERNEL);
> > if (!args)
> >         return -ENOMEM;
> >
> > args[0].fwnode = fwnode;
> > props->pointer = props;
> >
> > ie. As your patches add support for using the geniune firmware
> > node just do so.
> >
> 
> But do you have the firmware node at the time of doing the above? The
> software node must first be registered with the swnode subsystem to
> become an actual firmware node. Only then can you reference it by its
> firmware node address.

The firmware node here isn't referring to a software node it is
referring to the actual ACPI node. As in we are now correctly
specifying the GPIO using the ACPI node rather than depending on
the name based lookup to find the driver. The problem was before
your patches we couldn't do that as it wasn't possible.

I have sent a patch for you guys to have a look at and see what
you think. I am slightly inclined to favour that approach since
it changes a lot less about the system and once we are no longer
relying on name based look up I think everything the driver is
doing is all above board and legit.

Thanks,
Charels
Re: [PATCH RFT/RFC 2/2] mfd: cs42l43: use GPIO machine lookup for cs-gpios
Posted by Charles Keepax 1 week, 5 days ago
On Wed, Nov 19, 2025 at 03:52:01PM +0000, Charles Keepax wrote:
> On Wed, Nov 19, 2025 at 04:35:07PM +0100, Bartosz Golaszewski wrote:
> > On Wed, Nov 19, 2025 at 4:21 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> > >
> > > Currently the SPI driver sets up a software node referencing the GPIO
> > > controller exposing the chip-select GPIO but this node never gets
> > > attached to the actual GPIO provider. The lookup uses the weird way GPIO
> > > core performs the software node lookup by the swnode's name. We want to
> > > switch to a true firmware node lookup in GPIO core but without the true
> > > link, this driver will break.
> > >
> > > We can't use software nodes as only one software node per device is
> > > allowed and the ACPI node the MFD device uses has a secondary node
> > > already attached.
> > >
> > > Let's switch to GPIO machine lookup instead.
> > >
> > > Fixes: 439fbc97502a ("spi: cs42l43: Add bridged cs35l56 amplifiers")
> > > Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> > > Closes: https://lore.kernel.org/all/aRyf7qDdHKABppP8@opensource.cirrus.com/
> > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> > > ---
> > >
> > > +static struct gpiod_lookup_table cs42l43_gpio_lookup = {
> > > +       .dev_id = "cs42l43-spi",
> > > +       .table = {
> > > +               GPIO_LOOKUP("cs42l43-pinctrl", 0, "cs", GPIO_ACTIVE_LOW),
> > > +               GPIO_LOOKUP(INIT_ERR_PTR(-ENOENT), 0, "cs", 0),
> > 
> > I sent the wrong version, sorry. This should have been:
> > 
> > GPIO_LOOKUP_IDX("cs42l43-pinctrl", 0, "cs", 0, GPIO_ACTIVE_LOW),
> > GPIO_LOOKUP_IDX(INIT_ERR_PTR(-ENOENT), 0, "cs", 1, 0),
> > 
> > Charles: Can you fix it up yourself before testing?
> 
> Yeah can do, but I am still very nervous about how this approach
> interacts with device tree and ACPI systems doing things
> normally. Is this also ignored if the firmware specifies the
> properties correctly? I feel like if we go this route I am going
> to have to bring up a few extra things to test on as its quite a
> big change.
> 
> Apologies for the delay on my suggestion but something weird is
> happening deep in the swnode stuff and its taking me ages to peel
> back all the layers of in abstraction there. It seems something
> copies all the properties and somehow the fwnode I want doesn't
> make it through that process. But the basic idea is like:
> 
> props = devm_kmemdup(priv->dev, cs42l43_cs_props,
> 		     sizeof(cs42l43_cs_props), GFP_KERNEL);
> if (!props)
> 	return -ENOMEM;
> 
> args = devm_kmemdup(priv->dev, cs42l43_cs_refs,
> 		    sizeof(cs42l43_cs_refs), GFP_KERNEL);
> if (!args)
> 	return -ENOMEM;
> 
> args[0].fwnode = fwnode;
> props->pointer = props;

blargh... and of course that should be = args;

Thanks,
Charles