mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU
@ 2026-01-23  9:54 Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 1/5] dt-bindings: vendor-prefixes: Add AAEON vendor prefix Thomas Perrot (Schneider Electric)
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric),
	Krzysztof Kozlowski

This patch series introduces support for the AAEON SRG-IMX8PL embedded
controller (MCU). The MCU is connected via I2C and provides GPIO and
watchdog functionality for the SRG-IMX8PL board.

The series includes:
- Device tree binding for the MFD driver
- MFD driver that serves as the core driver for the MCU
- GPIO driver implementing the GPIO functionality
- Watchdog driver for system monitoring
- MAINTAINERS entry for the new drivers

The drivers follow the standard Linux kernel subsystem patterns, with
the MFD driver registering the sub-devices (GPIO and watchdog) which
are then handled by their respective subsystem drivers.

Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
Changes in v2:
- Fold GPIO and watchdog bindings into MFD binding
- Drop OF_GPIO dependency in GPIO Kconfig
- Use __set_bit/__clear_bit/__assign_bit instead of atomic variants
- Various driver cleanups and improvements
- Link to v1: https://lore.kernel.org/r/20251212-dev-b4-aaeon-mcu-driver-v1-0-6bd65bc8ef12@bootlin.com

---
Thomas Perrot (Schneider Electric) (5):
      dt-bindings: vendor-prefixes: Add AAEON vendor prefix
      dt-bindings: mfd: Add AAEON embedded controller
      mfd: aaeon: Add SRG-IMX8PL MCU driver
      gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU
      watchdog: aaeon: Add watchdog driver for SRG-IMX8PL MCU

 .../bindings/mfd/aaeon,srg-imx8pl-mcu.yaml         |  56 +++++
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 MAINTAINERS                                        |  10 +
 drivers/gpio/Kconfig                               |  10 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-aaeon-mcu.c                      | 238 +++++++++++++++++++++
 drivers/mfd/Kconfig                                |   9 +
 drivers/mfd/Makefile                               |   2 +
 drivers/mfd/aaeon-mcu.c                            | 129 +++++++++++
 drivers/watchdog/Kconfig                           |  10 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/aaeon_mcu_wdt.c                   | 110 ++++++++++
 include/linux/mfd/aaeon-mcu.h                      |  31 +++
 13 files changed, 609 insertions(+)
---
base-commit: d358e5254674b70f34c847715ca509e46eb81e6f
change-id: 20251211-dev-b4-aaeon-mcu-driver-e0e89ebf4afb

Best regards,
-- 
Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/5] dt-bindings: vendor-prefixes: Add AAEON vendor prefix
  2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
@ 2026-01-23  9:54 ` Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller Thomas Perrot (Schneider Electric)
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric),
	Krzysztof Kozlowski

Add the AAEON vendor prefix to support the AAEON SRG-IMX8PL MCU driver
devicetree bindings.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index c7591b2aec2a74560a4f687fe7a2070ca21b0752..0f84ee93b3a8473719ee92f8c046e350c4a20825 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -32,6 +32,8 @@ patternProperties:
     description: 8devices, UAB
   "^9tripod,.*":
     description: Shenzhen 9Tripod Innovation and Development CO., LTD.
+  "^aaeon,.*":
+    description: AAEON
   "^abb,.*":
     description: ABB
   "^abilis,.*":

-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller
  2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 1/5] dt-bindings: vendor-prefixes: Add AAEON vendor prefix Thomas Perrot (Schneider Electric)
@ 2026-01-23  9:54 ` Thomas Perrot (Schneider Electric)
  2026-01-23 11:38   ` Rob Herring (Arm)
  2026-01-23  9:54 ` [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver Thomas Perrot (Schneider Electric)
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric)

Add device tree binding documentation for the AAEON embedded controller
(MCU). This microcontroller is found on AAEON embedded boards, it is
connected via I2C and  and provides a GPIO control and watchdog timer.

Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
 .../bindings/mfd/aaeon,srg-imx8pl-mcu.yaml         | 56 ++++++++++++++++++++++
 MAINTAINERS                                        |  6 +++
 2 files changed, 62 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml b/Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b8eb5bf88853b6eb3d31841e1f6d6acd4b776bd4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/aaeon,srg-imx8pl-mcu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AAEON Embedded Controller
+
+maintainers:
+  - Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+  - Thomas Perrot <thomas.perrot@bootlin.com>
+
+description:
+  AAEON embeds a microcontroller on Standard RISC Gateway with ARM i.MX8M Plus
+  Quad-Core boards providing GPIO control and watchdog timer.
+
+  This MCU is connected via I2C bus.
+
+  Its GPIO controller provides 7 GPOs and 12 GPIOs.
+
+  Its watchdog has a fixed maximum hardware heartbeat of 25 seconds and supports
+  a timeout of 240 seconds through automatic pinging.
+  The timeout is not programmable and cannot be changed via device tree properties.
+
+properties:
+  compatible:
+    const: aaeon,srg-imx8pl-mcu
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      aaeon_mcu: embedded-controller@62 {
+        compatible = "aaeon,srg-imx8pl-mcu";
+        reg = <0x62>;
+
+        gpio-controller;
+        #gpio-cells = <2>;
+        gpio-line-names = "gpo-1", "gpo-2", "gpo-3", "gpo-4",
+                  "gpo-5", "gpo-6", "gpo-7",
+                  "gpio-1", "gpio-2", "gpio-3", "gpio-4",
+                  "gpio-5", "gpio-6", "gpio-7", "gpio-8",
+                  "gpio-9", "gpio-10", "gpio-11", "gpio-12";
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index c9e416ba74c64e90629c0b7d7941f879c9ac589e..10f7d5b183795376b3fcdedc9c3835eecb9d0a3b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -186,6 +186,12 @@ W:	http://www.adaptec.com/
 F:	Documentation/scsi/aacraid.rst
 F:	drivers/scsi/aacraid/
 
+AAEON SRG-IMX8PL CONTROLLER MFD DRIVER
+M:	Thomas Perrot <thomas.perrot@bootlin.com>
+R:	Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
+
 AAEON UPBOARD FPGA MFD DRIVER
 M:	Thomas Richard <thomas.richard@bootlin.com>
 S:	Maintained

-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver
  2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 1/5] dt-bindings: vendor-prefixes: Add AAEON vendor prefix Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller Thomas Perrot (Schneider Electric)
@ 2026-01-23  9:54 ` Thomas Perrot (Schneider Electric)
  2026-01-27  9:51   ` Bartosz Golaszewski
  2026-01-23  9:54 ` [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
  2026-01-23  9:54 ` [PATCH v2 5/5] watchdog: aaeon: Add watchdog " Thomas Perrot (Schneider Electric)
  4 siblings, 1 reply; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric)

Add Multi-Function Device (MFD) driver for the Aaeon SRG-IMX8PL
embedded controller. This driver provides the core I2C communication
interface and registers child devices (GPIO and watchdog controllers).

The MCU firmware version is queried during probe and logged for
diagnostic purposes. All I2C transactions are serialized using a mutex
to ensure proper communication with the microcontroller.

Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
 MAINTAINERS                   |   2 +
 drivers/mfd/Kconfig           |   9 +++
 drivers/mfd/Makefile          |   2 +
 drivers/mfd/aaeon-mcu.c       | 129 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/aaeon-mcu.h |  31 ++++++++++
 5 files changed, 173 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 10f7d5b183795376b3fcdedc9c3835eecb9d0a3b..175c1e1b28b8151580ed340207d4a6fd59aa8853 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -191,6 +191,8 @@ M:	Thomas Perrot <thomas.perrot@bootlin.com>
 R:	Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
 S:	Maintained
 F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
