public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
@ 2026-03-13 10:07 aspeedyh
  2026-03-13 10:07 ` [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller aspeedyh
                   ` (7 more replies)
  0 siblings, 8 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

This series adds initial support for the eSPI controller found on ASPEED
AST2600 BMC SoCs.

The series introduces a eSPI controller framework for ASPEED SoCs under
drivers/soc/aspeed/, adds AST2600-specific controller support for
peripheral and flash channels, defines the corresponding devicetree 
binding, and adds the AST2600 eSPI controller node to the SoC dtsi.

The driver is intended to support host-BMC communication over the BMC-side
eSPI slave controller present on AST2600 systems.

Patch summary:
1. dt-bindings: soc: aspeed: Add AST2600 eSPI controller
2. soc: aspeed: Introduce core eSPI controller support
3. soc: aspeed: Add AST2600 peripheral channel port I/O support
4. soc: aspeed: Add eSPI TAFS backend support
5. soc: aspeed: Add espi flash channel support
6. soc: aspeed: Add sysfs controls for flash LUN selection
7. arm: dts: aspeed: Add eSPI node for AST2600

This series has been tested on AST2600 platform with Intel's host eSPI
controller.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
aspeedyh (7):
      dt-bindings: soc: aspeed: Add AST2600 eSPI controller
      soc: aspeed: Introduce core eSPI controller support
      soc: aspeed: Add AST2600 peripheral channel port I/O support
      soc: aspeed: Add eSPI TAFS backend support
      soc: aspeed: Add eSPI flash channel support
      soc: aspeed: Add sysfs controls for flash backend selection
      arm: dts: aspeed: Add eSPI node for AST2600

 .../bindings/soc/aspeed/aspeed,ast2600-espi.yaml   |  74 +++
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi            |  11 +
 drivers/soc/aspeed/Kconfig                         |   7 +
 drivers/soc/aspeed/Makefile                        |   1 +
 drivers/soc/aspeed/espi/Makefile                   |   1 +
 drivers/soc/aspeed/espi/aspeed-espi-comm.h         |  62 +++
 drivers/soc/aspeed/espi/aspeed-espi.c              | 618 +++++++++++++++++++++
 drivers/soc/aspeed/espi/aspeed-espi.h              |  63 +++
 drivers/soc/aspeed/espi/ast2600-espi.c             | 304 ++++++++++
 drivers/soc/aspeed/espi/ast2600-espi.h             | 302 ++++++++++
 drivers/soc/aspeed/espi/espi_storage.c             | 322 +++++++++++
 drivers/soc/aspeed/espi/espi_storage.h             |  32 ++
 12 files changed, 1797 insertions(+)
---
base-commit: 0257f64bdac7fdca30fa3cae0df8b9ecbec7733a
change-id: 20260313-upstream_espi-d9fea66d1772

Best regards,
-- 
aspeedyh <yh_chung@aspeedtech.com>



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

