All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bin Meng <bin.meng@processmission.com>
To: QEMU <qemu-devel@nongnu.org>
Cc: "Bin Meng" <bmeng.cn@gmail.com>,
	"Fabiano Rosas" <farosas@suse.de>,
	"Laurent Vivier" <lvivier@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>,
	qemu-block@nongnu.org
Subject: [PATCH v2 06/32] tests/qtest: Add Synopsys DesignWare MCI coverage
Date: Tue,  8 Sep 2026 18:41:15 +0800	[thread overview]
Message-ID: <20260908104159.1621764-7-bin.meng@processmission.com> (raw)
In-Reply-To: <20260908104159.1621764-1-bin.meng@processmission.com>

Exercise the reusable DesignWare MCI behavior through the Phytium Pi
board integration. Cover register reset and interrupt handling, 64-bit
IDMAC write/read and suspend/resume paths, and FIFO PIO transfers
against an SD image.

Signed-off-by: Bin Meng <bin.meng@processmission.com>

---

Changes in v2:
- Follow the MCI device into the E2000 SoC QOM subtree

 MAINTAINERS               |   1 +
 tests/qtest/dw_mci-test.c | 417 ++++++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build   |   1 +
 3 files changed, 419 insertions(+)
 create mode 100644 tests/qtest/dw_mci-test.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 705a541b69..d577cdbda5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2419,6 +2419,7 @@ F: hw/sd/core.c
 F: hw/sd/dw_mci.c
 F: hw/sd/sd*
 F: hw/sd/ssi-sd.c
+F: tests/qtest/dw_mci-test.c
 F: tests/qtest/fuzz-sdcard-test.c
 F: tests/qtest/sdhci-test.c
 F: tests/qtest/xilinx-zynq-sdhci-test.c