+F:	drivers/mfd/aaeon-mcu.c
+F:	include/linux/mfd/aaeon-mcu.h
 
 AAEON UPBOARD FPGA MFD DRIVER
 M:	Thomas Richard <thomas.richard@bootlin.com>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index aace5766b38aa5e46e32a8a7b42eea238159fbcf..befcc36c12931b273e8e45fe968e9556514fb959 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1574,6 +1574,15 @@ config AB8500_CORE
 	  the irq_chip parts for handling the Mixed Signal chip events.
 	  This chip embeds various other multimedia functionalities as well.
 
+config MFD_AAEON_MCU
+	tristate "Aaeon SRG-IMX8PL MCU Driver"
+	depends on I2C
+	help
+	  Select this option to enable support for the Aaeon SRG-IMX8PL
+	  onboard microcontroller (MCU). This driver provides the core
+	  functionality to communicate with the MCU over I2C. The MCU
+	  provides GPIO and watchdog functionality.
+
 config MFD_DB8500_PRCMU
 	bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
 	depends on UX500_SOC_DB8500
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e75e8045c28afae975ac61d282b3b85af5440119..0bc3a10c787c55730131224fc1053fe35657dd71 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -304,3 +304,5 @@ obj-$(CONFIG_MFD_RSMU_SPI)	+= rsmu_spi.o rsmu_core.o
 obj-$(CONFIG_MFD_UPBOARD_FPGA)	+= upboard-fpga.o
 
 obj-$(CONFIG_MFD_LOONGSON_SE)	+= loongson-se.o
+
+obj-$(CONFIG_MFD_AAEON_MCU)	+= aaeon-mcu.o
diff --git a/drivers/mfd/aaeon-mcu.c b/drivers/mfd/aaeon-mcu.c
new file mode 100644
index 0000000000000000000000000000000000000000..b496fb6618ca49296c574531b778fcbb653a48f5
--- /dev/null
+++ b/drivers/mfd/aaeon-mcu.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Aaeon MCU driver
+ *
+ * Copyright (C) 2025 Bootlin
+ * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+ * Author: Thomas Perrot <thomas.perrot@bootlin.com>
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/aaeon-mcu.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+
+#define AAEON_MCU_FW_VERSION	0x76
+
+static struct mfd_cell aaeon_mcu_devs[] = {
+	{
+		.name = "aaeon-mcu-wdt",
+	},
+	{
+		.name = "aaeon-mcu-gpio",
+	},
+};
+
+static int aaeon_mcu_read_version(struct device *dev, u8 index, u8 *version)
+{
+	u8 cmd[3] = { AAEON_MCU_FW_VERSION, index, 0x00 };
+
+	return aaeon_mcu_i2c_xfer(dev, cmd, sizeof(cmd), version, sizeof(*version));
+}
+
+static int aaeon_mcu_print_fw_version(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	u8 major, minor;
+	int ret;
+
+	ret = aaeon_mcu_read_version(dev, 0x00, &major);
+	if (ret)
+		return ret;
+
+	ret = aaeon_mcu_read_version(dev, 0x01, &minor);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "firmware version: v%d.%d\n", major, minor);
+
+	return 0;
+}
+
+int aaeon_mcu_i2c_xfer(struct device *dev,
+		       const u8 *cmd, int cmd_len,
+		       u8 *rsp, int rsp_len)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct aaeon_mcu_dev *mcu = i2c_get_clientdata(client);
+	int ret;
+
+	mutex_lock(&mcu->i2c_lock);
+
+	ret = i2c_master_send(client, cmd, cmd_len);
+	if (ret < 0)
+		goto unlock;
+
+	ret = i2c_master_recv(client, rsp, rsp_len);
+	if (ret < 0)
+		goto unlock;
+
+	if (ret != rsp_len) {
+		dev_err(dev,
+			"i2c recv count error (expected: %d, actual: %d)\n",
+			rsp_len, ret);
+		ret = -EIO;
+		goto unlock;
+	}
+
+	ret = 0;
+
+unlock:
+	mutex_unlock(&mcu->i2c_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(aaeon_mcu_i2c_xfer);
+
+static int aaeon_mcu_probe(struct i2c_client *client)
+{
+	struct aaeon_mcu_dev *mcu;
+	int ret;
+
+	mcu = devm_kzalloc(&client->dev, sizeof(*mcu), GFP_KERNEL);
+	if (!mcu)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, mcu);
+	mcu->dev = &client->dev;
+	mutex_init(&mcu->i2c_lock);
+
+	ret = aaeon_mcu_print_fw_version(client);
+	if (ret) {
+		dev_err(&client->dev, "unable to read firmware version\n");
+		return ret;
+	}
+
+	return devm_mfd_add_devices(mcu->dev, PLATFORM_DEVID_NONE, aaeon_mcu_devs,
+				    ARRAY_SIZE(aaeon_mcu_devs), NULL, 0, NULL);
+}
+
+static const struct of_device_id aaeon_mcu_of_match[] = {
+	{ .compatible = "aaeon,srg-imx8pl-mcu" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, aaeon_mcu_of_match);
+
+static struct i2c_driver aaeon_mcu_driver = {
+	.driver = {
+		.name = "aaeon_mcu",
+		.of_match_table = aaeon_mcu_of_match,
+	},
+	.probe = aaeon_mcu_probe,
+};
+
+module_i2c_driver(aaeon_mcu_driver);
+
+MODULE_DESCRIPTION("Aaeon MCU Driver");
+MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/aaeon-mcu.h b/include/linux/mfd/aaeon-mcu.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9dc7a9adbc86c489f03a550e7776d3b1da4e7b2
--- /dev/null
+++ b/include/linux/mfd/aaeon-mcu.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Aaeon MCU driver definitions
+ *
+ * Copyright (C) 2025 Bootlin
+ * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+ * Author: Thomas Perrot <thomas.perrot@bootlin.com>
+ */
+
+#ifndef __LINUX_MFD_AAEON_MCU_H
+#define __LINUX_MFD_AAEON_MCU_H
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+/**
+ * struct aaeon_mcu_dev - Internal representation of the Aaeon MCU
+ * @dev: Pointer to kernel device structure
+ * @i2c_lock: Mutex to serialize I2C bus access
+ */
+
+struct aaeon_mcu_dev {
+	struct device *dev;
+	struct mutex i2c_lock;
+};
+
+int aaeon_mcu_i2c_xfer(struct device *dev,
+		       const u8 *cmd, int cmd_len,
+		       u8 *rsp, int rsp_len);
+
+#endif /*  __LINUX_MFD_AAEON_MCU_H */

-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU
  2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
                   ` (2 preceding siblings ...)
  2026-01-23  9:54 ` [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver Thomas Perrot (Schneider Electric)
@ 2026-01-23  9:54 ` Thomas Perrot (Schneider Electric)
  2026-01-27  9:41   ` Linus Walleij
  2026-01-27  9:54   ` Bartosz Golaszewski
  2026-01-23  9:54 ` [PATCH v2 5/5] watchdog: aaeon: Add watchdog " Thomas Perrot (Schneider Electric)
  4 siblings, 2 replies; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric)

Add GPIO driver for the Aaeon SRG-IMX8PL embedded controller. This
driver supports 7 GPO (General Purpose Output) pins and 12 GPIO pins
that can be configured as inputs or outputs.

The driver implements proper state management for GPO pins (which are
output-only) and full direction control for GPIO pins. During probe,
all pins are reset to a known state (GPOs low, GPIOs as inputs) to
prevent undefined behavior across system reboots, as the MCU does not
reset GPIO states on soft reboot.

Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
 MAINTAINERS                   |   1 +
 drivers/gpio/Kconfig          |  10 ++
 drivers/gpio/Makefile         |   1 +
 drivers/gpio/gpio-aaeon-mcu.c | 238 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 250 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 175c1e1b28b8151580ed340207d4a6fd59aa8853..28dd964cdf69bdcaec3eb82d6df851a2bad47415 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -191,6 +191,7 @@ M:	Thomas Perrot <thomas.perrot@bootlin.com>
 R:	Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
 S:	Maintained
 F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
+F:	drivers/gpio/gpio-aaeon-mcu.c
 F:	drivers/mfd/aaeon-mcu.c
 F:	include/linux/mfd/aaeon-mcu.h
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c74da29253e810b51540684b1186e8f274066b69..6142d50b92b3d8c1fac8b0d81397dc22428fbb51 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -157,6 +157,16 @@ config GPIO_74XX_MMIO
 	    8 bits:	74244 (Input), 74273 (Output)
 	    16 bits:	741624 (Input), 7416374 (Output)
 
+config GPIO_AAEON_MCU
+	tristate "Aaeon MCU GPIO support"
+	depends on MFD_AAEON_MCU
+	select GPIO_GENERIC
+	help
+	  Select this option to enable GPIO support for the Aaeon SRG-IMX8PL
+	  onboard MCU. This driver provides access to GPIO pins and GPO
+	  (General Purpose Output) pins controlled by the microcontroller.
+	  The driver handles both input and output configuration.
+
 config GPIO_ALTERA
 	tristate "Altera GPIO"
 	select GPIOLIB_IRQCHIP
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 2421a8fd3733e0b06c2581262aaa9cd629f66c7d..1ba6318bc558743fbe5910966c2c8fc3f792efe9 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_104_IDI_48)		+= gpio-104-idi-48.o
 obj-$(CONFIG_GPIO_104_IDIO_16)		+= gpio-104-idio-16.o
 obj-$(CONFIG_GPIO_74X164)		+= gpio-74x164.o
 obj-$(CONFIG_GPIO_74XX_MMIO)		+= gpio-74xx-mmio.o
