Merge tag 'pull-error-2022-10-28' of https://repo.or.cz/qemu/armbru into staging
[qemu/ar7.git] / tests / qtest / npcm7xx_sdhci-test.c
blob5d68540e5202812d1335550564c946a2b70461f4
1 /*
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
14 * for more details.
17 #include "qemu/osdep.h"
18 #include "hw/sd/npcm7xx_sdhci.h"
20 #include "libqtest.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)
29 char *sd_path;
31 static QTestState *setup_sd_card(void)
33 QTestState *qts = qtest_initf(
34 "-machine kudo-bmc "
35 "-device sd-card,drive=drive0 "
36 "-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off",
37 sd_path);
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 |
42 SDHC_CLOCK_INT_EN);
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);
50 return qts;
53 static void write_sdread(QTestState *qts, const char *msg)
55 int fd, ret;
56 size_t len = strlen(msg);
57 char *rmsg = g_malloc(len);
59 /* write message to sd */
60 fd = open(sd_path, O_WRONLY);
61 g_assert(fd >= 0);
62 ret = write(fd, msg, len);
63 close(fd);
64 g_assert(ret == len);
66 /* read message using sdhci */
67 ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len);
68 g_assert(ret == len);
69 g_assert(!memcmp(rmsg, msg, len));
71 g_free(rmsg);
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");
82 qtest_quit(qts);
85 static void sdwrite_read(QTestState *qts, const char *msg)
87 int fd, ret;
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);
96 g_assert(fd >= 0);
97 ret = read(fd, rmsg, len);
98 close(fd);
99 g_assert(ret == len);
101 g_assert(!memcmp(rmsg, msg, len));
103 g_free(rmsg);
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");
114 qtest_quit(qts);
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,
129 int i;
130 uint32_t mask;
132 while (addr < end_addr) {
133 switch (addr - NPCM7XX_MMC_BA) {
134 case SDHC_PRNSTS:
136 * ignores bits 20 to 24: they are changed when reading registers
138 mask = 0x1f00000;
139 g_assert_cmphex(qtest_readl(qts, addr) | mask, ==,
140 NPCM7XX_PRSNTS_RESET | mask);
141 addr += 4;
142 break;
143 case SDHC_BLKGAP:
144 g_assert_cmphex(qtest_readb(qts, addr), ==, NPCM7XX_BLKGAP_RESET);
145 addr += 1;
146 break;
147 case SDHC_CAPAB:
148 g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_CAPAB_RESET);
149 addr += 8;
150 break;
151 case SDHC_MAXCURR:
152 g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_MAXCURR_RESET);
153 addr += 8;
154 break;
155 case SDHC_HCVER:
156 g_assert_cmphex(qtest_readw(qts, addr), ==, NPCM7XX_HCVER_RESET);
157 addr += 2;
158 break;
159 case NPCM7XX_PRSTVALS:
160 for (i = 0; i < NPCM7XX_PRSTVALS_SIZE; ++i) {
161 g_assert_cmphex(qtest_readw(qts, addr + 2 * i), ==,
162 prstvals_resets[i]);
164 addr += NPCM7XX_PRSTVALS_SIZE * 2;
165 break;
166 default:
167 g_assert_cmphex(qtest_readb(qts, addr), ==, 0);
168 addr += 1;
172 qtest_quit(qts);
175 static void drive_destroy(void)
177 unlink(sd_path);
178 g_free(sd_path);
181 static void drive_create(void)
183 int fd, ret;
184 GError *error = NULL;
186 /* Create a temporary raw image */
187 fd = g_file_open_tmp("sdhci_XXXXXX", &sd_path, &error);
188 if (fd == -1) {
189 fprintf(stderr, "unable to create sdhci file: %s\n", error->message);
190 g_error_free(error);
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);
197 close(fd);
200 int main(int argc, char **argv)
202 int ret;
204 drive_create();
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);
212 ret = g_test_run();
213 drive_destroy();
214 return ret;