diff --git a/tests/qtest/dw_mci-test.c b/tests/qtest/dw_mci-test.c
new file mode 100644
index 0000000000..5adfc0bfca
--- /dev/null
+++ b/tests/qtest/dw_mci-test.c
@@ -0,0 +1,417 @@
+/*
+ * QTests for the Synopsys DesignWare Multimedia Card Interface
+ *
+ * Copyright (c) 2026 Process Mission
+ *
+ * Author:
+ *   Bin Meng <bin.meng@processmission.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "qemu/bswap.h"
+#include "qemu/units.h"
+#include "libqtest.h"
+
+#define DW_MCI_BASE             0x28001000
+
+#define DW_MCI_CTRL             0x000
+#define DW_MCI_PWREN            0x004
+#define DW_MCI_TMOUT            0x014
+#define DW_MCI_BLKSIZ           0x01c
+#define DW_MCI_BYTCNT           0x020
+#define DW_MCI_INTMASK          0x024
+#define DW_MCI_CMDARG           0x028
+#define DW_MCI_CMD              0x02c
+#define DW_MCI_RESP0            0x030
+#define DW_MCI_MINTSTS          0x040
+#define DW_MCI_RINTSTS          0x044
+#define DW_MCI_STATUS           0x048
+#define DW_MCI_FIFOTH           0x04c
+#define DW_MCI_CDETECT          0x050
+#define DW_MCI_TCBCNT           0x05c
+#define DW_MCI_TBBCNT           0x060
+#define DW_MCI_DEBNCE           0x064
+#define DW_MCI_VERID            0x06c
+#define DW_MCI_HCON             0x070
+#define DW_MCI_RST_N            0x078
+#define DW_MCI_BMOD             0x080
+#define DW_MCI_PLDMND           0x084
+#define DW_MCI_DBADDRL          0x088
+#define DW_MCI_DBADDRU          0x08c
+#define DW_MCI_IDSTS            0x090
+#define DW_MCI_IDINTEN          0x094
+#define DW_MCI_DSCADDRL         0x098
+#define DW_MCI_DSCADDRU         0x09c
+#define DW_MCI_BUFADDRL         0x0a0
+#define DW_MCI_BUFADDRU         0x0a4
+#define DW_MCI_FIFO             0x200
+
+#define DW_MCI_CTRL_INT_ENABLE  BIT(4)
+#define DW_MCI_CTRL_USE_IDMAC   BIT(25)
+
+#define DW_MCI_CMD_RESP_EXP     BIT(6)
+#define DW_MCI_CMD_RESP_LONG    BIT(7)
+#define DW_MCI_CMD_DAT_EXP      BIT(9)
+#define DW_MCI_CMD_DAT_WR       BIT(10)
+#define DW_MCI_CMD_UPD_CLK      BIT(21)
+#define DW_MCI_CMD_START        BIT(31)
+
+#define DW_MCI_INT_CMD_DONE     BIT(2)
+#define DW_MCI_INT_DATA_OVER    BIT(3)
+#define DW_MCI_INT_RTO          BIT(8)
+
+#define DW_MCI_BMOD_ENABLE      BIT(7)
+
+#define DW_MCI_IDSTS_TI         BIT(0)
+#define DW_MCI_IDSTS_RI         BIT(1)
+#define DW_MCI_IDSTS_DU         BIT(4)
+#define DW_MCI_IDSTS_NI         BIT(8)
+#define DW_MCI_IDSTS_AI         BIT(9)
+
+#define DW_MCI_IDMAC_LD         BIT(2)
+#define DW_MCI_IDMAC_FS         BIT(3)
+#define DW_MCI_IDMAC_OWN        BIT(31)
+
+#define DW_MCI_DESC_ADDR        0x80010000
+#define DW_MCI_DATA_ADDR        0x80011000
+#define DW_MCI_READ_ADDR        0x80012000
+#define DW_MCI_BLOCK_SIZE       512
+#define DW_MCI_IMAGE_SIZE       (1 * MiB)
+
+static QTestState *dw_mci_start(const char *sd_path)
+{
+    if (sd_path) {
+        return qtest_initf("-machine phytium-pi -m 1G -display none "
+                           "-drive file=%s,format=raw,if=sd,index=1",
+                           sd_path);
+    }
+
+    return qtest_init("-machine phytium-pi -m 1G -display none");
+}
+
+static char *dw_mci_create_image(void)
+{
+    g_autoptr(GError) error = NULL;
+    char *path = NULL;
+    int fd;
+    int ret;
+
+    fd = g_file_open_tmp("dw-mci-XXXXXX", &path, &error);
+    g_assert_no_error(error);
+    g_assert_cmpint(fd, >=, 0);
+    ret = ftruncate(fd, DW_MCI_IMAGE_SIZE);
+    g_assert_cmpint(ret, ==, 0);
+    close(fd);
+
+    return path;
+}
+
+static uint32_t dw_mci_command(QTestState *qts, uint32_t index,
+                               uint32_t argument, uint32_t flags)
+{
+    uint32_t raw;
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_RINTSTS, UINT32_MAX);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CMDARG, argument);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CMD,
+                 DW_MCI_CMD_START | flags | index);
+    raw = qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS);
+    g_assert_cmphex(raw & DW_MCI_INT_CMD_DONE, ==, DW_MCI_INT_CMD_DONE);
+    g_assert_cmphex(raw & DW_MCI_INT_RTO, ==, 0);
+
+    return qtest_readl(qts, DW_MCI_BASE + DW_MCI_RESP0);
+}
+
+static void dw_mci_init_card(QTestState *qts)
+{
+    uint32_t rca;
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_PWREN, 1);
+    dw_mci_command(qts, 0, 0, 0);
+    dw_mci_command(qts, 55, 0, DW_MCI_CMD_RESP_EXP);
+    dw_mci_command(qts, 41, 0x41200000, DW_MCI_CMD_RESP_EXP);
+    dw_mci_command(qts, 2, 0,
+                   DW_MCI_CMD_RESP_EXP | DW_MCI_CMD_RESP_LONG);
+    rca = dw_mci_command(qts, 3, 0, DW_MCI_CMD_RESP_EXP) & 0xffff0000;
+    g_assert_cmphex(rca, !=, 0);
+    dw_mci_command(qts, 7, rca, DW_MCI_CMD_RESP_EXP);
+    dw_mci_command(qts, 16, DW_MCI_BLOCK_SIZE, DW_MCI_CMD_RESP_EXP);
+}
+
+static void dw_mci_write_descriptor(QTestState *qts, uint32_t control,
+                                    uint32_t buffer)
+{
+    qtest_writel(qts, DW_MCI_DESC_ADDR, control);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 4, 0);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 8, DW_MCI_BLOCK_SIZE);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 12, 0);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 16, buffer);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 20, 0);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 24, 0);
+    qtest_writel(qts, DW_MCI_DESC_ADDR + 28, 0);
+}
+
+static void dw_mci_prepare_idmac(QTestState *qts, uint32_t interrupts)
+{
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CTRL,
+                 DW_MCI_CTRL_USE_IDMAC);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_BMOD,
+                 DW_MCI_BMOD_ENABLE);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_BLKSIZ,
+                 DW_MCI_BLOCK_SIZE);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_BYTCNT,
+                 DW_MCI_BLOCK_SIZE);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_DBADDRL,
+                 DW_MCI_DESC_ADDR);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_DBADDRU, 0);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_IDINTEN, interrupts);
+}
+
+static void test_registers_and_irq(void)
+{
+    QTestState *qts = dw_mci_start(NULL);
+
+    qtest_irq_intercept_out_named(qts, "/machine/soc/mci1", "sysbus-irq");
+
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_CTRL), ==,
+                    BIT(24));
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_STATUS) &
+                    (BIT(1) | BIT(2)), ==, BIT(1) | BIT(2));
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_TMOUT), ==,
+                    0xffffff40);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_BLKSIZ), ==,
+                    DW_MCI_BLOCK_SIZE);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_BYTCNT), ==,
+                    DW_MCI_BLOCK_SIZE);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_FIFOTH), ==,
+                    0x01ff0000);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_CDETECT), ==, 1);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DEBNCE), ==,
+                    0x00ffffff);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_VERID), ==,
+                    0x280a);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_HCON), ==,
+                    0x08000080);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RST_N), ==, 1);
+
+    /* Exercise the 64-bit IDMAC layout selected by HCON.ADDR_CONFIG */
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_DBADDRL,
+                 DW_MCI_DESC_ADDR + 3);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DBADDRL), ==,
+                    DW_MCI_DESC_ADDR);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_DBADDRU, 1);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DBADDRU), ==, 1);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_IDINTEN,
+                 DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDINTEN), ==,
+                    DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DSCADDRU), ==, 0);
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_RINTSTS, UINT32_MAX);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CMD,
+                 DW_MCI_CMD_START | DW_MCI_CMD_UPD_CLK);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS) &
+                    DW_MCI_INT_CMD_DONE, ==, 0);
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CTRL,
+                 DW_MCI_CTRL_INT_ENABLE);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_INTMASK,
+                 DW_MCI_INT_CMD_DONE | DW_MCI_INT_RTO);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_CMD,
+                 DW_MCI_CMD_START | DW_MCI_CMD_RESP_EXP);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_MINTSTS), ==,
+                    DW_MCI_INT_CMD_DONE | DW_MCI_INT_RTO);
+    g_assert_true(qtest_get_irq(qts, 0));
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_RINTSTS,
+                 DW_MCI_INT_CMD_DONE | DW_MCI_INT_RTO);
+    g_assert_false(qtest_get_irq(qts, 0));
+
+    qtest_system_reset(qts);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_CTRL), ==,
+                    BIT(24));
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_BMOD), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DBADDRL), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DBADDRU), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDINTEN), ==, 0);
+    qtest_quit(qts);
+}
+
+static void test_idmac_write_and_read(void)
+{
+    g_autofree char *sd_path = dw_mci_create_image();
+    uint8_t pattern[DW_MCI_BLOCK_SIZE];
+    uint8_t actual[DW_MCI_BLOCK_SIZE];
+    uint8_t zero[DW_MCI_BLOCK_SIZE] = { 0 };
+    QTestState *qts = dw_mci_start(sd_path);
+    uint32_t status;
+    size_t i;
+    ssize_t size;
+    int fd;
+
+    qtest_irq_intercept_out_named(qts, "/machine/soc/mci1", "sysbus-irq");
+    dw_mci_init_card(qts);
+
+    for (i = 0; i < sizeof(pattern); i++) {
+        pattern[i] = i ^ 0xa5;
+    }
+    qtest_memwrite(qts, DW_MCI_DATA_ADDR, pattern, sizeof(pattern));
+    dw_mci_write_descriptor(qts,
+                            DW_MCI_IDMAC_OWN | DW_MCI_IDMAC_FS |
+                            DW_MCI_IDMAC_LD,
+                            DW_MCI_DATA_ADDR);
+    dw_mci_prepare_idmac(qts, DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    dw_mci_command(qts, 24, 0,
+                   DW_MCI_CMD_RESP_EXP | DW_MCI_CMD_DAT_EXP |
+                   DW_MCI_CMD_DAT_WR);
+
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_DESC_ADDR) &
+                    DW_MCI_IDMAC_OWN, ==, 0);
+    status = qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDSTS);
+    g_assert_cmphex(status & (DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI), ==,
+                    DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DSCADDRL), ==,
+                    DW_MCI_DESC_ADDR);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_DSCADDRU), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_BUFADDRL), ==,
+                    DW_MCI_DATA_ADDR);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_BUFADDRU), ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS) &
+                    DW_MCI_INT_DATA_OVER, ==, DW_MCI_INT_DATA_OVER);
+    g_assert_true(qtest_get_irq(qts, 0));
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_IDSTS,
+                 DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    g_assert_false(qtest_get_irq(qts, 0));
+
+    qtest_memwrite(qts, DW_MCI_READ_ADDR, zero, sizeof(zero));
+    dw_mci_write_descriptor(qts,
+                            DW_MCI_IDMAC_OWN | DW_MCI_IDMAC_FS |
+                            DW_MCI_IDMAC_LD,
+                            DW_MCI_READ_ADDR);
+    dw_mci_prepare_idmac(qts, DW_MCI_IDSTS_RI | DW_MCI_IDSTS_NI);
+    dw_mci_command(qts, 17, 0,
+                   DW_MCI_CMD_RESP_EXP | DW_MCI_CMD_DAT_EXP);
+    qtest_memread(qts, DW_MCI_READ_ADDR, actual, sizeof(actual));
+    g_assert_cmpmem(actual, sizeof(actual), pattern, sizeof(pattern));
+    status = qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDSTS);
+    g_assert_cmphex(status & (DW_MCI_IDSTS_RI | DW_MCI_IDSTS_NI), ==,
+                    DW_MCI_IDSTS_RI | DW_MCI_IDSTS_NI);
+    qtest_quit(qts);
+
+    fd = open(sd_path, O_RDONLY);
+    g_assert_cmpint(fd, >=, 0);
+    size = read(fd, actual, sizeof(actual));
+    close(fd);
+    g_assert_cmpint(size, ==, sizeof(actual));
+    g_assert_cmpmem(actual, sizeof(actual), pattern, sizeof(pattern));
+    unlink(sd_path);
+}
+
+static void test_idmac_suspend_and_resume(void)
+{
+    g_autofree char *sd_path = dw_mci_create_image();
+    uint8_t pattern[DW_MCI_BLOCK_SIZE];
+    QTestState *qts = dw_mci_start(sd_path);
+    uint32_t status;
+    size_t i;
+
+    qtest_irq_intercept_out_named(qts, "/machine/soc/mci1", "sysbus-irq");
+    dw_mci_init_card(qts);
+
+    for (i = 0; i < sizeof(pattern); i++) {
+        pattern[i] = i ^ 0x69;
+    }
+    qtest_memwrite(qts, DW_MCI_DATA_ADDR, pattern, sizeof(pattern));
+    dw_mci_write_descriptor(qts, 0, DW_MCI_DATA_ADDR);
+    dw_mci_prepare_idmac(qts,
+                         DW_MCI_IDSTS_TI | DW_MCI_IDSTS_DU |
+                         DW_MCI_IDSTS_NI | DW_MCI_IDSTS_AI);
+    dw_mci_command(qts, 24, 0,
+                   DW_MCI_CMD_RESP_EXP | DW_MCI_CMD_DAT_EXP |
+                   DW_MCI_CMD_DAT_WR);
+
+    status = qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDSTS);
+    g_assert_cmphex(status & (DW_MCI_IDSTS_DU | DW_MCI_IDSTS_AI), ==,
+                    DW_MCI_IDSTS_DU | DW_MCI_IDSTS_AI);
+    g_assert_cmphex((status >> 13) & 0xf, ==, 1);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS) &
+                    DW_MCI_INT_DATA_OVER, ==, 0);
+    g_assert_true(qtest_get_irq(qts, 0));
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_IDSTS,
+                 DW_MCI_IDSTS_DU | DW_MCI_IDSTS_AI);
+    g_assert_false(qtest_get_irq(qts, 0));
+    dw_mci_write_descriptor(qts,
+                            DW_MCI_IDMAC_OWN | DW_MCI_IDMAC_FS |
+                            DW_MCI_IDMAC_LD,
+                            DW_MCI_DATA_ADDR);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_PLDMND, 0);
+
+    status = qtest_readl(qts, DW_MCI_BASE + DW_MCI_IDSTS);
+    g_assert_cmphex(status & (DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI), ==,
+                    DW_MCI_IDSTS_TI | DW_MCI_IDSTS_NI);
+    g_assert_cmphex((status >> 13) & 0xf, ==, 0);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS) &
+                    DW_MCI_INT_DATA_OVER, ==, DW_MCI_INT_DATA_OVER);
+    g_assert_true(qtest_get_irq(qts, 0));
+
+    qtest_quit(qts);
+    unlink(sd_path);
+}
+
+static void test_fifo_data_port(void)
+{
+    g_autofree char *sd_path = dw_mci_create_image();
+    uint8_t pattern[DW_MCI_BLOCK_SIZE];
+    uint8_t actual[DW_MCI_BLOCK_SIZE];
+    QTestState *qts = dw_mci_start(sd_path);
+    size_t i;
+    ssize_t size;
+    int fd;
+
+    dw_mci_init_card(qts);
+    for (i = 0; i < sizeof(pattern); i++) {
+        pattern[i] = i ^ 0x3c;
+    }
+
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_BLKSIZ, DW_MCI_BLOCK_SIZE);
+    qtest_writel(qts, DW_MCI_BASE + DW_MCI_BYTCNT, DW_MCI_BLOCK_SIZE);
+    dw_mci_command(qts, 24, 0,
+                   DW_MCI_CMD_RESP_EXP | DW_MCI_CMD_DAT_EXP |
+                   DW_MCI_CMD_DAT_WR);
+    for (i = 0; i < sizeof(pattern); i += sizeof(uint32_t)) {
+        qtest_writel(qts, DW_MCI_BASE + DW_MCI_FIFO + (i % 64),
+                     ldl_le_p(pattern + i));
+    }
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_TCBCNT), ==,
+                    DW_MCI_BLOCK_SIZE);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_TBBCNT), ==,
+                    DW_MCI_BLOCK_SIZE);
+    g_assert_cmphex(qtest_readl(qts, DW_MCI_BASE + DW_MCI_RINTSTS) &
+                    DW_MCI_INT_DATA_OVER, ==, DW_MCI_INT_DATA_OVER);
+    qtest_quit(qts);
+
+    fd = open(sd_path, O_RDONLY);
+    g_assert_cmpint(fd, >=, 0);
+    size = read(fd, actual, sizeof(actual));
+    close(fd);
+    g_assert_cmpint(size, ==, sizeof(actual));
+    g_assert_cmpmem(actual, sizeof(actual), pattern, sizeof(pattern));
+    unlink(sd_path);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("dw-mci/registers-and-irq", test_registers_and_irq);
+    qtest_add_func("dw-mci/idmac-write-and-read", test_idmac_write_and_read);
+    qtest_add_func("dw-mci/idmac-suspend-and-resume",
+                   test_idmac_suspend_and_resume);
+    qtest_add_func("dw-mci/fifo-data-port", test_fifo_data_port);
+
+    return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index c3593f7530..a7fc37e09d 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -282,6 +282,7 @@ qtests_aarch64 = \
    config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test', 'tpm-tis-i2c-swtpm-test'] : []) + \
   (config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed64 : []) + \
   (config_all_devices.has_key('CONFIG_NPCM8XX') ? qtests_npcm8xx : []) + \
+  (config_all_devices.has_key('CONFIG_PHYTIUM_E2000') ? ['dw_mci-test'] : []) + \
   (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and
    config_all_devices.has_key('CONFIG_ARM_VIRT') ?
    ['iommu-smmuv3-test'] : []) + \