+obj-$(CONFIG_GPIO_AAEON_MCU)		+= gpio-aaeon-mcu.o
 obj-$(CONFIG_GPIO_ADNP)			+= gpio-adnp.o
 obj-$(CONFIG_GPIO_ADP5520)		+= gpio-adp5520.o
 obj-$(CONFIG_GPIO_ADP5585)		+= gpio-adp5585.o
diff --git a/drivers/gpio/gpio-aaeon-mcu.c b/drivers/gpio/gpio-aaeon-mcu.c
new file mode 100644
index 0000000000000000000000000000000000000000..533eaf3e7f82f3b9e3f50a1a631c8e853adc1226
--- /dev/null
+++ b/drivers/gpio/gpio-aaeon-mcu.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Aaeon MCU GPIO driver
+ *
+ * Copyright (C) 2025 Bootlin
+ * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+ * Author: Thomas Perrot <thomas.perrot@bootlin.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/aaeon-mcu.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define AAEON_MCU_CONFIG_GPIO_INPUT 0x69
+#define AAEON_MCU_CONFIG_GPIO_OUTPUT 0x6F
+#define AAEON_MCU_READ_GPIO 0x72
+#define AAEON_MCU_WRITE_GPIO 0x77
+
+#define AAEON_MCU_CONTROL_GPO 0x6C
+
+#define MAX_GPIOS 12
+#define MAX_GPOS 7
+
+struct aaeon_mcu_gpio {
+	struct gpio_chip gc;
+	struct device *dev;
+	DECLARE_BITMAP(dir_in, MAX_GPOS + MAX_GPIOS);
+	DECLARE_BITMAP(gpo_state, MAX_GPOS);
+};
+
+static int aaeon_mcu_gpio_config_input_cmd(struct aaeon_mcu_gpio *data,
+					    unsigned int offset)
+{
+	u8 cmd[3], rsp;
+
+	cmd[0] = AAEON_MCU_CONFIG_GPIO_INPUT;
+	cmd[1] = offset - 7;
+	cmd[2] = 0x00;
+
+	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+}
+
+static int aaeon_mcu_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
+	int ret;
+
+	if (offset < MAX_GPOS) {
+		dev_err(gc->parent, "GPIO offset (%d) must be an output GPO\n", offset);
+		return -EOPNOTSUPP;
+	}
+
+	ret = aaeon_mcu_gpio_config_input_cmd(data, offset);
+	if (ret < 0)
+		return ret;
+
+	__set_bit(offset, data->dir_in);
+
+	return 0;
+}
+
+static int aaeon_mcu_gpio_config_output_cmd(struct aaeon_mcu_gpio *data,
+					     unsigned int offset,
+					     int value)
+{
+	u8 cmd[3], rsp;
+	int ret;
+
+	cmd[0] = AAEON_MCU_CONFIG_GPIO_OUTPUT;
+	cmd[1] = offset - 7;
+	cmd[2] = 0x00;
+
+	ret = aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+	if (ret < 0)
+		return ret;
+
+	cmd[0] = AAEON_MCU_WRITE_GPIO;
+	/* cmd[1] = offset - 7; */
+	cmd[2] = !!value;
+
+	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+}
+
+static int aaeon_mcu_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
+{
+	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
+	int ret;
+
+	if (offset < MAX_GPOS)
+		return 0;
+
+	ret = aaeon_mcu_gpio_config_output_cmd(data, offset, value);
+	if (ret < 0)
+		return ret;
+
+	__clear_bit(offset, data->dir_in);
+
+	return 0;
+}
+
+static int aaeon_mcu_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
+
+	return test_bit(offset, data->dir_in) ?
+		GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
+}
+
+static int aaeon_mcu_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
+	u8 cmd[3], rsp;
+	int ret;
+
+	if (offset < MAX_GPOS)
+		return test_bit(offset, data->gpo_state);
+
+	cmd[0] = AAEON_MCU_READ_GPIO;
+	cmd[1] = offset - 7;
+	cmd[2] = 0x00;
+
+	ret = aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+	if (ret < 0)
+		return ret;
+
+	return rsp;
+}
+
+static int aaeon_mcu_gpo_set_cmd(struct aaeon_mcu_gpio *data, unsigned int offset, int value)
+{
+	u8 cmd[3], rsp;
+
+	cmd[0] = AAEON_MCU_CONTROL_GPO;
+	cmd[1] = offset + 1;
+	cmd[2] = !!value;
+
+	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+}
+
+static int aaeon_mcu_gpio_set_cmd(struct aaeon_mcu_gpio *data, unsigned int offset, int value)
+{
+	u8 cmd[3], rsp;
+
+	cmd[0] = AAEON_MCU_WRITE_GPIO;
+	cmd[1] = offset - 7;
+	cmd[2] = !!value;
+
+	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
+}
+
+static int aaeon_mcu_gpio_set(struct gpio_chip *gc, unsigned int offset,
+			      int value)
+{
+	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
+
+	if (offset >= MAX_GPOS)
+		return aaeon_mcu_gpio_set_cmd(data, offset, value);
+
+	if (aaeon_mcu_gpo_set_cmd(data, offset, value) == 0)
+		__assign_bit(offset, data->gpo_state, value);
+
+	return 0;
+}
+
+static const struct gpio_chip aaeon_mcu_chip = {
+	.label			= "gpio-aaeon-mcu",
+	.owner			= THIS_MODULE,
+	.get_direction		= aaeon_mcu_gpio_get_direction,
+	.direction_input	= aaeon_mcu_gpio_direction_input,
+	.direction_output	= aaeon_mcu_gpio_direction_output,
+	.get			= aaeon_mcu_gpio_get,
+	.set			= aaeon_mcu_gpio_set,
+	.base			= -1,
+	.ngpio			= MAX_GPOS + MAX_GPIOS,
+	.can_sleep		= true,
+};
+
+static void aaeon_mcu_gpio_reset(struct aaeon_mcu_gpio *data, struct device *dev)
+{
+	unsigned int i;
+	int ret;
+
+	/* Reset all GPOs */
+	for (i = 0; i < MAX_GPOS; i++) {
+		ret = aaeon_mcu_gpo_set_cmd(data, i, 0);
+		if (ret < 0)
+			dev_warn(dev, "Failed to reset GPO %u state: %d\n", i, ret);
+		__clear_bit(i, data->dir_in);
+	}
+
+	/* Reset all GPIOs */
+	for (i = MAX_GPOS; i < MAX_GPOS + MAX_GPIOS; i++) {
+		ret = aaeon_mcu_gpio_config_input_cmd(data, i);
+		if (ret < 0)
+			dev_warn(dev, "Failed to reset GPIO %u state: %d\n", i, ret);
+		__set_bit(i, data->dir_in);
+	}
+}
+
+static int aaeon_mcu_gpio_probe(struct platform_device *pdev)
+{
+	struct aaeon_mcu_gpio *data;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = pdev->dev.parent;
+	data->gc = aaeon_mcu_chip;
+	data->gc.parent = data->dev;
+
+	/*
+	 * Reset all GPIO states to a known configuration. The MCU does not
+	 * reset GPIO state on soft reboot, only on power cycle (hard reboot).
+	 * Without this reset, GPIOs would retain their previous state across
+	 * reboots, which could lead to unexpected behavior.
+	 */
+	aaeon_mcu_gpio_reset(data, &pdev->dev);
+
+	return devm_gpiochip_add_data(&pdev->dev, &data->gc, data);
+}
+
+static struct platform_driver aaeon_mcu_gpio_driver = {
+	.driver = {
+		.name = "aaeon-mcu-gpio",
+	},
+	.probe = aaeon_mcu_gpio_probe,
+};
+
+module_platform_driver(aaeon_mcu_gpio_driver);
+
+MODULE_DESCRIPTION("GPIO interface for Aaeon MCU");
+MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
+MODULE_LICENSE("GPL");