* [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-16  7:07   ` Krzysztof Kozlowski
  2026-03-13 10:07 ` [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support aspeedyh
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

Introduce the device-tree bindings for the Enhanced Serial
Peripheral Interface (eSPI) controller found on AST2600
BMC SoCs.

The controller operates as the BMC-side eSPI slave and provides the
peripheral, virtual wire, out-of-band, and flash channels used for
host-BMC communication.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 .../bindings/soc/aspeed/aspeed,ast2600-espi.yaml   | 74 ++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed,ast2600-espi.yaml b/Documentation/devicetree/bindings/soc/aspeed/aspeed,ast2600-espi.yaml
new file mode 100644
index 000000000000..e22a10111138
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed,ast2600-espi.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (c) 2026 Aspeed Technology Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/aspeed/aspeed,ast2600-espi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASPEED AST2600 eSPI Controller
+
+maintainers:
+  - Yun-Hsuan Chung <yh_chung@aspeedtech.com>
+  - Ryan Chen <ryan_chen@aspeedtech.com>
+
+description: |
+  The ASPEED AST2600 BMC SoC provides an Enhanced Serial Peripheral
+  Interface (eSPI) controller used for host-BMC communication.
+
+  The controller supports the eSPI channels used for peripheral,
+  virtual wire, out-of-band, and flash communication.
+
+properties:
+  compatible:
+    const: aspeed,ast2600-espi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+    description:
+      Interrupt from the GIC for the eSPI controller.
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  pinctrl-names:
+    const: default
+
+  pinctrl-0:
+    maxItems: 1
+
+  aspeed,flash-dma-mode:
+    type: boolean
+    description:
+      Enable DMA support for eSPI flash channel
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - pinctrl-names
+  - pinctrl-0
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/aspeed-clock.h>
+    espi: espi@1e6ee000 {
+        compatible = "aspeed,ast2600-espi";
+        reg = <0x1e6ee000 0x1000>;
+        interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>;
+        resets = <&syscon 57>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_espi_default>;
+        aspeed,flash-dma-mode;
+    };

-- 
2.34.1



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

* [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
  2026-03-13 10:07 ` [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-16  9:57   ` Philipp Zabel
  2026-03-13 10:07 ` [PATCH 3/7] soc: aspeed: Add AST2600 peripheral channel port I/O support aspeedyh
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

Add core eSPI controller support and common code for ASPEED SoCs. The
eSPI engine is a slave device in BMC to communicate with the Host over
the eSPI interface.

The initial support includes basic eSPI driver probe/remove operations,
and provides operators for ASPEED SoCs to implement their own eSPI slave
device drivers that are different among SoC models.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 drivers/soc/aspeed/Kconfig            |   7 ++
 drivers/soc/aspeed/Makefile           |   1 +
 drivers/soc/aspeed/espi/Makefile      |   1 +
 drivers/soc/aspeed/espi/aspeed-espi.c | 143 ++++++++++++++++++++++++++++++++++
 drivers/soc/aspeed/espi/aspeed-espi.h |  27 +++++++
 5 files changed, 179 insertions(+)

diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
index f579ee0b5afa..677812fab11a 100644
--- a/drivers/soc/aspeed/Kconfig
+++ b/drivers/soc/aspeed/Kconfig
@@ -52,6 +52,13 @@ config ASPEED_SOCINFO
 	help
 	  Say yes to support decoding of ASPEED BMC information.
 
+config ASPEED_ESPI
+	tristate "ASPEED eSPI slave driver"
+	help
+	  Enable driver support for Aspeed eSPI controller. The eSPI controller
+	  plays as a slave device in BMC to communicate with the Host over the
+	  eSPI interface using peripheral, virtual wire, out of band, and flash
+	  channels.
 endmenu
 
 endif
diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
index b35d74592964..79d794de428a 100644
--- a/drivers/soc/aspeed/Makefile
+++ b/drivers/soc/aspeed/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP)		+= aspeed-lpc-snoop.o
 obj-$(CONFIG_ASPEED_UART_ROUTING)	+= aspeed-uart-routing.o
 obj-$(CONFIG_ASPEED_P2A_CTRL)		+= aspeed-p2a-ctrl.o
 obj-$(CONFIG_ASPEED_SOCINFO)		+= aspeed-socinfo.o
+obj-$(CONFIG_ASPEED_ESPI)		+= espi/
diff --git a/drivers/soc/aspeed/espi/Makefile b/drivers/soc/aspeed/espi/Makefile
new file mode 100644
index 000000000000..d96dc030e23b
--- /dev/null
+++ b/drivers/soc/aspeed/espi/Makefile
@@ -0,0 +1 @@
+obj-y += aspeed-espi.o
diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c b/drivers/soc/aspeed/espi/aspeed-espi.c
new file mode 100644
index 000000000000..15d58b38bbe4
--- /dev/null
+++ b/drivers/soc/aspeed/espi/aspeed-espi.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Unified Aspeed eSPI driver framework for different generation SoCs
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "aspeed-espi.h"
+
+struct aspeed_espi_ops {
+	void (*espi_pre_init)(struct aspeed_espi *espi);
+	void (*espi_post_init)(struct aspeed_espi *espi);
+	void (*espi_deinit)(struct aspeed_espi *espi);
+	irqreturn_t (*espi_isr)(int irq, void *espi);
+};
+
+static const struct of_device_id aspeed_espi_of_matches[] = {
+	{ }
+};
+MODULE_DEVICE_TABLE(of, aspeed_espi_of_matches);
+
+static int aspeed_espi_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct aspeed_espi *espi;
+	struct resource *res;
+	struct device *dev;
+	int rc;
+
+	dev = &pdev->dev;
+	espi = devm_kzalloc(dev, sizeof(*espi), GFP_KERNEL);
+	if (!espi)
+		return -ENOMEM;
+
+	espi->dev = dev;
+	match = of_match_device(aspeed_espi_of_matches, dev);
+	if (!match)
+		return -ENODEV;
+
+	espi->pdev = pdev;
+	espi->ops = match->data;
+	if (!espi->ops || !espi->ops->espi_isr)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "cannot get resource\n");
+		return -ENODEV;
+	}
+
+	espi->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(espi->regs)) {
+		dev_err(dev, "cannot map registers\n");
+		return PTR_ERR(espi->regs);
+	}
+
+	espi->irq = platform_get_irq(pdev, 0);
+	if (espi->irq < 0) {
+		dev_err(dev, "cannot get IRQ number\n");
+		return espi->irq;
+	}
+
+	espi->rst = devm_reset_control_get_optional(dev, NULL);
+	if (IS_ERR(espi->rst)) {
+		dev_err(dev, "cannot get reset control\n");
+		return PTR_ERR(espi->rst);
+	}
+
+	espi->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(espi->clk)) {
+		dev_err(dev, "cannot get clock control\n");
+		return PTR_ERR(espi->clk);
+	}
+
+	rc = clk_prepare_enable(espi->clk);
+	if (rc) {
+		dev_err(dev, "cannot enable clocks\n");
+		return rc;
+	}
+
+	if (espi->ops->espi_pre_init)
+		espi->ops->espi_pre_init(espi);
+
+	rc = devm_request_irq(dev, espi->irq, espi->ops->espi_isr, 0,
+			      dev_name(dev), espi);
+	if (rc) {
+		dev_err(dev, "cannot request IRQ\n");
+		goto err_deinit;
+	}
+
+	if (espi->ops->espi_post_init)
+		espi->ops->espi_post_init(espi);
+
+	platform_set_drvdata(pdev, espi);
+
+	dev_info(dev, "module loaded\n");
+
+	return 0;
+
+err_deinit:
+	if (espi->ops->espi_deinit)
+		espi->ops->espi_deinit(espi);
+	clk_disable_unprepare(espi->clk);
+
+	return rc;
+}
+
+static void aspeed_espi_remove(struct platform_device *pdev)
+{
+	struct aspeed_espi *espi;
+
+	espi = platform_get_drvdata(pdev);
+
+	if (!espi)
+		return;
+
+	if (espi->ops->espi_deinit)
+		espi->ops->espi_deinit(espi);
+
+	clk_disable_unprepare(espi->clk);
+}
+
+static struct platform_driver aspeed_espi_driver = {
+	.driver = {
+		.name = "aspeed-espi",
+		.of_match_table = aspeed_espi_of_matches,
+	},
+	.probe = aspeed_espi_probe,
+	.remove = aspeed_espi_remove,
+};
+
+module_platform_driver(aspeed_espi_driver);
+
+MODULE_AUTHOR("Aspeed Technology Inc.");
+MODULE_DESCRIPTION("Aspeed eSPI controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/aspeed/espi/aspeed-espi.h b/drivers/soc/aspeed/espi/aspeed-espi.h
new file mode 100644
index 000000000000..f4ad7f61fef6
--- /dev/null
+++ b/drivers/soc/aspeed/espi/aspeed-espi.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Unified eSPI driver header file and data structures
+ * Copyright 2026 Aspeed Technology Inc.
+ */
+#ifndef ASPEED_ESPI_H
+#define ASPEED_ESPI_H
+
+#include <linux/irqreturn.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define DEVICE_NAME		"aspeed-espi"
+
+struct aspeed_espi {
+	struct platform_device *pdev;
+	struct device *dev;
+	void __iomem *regs;
+	struct reset_control *rst;
+	struct clk *clk;
+	int dev_id;
+	int irq;
+	const struct aspeed_espi_ops *ops;
+};
+
+#endif

-- 
2.34.1



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

* [PATCH 3/7] soc: aspeed: Add AST2600 peripheral channel port I/O support
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
  2026-03-13 10:07 ` [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller aspeedyh
  2026-03-13 10:07 ` [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-13 10:07 ` [PATCH 4/7] soc: aspeed: Add eSPI TAFS backend support aspeedyh
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

Add initial support for the AST2600 eSPI peripheral channel handling of
port I/O transactions used for LPC-style accesses.

This patch does not yet implement peripheral memory read or write
cycles. Support for those transactions will be added in a follow-up
patch once the remaining transport and buffer handling pieces are in
place.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 drivers/soc/aspeed/espi/Makefile       |   2 +-
 drivers/soc/aspeed/espi/aspeed-espi.c  |  24 +++
 drivers/soc/aspeed/espi/ast2600-espi.c | 139 ++++++++++++++++
 drivers/soc/aspeed/espi/ast2600-espi.h | 291 +++++++++++++++++++++++++++++++++
 4 files changed, 455 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/aspeed/espi/Makefile b/drivers/soc/aspeed/espi/Makefile
index d96dc030e23b..30f9dbf92a0f 100644
--- a/drivers/soc/aspeed/espi/Makefile
+++ b/drivers/soc/aspeed/espi/Makefile
@@ -1 +1 @@
-obj-y += aspeed-espi.o
+obj-y += aspeed-espi.o ast2600-espi.o
diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c b/drivers/soc/aspeed/espi/aspeed-espi.c
index 15d58b38bbe4..e369738119bc 100644
--- a/drivers/soc/aspeed/espi/aspeed-espi.c
+++ b/drivers/soc/aspeed/espi/aspeed-espi.c
@@ -13,15 +13,28 @@
 #include <linux/reset.h>
 
 #include "aspeed-espi.h"
+#include "ast2600-espi.h"
 
 struct aspeed_espi_ops {
 	void (*espi_pre_init)(struct aspeed_espi *espi);
 	void (*espi_post_init)(struct aspeed_espi *espi);
 	void (*espi_deinit)(struct aspeed_espi *espi);
+	int (*espi_perif_probe)(struct aspeed_espi *espi);
+	int (*espi_perif_remove)(struct aspeed_espi *espi);
 	irqreturn_t (*espi_isr)(int irq, void *espi);
 };
 
+static const struct aspeed_espi_ops aspeed_espi_ast2600_ops = {
+	.espi_pre_init = ast2600_espi_pre_init,
+	.espi_post_init = ast2600_espi_post_init,
+	.espi_deinit = ast2600_espi_deinit,
+	.espi_perif_probe = ast2600_espi_perif_probe,
+	.espi_perif_remove = ast2600_espi_perif_remove,
+	.espi_isr = ast2600_espi_isr,
+};
+
 static const struct of_device_id aspeed_espi_of_matches[] = {
+	{ .compatible = "aspeed,ast2600-espi", .data = &aspeed_espi_ast2600_ops },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, aspeed_espi_of_matches);
@@ -88,6 +101,14 @@ static int aspeed_espi_probe(struct platform_device *pdev)
 	if (espi->ops->espi_pre_init)
 		espi->ops->espi_pre_init(espi);
 
+	if (espi->ops->espi_perif_probe) {
+		rc = espi->ops->espi_perif_probe(espi);
+		if (rc) {
+			dev_err(dev, "cannot init peripheral channel, rc=%d\n", rc);
+			goto err_deinit;
+		}
+	}
+
 	rc = devm_request_irq(dev, espi->irq, espi->ops->espi_isr, 0,
 			      dev_name(dev), espi);
 	if (rc) {
@@ -121,6 +142,9 @@ static void aspeed_espi_remove(struct platform_device *pdev)
 	if (!espi)
 		return;
 
+	if (espi->ops->espi_perif_remove)
+		espi->ops->espi_perif_remove(espi);
+
 	if (espi->ops->espi_deinit)
 		espi->ops->espi_deinit(espi);
 
diff --git a/drivers/soc/aspeed/espi/ast2600-espi.c b/drivers/soc/aspeed/espi/ast2600-espi.c
new file mode 100644
index 000000000000..8effd0404d1f
--- /dev/null
+++ b/drivers/soc/aspeed/espi/ast2600-espi.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright Aspeed Technology Inc.
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/reset.h>
+
+#include "aspeed-espi.h"
+#include "ast2600-espi.h"
+
+static void ast2600_espi_perif_isr(struct aspeed_espi *espi)
+{
+	u32 sts;
+
+	sts = readl(espi->regs + ESPI_INT_STS);
+
+	if (sts & ESPI_INT_STS_PERIF_PC_RX_CMPLT)
+		writel(ESPI_INT_STS_PERIF_PC_RX_CMPLT, espi->regs + ESPI_INT_STS);
+}
+
+static void ast2600_espi_perif_sw_reset(struct aspeed_espi *espi)
+{
+	u32 reg;
+
+	reg = readl(espi->regs + ESPI_CTRL);
+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_SW_RST
+		 | ESPI_CTRL_PERIF_NP_RX_SW_RST
+		 | ESPI_CTRL_PERIF_PC_TX_SW_RST
+		 | ESPI_CTRL_PERIF_PC_RX_SW_RST
+		 | ESPI_CTRL_PERIF_NP_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
+		 | ESPI_CTRL_PERIF_SW_RDY);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	udelay(1);
+
+	reg |= (ESPI_CTRL_PERIF_NP_TX_SW_RST
+		| ESPI_CTRL_PERIF_NP_RX_SW_RST
+		| ESPI_CTRL_PERIF_PC_TX_SW_RST
+		| ESPI_CTRL_PERIF_PC_RX_SW_RST);
+	writel(reg, espi->regs + ESPI_CTRL);
+}
+
+static void ast2600_espi_perif_reset(struct aspeed_espi *espi)
+{
+	u32 reg;
+
+	writel(ESPI_INT_EN_PERIF, espi->regs + ESPI_INT_EN_CLR);
+	writel(ESPI_INT_STS_PERIF, espi->regs + ESPI_INT_STS);
+
+	writel(0x0, espi->regs + ESPI_MMBI_INT_EN);
+	writel(0xffffffff, espi->regs + ESPI_MMBI_INT_STS);
+
+	reg = readl(espi->regs + ESPI_CTRL2);
+	reg &= ~(ESPI_CTRL2_MCYC_RD_DIS_WDT | ESPI_CTRL2_MCYC_WR_DIS_WDT);
+	writel(reg, espi->regs + ESPI_CTRL2);
+
+	reg = readl(espi->regs + ESPI_CTRL);
+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
+		 | ESPI_CTRL_PERIF_SW_RDY);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_PERIF_SW_RDY;
+	writel(reg, espi->regs + ESPI_CTRL);
+}
+
+int ast2600_espi_perif_probe(struct aspeed_espi *espi)
+{
+	ast2600_espi_perif_reset(espi);
+	return 0;
+}
+
+int ast2600_espi_perif_remove(struct aspeed_espi *espi)
+{
+	u32 reg;
+
+	writel(ESPI_INT_EN_PERIF, espi->regs + ESPI_INT_EN_CLR);
+
+	reg = readl(espi->regs + ESPI_CTRL2);
+	reg |= (ESPI_CTRL2_MCYC_RD_DIS | ESPI_CTRL2_MCYC_WR_DIS);
+	writel(reg, espi->regs + ESPI_CTRL2);
+
+	reg = readl(espi->regs + ESPI_CTRL);
+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
+		 | ESPI_CTRL_PERIF_SW_RDY);
+	writel(reg, espi->regs + ESPI_CTRL);
+	return 0;
+}
+
+/* global control */
+irqreturn_t ast2600_espi_isr(int irq, void *arg)
+{
+	struct aspeed_espi *espi;
+	u32 sts;
+
+	espi = (struct aspeed_espi *)arg;
+	sts = readl(espi->regs + ESPI_INT_STS);
+
+	if (!sts)
+		return IRQ_NONE;
+
+	if (sts & ESPI_INT_STS_PERIF)
+		ast2600_espi_perif_isr(espi);
+
+	if (sts & ESPI_INT_STS_RST_DEASSERT) {
+		/* this will clear all interrupt enable and status */
+		reset_control_assert(espi->rst);
+		reset_control_deassert(espi->rst);
+
+		ast2600_espi_perif_sw_reset(espi);
+		ast2600_espi_perif_reset(espi);
+
+		/* re-enable eSPI_RESET# interrupt */
+		writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void ast2600_espi_pre_init(struct aspeed_espi *espi)
+{
+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN_CLR);
+}
+
+void ast2600_espi_post_init(struct aspeed_espi *espi)
+{
+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN);
+}
+
+void ast2600_espi_deinit(struct aspeed_espi *espi)
+{
+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN_CLR);
+}
diff --git a/drivers/soc/aspeed/espi/ast2600-espi.h b/drivers/soc/aspeed/espi/ast2600-espi.h
new file mode 100644
index 000000000000..309479ee1187
--- /dev/null
+++ b/drivers/soc/aspeed/espi/ast2600-espi.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Register definitions for Aspeed AST2600 eSPI controller
+ * Copyright 2026 Aspeed Technology Inc.
+ */
+#ifndef AST2600_ESPI_H
+#define AST2600_ESPI_H
+
+#include <linux/bits.h>
+#include <linux/irqreturn.h>
+#include "aspeed-espi.h"
+
+/* registers */
+#define ESPI_CTRL				0x000
+#define   ESPI_CTRL_FLASH_TX_SW_RST		BIT(31)
+#define   ESPI_CTRL_FLASH_RX_SW_RST		BIT(30)
+#define   ESPI_CTRL_OOB_TX_SW_RST		BIT(29)
+#define   ESPI_CTRL_OOB_RX_SW_RST		BIT(28)
+#define   ESPI_CTRL_PERIF_NP_TX_SW_RST		BIT(27)
+#define   ESPI_CTRL_PERIF_NP_RX_SW_RST		BIT(26)
+#define   ESPI_CTRL_PERIF_PC_TX_SW_RST		BIT(25)
+#define   ESPI_CTRL_PERIF_PC_RX_SW_RST		BIT(24)
+#define   ESPI_CTRL_FLASH_TX_DMA_EN		BIT(23)
+#define   ESPI_CTRL_FLASH_RX_DMA_EN		BIT(22)
+#define   ESPI_CTRL_OOB_TX_DMA_EN		BIT(21)
+#define   ESPI_CTRL_OOB_RX_DMA_EN		BIT(20)
+#define   ESPI_CTRL_PERIF_NP_TX_DMA_EN		BIT(19)
+#define   ESPI_CTRL_PERIF_PC_TX_DMA_EN		BIT(17)
+#define   ESPI_CTRL_PERIF_PC_RX_DMA_EN		BIT(16)
+#define   ESPI_CTRL_FLASH_EDAF_MODE		GENMASK(11, 10)
+#define   ESPI_CTRL_VW_GPIO_SW			BIT(9)
+#define   ESPI_CTRL_FLASH_SW_RDY		BIT(7)
+#define   ESPI_CTRL_OOB_SW_RDY			BIT(4)
+#define   ESPI_CTRL_VW_SW_RDY			BIT(3)
+#define   ESPI_CTRL_PERIF_SW_RDY		BIT(1)
+#define ESPI_STS				0x004
+#define ESPI_INT_STS				0x008
+#define   ESPI_INT_STS_RST_DEASSERT		BIT(31)
+#define   ESPI_INT_STS_OOB_RX_TMOUT		BIT(23)
+#define   ESPI_INT_STS_VW_SYSEVT1		BIT(22)
+#define   ESPI_INT_STS_FLASH_TX_ERR		BIT(21)
+#define   ESPI_INT_STS_OOB_TX_ERR		BIT(20)
+#define   ESPI_INT_STS_FLASH_TX_ABT		BIT(19)
+#define   ESPI_INT_STS_OOB_TX_ABT		BIT(18)
+#define   ESPI_INT_STS_PERIF_NP_TX_ABT		BIT(17)
+#define   ESPI_INT_STS_PERIF_PC_TX_ABT		BIT(16)
+#define   ESPI_INT_STS_FLASH_RX_ABT		BIT(15)
+#define   ESPI_INT_STS_OOB_RX_ABT		BIT(14)
+#define   ESPI_INT_STS_PERIF_NP_RX_ABT		BIT(13)
+#define   ESPI_INT_STS_PERIF_PC_RX_ABT		BIT(12)
+#define   ESPI_INT_STS_PERIF_NP_TX_ERR		BIT(11)
+#define   ESPI_INT_STS_PERIF_PC_TX_ERR		BIT(10)
+#define   ESPI_INT_STS_VW_GPIO			BIT(9)
+#define   ESPI_INT_STS_VW_SYSEVT		BIT(8)
+#define   ESPI_INT_STS_FLASH_TX_CMPLT		BIT(7)
+#define   ESPI_INT_STS_FLASH_RX_CMPLT		BIT(6)
+#define   ESPI_INT_STS_OOB_TX_CMPLT		BIT(5)
+#define   ESPI_INT_STS_OOB_RX_CMPLT		BIT(4)
+#define   ESPI_INT_STS_PERIF_NP_TX_CMPLT	BIT(3)
+#define   ESPI_INT_STS_PERIF_PC_TX_CMPLT	BIT(1)
+#define   ESPI_INT_STS_PERIF_PC_RX_CMPLT	BIT(0)
+#define ESPI_INT_EN				0x00c
+#define   ESPI_INT_EN_RST_DEASSERT		BIT(31)
+#define   ESPI_INT_EN_OOB_RX_TMOUT		BIT(23)
+#define   ESPI_INT_EN_VW_SYSEVT1		BIT(22)
+#define   ESPI_INT_EN_FLASH_TX_ERR		BIT(21)
+#define   ESPI_INT_EN_OOB_TX_ERR		BIT(20)
+#define   ESPI_INT_EN_FLASH_TX_ABT		BIT(19)
+#define   ESPI_INT_EN_OOB_TX_ABT		BIT(18)
+#define   ESPI_INT_EN_PERIF_NP_TX_ABT		BIT(17)
+#define   ESPI_INT_EN_PERIF_PC_TX_ABT		BIT(16)
+#define   ESPI_INT_EN_FLASH_RX_ABT		BIT(15)
+#define   ESPI_INT_EN_OOB_RX_ABT		BIT(14)
+#define   ESPI_INT_EN_PERIF_NP_RX_ABT		BIT(13)
+#define   ESPI_INT_EN_PERIF_PC_RX_ABT		BIT(12)
+#define   ESPI_INT_EN_PERIF_NP_TX_ERR		BIT(11)
+#define   ESPI_INT_EN_PERIF_PC_TX_ERR		BIT(10)
+#define   ESPI_INT_EN_VW_GPIO			BIT(9)
+#define   ESPI_INT_EN_VW_SYSEVT			BIT(8)
+#define   ESPI_INT_EN_FLASH_TX_CMPLT		BIT(7)
+#define   ESPI_INT_EN_FLASH_RX_CMPLT		BIT(6)
+#define   ESPI_INT_EN_OOB_TX_CMPLT		BIT(5)
+#define   ESPI_INT_EN_OOB_RX_CMPLT		BIT(4)
+#define   ESPI_INT_EN_PERIF_NP_TX_CMPLT		BIT(3)
+#define   ESPI_INT_EN_PERIF_PC_TX_CMPLT		BIT(1)
+#define   ESPI_INT_EN_PERIF_PC_RX_CMPLT		BIT(0)
+#define ESPI_PERIF_PC_RX_DMA			0x010
+#define ESPI_PERIF_PC_RX_CTRL			0x014
+#define   ESPI_PERIF_PC_RX_CTRL_SERV_PEND	BIT(31)
+#define   ESPI_PERIF_PC_RX_CTRL_LEN		GENMASK(23, 12)
+#define   ESPI_PERIF_PC_RX_CTRL_TAG		GENMASK(11, 8)
+#define   ESPI_PERIF_PC_RX_CTRL_CYC		GENMASK(7, 0)
+#define ESPI_PERIF_PC_RX_DATA			0x018
+#define ESPI_PERIF_PC_TX_DMA			0x020
+#define ESPI_PERIF_PC_TX_CTRL			0x024
+#define	  ESPI_PERIF_PC_TX_CTRL_TRIG_PEND	BIT(31)
+#define	  ESPI_PERIF_PC_TX_CTRL_LEN		GENMASK(23, 12)
+#define	  ESPI_PERIF_PC_TX_CTRL_TAG		GENMASK(11, 8)
+#define	  ESPI_PERIF_PC_TX_CTRL_CYC		GENMASK(7, 0)
+#define ESPI_PERIF_PC_TX_DATA			0x028
+#define ESPI_PERIF_NP_TX_DMA			0x030
+#define ESPI_PERIF_NP_TX_CTRL			0x034
+#define   ESPI_PERIF_NP_TX_CTRL_TRIG_PEND	BIT(31)
+#define	  ESPI_PERIF_NP_TX_CTRL_LEN		GENMASK(23, 12)
+#define	  ESPI_PERIF_NP_TX_CTRL_TAG		GENMASK(11, 8)
+#define	  ESPI_PERIF_NP_TX_CTRL_CYC		GENMASK(7, 0)
+#define ESPI_PERIF_NP_TX_DATA			0x038
+#define ESPI_OOB_RX_DMA				0x040
+#define ESPI_OOB_RX_CTRL			0x044
+#define	  ESPI_OOB_RX_CTRL_SERV_PEND		BIT(31)
+#define	  ESPI_OOB_RX_CTRL_LEN			GENMASK(23, 12)
+#define	  ESPI_OOB_RX_CTRL_TAG			GENMASK(11, 8)
+#define	  ESPI_OOB_RX_CTRL_CYC			GENMASK(7, 0)
+#define ESPI_OOB_RX_DATA			0x048
+#define ESPI_OOB_TX_DMA				0x050
+#define ESPI_OOB_TX_CTRL			0x054
+#define	  ESPI_OOB_TX_CTRL_TRIG_PEND		BIT(31)
+#define	  ESPI_OOB_TX_CTRL_LEN			GENMASK(23, 12)
+#define	  ESPI_OOB_TX_CTRL_TAG			GENMASK(11, 8)
+#define	  ESPI_OOB_TX_CTRL_CYC			GENMASK(7, 0)
+#define ESPI_OOB_TX_DATA			0x058
+#define ESPI_FLASH_RX_DMA			0x060
+#define ESPI_FLASH_RX_CTRL			0x064
+#define	  ESPI_FLASH_RX_CTRL_SERV_PEND		BIT(31)
+#define	  ESPI_FLASH_RX_CTRL_LEN		GENMASK(23, 12)
+#define	  ESPI_FLASH_RX_CTRL_TAG		GENMASK(11, 8)
+#define	  ESPI_FLASH_RX_CTRL_CYC		GENMASK(7, 0)
+#define ESPI_FLASH_RX_DATA			0x068
+#define ESPI_FLASH_TX_DMA			0x070
+#define ESPI_FLASH_TX_CTRL			0x074
+#define	  ESPI_FLASH_TX_CTRL_TRIG_PEND		BIT(31)
+#define	  ESPI_FLASH_TX_CTRL_LEN		GENMASK(23, 12)
+#define	  ESPI_FLASH_TX_CTRL_TAG		GENMASK(11, 8)
+#define	  ESPI_FLASH_TX_CTRL_CYC		GENMASK(7, 0)
+#define ESPI_FLASH_TX_DATA			0x078
+#define ESPI_CTRL2				0x080
+#define   ESPI_CTRL2_VW_TX_SORT			BIT(30)
+#define   ESPI_CTRL2_MCYC_RD_DIS_WDT		BIT(11)
+#define   ESPI_CTRL2_MCYC_WR_DIS_WDT		BIT(10)
+#define   ESPI_CTRL2_MCYC_RD_DIS		BIT(6)
+#define   ESPI_CTRL2_MMBI_RD_DIS		ESPI_CTRL2_MCYC_RD_DIS
+#define   ESPI_CTRL2_MCYC_WR_DIS		BIT(4)
+#define   ESPI_CTRL2_MMBI_WR_DIS		ESPI_CTRL2_MCYC_WR_DIS
+#define ESPI_PERIF_MCYC_SADDR			0x084
+#define ESPI_PERIF_MMBI_SADDR			ESPI_PERIF_MCYC_SADDR
+#define ESPI_PERIF_MCYC_TADDR			0x088
+#define ESPI_PERIF_MMBI_TADDR			ESPI_PERIF_MCYC_TADDR
+#define ESPI_PERIF_MCYC_MASK			0x08c
+#define ESPI_PERIF_MMBI_MASK			ESPI_PERIF_MCYC_MASK
+#define ESPI_FLASH_EDAF_TADDR			0x090
+#define   ESPI_FLASH_EDAF_TADDR_BASE		GENMASK(31, 24)
+#define   ESPI_FLASH_EDAF_TADDR_MASK		GENMASK(15, 8)
+#define ESPI_VW_SYSEVT_INT_EN			0x094
+#define ESPI_VW_SYSEVT				0x098
+#define   ESPI_VW_SYSEVT_HOST_RST_ACK		BIT(27)
+#define   ESPI_VW_SYSEVT_RST_CPU_INIT		BIT(26)
+#define   ESPI_VW_SYSEVT_SLV_BOOT_STS		BIT(23)
+#define   ESPI_VW_SYSEVT_NON_FATAL_ERR		BIT(22)
+#define   ESPI_VW_SYSEVT_FATAL_ERR		BIT(21)
+#define   ESPI_VW_SYSEVT_SLV_BOOT_DONE		BIT(20)
+#define   ESPI_VW_SYSEVT_OOB_RST_ACK		BIT(16)
+#define   ESPI_VW_SYSEVT_NMI_OUT		BIT(10)
+#define   ESPI_VW_SYSEVT_SMI_OUT		BIT(9)
+#define   ESPI_VW_SYSEVT_HOST_RST_WARN		BIT(8)
+#define   ESPI_VW_SYSEVT_OOB_RST_WARN		BIT(6)
+#define   ESPI_VW_SYSEVT_PLTRSTN		BIT(5)
+#define   ESPI_VW_SYSEVT_SUSPEND		BIT(4)
+#define   ESPI_VW_SYSEVT_S5_SLEEP		BIT(2)
+#define   ESPI_VW_SYSEVT_S4_SLEEP		BIT(1)
+#define   ESPI_VW_SYSEVT_S3_SLEEP		BIT(0)
+#define ESPI_VW_GPIO_VAL			0x09c
+#define ESPI_GEN_CAP_N_CONF			0x0a0
+#define ESPI_CH0_CAP_N_CONF			0x0a4
+#define ESPI_CH1_CAP_N_CONF			0x0a8
+#define ESPI_CH2_CAP_N_CONF			0x0ac
+#define ESPI_CH3_CAP_N_CONF			0x0b0
+#define ESPI_CH3_CAP_N_CONF2			0x0b4
+#define ESPI_VW_GPIO_DIR			0x0c0
+#define ESPI_VW_GPIO_GRP			0x0c4
+#define ESPI_INT_EN_CLR				0x0fc
+#define ESPI_VW_SYSEVT1_INT_EN			0x100
+#define ESPI_VW_SYSEVT1				0x104
+#define   ESPI_VW_SYSEVT1_SUSPEND_ACK		BIT(20)
+#define   ESPI_VW_SYSEVT1_SUSPEND_WARN		BIT(0)
+#define ESPI_VW_SYSEVT_INT_T0			0x110
+#define ESPI_VW_SYSEVT_INT_T1			0x114
+#define ESPI_VW_SYSEVT_INT_T2			0x118
+#define ESPI_VW_SYSEVT_INT_STS			0x11c
+#define ESPI_VW_SYSEVT1_INT_T0			0x120
+#define ESPI_VW_SYSEVT1_INT_T1			0x124
+#define ESPI_VW_SYSEVT1_INT_T2			0x128
+#define ESPI_VW_SYSEVT1_INT_STS			0x12c
+#define ESPI_OOB_RX_DESC_NUM			0x130
+#define ESPI_OOB_RX_DESC_RPTR			0x134
+#define	  ESPI_OOB_RX_DESC_RPTR_UPDATE		BIT(31)
+#define   ESPI_OOB_RX_DESC_RPTR_RP		GENMASK(11, 0)
+#define ESPI_OOB_RX_DESC_WPTR			0x138
+#define   ESPI_OOB_RX_DESC_WPTR_RECV_EN		BIT(31)
+#define   ESPI_OOB_RX_DESC_WPTR_SP		GENMASK(27, 16)
+#define   ESPI_OOB_RX_DESC_WPTR_WP		GENMASK(11, 0)
+#define ESPI_OOB_TX_DESC_NUM			0x140
+#define ESPI_OOB_TX_DESC_RPTR			0x144
+#define	  ESPI_OOB_TX_DESC_RPTR_UPDATE		BIT(31)
+#define ESPI_OOB_TX_DESC_WPTR			0x148
+#define	  ESPI_OOB_TX_DESC_WPTR_SEND_EN		BIT(31)
+#define ESPI_MMBI_CTRL				0x800
+#define   ESPI_MMBI_CTRL_INST_SZ		GENMASK(10, 8)
+#define   ESPI_MMBI_CTRL_TOTAL_SZ		GENMASK(6, 4)
+#define   ESPI_MMBI_CTRL_EN			BIT(0)
+#define ESPI_MMBI_INT_STS			0x808
+#define ESPI_MMBI_INT_EN			0x80c
+#define ESPI_MMBI_HOST_RWP(x)			(0x810 + ((x) << 3))
+
+/* collect ESPI_INT_EN bits for convenience */
+#define ESPI_INT_EN_PERIF			\
+	(ESPI_INT_EN_PERIF_NP_TX_ABT |		\
+	 ESPI_INT_EN_PERIF_PC_TX_ABT |		\
+	 ESPI_INT_EN_PERIF_NP_RX_ABT |		\
+	 ESPI_INT_EN_PERIF_PC_RX_ABT |		\
+	 ESPI_INT_EN_PERIF_NP_TX_ERR |		\
+	 ESPI_INT_EN_PERIF_PC_TX_ERR |		\
+	 ESPI_INT_EN_PERIF_NP_TX_CMPLT |	\
+	 ESPI_INT_EN_PERIF_PC_TX_CMPLT |	\
+	 ESPI_INT_EN_PERIF_PC_RX_CMPLT)
+
+#define ESPI_INT_EN_VW			\
+	(ESPI_INT_EN_VW_SYSEVT1 |	\
+	 ESPI_INT_EN_VW_GPIO    |	\
+	 ESPI_INT_EN_VW_SYSEVT)
+
+#define ESPI_INT_EN_OOB		\
+	(ESPI_INT_EN_OOB_RX_TMOUT |	\
+	 ESPI_INT_EN_OOB_TX_ERR |	\
+	 ESPI_INT_EN_OOB_TX_ABT |	\
+	 ESPI_INT_EN_OOB_RX_ABT |	\
+	 ESPI_INT_EN_OOB_TX_CMPLT |	\
+	 ESPI_INT_EN_OOB_RX_CMPLT)
+
+#define ESPI_INT_EN_FLASH		\
+	(ESPI_INT_EN_FLASH_TX_ERR |	\
+	 ESPI_INT_EN_FLASH_TX_ABT |	\
+	 ESPI_INT_EN_FLASH_RX_ABT |	\
+	 ESPI_INT_EN_FLASH_TX_CMPLT |	\
+	 ESPI_INT_EN_FLASH_RX_CMPLT)
+
+/* collect ESPI_INT_STS bits for convenience */
+#define ESPI_INT_STS_PERIF			\
+	(ESPI_INT_STS_PERIF_NP_TX_ABT |		\
+	 ESPI_INT_STS_PERIF_PC_TX_ABT |		\
+	 ESPI_INT_STS_PERIF_NP_RX_ABT |		\
+	 ESPI_INT_STS_PERIF_PC_RX_ABT |		\
+	 ESPI_INT_STS_PERIF_NP_TX_ERR |		\
+	 ESPI_INT_STS_PERIF_PC_TX_ERR |		\
+	 ESPI_INT_STS_PERIF_NP_TX_CMPLT |	\
+	 ESPI_INT_STS_PERIF_PC_TX_CMPLT |	\
+	 ESPI_INT_STS_PERIF_PC_RX_CMPLT)
+
+#define ESPI_INT_STS_VW			\
+	(ESPI_INT_STS_VW_SYSEVT1 |	\
+	 ESPI_INT_STS_VW_GPIO    |	\
+	 ESPI_INT_STS_VW_SYSEVT)
+
+#define ESPI_INT_STS_OOB		\
+	(ESPI_INT_STS_OOB_RX_TMOUT |	\
+	 ESPI_INT_STS_OOB_TX_ERR |	\
+	 ESPI_INT_STS_OOB_TX_ABT |	\
+	 ESPI_INT_STS_OOB_RX_ABT |	\
+	 ESPI_INT_STS_OOB_TX_CMPLT |	\
+	 ESPI_INT_STS_OOB_RX_CMPLT)
+
+#define ESPI_INT_STS_FLASH		\
+	(ESPI_INT_STS_FLASH_TX_ERR |	\
+	 ESPI_INT_STS_FLASH_TX_ABT |	\
+	 ESPI_INT_STS_FLASH_RX_ABT |	\
+	 ESPI_INT_STS_FLASH_TX_CMPLT |	\
+	 ESPI_INT_STS_FLASH_RX_CMPLT)
+
+/* function operators */
+void ast2600_espi_pre_init(struct aspeed_espi *espi);
+void ast2600_espi_post_init(struct aspeed_espi *espi);
+void ast2600_espi_deinit(struct aspeed_espi *espi);
+int ast2600_espi_perif_probe(struct aspeed_espi *espi);
+int ast2600_espi_perif_remove(struct aspeed_espi *espi);
+int ast2600_espi_vw_probe(struct aspeed_espi *espi);
+int ast2600_espi_vw_remove(struct aspeed_espi *espi);
+int ast2600_espi_oob_probe(struct aspeed_espi *espi);
+int ast2600_espi_oob_remove(struct aspeed_espi *espi);
+int ast2600_espi_flash_probe(struct aspeed_espi *espi);
+int ast2600_espi_flash_remove(struct aspeed_espi *espi);
+irqreturn_t ast2600_espi_isr(int irq, void *arg);
+#endif

-- 
2.34.1



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

* [PATCH 4/7] soc: aspeed: Add eSPI TAFS backend support
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
                   ` (2 preceding siblings ...)
  2026-03-13 10:07 ` [PATCH 3/7] soc: aspeed: Add AST2600 peripheral channel port I/O support aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

eSPI Target Attached Flash Sharing (TAFS) refers to sharing the storage
mounted on eSPI devices to host via eSPI Flash Channel.

Add support for TAFS storage handling by creating a storage read/write
interface conceptually like Logical Unit Number (LUN) for driver to
route storage requests to the specified TAFS backend.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 drivers/soc/aspeed/espi/espi_storage.c | 322 +++++++++++++++++++++++++++++++++
 drivers/soc/aspeed/espi/espi_storage.h |  32 ++++
 2 files changed, 354 insertions(+)

diff --git a/drivers/soc/aspeed/espi/espi_storage.c b/drivers/soc/aspeed/espi/espi_storage.c
new file mode 100644
index 000000000000..71038e9bdd52
--- /dev/null
+++ b/drivers/soc/aspeed/espi/espi_storage.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * eSPI TAFS back storage interface
+ */
+
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "espi_storage.h"
+
+/*
+ * aspeed_espi_lun: use an existing block device or file as backend storage for eSPI flash channel.
+ *
+ * Typical path:
+ *   host <-> eSPI bus <-> eSPI slave protocol
+ *        <-> aspeed_espi_lun_*() helpers
+ *        <-> backend block device (e.g., /dev/mmcblk0p3)
+ */
+
+int aspeed_espi_lun_open(struct aspeed_espi_lun *lun, const char *path,
+			 bool initially_ro, bool cdrom)
+{
+	unsigned int blksize, blkbits;
+	loff_t size, num_sectors;
+	struct inode *inode;
+	struct file *filp;
+	int ro;
+	int rc;
+
+	filp = NULL;
+	ro = initially_ro;
+
+	if (!lun || !path) {
+		pr_err("espi_lun_open: invalid args lun=%p path=%p\n", lun,
+		       path);
+		return -EINVAL;
+	}
+
+	pr_info("espi_lun_open: path=%s ro=%d cdrom=%d\n", path, ro, cdrom);
+
+	/* Try R/W first, fallback to R/O if failed */
+	if (!ro) {
+		filp = filp_open(path, O_RDWR | O_LARGEFILE, 0);
+		if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES) {
+			pr_err("espi_lun_open: open rw failed rc=%ld, back to ro\n",
+			       PTR_ERR(filp));
+			ro = 1;
+		}
+	}
+
+	if (ro) {
+		filp = filp_open(path, O_RDONLY | O_LARGEFILE, 0);
+		if (IS_ERR_OR_NULL(filp)) {
+			rc = filp ? PTR_ERR(filp) : -ENODEV;
+			pr_err("espi_lun_open: open ro failed rc=%d\n", rc);
+			return rc;
+		}
+		pr_info("espi_lun_open: open ro ok filp=%p\n", filp);
+	}
+
+	if (!(filp->f_mode & FMODE_WRITE))
+		ro = 1;
+
+	pr_info("espi_lun_open: filp=%p f_inode=%p f_mode=0x%x\n", filp,
+		filp ? filp->f_inode : NULL, filp ? filp->f_mode : 0);
+
+	inode = filp->f_mapping->host;
+
+	pr_info("espi_lun_open: inode=%p mode=0%o\n", inode,
+		inode ? inode->i_mode : 0);
+	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) {
+		rc = -EINVAL;
+		goto out_put;
+	}
+
+	if (!(filp->f_mode & FMODE_CAN_READ)) {
+		rc = -EACCES;
+		goto out_put;
+	}
+	if (!(filp->f_mode & FMODE_CAN_WRITE))
+		ro = true;
+
+	size = i_size_read(inode);
+	if (size < 0) {
+		pr_info("unable to find file size: %s\n", path);
+		rc = (int)size;
+		goto out_put;
+	}
+
+	pr_info("espi_lun_open: size=%lld\n", size);
+
+	if (cdrom) {
+		blksize = 2048;
+		blkbits = 11;
+	} else if (S_ISBLK(inode->i_mode)) {
+		blksize = bdev_logical_block_size(I_BDEV(inode));
+		pr_info("espi_lun_open: blksize=%d\n", blksize);
+		blkbits = blksize_bits(blksize);
+		pr_info("espi_lun_open: bdev=%d\n", blkbits);
+	} else {
+		blksize = 512;
+		blkbits = 9;
+	}
+
+	pr_info("espi_lun_open: blksize=%u blkbits=%u\n", blksize, blkbits);
+	num_sectors = size >> blkbits;
+	if (num_sectors < 1) {
+		pr_info("file too small: %s\n", path);
+		rc = -ETOOSMALL;
+		goto out_put;
+	}
+
+	lun->blksize = blksize;
+	lun->blkbits = blkbits;
+	lun->ro = ro;
+	lun->filp = filp;
+	lun->file_length = size;
+	lun->num_sectors = num_sectors;
+
+	lun->cdrom = cdrom;
+
+	return 0;
+
+out_put:
+	fput(filp);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_open);
+
+void aspeed_espi_lun_close(struct aspeed_espi_lun *lun)
+{
+	if (!lun)
+		return;
+
+	if (lun->filp) {
+		fput(lun->filp);
+		lun->filp = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_close);
+
+int aspeed_espi_lun_rw(struct aspeed_espi_lun *lun, bool write, sector_t sector,
+		       unsigned int nsect, void *buf)
+{
+	ssize_t done;
+	loff_t pos;
+	size_t len;
+
+	if (!lun || !lun->filp || !buf)
+		return -EINVAL;
+
+	if (write && lun->ro)
+		return -EROFS;
+
+	if (sector >= lun->num_sectors || nsect > lun->num_sectors - sector)
+		return -EINVAL;
+
+	pos = (loff_t)sector << lun->blkbits;
+	len = (size_t)nsect << lun->blkbits;
+
+	if (write)
+		done = kernel_write(lun->filp, buf, len, &pos);
+	else
+		done = kernel_read(lun->filp, buf, len, &pos);
+
+	if (done != len)
+		return done < 0 ? (int)done : -EIO;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_rw);
+
+int aspeed_espi_lun_read(struct aspeed_espi_lun *lun, sector_t sector,
+			 unsigned int nsect, void *buf)
+{
+	return aspeed_espi_lun_rw(lun, false, sector, nsect, buf);
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_read);
+
+int aspeed_espi_lun_write(struct aspeed_espi_lun *lun, sector_t sector,
+			  unsigned int nsect, void *buf)
+{
+	return aspeed_espi_lun_rw(lun, true, sector, nsect, buf);
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_write);
+
+/*
+ * Byte-granular R/W, for eSPI protocol handler use:
+ *  - addr/len are in bytes, allowing arbitrary unaligned access
+ *  - internally handles sector alignment and RMW
+ */
+int aspeed_espi_lun_rw_bytes(struct aspeed_espi_lun *lun, bool write, u32 addr,
+			     u32 len, u8 *buf)
+{
+	u32 blk_mask;
+	u32 blksize;
+	u8 *bounce;
+	u32 done;
+	int rc;
+
+	done = 0;
+	rc = 0;
+
+	if (!lun || !lun->filp || !buf)
+		return -EINVAL;
+
+	if (!len)
+		return 0;
+
+	if (write && lun->ro)
+		return -EROFS;
+
+	blksize = lun->blksize;
+	blk_mask = blksize - 1;
+
+	bounce = kmalloc(blksize, GFP_KERNEL);
+	if (!bounce)
+		return -ENOMEM;
+
+	while (done < len) {
+		u32 cur_addr = addr + done;
+		u32 off_in_blk = cur_addr & blk_mask;
+		sector_t sector = cur_addr >> lun->blkbits;
+		u32 bytes_this;
+		u8 *p = buf + done;
+
+		/* Process up to the end of this sector */
+		bytes_this = blksize - off_in_blk;
+		if (bytes_this > (len - done))
+			bytes_this = len - done;
+
+		if (!off_in_blk && bytes_this == blksize) {
+			/* Fully aligned sector, use sector API directly */
+			if (write)
+				rc = aspeed_espi_lun_write(lun, sector, 1, p);
+			else
+				rc = aspeed_espi_lun_read(lun, sector, 1, p);
+		} else {
+			/* partial sector: read one sector first, then overwrite/extract part */
+			rc = aspeed_espi_lun_read(lun, sector, 1, bounce);
+			if (rc)
+				break;
+
+			if (write) {
+				memcpy(bounce + off_in_blk, p, bytes_this);
+				rc = aspeed_espi_lun_write(lun, sector, 1,
+							   bounce);
+			} else {
+				memcpy(p, bounce + off_in_blk, bytes_this);
+			}
+		}
+
+		if (rc)
+			break;
+
+		done += bytes_this;
+	}
+
+	kfree(bounce);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_rw_bytes);
+
+/*
+ * Erase: specify range in bytes, implemented as writing 0xFF pattern.
+ * For eSPI ERASE command use.
+ */
+int aspeed_espi_lun_erase_bytes(struct aspeed_espi_lun *lun, u32 addr, u32 len)
+{
+	u8 *pattern;
+	u32 chunk;
+	u32 done;
+	int rc;
+
+	done = 0;
+	rc = 0;
+
+	if (!lun || !lun->filp)
+		return -EINVAL;
+
+	if (!len)
+		return 0;
+
+	if (lun->ro)
+		return -EROFS;
+
+	chunk = lun->blksize;
+	if (chunk > len)
+		chunk = len;
+
+	pattern = kmalloc(chunk, GFP_KERNEL);
+	if (!pattern)
+		return -ENOMEM;
+
+	while (done < len) {
+		u32 this_len = len - done;
+
+		if (this_len > chunk)
+			this_len = chunk;
+
+		memset(pattern, 0xff, this_len);
+
+		rc = aspeed_espi_lun_rw_bytes(lun, true, addr + done, this_len,
+					      pattern);
+		if (rc)
+			break;
+
+		done += this_len;
+	}
+
+	kfree(pattern);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(aspeed_espi_lun_erase_bytes);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ASPEED eSPI slave storage backend helpers");
+MODULE_AUTHOR("ASPEED");
diff --git a/drivers/soc/aspeed/espi/espi_storage.h b/drivers/soc/aspeed/espi/espi_storage.h
new file mode 100644
index 000000000000..f0711328b03e
--- /dev/null
+++ b/drivers/soc/aspeed/espi/espi_storage.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASPEED_ESPI_STORAGE_H
+#define ASPEED_ESPI_STORAGE_H
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+struct aspeed_espi_lun {
+	struct file	*filp;
+	loff_t		 file_length;
+	loff_t		 num_sectors;
+	unsigned int	 blksize;
+	unsigned int	 blkbits;
+	bool		 ro;
+	bool		 cdrom;
+};
+
+int aspeed_espi_lun_open(struct aspeed_espi_lun *lun, const char *path,
+			 bool initially_ro, bool cdrom);
+void aspeed_espi_lun_close(struct aspeed_espi_lun *lun);
+int aspeed_espi_lun_rw(struct aspeed_espi_lun *lun, bool write,
+		       sector_t sector, unsigned int nsect, void *buf);
+int aspeed_espi_lun_read(struct aspeed_espi_lun *lun, sector_t sector,
+			 unsigned int nsect, void *buf);
+int aspeed_espi_lun_write(struct aspeed_espi_lun *lun, sector_t sector,
+			  unsigned int nsect, void *buf);
+int aspeed_espi_lun_rw_bytes(struct aspeed_espi_lun *lun, bool write,
+			     u32 addr, u32 len, u8 *buf);
+int aspeed_espi_lun_erase_bytes(struct aspeed_espi_lun *lun,
+				u32 addr, u32 len);
+
+#endif /* _ASPEED_ESPI_STORAGE_H_ */

-- 
2.34.1



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

* [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
                   ` (3 preceding siblings ...)
  2026-03-13 10:07 ` [PATCH 4/7] soc: aspeed: Add eSPI TAFS backend support aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-19 23:53   ` kernel test robot
                     ` (2 more replies)
  2026-03-13 10:07 ` [PATCH 6/7] soc: aspeed: Add sysfs controls for flash backend selection aspeedyh
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

Add flash channel probe/remove and function operators for core to
receive/send eSPI flash request packets. Flash channel packets are
handled in core to address storage requests via the LUN-like interface.

Note eSPI Flash channel may start transaction prior than kernel boots
due to host might accesses BIOS image in early stage. Busy checkings are
added to avoid resetting the Flash channel during probe if transaction
already begun.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 drivers/soc/aspeed/espi/Makefile           |   2 +-
 drivers/soc/aspeed/espi/aspeed-espi-comm.h |  62 ++++++++
 drivers/soc/aspeed/espi/aspeed-espi.c      | 239 ++++++++++++++++++++++++++++-
 drivers/soc/aspeed/espi/aspeed-espi.h      |  36 +++++
 drivers/soc/aspeed/espi/ast2600-espi.c     | 165 ++++++++++++++++++++
 drivers/soc/aspeed/espi/ast2600-espi.h     |  19 ++-
 6 files changed, 515 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/aspeed/espi/Makefile b/drivers/soc/aspeed/espi/Makefile
index 30f9dbf92a0f..44f2adc4d358 100644
--- a/drivers/soc/aspeed/espi/Makefile
+++ b/drivers/soc/aspeed/espi/Makefile
@@ -1 +1 @@
-obj-y += aspeed-espi.o ast2600-espi.o
+obj-y += aspeed-espi.o ast2600-espi.o espi_storage.o
diff --git a/drivers/soc/aspeed/espi/aspeed-espi-comm.h b/drivers/soc/aspeed/espi/aspeed-espi-comm.h
new file mode 100644
index 000000000000..510b4afee82f
--- /dev/null
+++ b/drivers/soc/aspeed/espi/aspeed-espi-comm.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Aspeed eSPI protocol packet definitions
+ * Copyright 2026 Aspeed Technology Inc.
+ */
+#ifndef __ASPEED_ESPI_COMM_H__
+#define __ASPEED_ESPI_COMM_H__
+
+#include <linux/bits.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * eSPI cycle type encoding
+ *
+ * Section 5.1 Cycle Types and Packet Format,
+ * Intel eSPI Interface Base Specification, Rev 1.0, Jan. 2016.
+ */
+#define ESPI_FLASH_READ			0x00
+#define ESPI_FLASH_WRITE		0x01
+#define ESPI_FLASH_ERASE		0x02
+#define ESPI_FLASH_SUC_CMPLT		0x06
+#define ESPI_FLASH_SUC_CMPLT_D_MIDDLE	0x09
+#define ESPI_FLASH_SUC_CMPLT_D_FIRST	0x0b
+#define ESPI_FLASH_SUC_CMPLT_D_LAST	0x0d
+#define ESPI_FLASH_SUC_CMPLT_D_ONLY	0x0f
+#define ESPI_FLASH_UNSUC_CMPLT		0x0c
+
+#define ESPI_PLD_LEN_MIN		BIT(6)
+#define ESPI_MAX_PLD_LEN		BIT(12)
+
+/*
+ * eSPI packet format structure
+ *
+ * Section 5.1 Cycle Types and Packet Format,
+ * Intel eSPI Interface Base Specification, Rev 1.0, Jan. 2016.
+ */
+struct espi_comm_hdr {
+	u8 cyc;
+	u8 len_h : 4;
+	u8 tag : 4;
+	u8 len_l;
+};
+
+struct espi_flash_rwe {
+	u8 cyc;
+	u8 len_h : 4;
+	u8 tag : 4;
+	u8 len_l;
+	u32 addr_be;
+	u8 data[];
+} __packed;
+
+struct espi_flash_cmplt {
+	u8 cyc;
+	u8 len_h : 4;
+	u8 tag : 4;
+	u8 len_l;
+	u8 data[];
+} __packed;
+
+#endif
diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c b/drivers/soc/aspeed/espi/aspeed-espi.c
index e369738119bc..7d58c78ed397 100644
--- a/drivers/soc/aspeed/espi/aspeed-espi.c
+++ b/drivers/soc/aspeed/espi/aspeed-espi.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/device/devres.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -13,7 +14,10 @@
 #include <linux/reset.h>
 
 #include "aspeed-espi.h"
+#include "aspeed-espi-comm.h"
 #include "ast2600-espi.h"
+#include "espi_storage.h"
+
 
 struct aspeed_espi_ops {
 	void (*espi_pre_init)(struct aspeed_espi *espi);
@@ -21,6 +25,16 @@ struct aspeed_espi_ops {
 	void (*espi_deinit)(struct aspeed_espi *espi);
 	int (*espi_perif_probe)(struct aspeed_espi *espi);
 	int (*espi_perif_remove)(struct aspeed_espi *espi);
+	int (*espi_flash_probe)(struct aspeed_espi *espi);
+	int (*espi_flash_remove)(struct aspeed_espi *espi);
+	int (*espi_flash_get_hdr)(struct aspeed_espi *espi,
+				  struct espi_comm_hdr *hdr);
+	int (*espi_flash_get_pkt)(struct aspeed_espi *espi, void *pkt_buf,
+				  size_t pkt_size);
+	int (*espi_flash_put_pkt)(struct aspeed_espi *espi,
+				  struct espi_flash_cmplt hdr, void *pkt_buf,
+				  size_t pkt_size);
+	void (*espi_flash_clr_pkt)(struct aspeed_espi *espi);
 	irqreturn_t (*espi_isr)(int irq, void *espi);
 };
 
@@ -30,6 +44,12 @@ static const struct aspeed_espi_ops aspeed_espi_ast2600_ops = {
 	.espi_deinit = ast2600_espi_deinit,
 	.espi_perif_probe = ast2600_espi_perif_probe,
 	.espi_perif_remove = ast2600_espi_perif_remove,
+	.espi_flash_probe = ast2600_espi_flash_probe,
+	.espi_flash_remove = ast2600_espi_flash_remove,
+	.espi_flash_get_hdr = ast2600_espi_flash_get_hdr,
+	.espi_flash_get_pkt = ast2600_espi_flash_get_pkt,
+	.espi_flash_put_pkt = ast2600_espi_flash_put_pkt,
+	.espi_flash_clr_pkt = ast2600_espi_flash_clr_pkt,
 	.espi_isr = ast2600_espi_isr,
 };
 
@@ -39,6 +59,207 @@ static const struct of_device_id aspeed_espi_of_matches[] = {
 };
 MODULE_DEVICE_TABLE(of, aspeed_espi_of_matches);
 
+static void aspeed_espi_flash_handle_lun(struct aspeed_espi *espi)
+{
+	u32 cyc, len, tag, pkt_len, addr, offset;
+	struct espi_flash_cmplt resp_pkt;
+	struct aspeed_espi_flash *flash;
+	struct espi_flash_rwe *req_pkt;
+	struct espi_comm_hdr hdr;
+	u8 *payload;
+	u8 *buf;
+	int rc;
+
+	payload = NULL;
+	buf = NULL;
+
+	flash = &espi->flash;
+	if (!flash->lun || !flash->lun->filp)
+		return;
+
+	rc = espi->ops->espi_flash_get_hdr(espi, &hdr);
+	if (rc) {
+		dev_err(espi->dev, "espi_flash_handle_lun: get_hdr failed rc=%d\n", rc);
+		return;
+	}
+
+	if (hdr.cyc != ESPI_FLASH_WRITE && hdr.cyc != ESPI_FLASH_READ &&
+	    hdr.cyc != ESPI_FLASH_ERASE) {
+		dev_err(espi->dev, "espi_flash_handle_lun: invalid cyc=0x%x\n",
+			hdr.cyc);
+		return;
+	}
+
+	cyc = hdr.cyc;
+	len = (hdr.len_h << 8) | hdr.len_l;
+	tag = hdr.tag;
+
+	len = len ? len : ESPI_MAX_PLD_LEN;
+	pkt_len = len + sizeof(struct espi_flash_rwe);
+
+	payload = kzalloc(pkt_len, GFP_KERNEL);
+	if (!payload)
+		return;
+
+	rc = espi->ops->espi_flash_get_pkt(espi, payload + sizeof(hdr), pkt_len - sizeof(hdr));
+	if (rc) {
+		dev_err(espi->dev, "espi_flash_handle_lun: get_pkt failed rc=%d\n", rc);
+		goto out_free;
+	}
+
+	req_pkt = (struct espi_flash_rwe *)payload;
+	req_pkt->cyc = hdr.cyc;
+	req_pkt->len_h = hdr.len_h;
+	req_pkt->len_l = hdr.len_l;
+	req_pkt->tag = hdr.tag;
+
+	addr = be32_to_cpu(req_pkt->addr_be);
+
+	switch (cyc) {
+	case ESPI_FLASH_ERASE:
+		rc = aspeed_espi_lun_erase_bytes(flash->lun, addr, len);
+		resp_pkt.cyc = (rc) ? ESPI_FLASH_UNSUC_CMPLT : ESPI_FLASH_SUC_CMPLT;
+		resp_pkt.len_h = 0;
+		resp_pkt.len_l = 0;
+		resp_pkt.tag = tag;
+		espi->ops->espi_flash_put_pkt(espi, resp_pkt, NULL, 0);
+		break;
+	case ESPI_FLASH_WRITE:
+		rc = aspeed_espi_lun_rw_bytes(flash->lun, true, addr, len,
+					      &payload[sizeof(struct espi_flash_rwe)]);
+
+		resp_pkt.cyc = (rc) ? ESPI_FLASH_UNSUC_CMPLT : ESPI_FLASH_SUC_CMPLT;
+		resp_pkt.len_h = 0;
+		resp_pkt.len_l = 0;
+		resp_pkt.tag = tag;
+		espi->ops->espi_flash_put_pkt(espi, resp_pkt, NULL, 0);
+		break;
+	case ESPI_FLASH_READ:
+		buf = kzalloc(len, GFP_KERNEL);
+		if (!buf)
+			goto out_free;
+
+		rc = aspeed_espi_lun_rw_bytes(flash->lun, false, addr, len, buf);
+		if (rc) {
+			resp_pkt.cyc = ESPI_FLASH_UNSUC_CMPLT;
+			resp_pkt.len_h = 0;
+			resp_pkt.len_l = 0;
+			resp_pkt.tag = tag;
+			espi->ops->espi_flash_put_pkt(espi, resp_pkt, NULL, 0);
+		} else {
+			if (len <= ESPI_PLD_LEN_MIN) {
+				resp_pkt.cyc = ESPI_FLASH_SUC_CMPLT_D_ONLY;
+				resp_pkt.tag = tag;
+				resp_pkt.len_h = (len >> 8) & 0xff;
+				resp_pkt.len_l = len & 0xff;
+				espi->ops->espi_flash_put_pkt(espi, resp_pkt, buf, len);
+			} else {
+				resp_pkt.cyc = ESPI_FLASH_SUC_CMPLT_D_FIRST;
+				resp_pkt.tag = tag;
+				resp_pkt.len_h = (ESPI_PLD_LEN_MIN >> 8) & 0xff;
+				resp_pkt.len_l = ESPI_PLD_LEN_MIN & 0xff;
+				espi->ops->espi_flash_put_pkt(espi, resp_pkt, buf,
+							      ESPI_PLD_LEN_MIN);
+				offset = ESPI_PLD_LEN_MIN;
+				len -= ESPI_PLD_LEN_MIN;
+
+				while (len > ESPI_PLD_LEN_MIN) {
+					resp_pkt.cyc = ESPI_FLASH_SUC_CMPLT_D_MIDDLE;
+					espi->ops->espi_flash_put_pkt(espi, resp_pkt,
+								     &buf[offset],
+								     ESPI_PLD_LEN_MIN);
+					offset += ESPI_PLD_LEN_MIN;
+					len -= ESPI_PLD_LEN_MIN;
+				}
+
+				resp_pkt.cyc = ESPI_FLASH_SUC_CMPLT_D_LAST;
+				resp_pkt.len_h = (len >> 8) & 0xff;
+				resp_pkt.len_l = len & 0xff;
+				espi->ops->espi_flash_put_pkt(espi, resp_pkt,
+							     &buf[offset], len);
+			}
+		}
+		break;
+	default:
+		dev_err(espi->dev, "espi_flash_handle_lun: unsupported cyc=0x%x\n", cyc);
+		break;
+	}
+	espi->ops->espi_flash_clr_pkt(espi);
+out_free:
+	kfree(buf);
+	kfree(payload);
+}
+
+static void aspeed_espi_flash_rx_work(struct work_struct *work)
+{
+	struct aspeed_espi_flash *flash = container_of(work, struct aspeed_espi_flash, rx_work);
+	struct aspeed_espi *espi = container_of(flash, struct aspeed_espi, flash);
+
+	mutex_lock(&flash->tx_mtx);
+	aspeed_espi_flash_handle_lun(espi);
+	mutex_unlock(&flash->tx_mtx);
+}
+
+static int aspeed_espi_flash_probe(struct aspeed_espi *espi)
+{
+	struct aspeed_espi_flash *flash;
+	struct device *dev;
+
+	flash = &espi->flash;
+	dev = espi->dev;
+
+	flash->dma.enable = of_property_read_bool(dev->of_node, "aspeed,flash-dma-mode");
+	if (flash->dma.enable) {
+		flash->dma.tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.tx_addr,
+							 GFP_KERNEL);
+		if (!flash->dma.tx_virt) {
+			dev_err(dev, "cannot allocate DMA TX buffer\n");
+			return -ENOMEM;
+		}
+
+		flash->dma.rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.rx_addr,
+							 GFP_KERNEL);
+		if (!flash->dma.rx_virt) {
+			dev_err(dev, "cannot allocate DMA RX buffer\n");
+			return -ENOMEM;
+		}
+	}
+
+	mutex_init(&flash->tx_mtx);
+	INIT_WORK(&flash->rx_work, aspeed_espi_flash_rx_work);
+
+	mutex_init(&espi->flash.lun_mtx);
+	espi->flash.lun = NULL;
+	espi->flash.lun_path[0] = '\0';
+	espi->flash.lun_ro = false;
+
+	return espi->ops->espi_flash_probe(espi);
+}
+
+static void aspeed_espi_flash_remove(struct aspeed_espi *espi)
+{
+	struct aspeed_espi_flash *flash;
+
+	flash = &espi->flash;
+
+	if (espi->ops->espi_flash_remove)
+		espi->ops->espi_flash_remove(espi);
+
+	cancel_work_sync(&flash->rx_work);
+
+	if (flash->dma.enable) {
+		dmam_free_coherent(espi->dev, PAGE_SIZE, flash->dma.tx_virt, flash->dma.tx_addr);
+		dmam_free_coherent(espi->dev, PAGE_SIZE, flash->dma.rx_virt, flash->dma.rx_addr);
+	}
+
+	mutex_destroy(&flash->lun_mtx);
+	mutex_destroy(&flash->tx_mtx);
+
+	flash->lun = NULL;
+	flash->lun_path[0] = '\0';
+	flash->lun_ro = false;
+}
+
 static int aspeed_espi_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
@@ -109,11 +330,17 @@ static int aspeed_espi_probe(struct platform_device *pdev)
 		}
 	}
 
+	rc = aspeed_espi_flash_probe(espi);
+	if (rc) {
+		dev_err(dev, "cannot init flash channel, rc=%d\n", rc);
+		goto err_remove_perif;
+	}
+
 	rc = devm_request_irq(dev, espi->irq, espi->ops->espi_isr, 0,
 			      dev_name(dev), espi);
 	if (rc) {
 		dev_err(dev, "cannot request IRQ\n");
-		goto err_deinit;
+		goto err_remove_flash;
 	}
 
 	if (espi->ops->espi_post_init)
@@ -125,12 +352,16 @@ static int aspeed_espi_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_remove_flash:
+	aspeed_espi_flash_remove(espi);
+err_remove_perif:
+	if (espi->ops->espi_perif_remove)
+		espi->ops->espi_perif_remove(espi);
 err_deinit:
 	if (espi->ops->espi_deinit)
 		espi->ops->espi_deinit(espi);
 	clk_disable_unprepare(espi->clk);
-
-	return rc;
+	return dev_err_probe(dev, rc, "%s failed\n", __func__);
 }
 
 static void aspeed_espi_remove(struct platform_device *pdev)
@@ -142,6 +373,8 @@ static void aspeed_espi_remove(struct platform_device *pdev)
 	if (!espi)
 		return;
 
+	aspeed_espi_flash_remove(espi);
+
 	if (espi->ops->espi_perif_remove)
 		espi->ops->espi_perif_remove(espi);
 
diff --git a/drivers/soc/aspeed/espi/aspeed-espi.h b/drivers/soc/aspeed/espi/aspeed-espi.h
index f4ad7f61fef6..7598bc622b95 100644
--- a/drivers/soc/aspeed/espi/aspeed-espi.h
+++ b/drivers/soc/aspeed/espi/aspeed-espi.h
@@ -9,9 +9,44 @@
 #include <linux/irqreturn.h>
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 
 #define DEVICE_NAME		"aspeed-espi"
+#define ASPEED_ESPI_LUN_PATH_MAX	256
+
+enum aspeed_tafs_mode {
+	TAFS_MODE_SW = 1,
+};
+
+struct aspeed_espi_lun;
+
+struct aspeed_espi_flash {
+	struct {
+		enum aspeed_tafs_mode mode;
+		phys_addr_t taddr;
+		resource_size_t size;
+	} tafs;
+
+	struct {
+		bool enable;
+		void *tx_virt;
+		dma_addr_t tx_addr;
+		void *rx_virt;
+		dma_addr_t rx_addr;
+	} dma;
+
+	struct mutex tx_mtx; /* protects tx virt/addr */
+
+	struct work_struct rx_work;
+
+	struct mutex lun_mtx; /* protects lun metadata r/w */
+	struct aspeed_espi_lun *lun;
+	char lun_path[ASPEED_ESPI_LUN_PATH_MAX];
+	bool lun_ro;
+};
 
 struct aspeed_espi {
 	struct platform_device *pdev;
@@ -21,6 +56,7 @@ struct aspeed_espi {
 	struct clk *clk;
 	int dev_id;
 	int irq;
+	struct aspeed_espi_flash flash;
 	const struct aspeed_espi_ops *ops;
 };
 
diff --git a/drivers/soc/aspeed/espi/ast2600-espi.c b/drivers/soc/aspeed/espi/ast2600-espi.c
index 8effd0404d1f..c3ea01866b45 100644
--- a/drivers/soc/aspeed/espi/ast2600-espi.c
+++ b/drivers/soc/aspeed/espi/ast2600-espi.c
@@ -7,6 +7,7 @@
 #include <linux/reset.h>
 
 #include "aspeed-espi.h"
+#include "aspeed-espi-comm.h"
 #include "ast2600-espi.h"
 
 static void ast2600_espi_perif_isr(struct aspeed_espi *espi)
@@ -93,6 +94,166 @@ int ast2600_espi_perif_remove(struct aspeed_espi *espi)
 	return 0;
 }
 
+static void ast2600_espi_flash_isr(struct aspeed_espi *espi)
+{
+	struct aspeed_espi_flash *flash;
+	u32 sts;
+
+	flash = &espi->flash;
+
+	sts = readl(espi->regs + ESPI_INT_STS);
+
+	if (sts & ESPI_INT_STS_FLASH_RX_CMPLT) {
+		writel(ESPI_INT_STS_FLASH_RX_CMPLT, espi->regs + ESPI_INT_STS);
+		queue_work(system_wq, &flash->rx_work);
+	}
+}
+
+static void ast2600_espi_flash_reset(struct aspeed_espi *espi)
+{
+	struct aspeed_espi_flash *flash;
+	u32 reg;
+
+	flash = &espi->flash;
+
+	writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
+	writel(ESPI_INT_STS_FLASH, espi->regs + ESPI_INT_STS);
+
+	reg = readl(espi->regs + ESPI_CTRL);
+	reg &= ~(ESPI_CTRL_FLASH_TX_SW_RST
+		 | ESPI_CTRL_FLASH_RX_SW_RST
+		 | ESPI_CTRL_FLASH_TX_DMA_EN
+		 | ESPI_CTRL_FLASH_RX_DMA_EN
+		 | ESPI_CTRL_FLASH_SW_RDY);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	udelay(1);
+
+	reg |= (ESPI_CTRL_FLASH_TX_SW_RST | ESPI_CTRL_FLASH_RX_SW_RST);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	flash->tafs.mode = TAFS_MODE_SW;
+	reg = readl(espi->regs + ESPI_CTRL) & ~ESPI_CTRL_FLASH_TAFS_MODE;
+	reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	if (flash->dma.enable) {
+		writel(flash->dma.tx_addr, espi->regs + ESPI_FLASH_TX_DMA);
+		writel(flash->dma.rx_addr, espi->regs + ESPI_FLASH_RX_DMA);
+
+		reg = readl(espi->regs + ESPI_CTRL)
+		      | ESPI_CTRL_FLASH_TX_DMA_EN
+		      | ESPI_CTRL_FLASH_RX_DMA_EN;
+		writel(reg, espi->regs + ESPI_CTRL);
+	}
+
+	writel(ESPI_INT_EN_FLASH_RX_CMPLT, espi->regs + ESPI_INT_EN);
+
+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SW_RDY;
+	writel(reg, espi->regs + ESPI_CTRL);
+}
+
+int ast2600_espi_flash_probe(struct aspeed_espi *espi)
+{
+	u32 regs;
+
+	regs = readl(espi->regs + ESPI_STS);
+	if (regs & (ESPI_STS_FLASH_TX_BUSY | ESPI_STS_FLASH_RX_BUSY)) {
+		dev_warn(espi->dev, "eSPI flash channel is busy, deferring...\n");
+		return -EPROBE_DEFER;
+	}
+
+	ast2600_espi_flash_reset(espi);
+	return 0;
+}
+
+int ast2600_espi_flash_remove(struct aspeed_espi *espi)
+{
+	struct aspeed_espi_flash *flash;
+	u32 reg;
+
+	flash = &espi->flash;
+
+	writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
+
+	reg = readl(espi->regs + ESPI_CTRL);
+	reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
+		 | ESPI_CTRL_FLASH_RX_DMA_EN
+		 | ESPI_CTRL_FLASH_SW_RDY);
+	writel(reg, espi->regs + ESPI_CTRL);
+
+	return 0;
+}
+
+int ast2600_espi_flash_get_hdr(struct aspeed_espi *espi,
+			       struct espi_comm_hdr *hdr)
+{
+	u32 reg, len;
+
+	reg = readl(espi->regs + ESPI_FLASH_RX_CTRL);
+	hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
+	hdr->tag = FIELD_GET(ESPI_FLASH_RX_CTRL_TAG, reg);
+	len = FIELD_GET(ESPI_FLASH_RX_CTRL_LEN, reg);
+	hdr->len_h = (len >> 8) & 0xff;
+	hdr->len_l = len & 0xff;
+
+	return 0;
+}
+
+int ast2600_espi_flash_get_pkt(struct aspeed_espi *espi, void *pkt_buf,
+			       size_t pkt_size)
+{
+	u32 i;
+	u8 *pkt;
+
+	pkt = (u8 *)pkt_buf;
+
+	if (espi->flash.dma.enable) {
+		memcpy(pkt, espi->flash.dma.rx_virt, pkt_size);
+	} else {
+		for (i = 0; i < pkt_size; ++i)
+			pkt[i] = readl(espi->regs + ESPI_FLASH_RX_DATA) & 0xff;
+	}
+
+	return 0;
+}
+
+int ast2600_espi_flash_put_pkt(struct aspeed_espi *espi,
+			       struct espi_flash_cmplt hdr, void *pkt_buf,
+			       size_t pkt_size)
+{
+	u32 i, cyc, tag, len, reg;
+	u8 *pkt;
+
+	pkt = (u8 *)pkt_buf;
+
+	if (pkt_buf && pkt_size > 0) {
+		if (espi->flash.dma.enable) {
+			memcpy(espi->flash.dma.tx_virt, pkt, pkt_size);
+			dma_wmb();
+		} else {
+			for (i = 0; i < pkt_size; ++i)
+				writel(pkt[i], espi->regs + ESPI_FLASH_TX_DATA);
+		}
+	}
+
+	cyc = hdr.cyc;
+	tag = hdr.tag;
+	len = (hdr.len_h << 8) | hdr.len_l;
+	reg = FIELD_PREP(ESPI_FLASH_TX_CTRL_CYC, cyc) |
+	      FIELD_PREP(ESPI_FLASH_TX_CTRL_TAG, tag) |
+	      FIELD_PREP(ESPI_FLASH_TX_CTRL_LEN, len) |
+	      ESPI_FLASH_TX_CTRL_TRIG_PEND;
+	writel(reg, espi->regs + ESPI_FLASH_TX_CTRL);
+
+	return 0;
+}
+
+void ast2600_espi_flash_clr_pkt(struct aspeed_espi *espi)
+{
+	writel(ESPI_FLASH_RX_CTRL_SERV_PEND, espi->regs + ESPI_FLASH_RX_CTRL);
+}
+
 /* global control */
 irqreturn_t ast2600_espi_isr(int irq, void *arg)
 {
@@ -108,6 +269,9 @@ irqreturn_t ast2600_espi_isr(int irq, void *arg)
 	if (sts & ESPI_INT_STS_PERIF)
 		ast2600_espi_perif_isr(espi);
 
+	if (sts & ESPI_INT_STS_FLASH_RX_CMPLT)
+		ast2600_espi_flash_isr(espi);
+
 	if (sts & ESPI_INT_STS_RST_DEASSERT) {
 		/* this will clear all interrupt enable and status */
 		reset_control_assert(espi->rst);
@@ -115,6 +279,7 @@ irqreturn_t ast2600_espi_isr(int irq, void *arg)
 
 		ast2600_espi_perif_sw_reset(espi);
 		ast2600_espi_perif_reset(espi);
+		ast2600_espi_flash_reset(espi);
 
 		/* re-enable eSPI_RESET# interrupt */
 		writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN);
diff --git a/drivers/soc/aspeed/espi/ast2600-espi.h b/drivers/soc/aspeed/espi/ast2600-espi.h
index 309479ee1187..251999dba73f 100644
--- a/drivers/soc/aspeed/espi/ast2600-espi.h
+++ b/drivers/soc/aspeed/espi/ast2600-espi.h
@@ -9,6 +9,7 @@
 #include <linux/bits.h>
 #include <linux/irqreturn.h>
 #include "aspeed-espi.h"
+#include "aspeed-espi-comm.h"
 
 /* registers */
 #define ESPI_CTRL				0x000
@@ -27,13 +28,15 @@
 #define   ESPI_CTRL_PERIF_NP_TX_DMA_EN		BIT(19)
 #define   ESPI_CTRL_PERIF_PC_TX_DMA_EN		BIT(17)
 #define   ESPI_CTRL_PERIF_PC_RX_DMA_EN		BIT(16)
-#define   ESPI_CTRL_FLASH_EDAF_MODE		GENMASK(11, 10)
+#define   ESPI_CTRL_FLASH_TAFS_MODE		GENMASK(11, 10)
 #define   ESPI_CTRL_VW_GPIO_SW			BIT(9)
 #define   ESPI_CTRL_FLASH_SW_RDY		BIT(7)
 #define   ESPI_CTRL_OOB_SW_RDY			BIT(4)
 #define   ESPI_CTRL_VW_SW_RDY			BIT(3)
 #define   ESPI_CTRL_PERIF_SW_RDY		BIT(1)
 #define ESPI_STS				0x004
+#define   ESPI_STS_FLASH_TX_BUSY		BIT(23)
+#define   ESPI_STS_FLASH_RX_BUSY		BIT(22)
 #define ESPI_INT_STS				0x008
 #define   ESPI_INT_STS_RST_DEASSERT		BIT(31)
 #define   ESPI_INT_STS_OOB_RX_TMOUT		BIT(23)
@@ -147,9 +150,9 @@
 #define ESPI_PERIF_MMBI_TADDR			ESPI_PERIF_MCYC_TADDR
 #define ESPI_PERIF_MCYC_MASK			0x08c
 #define ESPI_PERIF_MMBI_MASK			ESPI_PERIF_MCYC_MASK
-#define ESPI_FLASH_EDAF_TADDR			0x090
-#define   ESPI_FLASH_EDAF_TADDR_BASE		GENMASK(31, 24)
-#define   ESPI_FLASH_EDAF_TADDR_MASK		GENMASK(15, 8)
+#define ESPI_FLASH_TAFS_TADDR			0x090
+#define   ESPI_FLASH_TAFS_TADDR_BASE		GENMASK(31, 24)
+#define   ESPI_FLASH_TAFS_TADDR_MASK		GENMASK(15, 8)
 #define ESPI_VW_SYSEVT_INT_EN			0x094
 #define ESPI_VW_SYSEVT				0x098
 #define   ESPI_VW_SYSEVT_HOST_RST_ACK		BIT(27)
@@ -287,5 +290,13 @@ int ast2600_espi_oob_probe(struct aspeed_espi *espi);
 int ast2600_espi_oob_remove(struct aspeed_espi *espi);
 int ast2600_espi_flash_probe(struct aspeed_espi *espi);
 int ast2600_espi_flash_remove(struct aspeed_espi *espi);
+int ast2600_espi_flash_get_hdr(struct aspeed_espi *espi,
+			       struct espi_comm_hdr *hdr);
+int ast2600_espi_flash_get_pkt(struct aspeed_espi *espi, void *pkt_buf,
+			       size_t pkt_size);
+int ast2600_espi_flash_put_pkt(struct aspeed_espi *espi,
+			       struct espi_flash_cmplt hdr, void *pkt_buf,
+			       size_t pkt_size);
+void ast2600_espi_flash_clr_pkt(struct aspeed_espi *espi);
 irqreturn_t ast2600_espi_isr(int irq, void *arg);
 #endif

-- 
2.34.1



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

* [PATCH 6/7] soc: aspeed: Add sysfs controls for flash backend selection
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
                   ` (4 preceding siblings ...)
  2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-13 10:07 ` [PATCH 7/7] arm: dts: aspeed: Add eSPI node for AST2600 aspeedyh
  2026-03-13 16:24 ` [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support Conor Dooley
  7 siblings, 0 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

add following attributes to select backend storage for eSPI TAFS LUN
interface:
- flash_lun_path: specify path of backend storage for eSPI TAFS to share
  with host.
- flash_lun_readonly: set flash LUN to read-only or read-write mode to
  block host write operations.
- flash_lun_enable: open storage according to flash_lun_path as file for
  eSPI TAFS access.

Example usage:
- Select /dev/mtdblock8 as backend storage for eSPI TAFS LUN interface
  echo /dev/mtdblock8 > \
    /sys/bus/platform/devices/1e6ee000.espi/flash_lun_path
- Set LUN to read-only mode to block host write operations
  echo 1 > /sys/bus/platform/devices/1e6ee000.espi/flash_lun_readonly
- Enable flash LUN for eSPI TAFS access
  echo 1 > /sys/bus/platform/devices/1e6ee000.espi/flash_lun_enable

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 drivers/soc/aspeed/espi/aspeed-espi.c | 218 ++++++++++++++++++++++++++++++++++
 1 file changed, 218 insertions(+)

diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c b/drivers/soc/aspeed/espi/aspeed-espi.c
index 7d58c78ed397..2c8f9641174d 100644
--- a/drivers/soc/aspeed/espi/aspeed-espi.c
+++ b/drivers/soc/aspeed/espi/aspeed-espi.c
@@ -12,12 +12,224 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/kstrtox.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 
 #include "aspeed-espi.h"
 #include "aspeed-espi-comm.h"
 #include "ast2600-espi.h"
 #include "espi_storage.h"
 
+static ssize_t flash_lun_path_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	ssize_t rc;
+
+	espi = dev_get_drvdata(dev);
+
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	mutex_lock(&flash->lun_mtx);
+	rc = scnprintf(buf, PAGE_SIZE, "%s\n", flash->lun_path);
+	mutex_unlock(&flash->lun_mtx);
+
+	return rc;
+}
+
+static ssize_t flash_lun_path_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	char tmp[ASPEED_ESPI_LUN_PATH_MAX];
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	size_t len;
+
+	espi = dev_get_drvdata(dev);
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	len = strnlen(buf, count);
+	if (len && buf[len - 1] == '\n')
+		len--;
+
+	if (len >= sizeof(tmp))
+		return -ENAMETOOLONG;
+
+	memcpy(tmp, buf, len);
+	tmp[len] = '\0';
+
+	mutex_lock(&flash->lun_mtx);
+	if (flash->lun && flash->lun->filp) {
+		mutex_unlock(&flash->lun_mtx);
+		return -EBUSY;
+	}
+
+	strscpy(flash->lun_path, tmp, sizeof(flash->lun_path));
+	dev_info(dev, "flash lun path set to %s\n", flash->lun_path);
+	mutex_unlock(&flash->lun_mtx);
+
+	return count;
+}
+
+static ssize_t flash_lun_readonly_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	ssize_t rc;
+
+	espi = dev_get_drvdata(dev);
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	mutex_lock(&flash->lun_mtx);
+	rc = scnprintf(buf, PAGE_SIZE, "%u\n", flash->lun_ro);
+	mutex_unlock(&flash->lun_mtx);
+
+	return rc;
+}
+
+static ssize_t flash_lun_readonly_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	bool ro;
+	int rc;
+
+	espi = dev_get_drvdata(dev);
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	rc = kstrtobool(buf, &ro);
+	if (rc)
+		return rc;
+
+	mutex_lock(&flash->lun_mtx);
+	if (flash->lun && flash->lun->filp) {
+		mutex_unlock(&flash->lun_mtx);
+		return -EBUSY;
+	}
+
+	flash->lun_ro = ro;
+	dev_info(dev, "flash lun readonly set to %u\n", flash->lun_ro);
+	mutex_unlock(&flash->lun_mtx);
+
+	return count;
+}
+
+static ssize_t flash_lun_enable_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	bool enabled;
+	ssize_t rc;
+
+	espi = dev_get_drvdata(dev);
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	mutex_lock(&flash->lun_mtx);
+	enabled = flash->lun && flash->lun->filp;
+	mutex_unlock(&flash->lun_mtx);
+
+	rc = scnprintf(buf, PAGE_SIZE, "%u\n", enabled);
+	return rc;
+}
+
+static ssize_t flash_lun_enable_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct aspeed_espi_flash *flash;
+	struct aspeed_espi *espi;
+	bool enable;
+	int rc = 0;
+
+	espi = dev_get_drvdata(dev);
+	if (!espi)
+		return -ENODEV;
+
+	flash = &espi->flash;
+
+	rc = kstrtobool(buf, &enable);
+	if (rc)
+		return rc;
+
+	mutex_lock(&flash->lun_mtx);
+	if (!flash->lun) {
+		flash->lun = devm_kzalloc(dev, sizeof(*flash->lun), GFP_KERNEL);
+		if (!flash->lun) {
+			rc = -ENOMEM;
+			goto out_unlock;
+		}
+	}
+
+	if (enable) {
+		if (flash->lun->filp)
+			goto out_unlock;
+		if (!flash->lun_path[0]) {
+			rc = -EINVAL;
+			goto out_unlock;
+		}
+
+		dev_info(dev, "flash lun enable: path=%s ro=%u\n",
+			 flash->lun_path, flash->lun_ro);
+		mutex_lock(&flash->tx_mtx);
+		rc = aspeed_espi_lun_open(flash->lun, flash->lun_path,
+					  flash->lun_ro, false);
+		mutex_unlock(&flash->tx_mtx);
+	} else {
+		if (!flash->lun->filp)
+			goto out_unlock;
+
+		dev_info(dev, "flash lun disable\n");
+		mutex_lock(&flash->tx_mtx);
+		aspeed_espi_lun_close(flash->lun);
+		mutex_unlock(&flash->tx_mtx);
+	}
+
+out_unlock:
+	mutex_unlock(&flash->lun_mtx);
+	if (rc) {
+		dev_err(dev, "flash lun enable=%u failed: %d\n", enable, rc);
+		return rc;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(flash_lun_path);
+static DEVICE_ATTR_RW(flash_lun_readonly);
+static DEVICE_ATTR_RW(flash_lun_enable);
+
+static struct attribute *aspeed_espi_flash_attrs[] = {
+	&dev_attr_flash_lun_path.attr,
+	&dev_attr_flash_lun_readonly.attr,
+	&dev_attr_flash_lun_enable.attr,
+	NULL,
+};
+
+static const struct attribute_group aspeed_espi_flash_attr_group = {
+	.attrs = aspeed_espi_flash_attrs,
+};
 
 struct aspeed_espi_ops {
 	void (*espi_pre_init)(struct aspeed_espi *espi);
@@ -336,6 +548,12 @@ static int aspeed_espi_probe(struct platform_device *pdev)
 		goto err_remove_perif;
 	}
 
+	rc = devm_device_add_group(dev, &aspeed_espi_flash_attr_group);
+	if (rc) {
+		dev_err(dev, "cannot add flash LUN sysfs group, rc=%d\n", rc);
+		goto err_remove_flash;
+	}
+
 	rc = devm_request_irq(dev, espi->irq, espi->ops->espi_isr, 0,
 			      dev_name(dev), espi);
 	if (rc) {

-- 
2.34.1



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

* [PATCH 7/7] arm: dts: aspeed: Add eSPI node for AST2600
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
                   ` (5 preceding siblings ...)
  2026-03-13 10:07 ` [PATCH 6/7] soc: aspeed: Add sysfs controls for flash backend selection aspeedyh
@ 2026-03-13 10:07 ` aspeedyh
  2026-03-13 16:24 ` [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support Conor Dooley
  7 siblings, 0 replies; 30+ messages in thread
From: aspeedyh @ 2026-03-13 10:07 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, aspeedyh

Add the AST2600 eSPI controller node with the register region,
interrupt, clock, reset and pinctrl properties.

Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 189bc3bbb47c..84aec45f39e7 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -408,6 +408,17 @@ adc1: adc@1e6e9100 {
 				status = "disabled";
 			};
 
+			espi: espi@1e6ee000 {
+				compatible = "aspeed,ast2600-espi";
+				reg = <0x1e6ee000 0x1000>;
+				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>;
+				resets = <&syscon 57>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_espi_default>;
+				status = "disabled";
+			};
+
 			sbc: secure-boot-controller@1e6f2000 {
 				compatible = "aspeed,ast2600-sbc";
 				reg = <0x1e6f2000 0x1000>;

-- 
2.34.1



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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
                   ` (6 preceding siblings ...)
  2026-03-13 10:07 ` [PATCH 7/7] arm: dts: aspeed: Add eSPI node for AST2600 aspeedyh
@ 2026-03-13 16:24 ` Conor Dooley
  2026-03-13 16:32   ` Mark Brown
  2026-03-13 21:36   ` Arnd Bergmann
  7 siblings, 2 replies; 30+ messages in thread
From: Conor Dooley @ 2026-03-13 16:24 UTC (permalink / raw)
  To: aspeedyh
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, broonie

[-- Attachment #1: Type: text/plain, Size: 2895 bytes --]

On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> This series adds initial support for the eSPI controller found on ASPEED
> AST2600 BMC SoCs.
> 
> The series introduces a eSPI controller framework for ASPEED SoCs under
> drivers/soc/aspeed/, adds AST2600-specific controller support for
> peripheral and flash channels, defines the corresponding devicetree 
> binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
> 
> The driver is intended to support host-BMC communication over the BMC-side
> eSPI slave controller present on AST2600 systems.

This all seems to be in the wrong places entirely, shouldn't an eSPI
driver and bindings go in the spi subsystem? FSL's appears to be there.
Mark?

> 
> Patch summary:
> 1. dt-bindings: soc: aspeed: Add AST2600 eSPI controller
> 2. soc: aspeed: Introduce core eSPI controller support
> 3. soc: aspeed: Add AST2600 peripheral channel port I/O support
> 4. soc: aspeed: Add eSPI TAFS backend support
> 5. soc: aspeed: Add espi flash channel support
> 6. soc: aspeed: Add sysfs controls for flash LUN selection
> 7. arm: dts: aspeed: Add eSPI node for AST2600
> 
> This series has been tested on AST2600 platform with Intel's host eSPI
> controller.
> 
> Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>

Unless you're an fanatical employee of Aspeed, I doubt that this signoff
reflects your actual name!

> ---
> aspeedyh (7):
>       dt-bindings: soc: aspeed: Add AST2600 eSPI controller
>       soc: aspeed: Introduce core eSPI controller support
>       soc: aspeed: Add AST2600 peripheral channel port I/O support
>       soc: aspeed: Add eSPI TAFS backend support
>       soc: aspeed: Add eSPI flash channel support
>       soc: aspeed: Add sysfs controls for flash backend selection
>       arm: dts: aspeed: Add eSPI node for AST2600
> 
>  .../bindings/soc/aspeed/aspeed,ast2600-espi.yaml   |  74 +++
>  arch/arm/boot/dts/aspeed/aspeed-g6.dtsi            |  11 +
>  drivers/soc/aspeed/Kconfig                         |   7 +
>  drivers/soc/aspeed/Makefile                        |   1 +
>  drivers/soc/aspeed/espi/Makefile                   |   1 +
>  drivers/soc/aspeed/espi/aspeed-espi-comm.h         |  62 +++
>  drivers/soc/aspeed/espi/aspeed-espi.c              | 618 +++++++++++++++++++++
>  drivers/soc/aspeed/espi/aspeed-espi.h              |  63 +++
>  drivers/soc/aspeed/espi/ast2600-espi.c             | 304 ++++++++++
>  drivers/soc/aspeed/espi/ast2600-espi.h             | 302 ++++++++++
>  drivers/soc/aspeed/espi/espi_storage.c             | 322 +++++++++++
>  drivers/soc/aspeed/espi/espi_storage.h             |  32 ++
>  12 files changed, 1797 insertions(+)
> ---
> base-commit: 0257f64bdac7fdca30fa3cae0df8b9ecbec7733a
> change-id: 20260313-upstream_espi-d9fea66d1772
> 
> Best regards,
> -- 
> aspeedyh <yh_chung@aspeedtech.com>
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 16:24 ` [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support Conor Dooley
@ 2026-03-13 16:32   ` Mark Brown
  2026-03-13 16:48     ` Mark Brown
  2026-03-13 21:36   ` Arnd Bergmann
  1 sibling, 1 reply; 30+ messages in thread
From: Mark Brown @ 2026-03-13 16:32 UTC (permalink / raw)
  To: Conor Dooley
  Cc: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel,
	devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak

[-- Attachment #1: Type: text/plain, Size: 1481 bytes --]

On Fri, Mar 13, 2026 at 04:24:22PM +0000, Conor Dooley wrote:
> On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> > This series adds initial support for the eSPI controller found on ASPEED
> > AST2600 BMC SoCs.
> > 
> > The series introduces a eSPI controller framework for ASPEED SoCs under
> > drivers/soc/aspeed/, adds AST2600-specific controller support for
> > peripheral and flash channels, defines the corresponding devicetree 
> > binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
> > 
> > The driver is intended to support host-BMC communication over the BMC-side
> > eSPI slave controller present on AST2600 systems.
> 
> This all seems to be in the wrong places entirely, shouldn't an eSPI
> driver and bindings go in the spi subsystem? FSL's appears to be there.
> Mark?

As documented in submitting-patches.rst please send patches to the 
maintainers for the code you would like to change.  The normal kernel
workflow is that people apply patches from their inboxes, if they aren't
copied they are likely to not see the patch at all and it is much more
difficult to apply patches.

Please submit patches using subject lines reflecting the style for the
subsystem, this makes it easier for people to identify relevant patches.
Look at what existing commits in the area you're changing are doing and
make sure your subject lines visually resemble what they're doing.
There's no need to resubmit to fix this alone.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 16:32   ` Mark Brown
@ 2026-03-13 16:48     ` Mark Brown
  2026-03-16  3:07       ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Brown @ 2026-03-13 16:48 UTC (permalink / raw)
  To: Conor Dooley
  Cc: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel,
	devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak

[-- Attachment #1: Type: text/plain, Size: 1699 bytes --]

On Fri, Mar 13, 2026 at 04:32:31PM +0000, Mark Brown wrote:
> On Fri, Mar 13, 2026 at 04:24:22PM +0000, Conor Dooley wrote:
> > On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> > > This series adds initial support for the eSPI controller found on ASPEED
> > > AST2600 BMC SoCs.
> > > 
> > > The series introduces a eSPI controller framework for ASPEED SoCs under
> > > drivers/soc/aspeed/, adds AST2600-specific controller support for
> > > peripheral and flash channels, defines the corresponding devicetree 
> > > binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
> > > 
> > > The driver is intended to support host-BMC communication over the BMC-side
> > > eSPI slave controller present on AST2600 systems.
> > 
> > This all seems to be in the wrong places entirely, shouldn't an eSPI
> > driver and bindings go in the spi subsystem? FSL's appears to be there.
> > Mark?
> 
> As documented in submitting-patches.rst please send patches to the 
> maintainers for the code you would like to change.  The normal kernel
> workflow is that people apply patches from their inboxes, if they aren't
> copied they are likely to not see the patch at all and it is much more
> difficult to apply patches.
> 
> Please submit patches using subject lines reflecting the style for the
> subsystem, this makes it easier for people to identify relevant patches.
> Look at what existing commits in the area you're changing are doing and
> make sure your subject lines visually resemble what they're doing.
> There's no need to resubmit to fix this alone.

If this is a driver for SPI hardware it should be under drivers/spi and
use the framework there.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 16:24 ` [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support Conor Dooley
  2026-03-13 16:32   ` Mark Brown
@ 2026-03-13 21:36   ` Arnd Bergmann
  2026-03-14  1:02     ` Mark Brown
                       ` (2 more replies)
  1 sibling, 3 replies; 30+ messages in thread
From: Arnd Bergmann @ 2026-03-13 21:36 UTC (permalink / raw)
  To: Conor Dooley, aspeedyh
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, Mark Brown

On Fri, Mar 13, 2026, at 17:24, Conor Dooley wrote:
> On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
>> This series adds initial support for the eSPI controller found on ASPEED
>> AST2600 BMC SoCs.
>> 
>> The series introduces a eSPI controller framework for ASPEED SoCs under
>> drivers/soc/aspeed/, adds AST2600-specific controller support for
>> peripheral and flash channels, defines the corresponding devicetree 
>> binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
>> 
>> The driver is intended to support host-BMC communication over the BMC-side
>> eSPI slave controller present on AST2600 systems.
>
> This all seems to be in the wrong places entirely, shouldn't an eSPI
> driver and bindings go in the spi subsystem?

From an initial reading, my impression is that patches 1, 2, 3 and 7
should be modified to use the normal SPI interfaces to implement
an spi target driver, possibly a combined host/target driver.
Reworking this should be fairly straightforward because the interfaces
to the SPI core are well documented.

It is possible that the hardware can only be used to provide espi
device emulation. From what I could see in the code, there is
not much special in there, but I'm not that familiar with SPI

Patches 4, 5 and 6 in consequently would need to be reworked so
these can implement the TAFS spec independent of the SPI controller,
and can be shared e.g. with other OpenBMC targets using the same
module and the same user interface. None of this should be aspeed
specific. 

There is a good chance that both the user interface and the placing
of the code will need a more debate, but I would suggest first trying
to move everything over to use the SPI subsystem but leave other
parts untouched for the moment.

> FSL's appears to be there.

I think this is just a similarly named device: Freescale/NXP's eSPI
device driver is unrelated to the Intel eSPI spec but rather implements
a normal SPI driver the same way that eDMA and eSDHC are Freescale's
implementation of dmaengine and SDHCI drivers.

    Arnd


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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 21:36   ` Arnd Bergmann
@ 2026-03-14  1:02     ` Mark Brown
  2026-03-16  6:06     ` Ivan Mikhaylov
  2026-03-16  6:34     ` Andrew Jeffery
  2 siblings, 0 replies; 30+ messages in thread
From: Mark Brown @ 2026-03-14  1:02 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Conor Dooley, aspeedyh, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joel Stanley, Andrew Jeffery, Ryan Chen,
	Philipp Zabel, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, maciej.lawniczak

[-- Attachment #1: Type: text/plain, Size: 668 bytes --]

On Fri, Mar 13, 2026 at 10:36:02PM +0100, Arnd Bergmann wrote:
> On Fri, Mar 13, 2026, at 17:24, Conor Dooley wrote:

> > FSL's appears to be there.

> I think this is just a similarly named device: Freescale/NXP's eSPI
> device driver is unrelated to the Intel eSPI spec but rather implements
> a normal SPI driver the same way that eDMA and eSDHC are Freescale's
> implementation of dmaengine and SDHCI drivers.

Yeah, SPI with a random letter or string in front of it is usually just
someone made a new controller for some reason (often a new feature, like
all the QuadSPI devices) and wants to differentiate it from their old
ones or connect it to other branding.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* RE: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 16:48     ` Mark Brown
@ 2026-03-16  3:07       ` YH Chung
  0 siblings, 0 replies; 30+ messages in thread
From: YH Chung @ 2026-03-16  3:07 UTC (permalink / raw)
  To: Mark Brown, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com

Hi Mark, Conor,

>On Fri, Mar 13, 2026 at 04:32:31PM +0000, Mark Brown wrote:
>> On Fri, Mar 13, 2026 at 04:24:22PM +0000, Conor Dooley wrote:
>> > On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
>> > > This series adds initial support for the eSPI controller found on ASPEED
>> > > AST2600 BMC SoCs.
>> > >
>> > > The series introduces a eSPI controller framework for ASPEED SoCs under
>> > > drivers/soc/aspeed/, adds AST2600-specific controller support for
>> > > peripheral and flash channels, defines the corresponding devicetree
>> > > binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
>> > >
>> > > The driver is intended to support host-BMC communication over the BMC-side
>> > > eSPI slave controller present on AST2600 systems.
>> >
>> > This all seems to be in the wrong places entirely, shouldn't an eSPI
>> > driver and bindings go in the spi subsystem? FSL's appears to be there.
>> > Mark?
>>
>> As documented in submitting-patches.rst please send patches to the
>> maintainers for the code you would like to change.  The normal kernel
>> workflow is that people apply patches from their inboxes, if they aren't
>> copied they are likely to not see the patch at all and it is much more
>> difficult to apply patches.
>>
>> Please submit patches using subject lines reflecting the style for the
>> subsystem, this makes it easier for people to identify relevant patches.
>> Look at what existing commits in the area you're changing are doing and
>> make sure your subject lines visually resemble what they're doing.
>> There's no need to resubmit to fix this alone.
>
>If this is a driver for SPI hardware it should be under drivers/spi and
>use the framework there.

Thanks for the kind guidance.

This driver is for the Intel eSPI interface used by the AST2600 BMC, for functions such as Super I/O that were previously handled over the LPC interface.
As there does not appear to be an in-tree eSPI subsystem at present, our initial thought was to place it under drivers/soc/aspeed/. If that is not the preferred upstream location, we are happy to restructure the series accordingly.



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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 21:36   ` Arnd Bergmann
  2026-03-14  1:02     ` Mark Brown
@ 2026-03-16  6:06     ` Ivan Mikhaylov
  2026-03-16  6:34     ` Andrew Jeffery
  2 siblings, 0 replies; 30+ messages in thread
From: Ivan Mikhaylov @ 2026-03-16  6:06 UTC (permalink / raw)
  To: Arnd Bergmann, Conor Dooley, aspeedyh
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Ryan Chen, Philipp Zabel, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak, Mark Brown

On Fri, 2026-03-13 at 22:36 +0100, Arnd Bergmann wrote:
> On Fri, Mar 13, 2026, at 17:24, Conor Dooley wrote:
> > On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> > > This series adds initial support for the eSPI controller found on
> > > ASPEED
> > > AST2600 BMC SoCs.
> > > 
> > > The series introduces a eSPI controller framework for ASPEED SoCs
> > > under
> > > drivers/soc/aspeed/, adds AST2600-specific controller support for
> > > peripheral and flash channels, defines the corresponding
> > > devicetree 
> > > binding, and adds the AST2600 eSPI controller node to the SoC
> > > dtsi.
> > > 
> > > The driver is intended to support host-BMC communication over the
> > > BMC-side
> > > eSPI slave controller present on AST2600 systems.
> > 
> > This all seems to be in the wrong places entirely, shouldn't an
> > eSPI
> > driver and bindings go in the spi subsystem?
> 
> From an initial reading, my impression is that patches 1, 2, 3 and 7
> should be modified to use the normal SPI interfaces to implement
> an spi target driver, possibly a combined host/target driver.
> Reworking this should be fairly straightforward because the
> interfaces
> to the SPI core are well documented.

Arnd, that's would be nice if it would be standard SPI device. But what
if eSPI would be a bus? So, I assume all other which lying underneath 
eSPI would be much easier to implement as standard driver data set
SPI/GPIO/I2C with something like devm_regmap_init_espi(like for i2c/spi
or anything else) for example as common part for these drivers.

Thanks.


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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-13 21:36   ` Arnd Bergmann
  2026-03-14  1:02     ` Mark Brown
  2026-03-16  6:06     ` Ivan Mikhaylov
@ 2026-03-16  6:34     ` Andrew Jeffery
  2026-03-17  8:14       ` YH Chung
  2 siblings, 1 reply; 30+ messages in thread
From: Andrew Jeffery @ 2026-03-16  6:34 UTC (permalink / raw)
  To: Arnd Bergmann, Conor Dooley, aspeedyh
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree, linux-arm-kernel,
	linux-aspeed, linux-kernel, openbmc, maciej.lawniczak, Mark Brown

On Fri, 2026-03-13 at 22:36 +0100, Arnd Bergmann wrote:
> On Fri, Mar 13, 2026, at 17:24, Conor Dooley wrote:
> > On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> > > This series adds initial support for the eSPI controller found on ASPEED
> > > AST2600 BMC SoCs.
> > > 
> > > The series introduces a eSPI controller framework for ASPEED SoCs under
> > > drivers/soc/aspeed/, adds AST2600-specific controller support for
> > > peripheral and flash channels, defines the corresponding devicetree 
> > > binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
> > > 
> > > The driver is intended to support host-BMC communication over the BMC-side
> > > eSPI slave controller present on AST2600 systems.
> > 
> > This all seems to be in the wrong places entirely, shouldn't an eSPI
> > driver and bindings go in the spi subsystem?
> 
> From an initial reading, my impression is that patches 1, 2, 3 and 7
> should be modified to use the normal SPI interfaces to implement
> an spi target driver, possibly a combined host/target driver.
> Reworking this should be fairly straightforward because the interfaces
> to the SPI core are well documented.
> 
> It is possible that the hardware can only be used to provide espi
> device emulation. From what I could see in the code, there is
> not much special in there, but I'm not that familiar with SPI
> 
> Patches 4, 5 and 6 in consequently would need to be reworked so
> these can implement the TAFS spec independent of the SPI controller,
> and can be shared e.g. with other OpenBMC targets using the same
> module and the same user interface. None of this should be aspeed
> specific. 
> 
> There is a good chance that both the user interface and the placing
> of the code will need a more debate, but I would suggest first trying
> to move everything over to use the SPI subsystem but leave other
> parts untouched for the moment.

To extend Arnd's points here, some previous attempts were made to
support Intel's eSPI protocol on Aspeed's SoCs which aren't discussed
in this cover letter. I think it would be helpful to cover the history
and why we now have a third approach:

- https://lore.kernel.org/linux-aspeed/20240319093405.39833-1-manojkiran.eda@gmail.com/
- https://lore.kernel.org/openbmc/20220516005412.4844-1-chiawei_wang@aspeedtech.com/

Previously, Jeremy had some suggestions covering the various channels:

https://lore.kernel.org/linux-aspeed/20c13b9bb023091758cac3a07fb4037b7d796578.camel@codeconstruct.com.au/

Andrew


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

* Re: [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller
  2026-03-13 10:07 ` [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller aspeedyh
@ 2026-03-16  7:07   ` Krzysztof Kozlowski
  2026-03-16  8:17     ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-16  7:07 UTC (permalink / raw)
  To: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak

On 13/03/2026 11:07, aspeedyh wrote:
> Introduce the device-tree bindings for the Enhanced Serial
> Peripheral Interface (eSPI) controller found on AST2600
> BMC SoCs.
> 
> The controller operates as the BMC-side eSPI slave and provides the
> peripheral, virtual wire, out-of-band, and flash channels used for
> host-BMC communication.
> 
> Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>

Please use your full name. Semi-anonymous contributions are not accepted.

Best regards,
Krzysztof


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

* RE: [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller
  2026-03-16  7:07   ` Krzysztof Kozlowski
@ 2026-03-16  8:17     ` YH Chung
  2026-03-16 11:04       ` Conor Dooley
  0 siblings, 1 reply; 30+ messages in thread
From: YH Chung @ 2026-03-16  8:17 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joel Stanley, Andrew Jeffery, Ryan Chen,
	Philipp Zabel
  Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com

Hi Krzysztof,

> On 13/03/2026 11:07, aspeedyh wrote:
> > Introduce the device-tree bindings for the Enhanced Serial
> > Peripheral Interface (eSPI) controller found on AST2600
> > BMC SoCs.
> >
> > The controller operates as the BMC-side eSPI slave and provides the
> > peripheral, virtual wire, out-of-band, and flash channels used for
> > host-BMC communication.
> >
> > Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> 
> Please use your full name. Semi-anonymous contributions are not accepted.
> 
> Best regards,
> Krzysztof

Thanks for the reminder.
Would you prefer that I resend this series with the corrected sign-off, or would it be fine to update it in the next version?

Thanks,
YunHsuan

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

* Re: [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support
  2026-03-13 10:07 ` [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support aspeedyh
@ 2026-03-16  9:57   ` Philipp Zabel
  2026-03-17  8:40     ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Philipp Zabel @ 2026-03-16  9:57 UTC (permalink / raw)
  To: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, openbmc,
	maciej.lawniczak

On Fr, 2026-03-13 at 18:07 +0800, aspeedyh wrote:
> Add core eSPI controller support and common code for ASPEED SoCs. The
> eSPI engine is a slave device in BMC to communicate with the Host over
> the eSPI interface.
> 
> The initial support includes basic eSPI driver probe/remove operations,
> and provides operators for ASPEED SoCs to implement their own eSPI slave
> device drivers that are different among SoC models.
> 
> Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> ---
>  drivers/soc/aspeed/Kconfig            |   7 ++
>  drivers/soc/aspeed/Makefile           |   1 +
>  drivers/soc/aspeed/espi/Makefile      |   1 +
>  drivers/soc/aspeed/espi/aspeed-espi.c | 143 ++++++++++++++++++++++++++++++++++
>  drivers/soc/aspeed/espi/aspeed-espi.h |  27 +++++++
>  5 files changed, 179 insertions(+)
> 
[...]
> diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c b/drivers/soc/aspeed/espi/aspeed-espi.c
> new file mode 100644
> index 000000000000..15d58b38bbe4
> --- /dev/null
> +++ b/drivers/soc/aspeed/espi/aspeed-espi.c
> @@ -0,0 +1,143 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Unified Aspeed eSPI driver framework for different generation SoCs
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +
> +#include "aspeed-espi.h"
> +
> +struct aspeed_espi_ops {
> +	void (*espi_pre_init)(struct aspeed_espi *espi);
> +	void (*espi_post_init)(struct aspeed_espi *espi);
> +	void (*espi_deinit)(struct aspeed_espi *espi);
> +	irqreturn_t (*espi_isr)(int irq, void *espi);
> +};
> +
> +static const struct of_device_id aspeed_espi_of_matches[] = {
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_espi_of_matches);
> +
> +static int aspeed_espi_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct aspeed_espi *espi;
> +	struct resource *res;
> +	struct device *dev;
> +	int rc;
> +
> +	dev = &pdev->dev;
> +	espi = devm_kzalloc(dev, sizeof(*espi), GFP_KERNEL);
> +	if (!espi)
> +		return -ENOMEM;
> +
[...]
> +
> +	espi->irq = platform_get_irq(pdev, 0);
> +	if (espi->irq < 0) {
> +		dev_err(dev, "cannot get IRQ number\n");
> +		return espi->irq;
> +	}
> +
> +	espi->rst = devm_reset_control_get_optional(dev, NULL);

Please use devm_reset_control_get_optional_exclusive() directly.

> +	if (IS_ERR(espi->rst)) {
> +		dev_err(dev, "cannot get reset control\n");
> +		return PTR_ERR(espi->rst);

Consider using dev_err_probe, same for the other errors.
That way the driver won't print incorrect error messages on
-EPROBE_DEFER.

[...]
> diff --git a/drivers/soc/aspeed/espi/aspeed-espi.h b/drivers/soc/aspeed/espi/aspeed-espi.h
> new file mode 100644
> index 000000000000..f4ad7f61fef6
> --- /dev/null
> +++ b/drivers/soc/aspeed/espi/aspeed-espi.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Unified eSPI driver header file and data structures
> + * Copyright 2026 Aspeed Technology Inc.
> + */
> +#ifndef ASPEED_ESPI_H
> +#define ASPEED_ESPI_H
> +
> +#include <linux/irqreturn.h>
> +#include <linux/miscdevice.h>
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +
> +#define DEVICE_NAME		"aspeed-espi"
> +
> +struct aspeed_espi {
> +	struct platform_device *pdev;
> +	struct device *dev;

Storing both pdev and &pdev->dev seems unnecessary.
Is pdev used at all?

> +	void __iomem *regs;
> +	struct reset_control *rst;

This is missing a forward declaration for struct reset_control.


regards
Philipp


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

* Re: [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller
  2026-03-16  8:17     ` YH Chung
@ 2026-03-16 11:04       ` Conor Dooley
  2026-03-17  8:43         ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Conor Dooley @ 2026-03-16 11:04 UTC (permalink / raw)
  To: YH Chung
  Cc: Krzysztof Kozlowski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joel Stanley, Andrew Jeffery, Ryan Chen,
	Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com

[-- Attachment #1: Type: text/plain, Size: 881 bytes --]

On Mon, Mar 16, 2026 at 08:17:48AM +0000, YH Chung wrote:
> Hi Krzysztof,
> 
> > On 13/03/2026 11:07, aspeedyh wrote:
> > > Introduce the device-tree bindings for the Enhanced Serial
> > > Peripheral Interface (eSPI) controller found on AST2600
> > > BMC SoCs.
> > >
> > > The controller operates as the BMC-side eSPI slave and provides the
> > > peripheral, virtual wire, out-of-band, and flash channels used for
> > > host-BMC communication.
> > >
> > > Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> > 
> > Please use your full name. Semi-anonymous contributions are not accepted.
> > 
> > Best regards,
> > Krzysztof
> 
> Thanks for the reminder.
> Would you prefer that I resend this series with the corrected sign-off, or would it be fine to update it in the next version?

Next version, when the discussion on the cover letter concludes, please.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* RE: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-16  6:34     ` Andrew Jeffery
@ 2026-03-17  8:14       ` YH Chung
  2026-03-17  9:50         ` Arnd Bergmann
  0 siblings, 1 reply; 30+ messages in thread
From: YH Chung @ 2026-03-17  8:14 UTC (permalink / raw)
  To: Andrew Jeffery, Arnd Bergmann, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown

> On Fri, 2026-03-13 at 22:36 +0100, Arnd Bergmann wrote:
> > On Fri, Mar 13, 2026, at 17:24, Conor Dooley wrote:
> > > On Fri, Mar 13, 2026 at 06:07:35PM +0800, aspeedyh wrote:
> > > > This series adds initial support for the eSPI controller found on ASPEED
> > > > AST2600 BMC SoCs.
> > > >
> > > > The series introduces a eSPI controller framework for ASPEED SoCs under
> > > > drivers/soc/aspeed/, adds AST2600-specific controller support for
> > > > peripheral and flash channels, defines the corresponding devicetree
> > > > binding, and adds the AST2600 eSPI controller node to the SoC dtsi.
> > > >
> > > > The driver is intended to support host-BMC communication over the
> BMC-side
> > > > eSPI slave controller present on AST2600 systems.
> > >
> > > This all seems to be in the wrong places entirely, shouldn't an eSPI
> > > driver and bindings go in the spi subsystem?
> >
> > From an initial reading, my impression is that patches 1, 2, 3 and 7
> > should be modified to use the normal SPI interfaces to implement
> > an spi target driver, possibly a combined host/target driver.
> > Reworking this should be fairly straightforward because the interfaces
> > to the SPI core are well documented.
> >
> > It is possible that the hardware can only be used to provide espi
> > device emulation. From what I could see in the code, there is
> > not much special in there, but I'm not that familiar with SPI
> >
> > Patches 4, 5 and 6 in consequently would need to be reworked so
> > these can implement the TAFS spec independent of the SPI controller,
> > and can be shared e.g. with other OpenBMC targets using the same
> > module and the same user interface. None of this should be aspeed
> > specific.
> >
> > There is a good chance that both the user interface and the placing
> > of the code will need a more debate, but I would suggest first trying
> > to move everything over to use the SPI subsystem but leave other
> > parts untouched for the moment.
> 
> To extend Arnd's points here, some previous attempts were made to
> support Intel's eSPI protocol on Aspeed's SoCs which aren't discussed
> in this cover letter. I think it would be helpful to cover the history
> and why we now have a third approach:
> 
> -
> https://lore.kernel.org/linux-aspeed/20240319093405.39833-1-manojkiran.eda@g
> mail.com/
> -
> https://lore.kernel.org/openbmc/20220516005412.4844-1-chiawei_wang@aspeedt
> ech.com/
> 
> Previously, Jeremy had some suggestions covering the various channels:
> 
> https://lore.kernel.org/linux-aspeed/20c13b9bb023091758cac3a07fb4037b7d7965
> 78.camel@codeconstruct.com.au/
> 
> Andrew

Hi Andrew, Ivan, Arnd,

Thanks for the additional context and the review links. It was my mistake not to reference the previous
discussions in the cover letter.

This series is intended to support the Intel eSPI interface on AST2600, specifically the parts corresponding
to LPC-style accesses and Target Flash Access Sharing (TAFS), which are defined in the peripheral and flash
channels of the eSPI specification.

Because the earlier OpenBMC work from Chia-Wei dates back to 2021, and because the code structure and
overall approach in this series differs substantially from that earlier work, I chose to post this as a new series
rather than as a revision of the earlier one.

I agree that the cover letter should explain this history more clearly, including the definition of eSPI, how this 
series differs from the previous attempts and how it relates to the earlier feedback on the channel split.
I will revise the cover letter accordingly in the next version.

In the meantime, my understanding is that this driver is for the Intel eSPI interface used by the AST2600 BMC,
rather than fitting a conventional SPI controller/device model. That was the reason for initially placing it under
drivers/soc/aspeed/, since there does not appear to be an in-tree eSPI subsystem at present.
However, if that is not the preferred upstream direction, we are happy to restructure the series accordingly. 
It would be very helpful if you could advise on the preferred placement.

Thanks,
Yun Hsuan



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

* RE: [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support
  2026-03-16  9:57   ` Philipp Zabel
@ 2026-03-17  8:40     ` YH Chung
  0 siblings, 0 replies; 30+ messages in thread
From: YH Chung @ 2026-03-17  8:40 UTC (permalink / raw)
  To: Philipp Zabel, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen
  Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com

Hi Philipp,

Thanks for the review.

> On Fr, 2026-03-13 at 18:07 +0800, aspeedyh wrote:
> > Add core eSPI controller support and common code for ASPEED SoCs. The
> > eSPI engine is a slave device in BMC to communicate with the Host over
> > the eSPI interface.
> >
> > The initial support includes basic eSPI driver probe/remove operations,
> > and provides operators for ASPEED SoCs to implement their own eSPI slave
> > device drivers that are different among SoC models.
> >
> > Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> > ---
> >  drivers/soc/aspeed/Kconfig            |   7 ++
> >  drivers/soc/aspeed/Makefile           |   1 +
> >  drivers/soc/aspeed/espi/Makefile      |   1 +
> >  drivers/soc/aspeed/espi/aspeed-espi.c | 143
> ++++++++++++++++++++++++++++++++++
> >  drivers/soc/aspeed/espi/aspeed-espi.h |  27 +++++++
> >  5 files changed, 179 insertions(+)
> >
> [...]
> > diff --git a/drivers/soc/aspeed/espi/aspeed-espi.c
> b/drivers/soc/aspeed/espi/aspeed-espi.c
> > new file mode 100644
> > index 000000000000..15d58b38bbe4
> > --- /dev/null
> > +++ b/drivers/soc/aspeed/espi/aspeed-espi.c
> > @@ -0,0 +1,143 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Unified Aspeed eSPI driver framework for different generation SoCs
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +
> > +#include "aspeed-espi.h"
> > +
> > +struct aspeed_espi_ops {
> > +	void (*espi_pre_init)(struct aspeed_espi *espi);
> > +	void (*espi_post_init)(struct aspeed_espi *espi);
> > +	void (*espi_deinit)(struct aspeed_espi *espi);
> > +	irqreturn_t (*espi_isr)(int irq, void *espi);
> > +};
> > +
> > +static const struct of_device_id aspeed_espi_of_matches[] = {
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(of, aspeed_espi_of_matches);
> > +
> > +static int aspeed_espi_probe(struct platform_device *pdev)
> > +{
> > +	const struct of_device_id *match;
> > +	struct aspeed_espi *espi;
> > +	struct resource *res;
> > +	struct device *dev;
> > +	int rc;
> > +
> > +	dev = &pdev->dev;
> > +	espi = devm_kzalloc(dev, sizeof(*espi), GFP_KERNEL);
> > +	if (!espi)
> > +		return -ENOMEM;
> > +
> [...]
> > +
> > +	espi->irq = platform_get_irq(pdev, 0);
> > +	if (espi->irq < 0) {
> > +		dev_err(dev, "cannot get IRQ number\n");
> > +		return espi->irq;
> > +	}
> > +
> > +	espi->rst = devm_reset_control_get_optional(dev, NULL);
> 
> Please use devm_reset_control_get_optional_exclusive() directly.
> 
I will update this to use devm_reset_control_get_optional_exclusive()

> > +	if (IS_ERR(espi->rst)) {
> > +		dev_err(dev, "cannot get reset control\n");
> > +		return PTR_ERR(espi->rst);
> 
> Consider using dev_err_probe, same for the other errors.
> That way the driver won't print incorrect error messages on
> -EPROBE_DEFER.
I will switch these error paths to dev_err_probe() so that -EPROBE_DEFER can be handled correctly.

> 
> [...]
> > diff --git a/drivers/soc/aspeed/espi/aspeed-espi.h
> b/drivers/soc/aspeed/espi/aspeed-espi.h
> > new file mode 100644
> > index 000000000000..f4ad7f61fef6
> > --- /dev/null
> > +++ b/drivers/soc/aspeed/espi/aspeed-espi.h
> > @@ -0,0 +1,27 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Unified eSPI driver header file and data structures
> > + * Copyright 2026 Aspeed Technology Inc.
> > + */
> > +#ifndef ASPEED_ESPI_H
> > +#define ASPEED_ESPI_H
> > +
> > +#include <linux/irqreturn.h>
> > +#include <linux/miscdevice.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/types.h>
> > +
> > +#define DEVICE_NAME		"aspeed-espi"
> > +
> > +struct aspeed_espi {
> > +	struct platform_device *pdev;
> > +	struct device *dev;
> 
> Storing both pdev and &pdev->dev seems unnecessary.
> Is pdev used at all?
> 
Agreed, pdev is not used in the subsequent patches. I will remove it in the next revision.

> > +	void __iomem *regs;
> > +	struct reset_control *rst;
> 
> This is missing a forward declaration for struct reset_control.
> 
Will update to add <linux/reset.h> in the next revision to provide declaration for struct reset_control
> 
> regards
> Philipp

Thanks,
Yun Hsuan.

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

* RE: [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller
  2026-03-16 11:04       ` Conor Dooley
@ 2026-03-17  8:43         ` YH Chung
  0 siblings, 0 replies; 30+ messages in thread
From: YH Chung @ 2026-03-17  8:43 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Krzysztof Kozlowski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joel Stanley, Andrew Jeffery, Ryan Chen,
	Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com

Hi Conor,

> 
> On Mon, Mar 16, 2026 at 08:17:48AM +0000, YH Chung wrote:
> > Hi Krzysztof,
> >
> > > On 13/03/2026 11:07, aspeedyh wrote:
> > > > Introduce the device-tree bindings for the Enhanced Serial
> > > > Peripheral Interface (eSPI) controller found on AST2600
> > > > BMC SoCs.
> > > >
> > > > The controller operates as the BMC-side eSPI slave and provides the
> > > > peripheral, virtual wire, out-of-band, and flash channels used for
> > > > host-BMC communication.
> > > >
> > > > Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> > >
> > > Please use your full name. Semi-anonymous contributions are not accepted.
> > >
> > > Best regards,
> > > Krzysztof
> >
> > Thanks for the reminder.
> > Would you prefer that I resend this series with the corrected sign-off, or would it
> be fine to update it in the next version?
> 
> Next version, when the discussion on the cover letter concludes, please.

Got it, thanks for the guidance.

Thanks,
Yun Hsuan


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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-17  8:14       ` YH Chung
@ 2026-03-17  9:50         ` Arnd Bergmann
  2026-03-25  8:41           ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2026-03-17  9:50 UTC (permalink / raw)
  To: aspeedyh, Andrew Jeffery, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown

On Tue, Mar 17, 2026, at 09:14, YH Chung wrote:
>
> In the meantime, my understanding is that this driver is for the Intel 
> eSPI interface used by the AST2600 BMC,
> rather than fitting a conventional SPI controller/device model. That 
> was the reason for initially placing it under
> drivers/soc/aspeed/, since there does not appear to be an in-tree eSPI 
> subsystem at present.
> However, if that is not the preferred upstream direction, we are happy 
> to restructure the series accordingly. 
> It would be very helpful if you could advise on the preferred placement.

I think we need to make sure everyone understands what the options are
here based on what the hardware can do, and what your use cases require.

From reading the old comments that Andrew linked to at

https://lore.kernel.org/linux-aspeed/HK0PR06MB377924CFCBFE9BD40E1C4A5D91D49@HK0PR06MB3779.apcprd06.prod.outlook.com/

I understand that the SoC has a "hardware mode" in which eSPI is
directly implemented by redirecting upper-level eSPI transactions into
functional blocks of the chip, while the software mode behaves like
a regular SPI endpoint controller and your driver implements the 
same interfaces in a mix of kernel and userspace components. Can you
confirm that this is a correct understanding of what the hardware
does, or where I misunderstand parts?

If I understood this correctly, I think there is a general agreement
upstream that the low-level device access should indeed be in a
drivers/spi driver, with no ports of it in drivers/soc/aspeed. Using
a portable driver subsystem is always better than a custom solution
if it works at all.

For the higher-level interfaces (flash, gpio, ...), I don't think
there is any consensus yet about how this should be done, but again
I think this won't be drivers/soc but instead something more
generic.

One option here would be to sidestep this problem entirely by
moving all of the eSPI implementation out of the kernel but instead
have a hardware-independent userspace implementation that uses
the spidev ioctl interface. This is always going to be slower than
an in-kernel implementation, but also much easier to implement
and debug.

An in-kernel implementation of the eSPI backend (on top of
the SPI layer) is certainly a realistic option for the higher
layers, but requires finding consensus both on the the logistics
(subsystem, code ownership, interfaces to other subsystems)
and more importantly the user space interfaces that look like
they will require several revisions on top of what you have
today.

      Arnd


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

* Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
  2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
@ 2026-03-19 23:53   ` kernel test robot
  2026-03-20  1:17   ` kernel test robot
  2026-03-20  4:19   ` kernel test robot
  2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2026-03-19 23:53 UTC (permalink / raw)
  To: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: oe-kbuild-all, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, maciej.lawniczak, aspeedyh

Hi aspeedyh,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 0257f64bdac7fdca30fa3cae0df8b9ecbec7733a]

url:    https://github.com/intel-lab-lkp/linux/commits/aspeedyh/dt-bindings-soc-aspeed-Add-AST2600-eSPI-controller/20260315-101647
base:   0257f64bdac7fdca30fa3cae0df8b9ecbec7733a
patch link:    https://lore.kernel.org/r/20260313-upstream_espi-v1-5-9504428e1f43%40aspeedtech.com
patch subject: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20260320/202603200700.6fddOZHQ-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260320/202603200700.6fddOZHQ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603200700.6fddOZHQ-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_reset':
   drivers/soc/aspeed/espi/ast2600-espi.c:137:16: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
     137 |         reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
         |                ^~~~~~~~~~
   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_remove':
>> drivers/soc/aspeed/espi/ast2600-espi.c:172:35: warning: variable 'flash' set but not used [-Wunused-but-set-variable]
     172 |         struct aspeed_espi_flash *flash;
         |                                   ^~~~~
   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_get_hdr':
   drivers/soc/aspeed/espi/ast2600-espi.c:194:20: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
     194 |         hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
         |                    ^~~~~~~~~


vim +/flash +172 drivers/soc/aspeed/espi/ast2600-espi.c

   169	
   170	int ast2600_espi_flash_remove(struct aspeed_espi *espi)
   171	{
 > 172		struct aspeed_espi_flash *flash;
   173		u32 reg;
   174	
   175		flash = &espi->flash;
   176	
   177		writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
   178	
   179		reg = readl(espi->regs + ESPI_CTRL);
   180		reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
   181			 | ESPI_CTRL_FLASH_RX_DMA_EN
   182			 | ESPI_CTRL_FLASH_SW_RDY);
   183		writel(reg, espi->regs + ESPI_CTRL);
   184	
   185		return 0;
   186	}
   187	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
  2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
  2026-03-19 23:53   ` kernel test robot
@ 2026-03-20  1:17   ` kernel test robot
  2026-03-20  4:19   ` kernel test robot
  2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2026-03-20  1:17 UTC (permalink / raw)
  To: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: oe-kbuild-all, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, maciej.lawniczak, aspeedyh

Hi aspeedyh,

kernel test robot noticed the following build errors:

[auto build test ERROR on 0257f64bdac7fdca30fa3cae0df8b9ecbec7733a]

url:    https://github.com/intel-lab-lkp/linux/commits/aspeedyh/dt-bindings-soc-aspeed-Add-AST2600-eSPI-controller/20260315-101647
base:   0257f64bdac7fdca30fa3cae0df8b9ecbec7733a
patch link:    https://lore.kernel.org/r/20260313-upstream_espi-v1-5-9504428e1f43%40aspeedtech.com
patch subject: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20260320/202603200904.M00MLkjz-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260320/202603200904.M00MLkjz-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603200904.M00MLkjz-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_reset':
>> drivers/soc/aspeed/espi/ast2600-espi.c:137:16: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
     137 |         reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
         |                ^~~~~~~~~~
   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_remove':
   drivers/soc/aspeed/espi/ast2600-espi.c:172:35: warning: variable 'flash' set but not used [-Wunused-but-set-variable]
     172 |         struct aspeed_espi_flash *flash;
         |                                   ^~~~~
   drivers/soc/aspeed/espi/ast2600-espi.c: In function 'ast2600_espi_flash_get_hdr':
>> drivers/soc/aspeed/espi/ast2600-espi.c:194:20: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
     194 |         hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
         |                    ^~~~~~~~~


vim +/FIELD_PREP +137 drivers/soc/aspeed/espi/ast2600-espi.c

   111	
   112	static void ast2600_espi_flash_reset(struct aspeed_espi *espi)
   113	{
   114		struct aspeed_espi_flash *flash;
   115		u32 reg;
   116	
   117		flash = &espi->flash;
   118	
   119		writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
   120		writel(ESPI_INT_STS_FLASH, espi->regs + ESPI_INT_STS);
   121	
   122		reg = readl(espi->regs + ESPI_CTRL);
   123		reg &= ~(ESPI_CTRL_FLASH_TX_SW_RST
   124			 | ESPI_CTRL_FLASH_RX_SW_RST
   125			 | ESPI_CTRL_FLASH_TX_DMA_EN
   126			 | ESPI_CTRL_FLASH_RX_DMA_EN
   127			 | ESPI_CTRL_FLASH_SW_RDY);
   128		writel(reg, espi->regs + ESPI_CTRL);
   129	
   130		udelay(1);
   131	
   132		reg |= (ESPI_CTRL_FLASH_TX_SW_RST | ESPI_CTRL_FLASH_RX_SW_RST);
   133		writel(reg, espi->regs + ESPI_CTRL);
   134	
   135		flash->tafs.mode = TAFS_MODE_SW;
   136		reg = readl(espi->regs + ESPI_CTRL) & ~ESPI_CTRL_FLASH_TAFS_MODE;
 > 137		reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
   138		writel(reg, espi->regs + ESPI_CTRL);
   139	
   140		if (flash->dma.enable) {
   141			writel(flash->dma.tx_addr, espi->regs + ESPI_FLASH_TX_DMA);
   142			writel(flash->dma.rx_addr, espi->regs + ESPI_FLASH_RX_DMA);
   143	
   144			reg = readl(espi->regs + ESPI_CTRL)
   145			      | ESPI_CTRL_FLASH_TX_DMA_EN
   146			      | ESPI_CTRL_FLASH_RX_DMA_EN;
   147			writel(reg, espi->regs + ESPI_CTRL);
   148		}
   149	
   150		writel(ESPI_INT_EN_FLASH_RX_CMPLT, espi->regs + ESPI_INT_EN);
   151	
   152		reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SW_RDY;
   153		writel(reg, espi->regs + ESPI_CTRL);
   154	}
   155	
   156	int ast2600_espi_flash_probe(struct aspeed_espi *espi)
   157	{
   158		u32 regs;
   159	
   160		regs = readl(espi->regs + ESPI_STS);
   161		if (regs & (ESPI_STS_FLASH_TX_BUSY | ESPI_STS_FLASH_RX_BUSY)) {
   162			dev_warn(espi->dev, "eSPI flash channel is busy, deferring...\n");
   163			return -EPROBE_DEFER;
   164		}
   165	
   166		ast2600_espi_flash_reset(espi);
   167		return 0;
   168	}
   169	
   170	int ast2600_espi_flash_remove(struct aspeed_espi *espi)
   171	{
   172		struct aspeed_espi_flash *flash;
   173		u32 reg;
   174	
   175		flash = &espi->flash;
   176	
   177		writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
   178	
   179		reg = readl(espi->regs + ESPI_CTRL);
   180		reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
   181			 | ESPI_CTRL_FLASH_RX_DMA_EN
   182			 | ESPI_CTRL_FLASH_SW_RDY);
   183		writel(reg, espi->regs + ESPI_CTRL);
   184	
   185		return 0;
   186	}
   187	
   188	int ast2600_espi_flash_get_hdr(struct aspeed_espi *espi,
   189				       struct espi_comm_hdr *hdr)
   190	{
   191		u32 reg, len;
   192	
   193		reg = readl(espi->regs + ESPI_FLASH_RX_CTRL);
 > 194		hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
   195		hdr->tag = FIELD_GET(ESPI_FLASH_RX_CTRL_TAG, reg);
   196		len = FIELD_GET(ESPI_FLASH_RX_CTRL_LEN, reg);
   197		hdr->len_h = (len >> 8) & 0xff;
   198		hdr->len_l = len & 0xff;
   199	
   200		return 0;
   201	}
   202	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
  2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
  2026-03-19 23:53   ` kernel test robot
  2026-03-20  1:17   ` kernel test robot
@ 2026-03-20  4:19   ` kernel test robot
  2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2026-03-20  4:19 UTC (permalink / raw)
  To: aspeedyh, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Ryan Chen, Philipp Zabel
  Cc: llvm, oe-kbuild-all, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, maciej.lawniczak, aspeedyh

Hi aspeedyh,

kernel test robot noticed the following build errors:

[auto build test ERROR on 0257f64bdac7fdca30fa3cae0df8b9ecbec7733a]

url:    https://github.com/intel-lab-lkp/linux/commits/aspeedyh/dt-bindings-soc-aspeed-Add-AST2600-eSPI-controller/20260315-101647
base:   0257f64bdac7fdca30fa3cae0df8b9ecbec7733a
patch link:    https://lore.kernel.org/r/20260313-upstream_espi-v1-5-9504428e1f43%40aspeedtech.com
patch subject: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260320/202603201234.n0spXcAN-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260320/202603201234.n0spXcAN-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603201234.n0spXcAN-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/soc/aspeed/espi/ast2600-espi.c:137:9: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
           reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
                  ^
   drivers/soc/aspeed/espi/ast2600-espi.c:172:28: warning: variable 'flash' set but not used [-Wunused-but-set-variable]
           struct aspeed_espi_flash *flash;
                                     ^
>> drivers/soc/aspeed/espi/ast2600-espi.c:194:13: error: call to undeclared function 'FIELD_GET'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
           hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
                      ^
   drivers/soc/aspeed/espi/ast2600-espi.c:243:8: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
           reg = FIELD_PREP(ESPI_FLASH_TX_CTRL_CYC, cyc) |
                 ^
   1 warning and 3 errors generated.


vim +/FIELD_PREP +137 drivers/soc/aspeed/espi/ast2600-espi.c

   111	
   112	static void ast2600_espi_flash_reset(struct aspeed_espi *espi)
   113	{
   114		struct aspeed_espi_flash *flash;
   115		u32 reg;
   116	
   117		flash = &espi->flash;
   118	
   119		writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
   120		writel(ESPI_INT_STS_FLASH, espi->regs + ESPI_INT_STS);
   121	
   122		reg = readl(espi->regs + ESPI_CTRL);
   123		reg &= ~(ESPI_CTRL_FLASH_TX_SW_RST
   124			 | ESPI_CTRL_FLASH_RX_SW_RST
   125			 | ESPI_CTRL_FLASH_TX_DMA_EN
   126			 | ESPI_CTRL_FLASH_RX_DMA_EN
   127			 | ESPI_CTRL_FLASH_SW_RDY);
   128		writel(reg, espi->regs + ESPI_CTRL);
   129	
   130		udelay(1);
   131	
   132		reg |= (ESPI_CTRL_FLASH_TX_SW_RST | ESPI_CTRL_FLASH_RX_SW_RST);
   133		writel(reg, espi->regs + ESPI_CTRL);
   134	
   135		flash->tafs.mode = TAFS_MODE_SW;
   136		reg = readl(espi->regs + ESPI_CTRL) & ~ESPI_CTRL_FLASH_TAFS_MODE;
 > 137		reg |= FIELD_PREP(ESPI_CTRL_FLASH_TAFS_MODE, flash->tafs.mode);
   138		writel(reg, espi->regs + ESPI_CTRL);
   139	
   140		if (flash->dma.enable) {
   141			writel(flash->dma.tx_addr, espi->regs + ESPI_FLASH_TX_DMA);
   142			writel(flash->dma.rx_addr, espi->regs + ESPI_FLASH_RX_DMA);
   143	
   144			reg = readl(espi->regs + ESPI_CTRL)
   145			      | ESPI_CTRL_FLASH_TX_DMA_EN
   146			      | ESPI_CTRL_FLASH_RX_DMA_EN;
   147			writel(reg, espi->regs + ESPI_CTRL);
   148		}
   149	
   150		writel(ESPI_INT_EN_FLASH_RX_CMPLT, espi->regs + ESPI_INT_EN);
   151	
   152		reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SW_RDY;
   153		writel(reg, espi->regs + ESPI_CTRL);
   154	}
   155	
   156	int ast2600_espi_flash_probe(struct aspeed_espi *espi)
   157	{
   158		u32 regs;
   159	
   160		regs = readl(espi->regs + ESPI_STS);
   161		if (regs & (ESPI_STS_FLASH_TX_BUSY | ESPI_STS_FLASH_RX_BUSY)) {
   162			dev_warn(espi->dev, "eSPI flash channel is busy, deferring...\n");
   163			return -EPROBE_DEFER;
   164		}
   165	
   166		ast2600_espi_flash_reset(espi);
   167		return 0;
   168	}
   169	
   170	int ast2600_espi_flash_remove(struct aspeed_espi *espi)
   171	{
   172		struct aspeed_espi_flash *flash;
   173		u32 reg;
   174	
   175		flash = &espi->flash;
   176	
   177		writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
   178	
   179		reg = readl(espi->regs + ESPI_CTRL);
   180		reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
   181			 | ESPI_CTRL_FLASH_RX_DMA_EN
   182			 | ESPI_CTRL_FLASH_SW_RDY);
   183		writel(reg, espi->regs + ESPI_CTRL);
   184	
   185		return 0;
   186	}
   187	
   188	int ast2600_espi_flash_get_hdr(struct aspeed_espi *espi,
   189				       struct espi_comm_hdr *hdr)
   190	{
   191		u32 reg, len;
   192	
   193		reg = readl(espi->regs + ESPI_FLASH_RX_CTRL);
 > 194		hdr->cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
   195		hdr->tag = FIELD_GET(ESPI_FLASH_RX_CTRL_TAG, reg);
   196		len = FIELD_GET(ESPI_FLASH_RX_CTRL_LEN, reg);
   197		hdr->len_h = (len >> 8) & 0xff;
   198		hdr->len_l = len & 0xff;
   199	
   200		return 0;
   201	}
   202	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* RE: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-17  9:50         ` Arnd Bergmann
@ 2026-03-25  8:41           ` YH Chung
  2026-03-25 10:30             ` Arnd Bergmann
  0 siblings, 1 reply; 30+ messages in thread
From: YH Chung @ 2026-03-25  8:41 UTC (permalink / raw)
  To: Arnd Bergmann, Andrew Jeffery, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown

Hi Arnd,

> On Tue, Mar 17, 2026, at 09:14, YH Chung wrote:
> >
> > In the meantime, my understanding is that this driver is for the Intel
> > eSPI interface used by the AST2600 BMC,
> > rather than fitting a conventional SPI controller/device model. That
> > was the reason for initially placing it under
> > drivers/soc/aspeed/, since there does not appear to be an in-tree eSPI
> > subsystem at present.
> > However, if that is not the preferred upstream direction, we are happy
> > to restructure the series accordingly.
> > It would be very helpful if you could advise on the preferred placement.
> 
> I think we need to make sure everyone understands what the options are
> here based on what the hardware can do, and what your use cases require.
> 
For reference, Intel's eSPI base specification is defined here:
https://www.intel.com/content/www/us/en/content-details/841685/enhanced-serial-peripheral-interface-espi-interface-base-specification-for-client-and-server-platforms.html

Although eSPI physically reuses some SPI pins, it is not used as a
conventional SPI controller/device interface. It also adds RESET# and ALERT#
beyond the usual SPI signals.

The spec also defines two roles in eSPI transaction model: Controller and
Target Device. ASPEED SoCs act as the Target Device side to interact with the
host. In this case, the hardware is not exposed in a form that maps naturally
onto the existing SPI subsystem model.

> If I understood this correctly, I think there is a general agreement
> upstream that the low-level device access should indeed be in a
> drivers/spi driver, with no ports of it in drivers/soc/aspeed. Using
> a portable driver subsystem is always better than a custom solution
> if it works at all.

We understand the preference for using a generic subsystem where possible.
Our hesitation is that the eSPI functionality appears to software primarily
in terms of the eSPI Peripherals, Virtual Wires, OOB (SMBus), and Flash
channel semantics and backend routing, rather than low-level bus signaling.

Since this driver is responsible for configuring those Aspeed-specific
backend interfaces so they can service host requests, we initially placed it
under drivers/soc/aspeed.

> From reading the old comments that Andrew linked to at
> 
> https://lore.kernel.org/linux-aspeed/HK0PR06MB377924CFCBFE9BD40E1C4A5D91
> D49@HK0PR06MB3779.apcprd06.prod.outlook.com/
> 
> I understand that the SoC has a "hardware mode" in which eSPI is
> directly implemented by redirecting upper-level eSPI transactions into
> functional blocks of the chip, while the software mode behaves like
> a regular SPI endpoint controller and your driver implements the
> same interfaces in a mix of kernel and userspace components. Can you
> confirm that this is a correct understanding of what the hardware
> does, or where I misunderstand parts?

Broadly yes, except that the AST2600 does not operate in a single global
"hardware mode" or "software mode". Instead, some backends in the eSPI target
controller support per-function HW/SW mode selection.

Depending on that function-specific setting, the controller either forwards a
received transaction directly to the corresponding hardware block or traps it
for software handling instead.

This mechanism exists because some backend blocks include their own hardware
filtering, but not all request types could be validated generically in
hardware. For example, the LPC bridge can reject illegal requests. In some
cases, blindly forwarding host requests to the target block would also have
security implications.

The channel/backend mapping on AST2600 can be summarized as:

eSPI
├── Peripheral
│ ├── Memory (HW mode only)
│ └── LPC bridge (HW mode only)
├── Virtual Wire
│ └── GPIO (HW/SW mode selection)
├── Out-of-Band (SW mode only)
└── Flash
   └── Storage controller (HW/SW mode selection)

From the link thread, what Jeremy mentioned is the GPIO HW/SW mode for CH1,
which determines whether the host can directly control the corresponding BMC
GPIO output, or whether BMC software can inspect and decide whether to act on
that request.

Another example is the Target Attached Flash Sharing (TAFS) defined by the
eSPI specification that allows BMC to share its storage with the host.

In hardware mode, the eSPI Target Device controller routes the request
directly to a predefined storage controller on AST2600.
In software mode, it raises an interrupt and lets software handle the
transaction instead.

So I would not describe the AST2600 eSPI block as being globally in either
"hardware mode" or "software mode".
That choice is made per backend function, and some backend functions do not
implement such a switch at all.

So far, this series only covers the LPC bridge and flash channel parts.

> For the higher-level interfaces (flash, gpio, ...), I don't think
> there is any consensus yet about how this should be done, but again
> I think this won't be drivers/soc but instead something more
> generic.

For the flash-related interface, would it make sense to follow the
configuration model used by the USB gadget mass-storage function, and expose
the backing storage selection through configfs? 

For the attributes, perhaps the only backing storage object and read-only
flag would be required in our case.

For the Virtual Wire GPIO, we think GPIO subsystem may be leveraged here,
though some corner cases may not map cleanly to a typical GPIO controller
model.

For the Out-of-band channel, since the eSPI spec models it for tunneled SMBus
packets, we may want to integrate it with the kernel's MCTP stack if that is
a suitable fit.

Thanks,
Yun Hsuan



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

* Re: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-25  8:41           ` YH Chung
@ 2026-03-25 10:30             ` Arnd Bergmann
  2026-03-27  4:14               ` YH Chung
  0 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2026-03-25 10:30 UTC (permalink / raw)
  To: aspeedyh, Andrew Jeffery, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown

On Wed, Mar 25, 2026, at 09:41, YH Chung wrote:
>> On Tue, Mar 17, 2026, at 09:14, YH Chung wrote:
>> From reading the old comments that Andrew linked to at
>> 
>> https://lore.kernel.org/linux-aspeed/HK0PR06MB377924CFCBFE9BD40E1C4A5D91
>> D49@HK0PR06MB3779.apcprd06.prod.outlook.com/
>> 
>> I understand that the SoC has a "hardware mode" in which eSPI is
>> directly implemented by redirecting upper-level eSPI transactions into
>> functional blocks of the chip, while the software mode behaves like
>> a regular SPI endpoint controller and your driver implements the
>> same interfaces in a mix of kernel and userspace components. Can you
>> confirm that this is a correct understanding of what the hardware
>> does, or where I misunderstand parts?
>
> Broadly yes, except that the AST2600 does not operate in a single global
> "hardware mode" or "software mode". Instead, some backends in the eSPI target
> controller support per-function HW/SW mode selection.
>
> Depending on that function-specific setting, the controller either forwards a
> received transaction directly to the corresponding hardware block or traps it
> for software handling instead.
>
> This mechanism exists because some backend blocks include their own hardware
> filtering, but not all request types could be validated generically in
> hardware. For example, the LPC bridge can reject illegal requests. In some
> cases, blindly forwarding host requests to the target block would also have
> security implications.
>
> The channel/backend mapping on AST2600 can be summarized as:
>
> eSPI
> ├── Peripheral
> │ ├── Memory (HW mode only)
> │ └── LPC bridge (HW mode only)
> ├── Virtual Wire
> │ └── GPIO (HW/SW mode selection)
> ├── Out-of-Band (SW mode only)
> └── Flash
>    └── Storage controller (HW/SW mode selection)
>
> From the link thread, what Jeremy mentioned is the GPIO HW/SW mode for CH1,
> which determines whether the host can directly control the corresponding BMC
> GPIO output, or whether BMC software can inspect and decide whether to act on
> that request.
>
> Another example is the Target Attached Flash Sharing (TAFS) defined by the
> eSPI specification that allows BMC to share its storage with the host.
>
> In hardware mode, the eSPI Target Device controller routes the request
> directly to a predefined storage controller on AST2600.
> In software mode, it raises an interrupt and lets software handle the
> transaction instead.
>
> So I would not describe the AST2600 eSPI block as being globally in either
> "hardware mode" or "software mode".
> That choice is made per backend function, and some backend functions do not
> implement such a switch at all.

I see, thanks for the detailed explanation! Two follow-up questions:

- For the HW-mode-only peripherals (memory, LPC), is there any
  driver interaction at all for setting it up, or is this completely
  transparent to Linux running on the BMC?

- For the other devices running in SW mode, is the interface that the
  driver sees abstract in the sense that the same low-level code
  is shared for all of them, or are these still separate functional
  blocks that each need their own register-level interface?

>> For the higher-level interfaces (flash, gpio, ...), I don't think
>> there is any consensus yet about how this should be done, but again
>> I think this won't be drivers/soc but instead something more
>> generic.
>
> For the flash-related interface, would it make sense to follow the
> configuration model used by the USB gadget mass-storage function, and expose
> the backing storage selection through configfs? 
>
> For the attributes, perhaps the only backing storage object and read-only
> flag would be required in our case.
>
> For the Virtual Wire GPIO, we think GPIO subsystem may be leveraged here,
> though some corner cases may not map cleanly to a typical GPIO controller
> model.
>
> For the Out-of-band channel, since the eSPI spec models it for tunneled SMBus
> packets, we may want to integrate it with the kernel's MCTP stack if that is
> a suitable fit.

These all seem to be viable options, but I still think we should
focus on agreeing on a design for the low-level hardware interface
and whether this can or should be abstracted between SoC vendor
specific drivers before trying to solve the user interface side.

      Arnd


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

* RE: [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support
  2026-03-25 10:30             ` Arnd Bergmann
@ 2026-03-27  4:14               ` YH Chung
  0 siblings, 0 replies; 30+ messages in thread
From: YH Chung @ 2026-03-27  4:14 UTC (permalink / raw)
  To: Arnd Bergmann, Andrew Jeffery, Conor Dooley
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Ryan Chen, Philipp Zabel, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, maciej.lawniczak@intel.com, Mark Brown

Hi Arnd,

> - For the HW-mode-only peripherals (memory, LPC), is there any
>   driver interaction at all for setting it up, or is this completely
>   transparent to Linux running on the BMC?

For LPC-style IO accesses like Post Code Capture (PCC), the accesses are
completely transparent to Linux.

For memory accesses, they are also transparent to Linux on the BMC. It just
requires configuring the translation from the bus address to a reserved
memory region on the BMC during driver probe.


> - For the other devices running in SW mode, is the interface that the
>   driver sees abstract in the sense that the same low-level code
>   is shared for all of them, or are these still separate functional
>   blocks that each need their own register-level interface?

The channels are distinct functional blocks within the eSPI controller, each
using its own channel-specific registers regardless of whether they operate
in HW or SW mode. There is no common message flow or registers for the
software modes. The eSPI controller dispatches eSPI messages to the relevant
channel's hardware function block, which then takes action according to its
mode configuration.

Some low-level framework code may be shareable, for example a unified ISR
entry that checks interrupt status register and routes to channel-specific
handlers, but the corresponding handling will be channel-specific.

Thanks,
Yun Hsuan

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

end of thread, other threads:[~2026-03-27  4:14 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-13 10:07 [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support aspeedyh
2026-03-13 10:07 ` [PATCH 1/7] dt-bindings: soc: aspeed: Add AST2600 eSPI controller aspeedyh
2026-03-16  7:07   ` Krzysztof Kozlowski
2026-03-16  8:17     ` YH Chung
2026-03-16 11:04       ` Conor Dooley
2026-03-17  8:43         ` YH Chung
2026-03-13 10:07 ` [PATCH 2/7] soc: aspeed: Introduce core eSPI controller support aspeedyh
2026-03-16  9:57   ` Philipp Zabel
2026-03-17  8:40     ` YH Chung
2026-03-13 10:07 ` [PATCH 3/7] soc: aspeed: Add AST2600 peripheral channel port I/O support aspeedyh
2026-03-13 10:07 ` [PATCH 4/7] soc: aspeed: Add eSPI TAFS backend support aspeedyh
2026-03-13 10:07 ` [PATCH 5/7] soc: aspeed: Add eSPI flash channel support aspeedyh
2026-03-19 23:53   ` kernel test robot
2026-03-20  1:17   ` kernel test robot
2026-03-20  4:19   ` kernel test robot
2026-03-13 10:07 ` [PATCH 6/7] soc: aspeed: Add sysfs controls for flash backend selection aspeedyh
2026-03-13 10:07 ` [PATCH 7/7] arm: dts: aspeed: Add eSPI node for AST2600 aspeedyh
2026-03-13 16:24 ` [PATCH 0/7] soc: aspeed: Add AST2600 eSPI controller support Conor Dooley
2026-03-13 16:32   ` Mark Brown
2026-03-13 16:48     ` Mark Brown
2026-03-16  3:07       ` YH Chung
2026-03-13 21:36   ` Arnd Bergmann
2026-03-14  1:02     ` Mark Brown
2026-03-16  6:06     ` Ivan Mikhaylov
2026-03-16  6:34     ` Andrew Jeffery
2026-03-17  8:14       ` YH Chung
2026-03-17  9:50         ` Arnd Bergmann
2026-03-25  8:41           ` YH Chung
2026-03-25 10:30             ` Arnd Bergmann
2026-03-27  4:14               ` YH Chung

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