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é */ 10*0b8fa32fSMarkus Armbruster 118640cc11SPhilippe Mathieu-Daudé #include "qemu/osdep.h" 128640cc11SPhilippe Mathieu-Daudé #include "hw/registerfields.h" 138640cc11SPhilippe Mathieu-Daudé #include "libqtest.h" 14*0b8fa32fSMarkus 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é 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é 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é 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é 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é 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é 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é 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é 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