-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 5/5] watchdog: aaeon: Add watchdog driver for SRG-IMX8PL MCU
  2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
                   ` (3 preceding siblings ...)
  2026-01-23  9:54 ` [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
@ 2026-01-23  9:54 ` Thomas Perrot (Schneider Electric)
  2026-01-23 16:11   ` Guenter Roeck
  4 siblings, 1 reply; 11+ messages in thread
From: Thomas Perrot (Schneider Electric) @ 2026-01-23  9:54 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni,
	Thomas Perrot (Schneider Electric)

Add watchdog driver for the Aaeon SRG-IMX8PL embedded controller.
This driver provides system monitoring and recovery capabilities
through the MCU's watchdog timer.

The watchdog supports start, stop, and ping operations with a maximum
hardware heartbeat of 25 seconds and a default timeout of 240 seconds.
The driver assumes the watchdog is already running at probe time, as
the MCU typically enables it by default.

Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
---
 MAINTAINERS                      |   1 +
 drivers/watchdog/Kconfig         |  10 ++++
 drivers/watchdog/Makefile        |   1 +
 drivers/watchdog/aaeon_mcu_wdt.c | 110 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 28dd964cdf69bdcaec3eb82d6df851a2bad47415..66cc4a5dcbe0977e6baee6d3b5e6023dcc06847b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -193,6 +193,7 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
 F:	drivers/gpio/gpio-aaeon-mcu.c
 F:	drivers/mfd/aaeon-mcu.c
+F:	drivers/watchdog/aaeon_mcu_wdt.c
 F:	include/linux/mfd/aaeon-mcu.h
 
 AAEON UPBOARD FPGA MFD DRIVER
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d3b9df7d466b0b7215ee87b3040811d44ee53d2a..1bd4a7bee303e5e2508f540dc2c16e9e19ed18b0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -168,6 +168,16 @@ config SOFT_WATCHDOG_PRETIMEOUT
 	  watchdog. Be aware that governors might affect the watchdog because it
 	  is purely software, e.g. the panic governor will stall it!
 
+config AAEON_MCU_WATCHDOG
+	tristate "Aaeon MCU Watchdog"
+	depends on MFD_AAEON_MCU
+	select WATCHDOG_CORE
+	help
+	  Select this option to enable watchdog timer support for the Aaeon
+	  SRG-IMX8PL onboard microcontroller (MCU). This driver provides
+	  watchdog functionality through the MCU, allowing system monitoring
+	  and automatic recovery from system hangs.
+
 config BD957XMUF_WATCHDOG
 	tristate "ROHM BD9576MUF and BD9573MUF PMIC Watchdog"
 	depends on MFD_ROHM_BD957XMUF
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index ba52099b125398a32f80dad23317e223cc4af028..2deec425d3eafb6b208e061fda9f216f4baa8ecc 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 # ALPHA Architecture
 
 # ARM Architecture
+obj-$(CONFIG_AAEON_MCU_WATCHDOG) += aaeon_mcu_wdt.o
 obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
 obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
 obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
diff --git a/drivers/watchdog/aaeon_mcu_wdt.c b/drivers/watchdog/aaeon_mcu_wdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..99be3ce327f44063fce6ba77a7d4efcba34361df
--- /dev/null
+++ b/drivers/watchdog/aaeon_mcu_wdt.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Aaeon MCU Watchdog driver
+ *
+ * Copyright (C) 2025 Bootlin
+ * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
+ * Author: Thomas Perrot <thomas.perrot@bootlin.com>
+ */
+
+#include <linux/mfd/aaeon-mcu.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+#define AAEON_MCU_CONTROL_WDT	0x63
+#define AAEON_MCU_PING_WDT	0x73
+
+#define AAEON_MCU_WDT_TIMEOUT         240
+#define AAEON_MCU_WDT_HEARTBEAT_MS    25000
+
+struct aaeon_mcu_wdt {
+	struct watchdog_device wdt;
+	struct device *dev;
+};
+
+static int aaeon_mcu_wdt_cmd(struct device *dev, u8 opcode, u8 arg)
+{
+	u8 cmd[3] = { opcode, arg, 0x00 };
+	u8 rsp;
+
+	return aaeon_mcu_i2c_xfer(dev, cmd, sizeof(cmd), &rsp, sizeof(rsp));
+}
+
+static int aaeon_mcu_wdt_start(struct watchdog_device *wdt)
+{
+	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
+
+	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_CONTROL_WDT, 0x01);
+}
+
+static int aaeon_mcu_wdt_stop(struct watchdog_device *wdt)
+{
+	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
+
+	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_CONTROL_WDT, 0x00);
+}
+
+static int aaeon_mcu_wdt_ping(struct watchdog_device *wdt)
+{
+	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
+
+	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_PING_WDT, 0x00);
+}
+
+static const struct watchdog_info aaeon_mcu_wdt_info = {
+	.identity	= "Aaeon MCU Watchdog",
+	.options	= WDIOF_KEEPALIVEPING
+};
+
+static const struct watchdog_ops aaeon_mcu_wdt_ops = {
+	.owner		= THIS_MODULE,
+	.start		= aaeon_mcu_wdt_start,
+	.stop		= aaeon_mcu_wdt_stop,
+	.ping		= aaeon_mcu_wdt_ping,
+};
+
+static int aaeon_mcu_wdt_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdt;
+	struct aaeon_mcu_wdt *data;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev->parent;
+
+	wdt = &data->wdt;
+	wdt->parent = dev;
+	wdt->info = &aaeon_mcu_wdt_info;
+	wdt->ops = &aaeon_mcu_wdt_ops;
+	wdt->timeout = AAEON_MCU_WDT_TIMEOUT;
+	wdt->max_hw_heartbeat_ms = AAEON_MCU_WDT_HEARTBEAT_MS;
+
+	watchdog_set_drvdata(wdt, data);
+	platform_set_drvdata(pdev, data);
+
+	ret = aaeon_mcu_wdt_start(wdt);
+	if (ret)
+		return ret;
+
+	set_bit(WDOG_HW_RUNNING, &wdt->status);
+
+	return devm_watchdog_register_device(dev, wdt);
+}
+
+static struct platform_driver aaeon_mcu_wdt_driver = {
+	.driver		= {
+		.name	= "aaeon-mcu-wdt",
+	},
+	.probe		= aaeon_mcu_wdt_probe,
+};
+
+module_platform_driver(aaeon_mcu_wdt_driver);
+
+MODULE_DESCRIPTION("Aaeon MCU Watchdog Driver");
+MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
+MODULE_LICENSE("GPL");

