2 * QTest testcase for SDHCI controllers
4 * Written by Philippe Mathieu-Daudé <f4bug@amsat.org>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include "qemu/osdep.h"
12 #include "hw/registerfields.h"
13 #include "libqos/libqtest.h"
14 #include "qemu/module.h"
15 #include "libqos/pci-pc.h"
16 #include "hw/pci/pci.h"
17 #include "libqos/qgraph.h"
18 #include "libqos/sdhci.h"
20 #define SDHC_CAPAB 0x40
21 FIELD(SDHC_CAPAB
, BASECLKFREQ
, 8, 8); /* since v2 */
22 FIELD(SDHC_CAPAB
, SDMA
, 22, 1);
23 FIELD(SDHC_CAPAB
, SDR
, 32, 3); /* since v3 */
24 FIELD(SDHC_CAPAB
, DRIVER
, 36, 3); /* since v3 */
25 #define SDHC_HCVER 0xFE
27 static void check_specs_version(QSDHCI
*s
, uint8_t version
)
31 v
= s
->readw(s
, SDHC_HCVER
);
34 g_assert_cmpuint(v
, ==, version
);
37 static void check_capab_capareg(QSDHCI
*s
, uint64_t expec_capab
)
41 capab
= s
->readq(s
, SDHC_CAPAB
);
42 g_assert_cmphex(capab
, ==, expec_capab
);
45 static void check_capab_readonly(QSDHCI
*s
)
47 const uint64_t vrand
= 0x123456789abcdef;
48 uint64_t capab0
, capab1
;
50 capab0
= s
->readq(s
, SDHC_CAPAB
);
51 g_assert_cmpuint(capab0
, !=, vrand
);
53 s
->writeq(s
, SDHC_CAPAB
, vrand
);
54 capab1
= s
->readq(s
, SDHC_CAPAB
);
55 g_assert_cmpuint(capab1
, !=, vrand
);
56 g_assert_cmpuint(capab1
, ==, capab0
);
59 static void check_capab_baseclock(QSDHCI
*s
, uint8_t expec_freq
)
61 uint64_t capab
, capab_freq
;
66 capab
= s
->readq(s
, SDHC_CAPAB
);
67 capab_freq
= FIELD_EX64(capab
, SDHC_CAPAB
, BASECLKFREQ
);
68 g_assert_cmpuint(capab_freq
, ==, expec_freq
);
71 static void check_capab_sdma(QSDHCI
*s
, bool supported
)
73 uint64_t capab
, capab_sdma
;
75 capab
= s
->readq(s
, SDHC_CAPAB
);
76 capab_sdma
= FIELD_EX64(capab
, SDHC_CAPAB
, SDMA
);
77 g_assert_cmpuint(capab_sdma
, ==, supported
);
80 static void check_capab_v3(QSDHCI
*s
, uint8_t version
)
82 uint64_t capab
, capab_v3
;
85 /* before v3 those fields are RESERVED */
86 capab
= s
->readq(s
, SDHC_CAPAB
);
87 capab_v3
= FIELD_EX64(capab
, SDHC_CAPAB
, SDR
);
88 g_assert_cmpuint(capab_v3
, ==, 0);
89 capab_v3
= FIELD_EX64(capab
, SDHC_CAPAB
, DRIVER
);
90 g_assert_cmpuint(capab_v3
, ==, 0);
94 static void test_registers(void *obj
, void *data
, QGuestAllocator
*alloc
)
98 check_specs_version(s
, s
->props
.version
);
99 check_capab_capareg(s
, s
->props
.capab
.reg
);
100 check_capab_readonly(s
);
101 check_capab_v3(s
, s
->props
.version
);
102 check_capab_sdma(s
, s
->props
.capab
.sdma
);
103 check_capab_baseclock(s
, s
->props
.baseclock
);
106 static void register_sdhci_test(void)
108 qos_add_test("registers", "sdhci", test_registers
, NULL
);
111 libqos_init(register_sdhci_test
);