]>
Commit | Line | Data |
---|---|---|
8640cc11 PMD |
1 | /* |
2 | * QTest testcase for SDHCI controllers | |
3 | * | |
4 | * Written by Philippe Mathieu-Daudé <[email protected]> | |
5 | * | |
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 | |
9 | */ | |
10 | #include "qemu/osdep.h" | |
11 | #include "hw/registerfields.h" | |
12 | #include "libqtest.h" | |
13 | #include "libqos/pci-pc.h" | |
14 | #include "hw/pci/pci.h" | |
757c6eac EGE |
15 | #include "libqos/qgraph.h" |
16 | #include "libqos/sdhci.h" | |
8640cc11 PMD |
17 | |
18 | #define SDHC_CAPAB 0x40 | |
0c78f51e | 19 | FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8); /* since v2 */ |
bc13038f | 20 | FIELD(SDHC_CAPAB, SDMA, 22, 1); |
f18e6d50 PMD |
21 | FIELD(SDHC_CAPAB, SDR, 32, 3); /* since v3 */ |
22 | FIELD(SDHC_CAPAB, DRIVER, 36, 3); /* since v3 */ | |
8640cc11 PMD |
23 | #define SDHC_HCVER 0xFE |
24 | ||
efe9d524 PMD |
25 | static void check_specs_version(QSDHCI *s, uint8_t version) |
26 | { | |
27 | uint32_t v; | |
28 | ||
757c6eac | 29 | v = s->readw(s, SDHC_HCVER); |
efe9d524 PMD |
30 | v &= 0xff; |
31 | v += 1; | |
32 | g_assert_cmpuint(v, ==, version); | |
33 | } | |
34 | ||
8640cc11 PMD |
35 | static void check_capab_capareg(QSDHCI *s, uint64_t expec_capab) |
36 | { | |
37 | uint64_t capab; | |
38 | ||
757c6eac | 39 | capab = s->readq(s, SDHC_CAPAB); |
8640cc11 PMD |
40 | g_assert_cmphex(capab, ==, expec_capab); |
41 | } | |
42 | ||
556f9aca PMD |
43 | static void check_capab_readonly(QSDHCI *s) |
44 | { | |
45 | const uint64_t vrand = 0x123456789abcdef; | |
46 | uint64_t capab0, capab1; | |
47 | ||
757c6eac | 48 | capab0 = s->readq(s, SDHC_CAPAB); |
556f9aca PMD |
49 | g_assert_cmpuint(capab0, !=, vrand); |
50 | ||
757c6eac EGE |
51 | s->writeq(s, SDHC_CAPAB, vrand); |
52 | capab1 = s->readq(s, SDHC_CAPAB); | |
556f9aca PMD |
53 | g_assert_cmpuint(capab1, !=, vrand); |
54 | g_assert_cmpuint(capab1, ==, capab0); | |
55 | } | |
56 | ||
0c78f51e PMD |
57 | static void check_capab_baseclock(QSDHCI *s, uint8_t expec_freq) |
58 | { | |
59 | uint64_t capab, capab_freq; | |
60 | ||
61 | if (!expec_freq) { | |
62 | return; | |
63 | } | |
757c6eac | 64 | capab = s->readq(s, SDHC_CAPAB); |
0c78f51e PMD |
65 | capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ); |
66 | g_assert_cmpuint(capab_freq, ==, expec_freq); | |
67 | } | |
68 | ||
bc13038f PMD |
69 | static void check_capab_sdma(QSDHCI *s, bool supported) |
70 | { | |
71 | uint64_t capab, capab_sdma; | |
72 | ||
757c6eac | 73 | capab = s->readq(s, SDHC_CAPAB); |
bc13038f PMD |
74 | capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA); |
75 | g_assert_cmpuint(capab_sdma, ==, supported); | |
76 | } | |
77 | ||
f18e6d50 PMD |
78 | static void check_capab_v3(QSDHCI *s, uint8_t version) |
79 | { | |
80 | uint64_t capab, capab_v3; | |
81 | ||
82 | if (version < 3) { | |
83 | /* before v3 those fields are RESERVED */ | |
757c6eac | 84 | capab = s->readq(s, SDHC_CAPAB); |
f18e6d50 PMD |
85 | capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR); |
86 | g_assert_cmpuint(capab_v3, ==, 0); | |
87 | capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER); | |
88 | g_assert_cmpuint(capab_v3, ==, 0); | |
89 | } | |
90 | } | |
91 | ||
757c6eac | 92 | static void test_registers(void *obj, void *data, QGuestAllocator *alloc) |
8640cc11 | 93 | { |
757c6eac | 94 | QSDHCI *s = obj; |
8640cc11 | 95 | |
757c6eac EGE |
96 | check_specs_version(s, s->props.version); |
97 | check_capab_capareg(s, s->props.capab.reg); | |
556f9aca | 98 | check_capab_readonly(s); |
757c6eac EGE |
99 | check_capab_v3(s, s->props.version); |
100 | check_capab_sdma(s, s->props.capab.sdma); | |
101 | check_capab_baseclock(s, s->props.baseclock); | |
8640cc11 PMD |
102 | } |
103 | ||
757c6eac | 104 | static void register_sdhci_test(void) |
8640cc11 | 105 | { |
757c6eac | 106 | qos_add_test("registers", "sdhci", test_registers, NULL); |
8640cc11 | 107 | } |
757c6eac EGE |
108 | |
109 | libqos_init(register_sdhci_test); |