-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller
  2026-01-23  9:54 ` [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller Thomas Perrot (Schneider Electric)
@ 2026-01-23 11:38   ` Rob Herring (Arm)
  0 siblings, 0 replies; 11+ messages in thread
From: Rob Herring (Arm) @ 2026-01-23 11:38 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric)
  Cc: linux-gpio, Sascha Hauer, linux-kernel, Linus Walleij, Lee Jones,
	Pengutronix Kernel Team, Krzysztof Kozlowski, devicetree,
	Thomas Petazzoni, linux-arm-kernel, imx, linux-watchdog,
	Wim Van Sebroeck, Shawn Guo, Bartosz Golaszewski, Guenter Roeck,
	Jérémie Dautheribes, Conor Dooley, Fabio Estevam


On Fri, 23 Jan 2026 10:54:31 +0100, Thomas Perrot (Schneider Electric) wrote:
> Add device tree binding documentation for the AAEON embedded controller
> (MCU). This microcontroller is found on AAEON embedded boards, it is
> connected via I2C and  and provides a GPIO control and watchdog timer.
> 
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
> ---
>  .../bindings/mfd/aaeon,srg-imx8pl-mcu.yaml         | 56 ++++++++++++++++++++++
>  MAINTAINERS                                        |  6 +++
>  2 files changed, 62 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.example.dtb: embedded-controller@62 (aaeon,srg-imx8pl-mcu): '#gpio-cells', 'gpio-controller', 'gpio-line-names' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/mfd/aaeon,srg-imx8pl-mcu.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.kernel.org/project/devicetree/patch/20260123-dev-b4-aaeon-mcu-driver-v2-2-9f4c00bfb5cb@bootlin.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 5/5] watchdog: aaeon: Add watchdog driver for SRG-IMX8PL MCU
  2026-01-23  9:54 ` [PATCH v2 5/5] watchdog: aaeon: Add watchdog " Thomas Perrot (Schneider Electric)
@ 2026-01-23 16:11   ` Guenter Roeck
  0 siblings, 0 replies; 11+ messages in thread
From: Guenter Roeck @ 2026-01-23 16:11 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric),
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni

On 1/23/26 01:54, Thomas Perrot (Schneider Electric) wrote:
> Add watchdog driver for the Aaeon SRG-IMX8PL embedded controller.
> This driver provides system monitoring and recovery capabilities
> through the MCU's watchdog timer.
> 
> The watchdog supports start, stop, and ping operations with a maximum
> hardware heartbeat of 25 seconds and a default timeout of 240 seconds.
> The driver assumes the watchdog is already running at probe time, as
> the MCU typically enables it by default.
> 
> Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
> ---
>   MAINTAINERS                      |   1 +
>   drivers/watchdog/Kconfig         |  10 ++++
>   drivers/watchdog/Makefile        |   1 +
>   drivers/watchdog/aaeon_mcu_wdt.c | 110 +++++++++++++++++++++++++++++++++++++++
>   4 files changed, 122 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 28dd964cdf69bdcaec3eb82d6df851a2bad47415..66cc4a5dcbe0977e6baee6d3b5e6023dcc06847b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -193,6 +193,7 @@ S:	Maintained
>   F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
>   F:	drivers/gpio/gpio-aaeon-mcu.c
>   F:	drivers/mfd/aaeon-mcu.c
> +F:	drivers/watchdog/aaeon_mcu_wdt.c
>   F:	include/linux/mfd/aaeon-mcu.h
>   
>   AAEON UPBOARD FPGA MFD DRIVER
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index d3b9df7d466b0b7215ee87b3040811d44ee53d2a..1bd4a7bee303e5e2508f540dc2c16e9e19ed18b0 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -168,6 +168,16 @@ config SOFT_WATCHDOG_PRETIMEOUT
>   	  watchdog. Be aware that governors might affect the watchdog because it
>   	  is purely software, e.g. the panic governor will stall it!
>   
> +config AAEON_MCU_WATCHDOG
> +	tristate "Aaeon MCU Watchdog"
> +	depends on MFD_AAEON_MCU
> +	select WATCHDOG_CORE
> +	help
> +	  Select this option to enable watchdog timer support for the Aaeon
> +	  SRG-IMX8PL onboard microcontroller (MCU). This driver provides
> +	  watchdog functionality through the MCU, allowing system monitoring
> +	  and automatic recovery from system hangs.
> +
>   config BD957XMUF_WATCHDOG
>   	tristate "ROHM BD9576MUF and BD9573MUF PMIC Watchdog"
>   	depends on MFD_ROHM_BD957XMUF
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index ba52099b125398a32f80dad23317e223cc4af028..2deec425d3eafb6b208e061fda9f216f4baa8ecc 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
>   # ALPHA Architecture
>   
>   # ARM Architecture
> +obj-$(CONFIG_AAEON_MCU_WATCHDOG) += aaeon_mcu_wdt.o
>   obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
>   obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
>   obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
> diff --git a/drivers/watchdog/aaeon_mcu_wdt.c b/drivers/watchdog/aaeon_mcu_wdt.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..99be3ce327f44063fce6ba77a7d4efcba34361df
> --- /dev/null
> +++ b/drivers/watchdog/aaeon_mcu_wdt.c
> @@ -0,0 +1,110 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Aaeon MCU Watchdog driver
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
> +
> +#include <linux/mfd/aaeon-mcu.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/watchdog.h>
> +
> +#define AAEON_MCU_CONTROL_WDT	0x63
> +#define AAEON_MCU_PING_WDT	0x73
> +
> +#define AAEON_MCU_WDT_TIMEOUT         240
> +#define AAEON_MCU_WDT_HEARTBEAT_MS    25000
> +
> +struct aaeon_mcu_wdt {
> +	struct watchdog_device wdt;
> +	struct device *dev;
> +};
> +
> +static int aaeon_mcu_wdt_cmd(struct device *dev, u8 opcode, u8 arg)
> +{
> +	u8 cmd[3] = { opcode, arg, 0x00 };
> +	u8 rsp;
> +
> +	return aaeon_mcu_i2c_xfer(dev, cmd, sizeof(cmd), &rsp, sizeof(rsp));
> +}
> +
> +static int aaeon_mcu_wdt_start(struct watchdog_device *wdt)
> +{
> +	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
> +
> +	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_CONTROL_WDT, 0x01);
> +}
> +
> +static int aaeon_mcu_wdt_stop(struct watchdog_device *wdt)
> +{
> +	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
> +
> +	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_CONTROL_WDT, 0x00);
> +}
> +
> +static int aaeon_mcu_wdt_ping(struct watchdog_device *wdt)
> +{
> +	struct aaeon_mcu_wdt *data = watchdog_get_drvdata(wdt);
> +
> +	return aaeon_mcu_wdt_cmd(data->dev, AAEON_MCU_PING_WDT, 0x00);
> +}
> +
> +static const struct watchdog_info aaeon_mcu_wdt_info = {
> +	.identity	= "Aaeon MCU Watchdog",
> +	.options	= WDIOF_KEEPALIVEPING
> +};
> +
> +static const struct watchdog_ops aaeon_mcu_wdt_ops = {
> +	.owner		= THIS_MODULE,
> +	.start		= aaeon_mcu_wdt_start,
> +	.stop		= aaeon_mcu_wdt_stop,
> +	.ping		= aaeon_mcu_wdt_ping,
> +};
> +
> +static int aaeon_mcu_wdt_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct watchdog_device *wdt;
> +	struct aaeon_mcu_wdt *data;
> +	int ret;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->dev = dev->parent;
> +
> +	wdt = &data->wdt;
> +	wdt->parent = dev;
> +	wdt->info = &aaeon_mcu_wdt_info;
> +	wdt->ops = &aaeon_mcu_wdt_ops;
> +	wdt->timeout = AAEON_MCU_WDT_TIMEOUT;
> +	wdt->max_hw_heartbeat_ms = AAEON_MCU_WDT_HEARTBEAT_MS;

