]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
MIPS: alchemy: mtx1: attach software nodes to GPIO chips
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 26 May 2026 16:40:34 +0000 (18:40 +0200)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Wed, 27 May 2026 07:52:35 +0000 (09:52 +0200)
GPIO subsystem is switching the way it locates GPIO chip instances for
GPIO references in software nodes from matching on node names to
identity matching, which necessitates assigning firmware nodes
(software nodes) to GPIO chips.

Move the node definitions for alchemy-gpio1 and alchemy-gpio2 to
arch/misp/alchemy/common/gpiolib.c, register them there, and attach
them to gpio_chip instances. Adjust MTX1 board file to use these nodes.

Note that because nodes need to be registered before they can be used in
PROPERTY_ENTRY_GPIO() we have to do the registration at
postcore_initcall level, otherwise (due to the link order) MTX1 board
initialization code will run first.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
[Bartosz: use platform_device_info::swnode]
Tested-by: Manuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
arch/mips/alchemy/board-mtx1.c
arch/mips/alchemy/common/gpiolib.c
arch/mips/include/asm/mach-au1x00/gpio-au1000.h

index cb6be58808a08e667a401573d6ba515d70a58aa2..88c20c0ca96d4fc8511c214e3d6dd2c820c8eaaa 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/gpio/machine.h>
 #include <linux/gpio/property.h>
 #include <linux/input.h>
@@ -78,17 +79,13 @@ void __init board_setup(void)
 
 /******************************************************************************/
 
-static const struct software_node mtx1_gpiochip_node = {
-       .name = "alchemy-gpio2",
-};
-
 static const struct software_node mtx1_gpio_keys_node = {
        .name = "mtx1-gpio-keys",
 };
 
 static const struct property_entry mtx1_button_props[] = {
        PROPERTY_ENTRY_U32("linux,code", BTN_0),
-       PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 7, GPIO_ACTIVE_HIGH),
+       PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 7, GPIO_ACTIVE_HIGH),
        PROPERTY_ENTRY_STRING("label", "System button"),
        { }
 };
@@ -98,7 +95,7 @@ static const struct software_node mtx1_button_node = {
        .properties = mtx1_button_props,
 };
 
-static const struct software_node *mtx1_gpio_keys_swnodes[] __initconst = {
+static const struct software_node * const mtx1_gpio_keys_swnodes[] __initconst = {
        &mtx1_gpio_keys_node,
        &mtx1_button_node,
        NULL
@@ -127,13 +124,13 @@ static void __init mtx1_keys_init(void)
                pr_err("failed to create gpio-keys device: %d\n", err);
 }
 
-/* Global number 215 is offset 15 on Alchemy GPIO 2 */
 static const struct property_entry mtx1_wdt_props[] = {
-       PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 15, GPIO_ACTIVE_HIGH),
+       /* Global number 215 is offset 15 on Alchemy GPIO 2 */
+       PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 15, GPIO_ACTIVE_HIGH),
        { }
 };
 
-static struct platform_device_info mtx1_wdt_info __initconst = {
+static const struct platform_device_info mtx1_wdt_info __initconst = {
        .name = "mtx1-wdt",
        .id = 0,
        .properties = mtx1_wdt_props,
@@ -147,7 +144,7 @@ static void __init mtx1_wdt_init(void)
        pd = platform_device_register_full(&mtx1_wdt_info);
        err = PTR_ERR_OR_ZERO(pd);
        if (err)
-               pr_err("failed to create gpio-keys device: %d\n", err);
+               pr_err("failed to create watchdog device: %d\n", err);
 }
 
 static const struct software_node mtx1_gpio_leds_node = {
@@ -155,7 +152,7 @@ static const struct software_node mtx1_gpio_leds_node = {
 };
 
 static const struct property_entry mtx1_green_led_props[] = {
-       PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 11, GPIO_ACTIVE_HIGH),
+       PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 11, GPIO_ACTIVE_HIGH),
        { }
 };
 
@@ -166,7 +163,7 @@ static const struct software_node mtx1_green_led_node = {
 };
 
 static const struct property_entry mtx1_red_led_props[] = {
-       PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 12, GPIO_ACTIVE_HIGH),
+       PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 12, GPIO_ACTIVE_HIGH),
        { }
 };
 
