[PATCH 5/7] soc: aspeed: Add eSPI flash channel support

aspeedyh posted 7 patches 3 weeks, 4 days ago
[PATCH 5/7] soc: aspeed: Add eSPI flash channel support
Posted by aspeedyh 3 weeks, 4 days ago
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
Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
Posted by kernel test robot 2 weeks, 4 days ago
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
Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
Posted by kernel test robot 2 weeks, 4 days ago
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
Re: [PATCH 5/7] soc: aspeed: Add eSPI flash channel support
Posted by kernel test robot 2 weeks, 4 days ago
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