[PATCH v5 2/2] platform/x86: x86-android-tablets: enable fwnode matching of GPIO chips

From: Bartosz Golaszewski

Date: Mon May 04 2026 - 07:00:16 EST


In order to allow GPIOLIB to match cherryview and baytrail GPIO
controllers by their firmware nodes instead of their names, we need to
attach the - currently "dangling" - existing software nodes to their
target devices dynamically.

The driver uses platform_create_bundle() and expects all required
providers to be present before it itself is probed. We know the name of
the device we're waiting for so look them up and assign the appropriate
software node as the secondary firmware node of the underlying ACPI node.

Scheduling fine-grained devres actions allows for proper teardown and
unsetting of the secondary firmware nodes.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
---
drivers/platform/x86/x86-android-tablets/core.c | 63 +++++++++++++++++++++++--
1 file changed, 60 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c
index 021009e9085bec3db9c4daa1f6235600210a6099..4126b49e7d07b64ab9cdb876326c315f9a73b16c 100644
--- a/drivers/platform/x86/x86-android-tablets/core.c
+++ b/drivers/platform/x86/x86-android-tablets/core.c
@@ -13,6 +13,7 @@
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/dmi.h>
+#include <linux/fwnode.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/irq.h>
@@ -360,6 +361,61 @@ static const struct software_node *cherryview_gpiochip_node_group[] = {
NULL
};

+static void gpio_secondary_unset(void *data)
+{
+ struct device *dev = data;
+
+ set_secondary_fwnode(dev, NULL);
+}
+
+static void gpio_secondary_unregister_node_group(void *data)
+{
+ const struct software_node **nodes = data;
+
+ software_node_unregister_node_group(nodes);
+}
+
+static int gpio_secondary_fwnode_init(struct device *parent)
+{
+ const struct software_node *const *swnode;
+ struct fwnode_handle *fwnode;
+ int ret;
+
+ if (!gpiochip_node_group)
+ return 0;
+
+ ret = software_node_register_node_group(gpiochip_node_group);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(parent,
+ gpio_secondary_unregister_node_group,
+ gpiochip_node_group);
+ if (ret)
+ return ret;
+
+ for (swnode = gpiochip_node_group; *swnode; swnode++) {
+ struct device *dev __free(put_device) =
+ acpi_bus_find_device_by_name((*swnode)->name);
+ if (!dev)
+ return dev_err_probe(parent,
+ -ENODEV, "Failed to find the required GPIO controller: %s\n",
+ (*swnode)->name);
+
+ fwnode = software_node_fwnode(*swnode);
+ if (WARN_ON(!fwnode))
+ return -ENOENT;
+
+ set_secondary_fwnode(dev, fwnode);
+
+ ret = devm_add_action_or_reset(parent, gpio_secondary_unset, dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static void x86_android_tablet_remove(struct platform_device *pdev)
{
int i;
@@ -391,7 +447,6 @@ static void x86_android_tablet_remove(struct platform_device *pdev)

software_node_unregister_node_group(gpio_button_swnodes);
software_node_unregister_node_group(swnode_group);
- software_node_unregister_node_group(gpiochip_node_group);
}

static __init int x86_android_tablet_probe(struct platform_device *pdev)
@@ -427,9 +482,11 @@ static __init int x86_android_tablet_probe(struct platform_device *pdev)
break;
}

- ret = software_node_register_node_group(gpiochip_node_group);
- if (ret)
+ ret = gpio_secondary_fwnode_init(&pdev->dev);
+ if (ret) {
+ x86_android_tablet_remove(pdev);
return ret;
+ }

ret = software_node_register_node_group(dev_info->swnode_group);
if (ret) {

--
2.47.3