xref: /qemu/tests/qtest/sdhci-test.c (revision 907b5105f1b9e1af1abbdbb4f2039c7ab105c001)
18640cc11SPhilippe Mathieu-Daudé /*
28640cc11SPhilippe Mathieu-Daudé  * QTest testcase for SDHCI controllers
38640cc11SPhilippe Mathieu-Daudé  *
48640cc11SPhilippe Mathieu-Daudé  * Written by Philippe Mathieu-Daudé <f4bug@amsat.org>
58640cc11SPhilippe Mathieu-Daudé  *
68640cc11SPhilippe Mathieu-Daudé  * This work is licensed under the terms of the GNU GPL, version 2 or later.
78640cc11SPhilippe Mathieu-Daudé  * See the COPYING file in the top-level directory.
88640cc11SPhilippe Mathieu-Daudé  * SPDX-License-Identifier: GPL-2.0-or-later
98640cc11SPhilippe Mathieu-Daudé  */
100b8fa32fSMarkus Armbruster 
118640cc11SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
128640cc11SPhilippe Mathieu-Daudé #include "hw/registerfields.h"
13*907b5105SMarc-André Lureau #include "libqtest.h"
140b8fa32fSMarkus Armbruster #include "qemu/module.h"
158640cc11SPhilippe Mathieu-Daudé #include "libqos/pci-pc.h"
168640cc11SPhilippe Mathieu-Daudé #include "hw/pci/pci.h"
17757c6eacSEmanuele Giuseppe Esposito #include "libqos/qgraph.h"
18757c6eacSEmanuele Giuseppe Esposito #include "libqos/sdhci.h"
198640cc11SPhilippe Mathieu-Daudé 
208640cc11SPhilippe Mathieu-Daudé #define SDHC_CAPAB                      0x40
210c78f51eSPhilippe Mathieu-Daudé FIELD(SDHC_CAPAB, BASECLKFREQ,               8, 8); /* since v2 */
22bc13038fSPhilippe Mathieu-Daudé FIELD(SDHC_CAPAB, SDMA,                     22, 1);
23f18e6d50SPhilippe Mathieu-Daudé FIELD(SDHC_CAPAB, SDR,                      32, 3); /* since v3 */
24f18e6d50SPhilippe Mathieu-Daudé FIELD(SDHC_CAPAB, DRIVER,                   36, 3); /* since v3 */
258640cc11SPhilippe Mathieu-Daudé #define SDHC_HCVER                      0xFE
268640cc11SPhilippe Mathieu-Daudé 
check_specs_version(QSDHCI * s,uint8_t version)27efe9d524SPhilippe Mathieu-Daudé static void check_specs_version(QSDHCI *s, uint8_t version)
28efe9d524SPhilippe Mathieu-Daudé {
29efe9d524SPhilippe Mathieu-Daudé     uint32_t v;
30efe9d524SPhilippe Mathieu-Daudé 
31757c6eacSEmanuele Giuseppe Esposito     v = s->readw(s, SDHC_HCVER);
32efe9d524SPhilippe Mathieu-Daudé     v &= 0xff;
33efe9d524SPhilippe Mathieu-Daudé     v += 1;
34efe9d524SPhilippe Mathieu-Daudé     g_assert_cmpuint(v, ==, version);
35efe9d524SPhilippe Mathieu-Daudé }
36efe9d524SPhilippe Mathieu-Daudé 
check_capab_capareg(QSDHCI * s,uint64_t expec_capab)378640cc11SPhilippe Mathieu-Daudé static void check_capab_capareg(QSDHCI *s, uint64_t expec_capab)
388640cc11SPhilippe Mathieu-Daudé {
398640cc11SPhilippe Mathieu-Daudé     uint64_t capab;
408640cc11SPhilippe Mathieu-Daudé 
41757c6eacSEmanuele Giuseppe Esposito     capab = s->readq(s, SDHC_CAPAB);
428640cc11SPhilippe Mathieu-Daudé     g_assert_cmphex(capab, ==, expec_capab);
438640cc11SPhilippe Mathieu-Daudé }
448640cc11SPhilippe Mathieu-Daudé 
check_capab_readonly(QSDHCI * s)45556f9acaSPhilippe Mathieu-Daudé static void check_capab_readonly(QSDHCI *s)
46556f9acaSPhilippe Mathieu-Daudé {
47556f9acaSPhilippe Mathieu-Daudé     const uint64_t vrand = 0x123456789abcdef;
48556f9acaSPhilippe Mathieu-Daudé     uint64_t capab0, capab1;
49556f9acaSPhilippe Mathieu-Daudé 
50757c6eacSEmanuele Giuseppe Esposito     capab0 = s->readq(s, SDHC_CAPAB);
51556f9acaSPhilippe Mathieu-Daudé     g_assert_cmpuint(capab0, !=, vrand);
52556f9acaSPhilippe Mathieu-Daudé 
53757c6eacSEmanuele Giuseppe Esposito     s->writeq(s, SDHC_CAPAB, vrand);
54757c6eacSEmanuele Giuseppe Esposito     capab1 = s->readq(s, SDHC_CAPAB);
55556f9acaSPhilippe Mathieu-Daudé     g_assert_cmpuint(capab1, !=, vrand);
56556f9acaSPhilippe Mathieu-Daudé     g_assert_cmpuint(capab1, ==, capab0);
57556f9acaSPhilippe Mathieu-Daudé }
58556f9acaSPhilippe Mathieu-Daudé 
check_capab_baseclock(QSDHCI * s,uint8_t expec_freq)590c78f51eSPhilippe Mathieu-Daudé static void check_capab_baseclock(QSDHCI *s, uint8_t expec_freq)
600c78f51eSPhilippe Mathieu-Daudé {
610c78f51eSPhilippe Mathieu-Daudé     uint64_t capab, capab_freq;
620c78f51eSPhilippe Mathieu-Daudé 
630c78f51eSPhilippe Mathieu-Daudé     if (!expec_freq) {
640c78f51eSPhilippe Mathieu-Daudé         return;
650c78f51eSPhilippe Mathieu-Daudé     }
66757c6eacSEmanuele Giuseppe Esposito     capab = s->readq(s, SDHC_CAPAB);
670c78f51eSPhilippe Mathieu-Daudé     capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ);
680c78f51eSPhilippe Mathieu-Daudé     g_assert_cmpuint(capab_freq, ==, expec_freq);
690c78f51eSPhilippe Mathieu-Daudé }
700c78f51eSPhilippe Mathieu-Daudé 
check_capab_sdma(QSDHCI * s,bool supported)71bc13038fSPhilippe Mathieu-Daudé static void check_capab_sdma(QSDHCI *s, bool supported)
72bc13038fSPhilippe Mathieu-Daudé {
73bc13038fSPhilippe Mathieu-Daudé     uint64_t capab, capab_sdma;
74bc13038fSPhilippe Mathieu-Daudé 
75757c6eacSEmanuele Giuseppe Esposito     capab = s->readq(s, SDHC_CAPAB);
76bc13038fSPhilippe Mathieu-Daudé     capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA);
77bc13038fSPhilippe Mathieu-Daudé     g_assert_cmpuint(capab_sdma, ==, supported);
78bc13038fSPhilippe Mathieu-Daudé }
79bc13038fSPhilippe Mathieu-Daudé 
check_capab_v3(QSDHCI * s,uint8_t version)80f18e6d50SPhilippe Mathieu-Daudé static void check_capab_v3(QSDHCI *s, uint8_t version)
81f18e6d50SPhilippe Mathieu-Daudé {
82f18e6d50SPhilippe Mathieu-Daudé     uint64_t capab, capab_v3;
83f18e6d50SPhilippe Mathieu-Daudé 
84f18e6d50SPhilippe Mathieu-Daudé     if (version < 3) {
85f18e6d50SPhilippe Mathieu-Daudé         /* before v3 those fields are RESERVED */
86757c6eacSEmanuele Giuseppe Esposito         capab = s->readq(s, SDHC_CAPAB);
87f18e6d50SPhilippe Mathieu-Daudé         capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR);
88f18e6d50SPhilippe Mathieu-Daudé         g_assert_cmpuint(capab_v3, ==, 0);
89f18e6d50SPhilippe Mathieu-Daudé         capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER);
90f18e6d50SPhilippe Mathieu-Daudé         g_assert_cmpuint(capab_v3, ==, 0);
91f18e6d50SPhilippe Mathieu-Daudé     }
92f18e6d50SPhilippe Mathieu-Daudé }
93f18e6d50SPhilippe Mathieu-Daudé 
test_registers(void * obj,void * data,QGuestAllocator * alloc)94757c6eacSEmanuele Giuseppe Esposito static void test_registers(void *obj, void *data, QGuestAllocator *alloc)
958640cc11SPhilippe Mathieu-Daudé {
96757c6eacSEmanuele Giuseppe Esposito     QSDHCI *s = obj;
978640cc11SPhilippe Mathieu-Daudé 
98757c6eacSEmanuele Giuseppe Esposito     check_specs_version(s, s->props.version);
99757c6eacSEmanuele Giuseppe Esposito     check_capab_capareg(s, s->props.capab.reg);
100556f9acaSPhilippe Mathieu-Daudé     check_capab_readonly(s);
101757c6eacSEmanuele Giuseppe Esposito     check_capab_v3(s, s->props.version);
102757c6eacSEmanuele Giuseppe Esposito     check_capab_sdma(s, s->props.capab.sdma);
103757c6eacSEmanuele Giuseppe Esposito     check_capab_baseclock(s, s->props.baseclock);
1048640cc11SPhilippe Mathieu-Daudé }
1058640cc11SPhilippe Mathieu-Daudé 
register_sdhci_test(void)106757c6eacSEmanuele Giuseppe Esposito static void register_sdhci_test(void)
1078640cc11SPhilippe Mathieu-Daudé {
108757c6eacSEmanuele Giuseppe Esposito     qos_add_test("registers", "sdhci", test_registers, NULL);
1098640cc11SPhilippe Mathieu-Daudé }
1108640cc11SPhilippe Mathieu-Daudé 
111757c6eacSEmanuele Giuseppe Esposito libqos_init(register_sdhci_test);
112