If this is the only supported timeout, and the timeout can not be updated,
that should be explained in the code. That explanation will need to include
the reason why the timeout is being fixed to 240 seconds and can not be
updated, even in software. Without that, it just does not make sense
to have a fixed hardware timeout of 25 seconds and a fixed software timeout
of 240 seconds without means to change the latter.

> +
> +	watchdog_set_drvdata(wdt, data);
> +	platform_set_drvdata(pdev, data);
> +

platform_set_drvdata() seems unnecessary; I don't see where it is used.

> +	ret = aaeon_mcu_wdt_start(wdt);
> +	if (ret)
> +		return ret;
> +
> +	set_bit(WDOG_HW_RUNNING, &wdt->status);
> +

This is only acceptable if there is no means to detect if the watchdog is
running. If so, that warrants a comment in the code.

Thanks,
Guenter

> +	return devm_watchdog_register_device(dev, wdt);
> +}
> +
> +static struct platform_driver aaeon_mcu_wdt_driver = {
> +	.driver		= {
> +		.name	= "aaeon-mcu-wdt",
> +	},
> +	.probe		= aaeon_mcu_wdt_probe,
> +};
> +
> +module_platform_driver(aaeon_mcu_wdt_driver);
> +
> +MODULE_DESCRIPTION("Aaeon MCU Watchdog Driver");
> +MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
> +MODULE_LICENSE("GPL");
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU
  2026-01-23  9:54 ` [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
@ 2026-01-27  9:41   ` Linus Walleij
  2026-01-27  9:54   ` Bartosz Golaszewski
  1 sibling, 0 replies; 11+ messages in thread
From: Linus Walleij @ 2026-01-27  9:41 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric)
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones, devicetree, linux-kernel, linux-gpio, imx,
	linux-arm-kernel, linux-watchdog, Thomas Petazzoni

On Fri, Jan 23, 2026 at 10:55 AM Thomas Perrot (Schneider Electric)
<thomas.perrot@bootlin.com> wrote:

> Add GPIO driver for the Aaeon SRG-IMX8PL embedded controller. This
> driver supports 7 GPO (General Purpose Output) pins and 12 GPIO pins
> that can be configured as inputs or outputs.
>
> The driver implements proper state management for GPO pins (which are
> output-only) and full direction control for GPIO pins. During probe,
> all pins are reset to a known state (GPOs low, GPIOs as inputs) to
> prevent undefined behavior across system reboots, as the MCU does not
> reset GPIO states on soft reboot.
>
> Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>

Looks Good to Me!
Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver
  2026-01-23  9:54 ` [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver Thomas Perrot (Schneider Electric)
@ 2026-01-27  9:51   ` Bartosz Golaszewski
  0 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2026-01-27  9:51 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric)
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones

On Fri, 23 Jan 2026 10:54:32 +0100, "Thomas Perrot (Schneider
Electric)" <thomas.perrot@bootlin.com> said:
> Add Multi-Function Device (MFD) driver for the Aaeon SRG-IMX8PL
> embedded controller. This driver provides the core I2C communication
> interface and registers child devices (GPIO and watchdog controllers).
>
> The MCU firmware version is queried during probe and logged for
> diagnostic purposes. All I2C transactions are serialized using a mutex
> to ensure proper communication with the microcontroller.
>
> Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
> ---

[snip]

 +++ b/drivers/mfd/aaeon-mcu.c
> @@ -0,0 +1,129 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Aaeon MCU driver
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
> +
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/aaeon-mcu.h>
> +#include <linux/mfd/core.h>
> +#include <linux/platform_device.h>
> +
> +#define AAEON_MCU_FW_VERSION	0x76
> +
> +static struct mfd_cell aaeon_mcu_devs[] = {

Can be const.

> +	{
> +		.name = "aaeon-mcu-wdt",
> +	},
> +	{
> +		.name = "aaeon-mcu-gpio",
> +	},
> +};
> +
> +static int aaeon_mcu_read_version(struct device *dev, u8 index, u8 *version)
> +{
> +	u8 cmd[3] = { AAEON_MCU_FW_VERSION, index, 0x00 };
> +
> +	return aaeon_mcu_i2c_xfer(dev, cmd, sizeof(cmd), version, sizeof(*version));
> +}
> +
> +static int aaeon_mcu_print_fw_version(struct i2c_client *client)
> +{
> +	struct device *dev = &client->dev;
> +	u8 major, minor;
> +	int ret;
> +
> +	ret = aaeon_mcu_read_version(dev, 0x00, &major);
> +	if (ret)
> +		return ret;
> +
> +	ret = aaeon_mcu_read_version(dev, 0x01, &minor);
> +	if (ret)
> +		return ret;
> +
> +	dev_info(dev, "firmware version: v%d.%d\n", major, minor);

I would drop this entirely or demote it to dev_dbg(), there's no reason for
a successfully probed device to yell about it.

> +
> +	return 0;
> +}
> +
> +int aaeon_mcu_i2c_xfer(struct device *dev,
> +		       const u8 *cmd, int cmd_len,
> +		       u8 *rsp, int rsp_len)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct aaeon_mcu_dev *mcu = i2c_get_clientdata(client);
> +	int ret;
> +
> +	mutex_lock(&mcu->i2c_lock);
> +
> +	ret = i2c_master_send(client, cmd, cmd_len);
> +	if (ret < 0)
> +		goto unlock;
> +
> +	ret = i2c_master_recv(client, rsp, rsp_len);
> +	if (ret < 0)
> +		goto unlock;
> +
> +	if (ret != rsp_len) {
> +		dev_err(dev,
> +			"i2c recv count error (expected: %d, actual: %d)\n",
> +			rsp_len, ret);
> +		ret = -EIO;
> +		goto unlock;
> +	}
> +
> +	ret = 0;
> +
> +unlock:

Just use guard(mutex) from cleanup.h and drop the label.

> +	mutex_unlock(&mcu->i2c_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(aaeon_mcu_i2c_xfer);
> +
> +static int aaeon_mcu_probe(struct i2c_client *client)
> +{
> +	struct aaeon_mcu_dev *mcu;
> +	int ret;
> +
> +	mcu = devm_kzalloc(&client->dev, sizeof(*mcu), GFP_KERNEL);
> +	if (!mcu)
> +		return -ENOMEM;
> +
> +	i2c_set_clientdata(client, mcu);
> +	mcu->dev = &client->dev;
> +	mutex_init(&mcu->i2c_lock);

For lock debugging purposes it's better to destroy the mutex too. Or use
devm_mutex_init().

> +
> +	ret = aaeon_mcu_print_fw_version(client);
> +	if (ret) {
> +		dev_err(&client->dev, "unable to read firmware version\n");
> +		return ret;
> +	}
> +
> +	return devm_mfd_add_devices(mcu->dev, PLATFORM_DEVID_NONE, aaeon_mcu_devs,
> +				    ARRAY_SIZE(aaeon_mcu_devs), NULL, 0, NULL);
> +}
> +
> +static const struct of_device_id aaeon_mcu_of_match[] = {
> +	{ .compatible = "aaeon,srg-imx8pl-mcu" },
> +	{},
> +};
> +

Unneeded newline.

> +MODULE_DEVICE_TABLE(of, aaeon_mcu_of_match);
> +
> +static struct i2c_driver aaeon_mcu_driver = {
> +	.driver = {
> +		.name = "aaeon_mcu",
> +		.of_match_table = aaeon_mcu_of_match,
> +	},
> +	.probe = aaeon_mcu_probe,
> +};
> +

Same here.

> +module_i2c_driver(aaeon_mcu_driver);
> +
> +MODULE_DESCRIPTION("Aaeon MCU Driver");
> +MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/aaeon-mcu.h b/include/linux/mfd/aaeon-mcu.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..c9dc7a9adbc86c489f03a550e7776d3b1da4e7b2
> --- /dev/null
> +++ b/include/linux/mfd/aaeon-mcu.h
> @@ -0,0 +1,31 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Aaeon MCU driver definitions
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
> +
> +#ifndef __LINUX_MFD_AAEON_MCU_H
> +#define __LINUX_MFD_AAEON_MCU_H
> +
> +#include <linux/mutex.h>
> +#include <linux/types.h>
> +
> +/**
> + * struct aaeon_mcu_dev - Internal representation of the Aaeon MCU
> + * @dev: Pointer to kernel device structure
> + * @i2c_lock: Mutex to serialize I2C bus access
> + */
> +

Kerneldocs should be attached to the struct they describe. But...

> +struct aaeon_mcu_dev {
> +	struct device *dev;
> +	struct mutex i2c_lock;
> +};

... you don't seem to need to export this structure. You don't use it at all
in the subsequent GPIO patch.

> +
> +int aaeon_mcu_i2c_xfer(struct device *dev,
> +		       const u8 *cmd, int cmd_len,
> +		       u8 *rsp, int rsp_len);
> +
> +#endif /*  __LINUX_MFD_AAEON_MCU_H */
>
> --
> 2.52.0
>
>

Bart

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU
  2026-01-23  9:54 ` [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
  2026-01-27  9:41   ` Linus Walleij
@ 2026-01-27  9:54   ` Bartosz Golaszewski
  1 sibling, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2026-01-27  9:54 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric)
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
	Lee Jones

On Fri, 23 Jan 2026 10:54:33 +0100, "Thomas Perrot (Schneider
Electric)" <thomas.perrot@bootlin.com> said:
> Add GPIO driver for the Aaeon SRG-IMX8PL embedded controller. This
> driver supports 7 GPO (General Purpose Output) pins and 12 GPIO pins
> that can be configured as inputs or outputs.
>
> The driver implements proper state management for GPO pins (which are
> output-only) and full direction control for GPIO pins. During probe,
> all pins are reset to a known state (GPOs low, GPIOs as inputs) to
> prevent undefined behavior across system reboots, as the MCU does not
> reset GPIO states on soft reboot.
>
> Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
> ---
>  MAINTAINERS                   |   1 +
>  drivers/gpio/Kconfig          |  10 ++
>  drivers/gpio/Makefile         |   1 +
>  drivers/gpio/gpio-aaeon-mcu.c | 238 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 250 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 175c1e1b28b8151580ed340207d4a6fd59aa8853..28dd964cdf69bdcaec3eb82d6df851a2bad47415 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -191,6 +191,7 @@ M:	Thomas Perrot <thomas.perrot@bootlin.com>
>  R:	Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/mfd/aaeon,srg-imx8pl-mcu.yaml
> +F:	drivers/gpio/gpio-aaeon-mcu.c
>  F:	drivers/mfd/aaeon-mcu.c
>  F:	include/linux/mfd/aaeon-mcu.h
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index c74da29253e810b51540684b1186e8f274066b69..6142d50b92b3d8c1fac8b0d81397dc22428fbb51 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -157,6 +157,16 @@ config GPIO_74XX_MMIO
>  	    8 bits:	74244 (Input), 74273 (Output)
>  	    16 bits:	741624 (Input), 7416374 (Output)
>
> +config GPIO_AAEON_MCU
> +	tristate "Aaeon MCU GPIO support"
> +	depends on MFD_AAEON_MCU

