aboutsummaryrefslogtreecommitdiff
path: root/tests/qtest
diff options
context:
space:
mode:
authorShengtan Mao <stmao@google.com>2021-10-07 17:26:27 -0700
committerRichard Henderson <richard.henderson@linaro.org>2021-11-02 14:14:55 -0400
commitda2f02b360f405d7badc4a3028276e07db58026c (patch)
tree1afd169312b5814817f31338ba2e4cba96a09658 /tests/qtest
parent2cb06d492da9f7054eaa9ecbff1e0538b2cf49f8 (diff)
downloadqemu-da2f02b360f405d7badc4a3028276e07db58026c.zip
qemu-da2f02b360f405d7badc4a3028276e07db58026c.tar.gz
qemu-da2f02b360f405d7badc4a3028276e07db58026c.tar.bz2
tests/qtest/libqos: add SDHCI commands
Signed-off-by: Shengtan Mao <stmao@google.com> Signed-off-by: Hao Wu <wuhaotsh@google.com> Reviewed-by: Hao Wu <wuhaotsh@google.com> Reviewed-by: Chris Rauer <crauer@google.com> Reviewed-by: Tyrone Ting <kfting@nuvoton.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-Id: <20211008002628.1958285-5-wuhaotsh@google.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tests/qtest')
-rw-r--r--tests/qtest/libqos/meson.build1
-rw-r--r--tests/qtest/libqos/sdhci-cmd.c116
-rw-r--r--tests/qtest/libqos/sdhci-cmd.h70
3 files changed, 187 insertions, 0 deletions
diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 1f5c8f1..4af1f04 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c',
'fw_cfg.c',
'malloc.c',
'libqos.c',
+ 'sdhci-cmd.c',
# spapr
'malloc-spapr.c',
diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c
new file mode 100644
index 0000000..2d9e518
--- /dev/null
+++ b/tests/qtest/libqos/sdhci-cmd.c
@@ -0,0 +1,116 @@
+/*
+ * MMC Host Controller Commands
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "sdhci-cmd.h"
+#include "libqtest.h"
+
+static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count)
+{
+ uint32_t mask = 0xff;
+ size_t index = 0;
+ uint32_t msg_frag;
+ int size;
+ while (index < count) {
+ size = count - index;
+ if (size > 4) {
+ size = 4;
+ }
+ msg_frag = qtest_readl(qts, reg);
+ while (size > 0) {
+ msg[index] = msg_frag & mask;
+ if (msg[index++] == 0) {
+ return index;
+ }
+ msg_frag >>= 8;
+ --size;
+ }
+ }
+ return index;
+}
+
+static void write_fifo(QTestState *qts, uint64_t reg, const char *msg,
+ size_t count)
+{
+ size_t index = 0;
+ uint32_t msg_frag;
+ int size;
+ int frag_i;
+ while (index < count) {
+ size = count - index;
+ if (size > 4) {
+ size = 4;
+ }
+ msg_frag = 0;
+ frag_i = 0;
+ while (frag_i < size) {
+ msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8);
+ ++frag_i;
+ }
+ qtest_writel(qts, reg, msg_frag);
+ }
+}
+
+static void fill_block(QTestState *qts, uint64_t reg, int count)
+{
+ while (--count >= 0) {
+ qtest_writel(qts, reg, 0);
+ }
+}
+
+void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
+ uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
+ uint16_t cmdreg)
+{
+ qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize);
+ qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt);
+ qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument);
+ qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod);
+ qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg);
+}
+
+ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
+ size_t count)
+{
+ sdhci_cmd_regs(qts, base_addr, count, 1, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
+
+ /* read sd fifo_buffer */
+ ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count);
+
+ sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_STOP_TRANSMISSION);
+
+ return bytes_read;
+}
+
+void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
+ size_t count, size_t blksize)
+{
+ sdhci_cmd_regs(qts, base_addr, blksize, 1, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
+
+ /* write to sd fifo_buffer */
+ write_fifo(qts, base_addr + SDHC_BDATA, msg, count);
+ fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4);
+
+ sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_STOP_TRANSMISSION);
+}
diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h
new file mode 100644
index 0000000..64763c5
--- /dev/null
+++ b/tests/qtest/libqos/sdhci-cmd.h
@@ -0,0 +1,70 @@
+/*
+ * MMC Host Controller Commands
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "libqtest.h"
+
+/* more details at hw/sd/sdhci-internal.h */
+#define SDHC_BLKSIZE 0x04
+#define SDHC_BLKCNT 0x06
+#define SDHC_ARGUMENT 0x08
+#define SDHC_TRNMOD 0x0C
+#define SDHC_CMDREG 0x0E
+#define SDHC_BDATA 0x20
+#define SDHC_PRNSTS 0x24
+#define SDHC_BLKGAP 0x2A
+#define SDHC_CLKCON 0x2C
+#define SDHC_SWRST 0x2F
+#define SDHC_CAPAB 0x40
+#define SDHC_MAXCURR 0x48
+#define SDHC_HCVER 0xFE
+
+/* TRNSMOD Reg */
+#define SDHC_TRNS_BLK_CNT_EN 0x0002
+#define SDHC_TRNS_READ 0x0010
+#define SDHC_TRNS_WRITE 0x0000
+#define SDHC_TRNS_MULTI 0x0020
+
+/* CMD Reg */
+#define SDHC_CMD_DATA_PRESENT (1 << 5)
+#define SDHC_ALL_SEND_CID (2 << 8)
+#define SDHC_SEND_RELATIVE_ADDR (3 << 8)
+#define SDHC_SELECT_DESELECT_CARD (7 << 8)
+#define SDHC_SEND_CSD (9 << 8)
+#define SDHC_STOP_TRANSMISSION (12 << 8)
+#define SDHC_READ_MULTIPLE_BLOCK (18 << 8)
+#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8)
+#define SDHC_APP_CMD (55 << 8)
+
+/* SWRST Reg */
+#define SDHC_RESET_ALL 0x01
+
+/* CLKCTRL Reg */
+#define SDHC_CLOCK_INT_EN 0x0001
+#define SDHC_CLOCK_INT_STABLE 0x0002
+#define SDHC_CLOCK_SDCLK_EN (1 << 2)
+
+/* Set registers needed to send commands to SD */
+void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
+ uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
+ uint16_t cmdreg);
+
+/* Read at most 1 block of SD using non-DMA */
+ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
+ size_t count);
+
+/* Write at most 1 block of SD using non-DMA */
+void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
+ size_t count, size_t blksize);