@@ -176,7 +173,7 @@ static const struct software_node mtx1_red_led_node = {
        .properties = mtx1_red_led_props,
 };
 
-static const struct software_node *mtx1_gpio_leds_swnodes[] = {
+static const struct software_node * const mtx1_gpio_leds_swnodes[] __initconst = {
        &mtx1_gpio_leds_node,
        &mtx1_green_led_node,
        &mtx1_red_led_node,
@@ -185,9 +182,10 @@ static const struct software_node *mtx1_gpio_leds_swnodes[] = {
 
 static void __init mtx1_leds_init(void)
 {
-       struct platform_device_info led_info = {
+       const struct platform_device_info pdevinfo = {
                .name   = "leds-gpio",
                .id     = PLATFORM_DEVID_NONE,
+               .swnode = &mtx1_gpio_leds_node,
        };
        struct platform_device *led_dev;
        int err;
@@ -198,9 +196,7 @@ static void __init mtx1_leds_init(void)
                return;
        }
 
-       led_info.fwnode = software_node_fwnode(&mtx1_gpio_leds_node);
-
-       led_dev = platform_device_register_full(&led_info);
+       led_dev = platform_device_register_full(&pdevinfo);
        err = PTR_ERR_OR_ZERO(led_dev);
        if (err)
                pr_err("failed to create LED device: %d\n", err);
@@ -335,10 +331,6 @@ static int __init mtx1_register_devices(void)
 
        au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);
 
-       rc = software_node_register(&mtx1_gpiochip_node);
-       if (rc)
-               return rc;
-
        rc = platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
        if (rc)
                return rc;
index e79e26ffac99e6b12b430ab60df1cc7d42afd4a8..2141eae5ce4502aad920333cba1f7a6e08411f9e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/property.h>
 #include <linux/types.h>
 #include <linux/gpio/driver.h>
 #include <asm/mach-au1x00/gpio-au1000.h>
@@ -95,7 +96,21 @@ static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
        return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
 }
 
-struct gpio_chip alchemy_gpio_chip[] = {
+const struct software_node alchemy_gpio1_node = {
+       .name = "alchemy-gpio1",
+};
+
+const struct software_node alchemy_gpio2_node = {
+       .name = "alchemy-gpio2",
+};
+
+static const struct software_node *alchemy_gpio_node_group[] = {
+       &alchemy_gpio1_node,
+       &alchemy_gpio2_node,
+       NULL
+};
+
+static struct gpio_chip alchemy_gpio_chip[] = {
        [0] = {
                .label                  = "alchemy-gpio1",
                .direction_input        = gpio1_direction_input,
@@ -157,6 +172,28 @@ static struct gpio_chip au1300_gpiochip = {
        .ngpio                  = AU1300_GPIO_NUM,
 };
 
+/*
+ * Software nodes must be registered before board-specific code (that runs
+ * at arch_initcall level) attempts to use them as GPIO targets or as fwnodes
+ * for registered devices. We can not do registration in alchemy_gpiochip_init
+ * because it also runs as arch_initcall and runs after board-specific code
+ * because of the link order, and so we do it at postcore_initcall level.
+ */
+static int __init alchemy_gpio_nodes_init(void)
+{
+       int ret;
+
+       ret = software_node_register_node_group(alchemy_gpio_node_group);
+       if (ret)
+               return ret;
+
+       alchemy_gpio_chip[0].fwnode = software_node_fwnode(&alchemy_gpio1_node);
+       alchemy_gpio_chip[1].fwnode = software_node_fwnode(&alchemy_gpio2_node);
+
+       return 0;
+}
+postcore_initcall(alchemy_gpio_nodes_init);
+
 static int __init alchemy_gpiochip_init(void)
 {
        int ret = 0;
index e6306f6820e64e193b1be5e258211cca509edaa6..de7f857cb333a209c43fd6ca7198d2aa988c0bd7 100644 (file)
 #define AU1000_GPIO2_INTENABLE 0x10
 #define AU1000_GPIO2_ENABLE    0x14
 
+struct software_node;
+
+extern const struct software_node alchemy_gpio1_node;
+extern const struct software_node alchemy_gpio2_node;
+
 static inline int au1000_gpio1_to_irq(int gpio)
 {
        return MAKE_IRQ(1, gpio - ALCHEMY_GPIO1_BASE);