Can you add support for COMPILE_TEST here and in the MFD part?

> +	select GPIO_GENERIC
> +	help
> +	  Select this option to enable GPIO support for the Aaeon SRG-IMX8PL
> +	  onboard MCU. This driver provides access to GPIO pins and GPO
> +	  (General Purpose Output) pins controlled by the microcontroller.
> +	  The driver handles both input and output configuration.
> +
>  config GPIO_ALTERA
>  	tristate "Altera GPIO"
>  	select GPIOLIB_IRQCHIP
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 2421a8fd3733e0b06c2581262aaa9cd629f66c7d..1ba6318bc558743fbe5910966c2c8fc3f792efe9 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_104_IDI_48)		+= gpio-104-idi-48.o
>  obj-$(CONFIG_GPIO_104_IDIO_16)		+= gpio-104-idio-16.o
>  obj-$(CONFIG_GPIO_74X164)		+= gpio-74x164.o
>  obj-$(CONFIG_GPIO_74XX_MMIO)		+= gpio-74xx-mmio.o
> +obj-$(CONFIG_GPIO_AAEON_MCU)		+= gpio-aaeon-mcu.o
>  obj-$(CONFIG_GPIO_ADNP)			+= gpio-adnp.o
>  obj-$(CONFIG_GPIO_ADP5520)		+= gpio-adp5520.o
>  obj-$(CONFIG_GPIO_ADP5585)		+= gpio-adp5585.o
> diff --git a/drivers/gpio/gpio-aaeon-mcu.c b/drivers/gpio/gpio-aaeon-mcu.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..533eaf3e7f82f3b9e3f50a1a631c8e853adc1226
> --- /dev/null
> +++ b/drivers/gpio/gpio-aaeon-mcu.c
> @@ -0,0 +1,238 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Aaeon MCU GPIO driver
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/device.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/mfd/aaeon-mcu.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#define AAEON_MCU_CONFIG_GPIO_INPUT 0x69
> +#define AAEON_MCU_CONFIG_GPIO_OUTPUT 0x6F
> +#define AAEON_MCU_READ_GPIO 0x72
> +#define AAEON_MCU_WRITE_GPIO 0x77
> +
> +#define AAEON_MCU_CONTROL_GPO 0x6C
> +
> +#define MAX_GPIOS 12
> +#define MAX_GPOS 7
> +
> +struct aaeon_mcu_gpio {
> +	struct gpio_chip gc;
> +	struct device *dev;
> +	DECLARE_BITMAP(dir_in, MAX_GPOS + MAX_GPIOS);
> +	DECLARE_BITMAP(gpo_state, MAX_GPOS);
> +};
> +
> +static int aaeon_mcu_gpio_config_input_cmd(struct aaeon_mcu_gpio *data,
> +					    unsigned int offset)
> +{
> +	u8 cmd[3], rsp;
> +
> +	cmd[0] = AAEON_MCU_CONFIG_GPIO_INPUT;
> +	cmd[1] = offset - 7;
> +	cmd[2] = 0x00;
> +
> +	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +}
> +
> +static int aaeon_mcu_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
> +{
> +	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
> +	int ret;
> +
> +	if (offset < MAX_GPOS) {
> +		dev_err(gc->parent, "GPIO offset (%d) must be an output GPO\n", offset);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	ret = aaeon_mcu_gpio_config_input_cmd(data, offset);
> +	if (ret < 0)
> +		return ret;
> +
> +	__set_bit(offset, data->dir_in);
> +
> +	return 0;
> +}
> +
> +static int aaeon_mcu_gpio_config_output_cmd(struct aaeon_mcu_gpio *data,
> +					     unsigned int offset,
> +					     int value)
> +{
> +	u8 cmd[3], rsp;
> +	int ret;
> +
> +	cmd[0] = AAEON_MCU_CONFIG_GPIO_OUTPUT;
> +	cmd[1] = offset - 7;
> +	cmd[2] = 0x00;
> +
> +	ret = aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	cmd[0] = AAEON_MCU_WRITE_GPIO;
> +	/* cmd[1] = offset - 7; */
> +	cmd[2] = !!value;
> +
> +	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +}
> +
> +static int aaeon_mcu_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
> +{
> +	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
> +	int ret;
> +
> +	if (offset < MAX_GPOS)
> +		return 0;
> +
> +	ret = aaeon_mcu_gpio_config_output_cmd(data, offset, value);
> +	if (ret < 0)
> +		return ret;
> +
> +	__clear_bit(offset, data->dir_in);
> +
> +	return 0;
> +}
> +
> +static int aaeon_mcu_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
> +{
> +	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
> +
> +	return test_bit(offset, data->dir_in) ?
> +		GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
> +}
> +
> +static int aaeon_mcu_gpio_get(struct gpio_chip *gc, unsigned int offset)
> +{
> +	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
> +	u8 cmd[3], rsp;
> +	int ret;
> +
> +	if (offset < MAX_GPOS)
> +		return test_bit(offset, data->gpo_state);
> +
> +	cmd[0] = AAEON_MCU_READ_GPIO;
> +	cmd[1] = offset - 7;
> +	cmd[2] = 0x00;
> +
> +	ret = aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	return rsp;
> +}
> +
> +static int aaeon_mcu_gpo_set_cmd(struct aaeon_mcu_gpio *data, unsigned int offset, int value)
> +{
> +	u8 cmd[3], rsp;
> +
> +	cmd[0] = AAEON_MCU_CONTROL_GPO;
> +	cmd[1] = offset + 1;
> +	cmd[2] = !!value;
> +
> +	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +}
> +
> +static int aaeon_mcu_gpio_set_cmd(struct aaeon_mcu_gpio *data, unsigned int offset, int value)
> +{
> +	u8 cmd[3], rsp;
> +
> +	cmd[0] = AAEON_MCU_WRITE_GPIO;
> +	cmd[1] = offset - 7;
> +	cmd[2] = !!value;
> +
> +	return aaeon_mcu_i2c_xfer(data->dev, cmd, 3, &rsp, 1);
> +}
> +
> +static int aaeon_mcu_gpio_set(struct gpio_chip *gc, unsigned int offset,
> +			      int value)
> +{
> +	struct aaeon_mcu_gpio *data = gpiochip_get_data(gc);
> +
> +	if (offset >= MAX_GPOS)
> +		return aaeon_mcu_gpio_set_cmd(data, offset, value);
> +
> +	if (aaeon_mcu_gpo_set_cmd(data, offset, value) == 0)
> +		__assign_bit(offset, data->gpo_state, value);
> +
> +	return 0;
> +}
> +
> +static const struct gpio_chip aaeon_mcu_chip = {
> +	.label			= "gpio-aaeon-mcu",
> +	.owner			= THIS_MODULE,
> +	.get_direction		= aaeon_mcu_gpio_get_direction,
> +	.direction_input	= aaeon_mcu_gpio_direction_input,
> +	.direction_output	= aaeon_mcu_gpio_direction_output,
> +	.get			= aaeon_mcu_gpio_get,
> +	.set			= aaeon_mcu_gpio_set,
> +	.base			= -1,
> +	.ngpio			= MAX_GPOS + MAX_GPIOS,
> +	.can_sleep		= true,
> +};
> +
> +static void aaeon_mcu_gpio_reset(struct aaeon_mcu_gpio *data, struct device *dev)
> +{
> +	unsigned int i;
> +	int ret;
> +
> +	/* Reset all GPOs */
> +	for (i = 0; i < MAX_GPOS; i++) {
> +		ret = aaeon_mcu_gpo_set_cmd(data, i, 0);
> +		if (ret < 0)
> +			dev_warn(dev, "Failed to reset GPO %u state: %d\n", i, ret);
> +		__clear_bit(i, data->dir_in);
> +	}
> +
> +	/* Reset all GPIOs */
> +	for (i = MAX_GPOS; i < MAX_GPOS + MAX_GPIOS; i++) {
> +		ret = aaeon_mcu_gpio_config_input_cmd(data, i);
> +		if (ret < 0)
> +			dev_warn(dev, "Failed to reset GPIO %u state: %d\n", i, ret);
> +		__set_bit(i, data->dir_in);
> +	}
> +}
> +
> +static int aaeon_mcu_gpio_probe(struct platform_device *pdev)
> +{
> +	struct aaeon_mcu_gpio *data;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->dev = pdev->dev.parent;
> +	data->gc = aaeon_mcu_chip;
> +	data->gc.parent = data->dev;
> +
> +	/*
> +	 * Reset all GPIO states to a known configuration. The MCU does not
> +	 * reset GPIO state on soft reboot, only on power cycle (hard reboot).
> +	 * Without this reset, GPIOs would retain their previous state across
> +	 * reboots, which could lead to unexpected behavior.
> +	 */
> +	aaeon_mcu_gpio_reset(data, &pdev->dev);
> +
> +	return devm_gpiochip_add_data(&pdev->dev, &data->gc, data);
> +}
> +
> +static struct platform_driver aaeon_mcu_gpio_driver = {
> +	.driver = {
> +		.name = "aaeon-mcu-gpio",
> +	},
> +	.probe = aaeon_mcu_gpio_probe,
> +};
> +

Drop the newline.

> +module_platform_driver(aaeon_mcu_gpio_driver);
> +
> +MODULE_DESCRIPTION("GPIO interface for Aaeon MCU");
> +MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
> +MODULE_LICENSE("GPL");
>
> --
> 2.52.0
>
>

Looks pretty good, just some nits.

Bartosz

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-01-27  9:54 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-23  9:54 [PATCH v2 0/5] Add support for AAEON SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
2026-01-23  9:54 ` [PATCH v2 1/5] dt-bindings: vendor-prefixes: Add AAEON vendor prefix Thomas Perrot (Schneider Electric)
2026-01-23  9:54 ` [PATCH v2 2/5] dt-bindings: mfd: Add AAEON embedded controller Thomas Perrot (Schneider Electric)
2026-01-23 11:38   ` Rob Herring (Arm)
2026-01-23  9:54 ` [PATCH v2 3/5] mfd: aaeon: Add SRG-IMX8PL MCU driver Thomas Perrot (Schneider Electric)
2026-01-27  9:51   ` Bartosz Golaszewski
2026-01-23  9:54 ` [PATCH v2 4/5] gpio: aaeon: Add GPIO driver for SRG-IMX8PL MCU Thomas Perrot (Schneider Electric)
2026-01-27  9:41   ` Linus Walleij
2026-01-27  9:54   ` Bartosz Golaszewski
2026-01-23  9:54 ` [PATCH v2 5/5] watchdog: aaeon: Add watchdog " Thomas Perrot (Schneider Electric)
2026-01-23 16:11   ` Guenter Roeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®