* [PATCH 1/4] MIPS: alchemy: mtx1: attach software nodes to GPIO chips
2026-03-10 6:11 [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Dmitry Torokhov
@ 2026-03-10 6:11 ` Dmitry Torokhov
2026-03-10 6:11 ` [PATCH 2/4] MIPS: alchemy: db1000: use nodes attached to GPIO chips in properties Dmitry Torokhov
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-03-10 6:11 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
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>
---
arch/mips/alchemy/board-mtx1.c | 79 +++++++++++--------------
arch/mips/alchemy/common/gpiolib.c | 39 +++++++++++-
arch/mips/include/asm/mach-au1x00/gpio-au1000.h | 4 ++
3 files changed, 75 insertions(+), 47 deletions(-)
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index cb6be58808a0..740b38c0b81e 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -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,27 +79,22 @@ 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_STRING("label", "System button"),
- { }
-};
-
static const struct software_node mtx1_button_node = {
.parent = &mtx1_gpio_keys_node,
- .properties = mtx1_button_props,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", BTN_0),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 7,
+ GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_STRING("label", "System button"),
+ { }
+ },
};
-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,16 +123,15 @@ 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),
- { }
-};
-
-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,
+ .properties = (const struct property_entry[]){
+ /* Global number 215 is offset 15 on Alchemy GPIO 2 */
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 15,
+ GPIO_ACTIVE_HIGH),
+ { }
+ },
};
static void __init mtx1_wdt_init(void)
@@ -147,36 +142,34 @@ 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 = {
.name = "mtx1-leds",
};
-static const struct property_entry mtx1_green_led_props[] = {
- PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 11, GPIO_ACTIVE_HIGH),
- { }
-};
-
static const struct software_node mtx1_green_led_node = {
.name = "mtx1:green",
.parent = &mtx1_gpio_leds_node,
- .properties = mtx1_green_led_props,
-};
-
-static const struct property_entry mtx1_red_led_props[] = {
- PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 12, GPIO_ACTIVE_HIGH),
- { }
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 11,
+ GPIO_ACTIVE_HIGH),
+ { }
+ },
};
static const struct software_node mtx1_red_led_node = {
.name = "mtx1:red",
.parent = &mtx1_gpio_leds_node,
- .properties = mtx1_red_led_props,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpio2_node, 12,
+ GPIO_ACTIVE_HIGH),
+ { }
+ },
};
-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,10 +178,6 @@ static const struct software_node *mtx1_gpio_leds_swnodes[] = {
static void __init mtx1_leds_init(void)
{
- struct platform_device_info led_info = {
- .name = "leds-gpio",
- .id = PLATFORM_DEVID_NONE,
- };
struct platform_device *led_dev;
int err;
@@ -198,9 +187,11 @@ 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(&(struct platform_device_info){
+ .name = "leds-gpio",
+ .id = PLATFORM_DEVID_NONE,
+ .fwnode = software_node_fwnode(&mtx1_gpio_leds_node),
+ });
err = PTR_ERR_OR_ZERO(led_dev);
if (err)
pr_err("failed to create LED device: %d\n", err);
@@ -335,10 +326,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;
diff --git a/arch/mips/alchemy/common/gpiolib.c b/arch/mips/alchemy/common/gpiolib.c
index e79e26ffac99..2141eae5ce45 100644
--- a/arch/mips/alchemy/common/gpiolib.c
+++ b/arch/mips/alchemy/common/gpiolib.c
@@ -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;
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
index d820b481ac56..a0eebc24c4a8 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
@@ -41,6 +41,10 @@
#define AU1000_GPIO2_ENABLE 0x14
struct gpio;
+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)
{
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 2/4] MIPS: alchemy: db1000: use nodes attached to GPIO chips in properties
2026-03-10 6:11 [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Dmitry Torokhov
2026-03-10 6:11 ` [PATCH 1/4] MIPS: alchemy: mtx1: attach software nodes to GPIO chips Dmitry Torokhov
@ 2026-03-10 6:11 ` Dmitry Torokhov
2026-03-10 6:12 ` [PATCH 3/4] MIPS: alchemy: gpr: switch to static device properties Dmitry Torokhov
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-03-10 6:11 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
GPIO subsystem is switching the way it locates GPIO chip instances for
GPIO references in software nodes by doing identity matching instead of
matching on node names. Switch to using software nodes attached to gpio
chips instead of using freestanding software nodes.
Also stop supplying platform data for the spi-gpio controller since
spi-gpio driver can derive number of chipselect lines from device
properties.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
arch/mips/alchemy/devboards/db1000.c | 36 +++++++++++-------------------------
1 file changed, 11 insertions(+), 25 deletions(-)
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 6984cd5169b5..d9dffacc5f5a 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -19,7 +19,6 @@
#include <linux/property.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
-#include <linux/spi/spi_gpio.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/au1000_dma.h>
@@ -375,20 +374,14 @@ static struct platform_device db1100_mmc1_dev = {
/******************************************************************************/
-static const struct software_node db1100_alchemy2_gpiochip = {
- .name = "alchemy-gpio2",
-};
-
-static const struct property_entry db1100_ads7846_properties[] = {
- PROPERTY_ENTRY_U16("ti,vref_min", 3300),
- PROPERTY_ENTRY_GPIO("pendown-gpios",
- &db1100_alchemy2_gpiochip, 21, GPIO_ACTIVE_LOW),
- { }
-};
-
static const struct software_node db1100_ads7846_swnode = {
.name = "ads7846",
- .properties = db1100_ads7846_properties,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U16("ti,vref_min", 3300),
+ PROPERTY_ENTRY_GPIO("pendown-gpios",
+ &alchemy_gpio2_node, 21, GPIO_ACTIVE_LOW),
+ { }
+ },
};
static struct spi_board_info db1100_spi_info[] __initdata = {
@@ -403,32 +396,26 @@ static struct spi_board_info db1100_spi_info[] __initdata = {
},
};
-static const struct spi_gpio_platform_data db1100_spictl_pd __initconst = {
- .num_chipselect = 1,
-};
-
/*
* Alchemy GPIO 2 has its base at 200 so the GPIO lines
* 207 thru 210 are GPIOs at offset 7 thru 10 at this chip.
*/
static const struct property_entry db1100_spi_dev_properties[] __initconst = {
PROPERTY_ENTRY_GPIO("miso-gpios",
- &db1100_alchemy2_gpiochip, 7, GPIO_ACTIVE_HIGH),
+ &alchemy_gpio2_node, 7, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("mosi-gpios",
- &db1100_alchemy2_gpiochip, 8, GPIO_ACTIVE_HIGH),
+ &alchemy_gpio2_node, 8, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("sck-gpios",
- &db1100_alchemy2_gpiochip, 9, GPIO_ACTIVE_HIGH),
+ &alchemy_gpio2_node, 9, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("cs-gpios",
- &db1100_alchemy2_gpiochip, 10, GPIO_ACTIVE_HIGH),
+ &alchemy_gpio2_node, 10, GPIO_ACTIVE_HIGH),
{ }
};
static const struct platform_device_info db1100_spi_dev_info __initconst = {
.name = "spi_gpio",
.id = 0,
- .data = &db1100_spictl_pd,
- .size_data = sizeof(db1100_spictl_pd),
- .dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = DMA_BIT_MASK(32),
.properties = db1100_spi_dev_properties,
};
@@ -481,7 +468,6 @@ int __init db1000_dev_setup(void)
pfc |= (1 << 0); /* SSI0 pins as GPIOs */
alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
- software_node_register(&db1100_alchemy2_gpiochip);
spi_register_board_info(db1100_spi_info,
ARRAY_SIZE(db1100_spi_info));
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 3/4] MIPS: alchemy: gpr: switch to static device properties
2026-03-10 6:11 [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Dmitry Torokhov
2026-03-10 6:11 ` [PATCH 1/4] MIPS: alchemy: mtx1: attach software nodes to GPIO chips Dmitry Torokhov
2026-03-10 6:11 ` [PATCH 2/4] MIPS: alchemy: db1000: use nodes attached to GPIO chips in properties Dmitry Torokhov
@ 2026-03-10 6:12 ` Dmitry Torokhov
2026-03-10 6:12 ` [PATCH 4/4] MIPS: alchemy: db1300: " Dmitry Torokhov
2026-04-30 9:30 ` [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-03-10 6:12 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
Convert I2C-gpio device and GPIO-connected LEDs on GPR board to software
nodes/properties, so that support for platform data can be removed from
gpio-leds driver (which will rely purely on generic device properties
for configuration).
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
arch/mips/alchemy/board-gpr.c | 122 ++++++++++++++++++++++++------------------
1 file changed, 71 insertions(+), 51 deletions(-)
diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
index f587c40b6d00..3e9bd179844f 100644
--- a/arch/mips/alchemy/board-gpr.c
+++ b/arch/mips/alchemy/board-gpr.c
@@ -13,11 +13,11 @@
#include <linux/pm.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
+#include <linux/property.h>
#include <asm/bootinfo.h>
#include <asm/idle.h>
#include <asm/reboot.h>
@@ -161,66 +161,87 @@ static struct platform_device gpr_mtd_device = {
/*
* LEDs
*/
-static const struct gpio_led gpr_gpio_leds[] = {
- { /* green */
- .name = "gpr:green",
- .gpio = 4,
- .active_low = 1,
+static const struct software_node gpr_gpio_leds_node = {
+ .name = "gpr-leds",
+};
+
+static const struct software_node gpr_green_led_node = {
+ .name = "gpr:green",
+ .parent = &gpr_gpio_leds_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_GPIO("gpios",
+ &alchemy_gpio1_node, 4, GPIO_ACTIVE_LOW),
+ { }
},
- { /* red */
- .name = "gpr:red",
- .gpio = 5,
- .active_low = 1,
- }
};
-static struct gpio_led_platform_data gpr_led_data = {
- .num_leds = ARRAY_SIZE(gpr_gpio_leds),
- .leds = gpr_gpio_leds,
+static const struct software_node gpr_red_led_node = {
+ .name = "gpr:red",
+ .parent = &gpr_gpio_leds_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_GPIO("gpios",
+ &alchemy_gpio1_node, 5, GPIO_ACTIVE_LOW),
+ { }
+ },
};
-static struct platform_device gpr_led_devices = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &gpr_led_data,
- }
+static const struct software_node * const gpr_gpio_leds_swnodes[] __initconst = {
+ &gpr_gpio_leds_node,
+ &gpr_green_led_node,
+ &gpr_red_led_node,
+ NULL
};
+static void __init gpr_leds_init(void)
+{
+ struct platform_device *pd;
+ int err;
+
+ err = software_node_register_node_group(gpr_gpio_leds_swnodes);
+ if (err) {
+ pr_err("failed to register LED software nodes: %d\n", err);
+ return;
+ }
+
+ pd = platform_device_register_full(&(struct platform_device_info){
+ .name = "leds-gpio",
+ .id = PLATFORM_DEVID_NONE,
+ .fwnode = software_node_fwnode(&gpr_gpio_leds_node),
+ });
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create LED device: %d\n", err);
+}
+
/*
* I2C
*/
-static struct gpiod_lookup_table gpr_i2c_gpiod_table = {
- .dev_id = "i2c-gpio",
- .table = {
- /*
- * This should be on "GPIO2" which has base at 200 so
- * the global numbers 209 and 210 should correspond to
- * local offsets 9 and 10.
- */
- GPIO_LOOKUP_IDX("alchemy-gpio2", 9, NULL, 0,
- GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP_IDX("alchemy-gpio2", 10, NULL, 1,
- GPIO_ACTIVE_HIGH),
- },
+static const struct property_entry gpr_i2c_props[] __initconst = {
+ PROPERTY_ENTRY_GPIO("sda-gpios", &alchemy_gpio2_node, 9, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("scl-gpios", &alchemy_gpio2_node, 10, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_U32("i2c-gpio,delay-us", 2), /* ~100 kHz */
+ PROPERTY_ENTRY_U32("i2c-gpio,timeout-ms", 1000),
+ PROPERTY_ENTRY_BOOL("i2c-gpio,sda-open-drain"),
+ PROPERTY_ENTRY_BOOL("i2c-gpio,scl-open-drain"),
+ { }
};
-static struct i2c_gpio_platform_data gpr_i2c_data = {
- /*
- * The open drain mode is hardwired somewhere or an electrical
- * property of the alchemy GPIO controller.
- */
- .sda_is_open_drain = 1,
- .scl_is_open_drain = 1,
- .udelay = 2, /* ~100 kHz */
- .timeout = HZ,
+static const struct platform_device_info gpr_i2c_pdev_info __initconst = {
+ .name = "i2c-gpio",
+ .id = PLATFORM_DEVID_NONE,
+ .properties = gpr_i2c_props,
};
-static struct platform_device gpr_i2c_device = {
- .name = "i2c-gpio",
- .id = -1,
- .dev.platform_data = &gpr_i2c_data,
-};
+static void __init gpr_i2c_init(void)
+{
+ struct platform_device *pd;
+ int err;
+
+ pd = platform_device_register_full(&gpr_i2c_pdev_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create I2C device: %d\n", err);
+}
static struct i2c_board_info gpr_i2c_info[] __initdata = {
{
@@ -270,8 +291,6 @@ static struct platform_device gpr_pci_host_dev = {
static struct platform_device *gpr_devices[] __initdata = {
&gpr_wdt_device,
&gpr_mtd_device,
- &gpr_i2c_device,
- &gpr_led_devices,
};
static int __init gpr_pci_init(void)
@@ -284,8 +303,9 @@ arch_initcall(gpr_pci_init);
static int __init gpr_dev_init(void)
{
- gpiod_add_lookup_table(&gpr_i2c_gpiod_table);
i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
+ gpr_i2c_init();
+ gpr_leds_init();
return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));
}
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 4/4] MIPS: alchemy: db1300: switch to static device properties
2026-03-10 6:11 [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Dmitry Torokhov
` (2 preceding siblings ...)
2026-03-10 6:12 ` [PATCH 3/4] MIPS: alchemy: gpr: switch to static device properties Dmitry Torokhov
@ 2026-03-10 6:12 ` Dmitry Torokhov
2026-04-30 9:30 ` [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-03-10 6:12 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
Convert "5way switch" gpio-keys device and smsc911x ethernet controller
to use static device properties instead of bespoke platform data
structures for configuration.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
arch/mips/alchemy/common/gpiolib.c | 6 +
arch/mips/alchemy/devboards/db1300.c | 209 +++++++++++++++---------
arch/mips/include/asm/mach-au1x00/gpio-au1300.h | 3 +
3 files changed, 144 insertions(+), 74 deletions(-)
diff --git a/arch/mips/alchemy/common/gpiolib.c b/arch/mips/alchemy/common/gpiolib.c
index 2141eae5ce45..c926cc137561 100644
--- a/arch/mips/alchemy/common/gpiolib.c
+++ b/arch/mips/alchemy/common/gpiolib.c
@@ -104,9 +104,14 @@ const struct software_node alchemy_gpio2_node = {
.name = "alchemy-gpio2",
};
+const struct software_node alchemy_gpic_node = {
+ .name = "alchemy-gpic",
+};
+
static const struct software_node *alchemy_gpio_node_group[] = {
&alchemy_gpio1_node,
&alchemy_gpio2_node,
+ &alchemy_gpic_node,
NULL
};
@@ -189,6 +194,7 @@ static int __init alchemy_gpio_nodes_init(void)
alchemy_gpio_chip[0].fwnode = software_node_fwnode(&alchemy_gpio1_node);
alchemy_gpio_chip[1].fwnode = software_node_fwnode(&alchemy_gpio2_node);
+ au1300_gpiochip.fwnode = software_node_fwnode(&alchemy_gpic_node);
return 0;
}
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index d377e043b49f..1c8b01e5263a 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -7,10 +7,10 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
#include <linux/init.h>
-#include <linux/input.h> /* KEY_* codes */
+#include <linux/input-event-codes.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/leds.h>
@@ -20,6 +20,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/platnand.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/smsc911x.h>
#include <linux/wm97xx.h>
@@ -236,23 +237,36 @@ static struct resource db1300_eth_res[] = {
},
};
-static struct smsc911x_platform_config db1300_eth_config = {
- .phy_interface = PHY_INTERFACE_MODE_MII,
- .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
- .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
- .flags = SMSC911X_USE_32BIT,
-};
+static u8 db1300_eth_macaddr[6];
-static struct platform_device db1300_eth_dev = {
- .name = "smsc911x",
- .id = -1,
- .num_resources = ARRAY_SIZE(db1300_eth_res),
- .resource = db1300_eth_res,
- .dev = {
- .platform_data = &db1300_eth_config,
+static const struct platform_device_info db1300_eth_info __initconst = {
+ .name = "smsc911x",
+ .id = PLATFORM_DEVID_NONE,
+ .res = db1300_eth_res,
+ .num_res = ARRAY_SIZE(db1300_eth_res),
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("reg-io-width", 4),
+ PROPERTY_ENTRY_U32("reg-shift", 0),
+ PROPERTY_ENTRY_BOOL("smsc,irq-push-pull"),
+ PROPERTY_ENTRY_STRING("phy-mode", "mii"),
+ PROPERTY_ENTRY_U8_ARRAY("local-mac-address", db1300_eth_macaddr),
+ { }
},
};
+static void __init db1300_eth_init(void)
+{
+ struct platform_device *pd;
+ int err;
+
+ prom_get_ethernet_addr(db1300_eth_macaddr);
+
+ pd = platform_device_register_full(&db1300_eth_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create eth device: %d\n", err);
+}
+
/**********************************************************************/
static struct resource au1300_psc1_res[] = {
@@ -355,62 +369,110 @@ static struct platform_device db1300_i2c_dev = {
* according to the schematics swap up with down and left with right.
* I chose to use it to emulate the arrow keys of a keyboard.
*/
-static struct gpio_keys_button db1300_5waysw_arrowkeys[] = {
- {
- .code = KEY_DOWN,
- .gpio = AU1300_PIN_LCDPWM0,
- .type = EV_KEY,
- .debounce_interval = 1,
- .active_low = 1,
- .desc = "5waysw-down",
- },
- {
- .code = KEY_UP,
- .gpio = AU1300_PIN_PSC2SYNC1,
- .type = EV_KEY,
- .debounce_interval = 1,
- .active_low = 1,
- .desc = "5waysw-up",
- },
- {
- .code = KEY_RIGHT,
- .gpio = AU1300_PIN_WAKE3,
- .type = EV_KEY,
- .debounce_interval = 1,
- .active_low = 1,
- .desc = "5waysw-right",
- },
- {
- .code = KEY_LEFT,
- .gpio = AU1300_PIN_WAKE2,
- .type = EV_KEY,
- .debounce_interval = 1,
- .active_low = 1,
- .desc = "5waysw-left",
- },
- {
- .code = KEY_ENTER,
- .gpio = AU1300_PIN_WAKE1,
- .type = EV_KEY,
- .debounce_interval = 1,
- .active_low = 1,
- .desc = "5waysw-push",
- },
-};
+static const struct software_node db1300_5waysw_node = {
+ .name = "db1300-5wayswitch",
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_BOOL("autorepeat"),
+ PROPERTY_ENTRY_STRING("label", "db1300-5wayswitch"),
+ { }
+ },
+};
+
+static const struct software_node db1300_5waysw_down_node = {
+ .name = "5waysw-down",
+ .parent = &db1300_5waysw_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", KEY_DOWN),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpic_node,
+ AU1300_PIN_LCDPWM0, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_U32("debounce-interval", 1),
+ PROPERTY_ENTRY_STRING("label", "5waysw-down"),
+ { }
+ },
+};
+
+static const struct software_node db1300_5waysw_up_node = {
+ .name = "5waysw-up",
+ .parent = &db1300_5waysw_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", KEY_UP),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpic_node,
+ AU1300_PIN_PSC2SYNC1, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_U32("debounce-interval", 1),
+ PROPERTY_ENTRY_STRING("label", "5waysw-up"),
+ { }
+ },
+};
+
+static const struct software_node db1300_5waysw_right_node = {
+ .name = "5waysw-right",
+ .parent = &db1300_5waysw_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", KEY_RIGHT),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpic_node,
+ AU1300_PIN_WAKE3, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_U32("debounce-interval", 1),
+ PROPERTY_ENTRY_STRING("label", "5waysw-right"),
+ { }
+ },
+};
+
+static const struct software_node db1300_5waysw_left_node = {
+ .name = "5waysw-left",
+ .parent = &db1300_5waysw_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", KEY_LEFT),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpic_node,
+ AU1300_PIN_WAKE2, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_U32("debounce-interval", 1),
+ PROPERTY_ENTRY_STRING("label", "5waysw-left"),
+ { }
+ },
+};
+
+static const struct software_node db1300_5waysw_push_node = {
+ .name = "5waysw-push",
+ .parent = &db1300_5waysw_node,
+ .properties = (const struct property_entry[]){
+ PROPERTY_ENTRY_U32("linux,code", KEY_ENTER),
+ PROPERTY_ENTRY_GPIO("gpios", &alchemy_gpic_node,
+ AU1300_PIN_WAKE1, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_U32("debounce-interval", 1),
+ PROPERTY_ENTRY_STRING("label", "5waysw-push"),
+ { }
+ },
+};
+
+static const struct software_node * const db1300_5waysw_swnodes[] __initconst = {
+ &db1300_5waysw_node,
+ &db1300_5waysw_down_node,
+ &db1300_5waysw_up_node,
+ &db1300_5waysw_right_node,
+ &db1300_5waysw_left_node,
+ &db1300_5waysw_push_node,
+ NULL
+};
+
+static void __init db1300_5waysw_init(void)
+{
+ struct platform_device *pd;
+ int err;
-static struct gpio_keys_platform_data db1300_5waysw_data = {
- .buttons = db1300_5waysw_arrowkeys,
- .nbuttons = ARRAY_SIZE(db1300_5waysw_arrowkeys),
- .rep = 1,
- .name = "db1300-5wayswitch",
-};
+ err = software_node_register_node_group(db1300_5waysw_swnodes);
+ if (err) {
+ pr_err("failed to register 5waysw software nodes: %d\n", err);
+ return;
+ }
-static struct platform_device db1300_5waysw_dev = {
- .name = "gpio-keys",
- .dev = {
- .platform_data = &db1300_5waysw_data,
- },
-};
+ pd = platform_device_register_full(&(struct platform_device_info){
+ .name = "gpio-keys",
+ .id = PLATFORM_DEVID_NONE,
+ .fwnode = software_node_fwnode(&db1300_5waysw_node),
+ });
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create 5waysw device: %d\n", err);
+}
/**********************************************************************/
@@ -764,9 +826,7 @@ static struct platform_driver db1300_wm97xx_driver = {
/**********************************************************************/
static struct platform_device *db1300_dev[] __initdata = {
- &db1300_eth_dev,
&db1300_i2c_dev,
- &db1300_5waysw_dev,
&db1300_nand_dev,
&db1300_ide_dev,
#ifdef CONFIG_MMC_AU1X
@@ -804,8 +864,6 @@ int __init db1300_dev_setup(void)
/*
* setup board
*/
- prom_get_ethernet_addr(&db1300_eth_config.mac[0]);
-
i2c_register_board_info(0, db1300_i2c_devs,
ARRAY_SIZE(db1300_i2c_devs));
@@ -848,6 +906,9 @@ int __init db1300_dev_setup(void)
swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1200_SWAPBOOT;
db1x_register_norflash(64 << 20, 2, swapped);
+ db1300_eth_init();
+ db1300_5waysw_init();
+
return platform_add_devices(db1300_dev, ARRAY_SIZE(db1300_dev));
}
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
index 43d44f384f97..912534ecb1a4 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
@@ -14,6 +14,9 @@
struct gpio;
struct gpio_chip;
+struct software_node;
+
+extern const struct software_node alchemy_gpic_node;
/* with the current GPIC design, up to 128 GPIOs are possible.
* The only implementation so far is in the Au1300, which has 75 externally
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties
2026-03-10 6:11 [PATCH 0/4] MIPS: alchemy: attach software nodes to GPIO controllers and use properties Dmitry Torokhov
` (3 preceding siblings ...)
2026-03-10 6:12 ` [PATCH 4/4] MIPS: alchemy: db1300: " Dmitry Torokhov
@ 2026-04-30 9:30 ` Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-04-30 9:30 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Thomas Bogendoerfer, linux-mips, linux-kernel
On Tue, Mar 10, 2026 at 7:12 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> This series of patches updates board previously converted to use static
> device properties/software nodes to attach and use nodes attached to the
> respective gpiochip devices rather than simply defining unattached
> software nodes with matching name. This is a requirement of newer
> gpiolib code. Note that there is currently a workaround preserving the
> lookup based on the software node name, but it will be removed soon.
>
> The additional 2 patches convert the remaining 2 boards to use software
> nodes as well.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
Hi Dmitry!
This missed the last merge window. Do you indent to resend it using
the new swnode field in struct platform_device_info?
Bart
^ permalink raw reply [flat|nested] 6+ messages in thread