2 * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller
4 * Copyright (c) 2022 Google LLC
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "qemu/osdep.h"
18 #include "hw/sd/npcm7xx_sdhci.h"
21 #include "libqtest-single.h"
22 #include "libqos/sdhci-cmd.h"
24 #define NPCM7XX_REG_SIZE 0x100
25 #define NPCM7XX_MMC_BA 0xF0842000
26 #define NPCM7XX_BLK_SIZE 512
27 #define NPCM7XX_TEST_IMAGE_SIZE (1 << 20)
31 static QTestState
*setup_sd_card(void)
33 QTestState
*qts
= qtest_initf(
35 "-device sd-card,drive=drive0 "
36 "-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off",
39 qtest_writew(qts
, NPCM7XX_MMC_BA
+ SDHC_SWRST
, SDHC_RESET_ALL
);
40 qtest_writew(qts
, NPCM7XX_MMC_BA
+ SDHC_CLKCON
,
41 SDHC_CLOCK_SDCLK_EN
| SDHC_CLOCK_INT_STABLE
|
43 sdhci_cmd_regs(qts
, NPCM7XX_MMC_BA
, 0, 0, 0, 0, SDHC_APP_CMD
);
44 sdhci_cmd_regs(qts
, NPCM7XX_MMC_BA
, 0, 0, 0x41200000, 0, (41 << 8));
45 sdhci_cmd_regs(qts
, NPCM7XX_MMC_BA
, 0, 0, 0, 0, SDHC_ALL_SEND_CID
);
46 sdhci_cmd_regs(qts
, NPCM7XX_MMC_BA
, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR
);
47 sdhci_cmd_regs(qts
, NPCM7XX_MMC_BA
, 0, 0, 0x45670000, 0,
48 SDHC_SELECT_DESELECT_CARD
);
53 static void write_sdread(QTestState
*qts
, const char *msg
)
56 size_t len
= strlen(msg
);
57 char *rmsg
= g_malloc(len
);
59 /* write message to sd */
60 fd
= open(sd_path
, O_WRONLY
);
62 ret
= write(fd
, msg
, len
);
66 /* read message using sdhci */
67 ret
= sdhci_read_cmd(qts
, NPCM7XX_MMC_BA
, rmsg
, len
);
69 g_assert(!memcmp(rmsg
, msg
, len
));
74 /* Check MMC can read values from sd */
75 static void test_read_sd(void)
77 QTestState
*qts
= setup_sd_card();
79 write_sdread(qts
, "hello world");
80 write_sdread(qts
, "goodbye");
85 static void sdwrite_read(QTestState
*qts
, const char *msg
)
88 size_t len
= strlen(msg
);
89 char *rmsg
= g_malloc(len
);
91 /* write message using sdhci */
92 sdhci_write_cmd(qts
, NPCM7XX_MMC_BA
, msg
, len
, NPCM7XX_BLK_SIZE
);
94 /* read message from sd */
95 fd
= open(sd_path
, O_RDONLY
);
97 ret
= read(fd
, rmsg
, len
);
101 g_assert(!memcmp(rmsg
, msg
, len
));
106 /* Check MMC can write values to sd */
107 static void test_write_sd(void)
109 QTestState
*qts
= setup_sd_card();
111 sdwrite_read(qts
, "hello world");
112 sdwrite_read(qts
, "goodbye");
117 /* Check SDHCI has correct default values. */
118 static void test_reset(void)
120 QTestState
*qts
= qtest_init("-machine kudo-bmc");
121 uint64_t addr
= NPCM7XX_MMC_BA
;
122 uint64_t end_addr
= addr
+ NPCM7XX_REG_SIZE
;
123 uint16_t prstvals_resets
[] = {NPCM7XX_PRSTVALS_0_RESET
,
124 NPCM7XX_PRSTVALS_1_RESET
,
126 NPCM7XX_PRSTVALS_3_RESET
,
132 while (addr
< end_addr
) {
133 switch (addr
- NPCM7XX_MMC_BA
) {
136 * ignores bits 20 to 24: they are changed when reading registers
139 g_assert_cmphex(qtest_readl(qts
, addr
) | mask
, ==,
140 NPCM7XX_PRSNTS_RESET
| mask
);
144 g_assert_cmphex(qtest_readb(qts
, addr
), ==, NPCM7XX_BLKGAP_RESET
);
148 g_assert_cmphex(qtest_readq(qts
, addr
), ==, NPCM7XX_CAPAB_RESET
);
152 g_assert_cmphex(qtest_readq(qts
, addr
), ==, NPCM7XX_MAXCURR_RESET
);
156 g_assert_cmphex(qtest_readw(qts
, addr
), ==, NPCM7XX_HCVER_RESET
);
159 case NPCM7XX_PRSTVALS
:
160 for (i
= 0; i
< NPCM7XX_PRSTVALS_SIZE
; ++i
) {
161 g_assert_cmphex(qtest_readw(qts
, addr
+ 2 * i
), ==,
164 addr
+= NPCM7XX_PRSTVALS_SIZE
* 2;
167 g_assert_cmphex(qtest_readb(qts
, addr
), ==, 0);
175 static void drive_destroy(void)
181 static void drive_create(void)
184 GError
*error
= NULL
;
186 /* Create a temporary raw image */
187 fd
= g_file_open_tmp("sdhci_XXXXXX", &sd_path
, &error
);
189 fprintf(stderr
, "unable to create sdhci file: %s\n", error
->message
);
192 g_assert(sd_path
!= NULL
);
194 ret
= ftruncate(fd
, NPCM7XX_TEST_IMAGE_SIZE
);
195 g_assert_cmpint(ret
, ==, 0);
196 g_message("%s", sd_path
);
200 int main(int argc
, char **argv
)
206 g_test_init(&argc
, &argv
, NULL
);
208 qtest_add_func("npcm7xx_sdhci/reset", test_reset
);
209 qtest_add_func("npcm7xx_sdhci/write_sd", test_write_sd
);
210 qtest_add_func("npcm7xx_sdhci/read_sd", test_read_sd
);