-- 
2.53.0



  parent reply	other threads:[~2026-09-08 10:42 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08 10:41 [PATCH v2 00/32] hw/arm: Add Phytium E2000Q SoC and board support Bin Meng
2026-09-08 10:41 ` [PATCH v2 01/32] hw/arm: Add Phytium E2000 SoC and Phytium Pi machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 02/32] hw/arm: phytium: Add Phytium E2000 PCIe host Bin Meng
2026-09-08 10:41 ` [PATCH v2 03/32] hw/sd: Add Synopsys DesignWare MCI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 04/32] hw/sd: Add Phytium E2000 " Bin Meng
2026-09-08 10:41 ` [PATCH v2 05/32] hw/arm: phytium: Connect Phytium E2000 MCI controllers Bin Meng
2026-09-08 10:41 ` Bin Meng [this message]
2026-09-08 10:41 ` [PATCH v2 07/32] hw/arm: phytium: Connect Phytium E2000 GEM controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 08/32] hw/misc: Add Phytium E2000 DDR controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 09/32] hw/arm: phytium: Connect the " Bin Meng
2026-09-08 10:41 ` [PATCH v2 10/32] hw/misc: Add Phytium E2000 MHU doorbell Bin Meng
2026-09-08 10:41 ` [PATCH v2 11/32] hw/arm: phytium: Connect the Phytium E2000 MHU Bin Meng
2026-09-08 10:41 ` [PATCH v2 12/32] hw/ssi: Add Phytium E2000 QSPI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 13/32] hw/arm: phytium: Connect the " Bin Meng
2026-09-08 10:41 ` [PATCH v2 14/32] hw/misc: Add Phytium E2000 PBR model Bin Meng
2026-09-08 10:41 ` [PATCH v2 15/32] hw/arm: phytium: Integrate the Phytium E2000 PBR Bin Meng
2026-09-08 10:41 ` [PATCH v2 16/32] hw/arm: phytium: Add Phytium E2000 control region placeholders Bin Meng
2026-09-08 10:41 ` [PATCH v2 17/32] hw/misc: Support Phytium E2000 SCMI CPU power control Bin Meng
2026-09-08 10:41 ` [PATCH v2 18/32] hw/arm: phytium: Select the Phytium E2000 PBR boot medium Bin Meng
2026-09-08 10:41 ` [PATCH v2 19/32] hw/arm: phytium: Connect the Phytium E2000 I2C controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 20/32] hw/arm: phytium: Add Phytium E2000 xHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 21/32] hw/misc: Model the Phytium E2000 random generator Bin Meng
2026-09-08 10:41 ` [PATCH v2 22/32] hw/arm: phytium: Connect " Bin Meng
2026-09-08 10:41 ` [PATCH v2 23/32] hw/arm: phytium: Support Phytium E2000 direct Linux boot Bin Meng
2026-09-08 10:41 ` [PATCH v2 24/32] hw/arm: phytium: Add Phytium E2000Q COMe machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 25/32] hw/block: m25p80: Add GigaDevice GD25Q128 flash Bin Meng
2026-09-08 10:41 ` [PATCH v2 26/32] hw/arm: phytium: Connect the Phytium E2000Q COMe QSPI flash Bin Meng
2026-09-08 10:41 ` [PATCH v2 27/32] hw/arm: phytium: Add Phytium E2000 AHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 28/32] hw/arm: Add Phytium E2000 Linux SCMI channel Bin Meng
2026-09-08 10:41 ` [PATCH v2 29/32] hw/arm: phytium: Connect the Phytium E2000 SMMUv3 Bin Meng
2026-09-08 10:41 ` [PATCH v2 30/32] docs/system/arm: Document Phytium E2000 machines Bin Meng
2026-09-08 10:41 ` [PATCH v2 31/32] tests/functional/aarch64: Add Phytium Pi boot tests Bin Meng
2026-09-08 10:41 ` [PATCH v2 32/32] MAINTAINERS: Add Phytium E2000Q machines Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908104159.1621764-7-bin.meng@processmission.com \
    --to=bin.meng@processmission.com \
    --cc=bmeng.cn@gmail.com \
    --cc=farosas@suse.de \
    --cc=lvivier@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@oss.qualcomm.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.