xref: /openbmc/qemu/tests/qtest/sdhci-test.c (revision 907b5105)
11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth  * QTest testcase for SDHCI controllers
31e8a1faeSThomas Huth  *
41e8a1faeSThomas Huth  * Written by Philippe Mathieu-Daudé <f4bug@amsat.org>
51e8a1faeSThomas Huth  *
61e8a1faeSThomas Huth  * This work is licensed under the terms of the GNU GPL, version 2 or later.
71e8a1faeSThomas Huth  * See the COPYING file in the top-level directory.
81e8a1faeSThomas Huth  * SPDX-License-Identifier: GPL-2.0-or-later
91e8a1faeSThomas Huth  */
101e8a1faeSThomas Huth 
111e8a1faeSThomas Huth #include "qemu/osdep.h"
121e8a1faeSThomas Huth #include "hw/registerfields.h"
13*907b5105SMarc-André Lureau #include "libqtest.h"
141e8a1faeSThomas Huth #include "qemu/module.h"
151e8a1faeSThomas Huth #include "libqos/pci-pc.h"
161e8a1faeSThomas Huth #include "hw/pci/pci.h"
171e8a1faeSThomas Huth #include "libqos/qgraph.h"
181e8a1faeSThomas Huth #include "libqos/sdhci.h"
191e8a1faeSThomas Huth 
201e8a1faeSThomas Huth #define SDHC_CAPAB                      0x40
211e8a1faeSThomas Huth FIELD(SDHC_CAPAB, BASECLKFREQ,               8, 8); /* since v2 */
221e8a1faeSThomas Huth FIELD(SDHC_CAPAB, SDMA,                     22, 1);
231e8a1faeSThomas Huth FIELD(SDHC_CAPAB, SDR,                      32, 3); /* since v3 */
241e8a1faeSThomas Huth FIELD(SDHC_CAPAB, DRIVER,                   36, 3); /* since v3 */
251e8a1faeSThomas Huth #define SDHC_HCVER                      0xFE
261e8a1faeSThomas Huth 
check_specs_version(QSDHCI * s,uint8_t version)271e8a1faeSThomas Huth static void check_specs_version(QSDHCI *s, uint8_t version)
281e8a1faeSThomas Huth {
291e8a1faeSThomas Huth     uint32_t v;
301e8a1faeSThomas Huth 
311e8a1faeSThomas Huth     v = s->readw(s, SDHC_HCVER);
321e8a1faeSThomas Huth     v &= 0xff;
331e8a1faeSThomas Huth     v += 1;
341e8a1faeSThomas Huth     g_assert_cmpuint(v, ==, version);
351e8a1faeSThomas Huth }
361e8a1faeSThomas Huth 
check_capab_capareg(QSDHCI * s,uint64_t expec_capab)371e8a1faeSThomas Huth static void check_capab_capareg(QSDHCI *s, uint64_t expec_capab)
381e8a1faeSThomas Huth {
391e8a1faeSThomas Huth     uint64_t capab;
401e8a1faeSThomas Huth 
411e8a1faeSThomas Huth     capab = s->readq(s, SDHC_CAPAB);
421e8a1faeSThomas Huth     g_assert_cmphex(capab, ==, expec_capab);
431e8a1faeSThomas Huth }
441e8a1faeSThomas Huth 
check_capab_readonly(QSDHCI * s)451e8a1faeSThomas Huth static void check_capab_readonly(QSDHCI *s)
461e8a1faeSThomas Huth {
471e8a1faeSThomas Huth     const uint64_t vrand = 0x123456789abcdef;
481e8a1faeSThomas Huth     uint64_t capab0, capab1;
491e8a1faeSThomas Huth 
501e8a1faeSThomas Huth     capab0 = s->readq(s, SDHC_CAPAB);
511e8a1faeSThomas Huth     g_assert_cmpuint(capab0, !=, vrand);
521e8a1faeSThomas Huth 
531e8a1faeSThomas Huth     s->writeq(s, SDHC_CAPAB, vrand);
541e8a1faeSThomas Huth     capab1 = s->readq(s, SDHC_CAPAB);
551e8a1faeSThomas Huth     g_assert_cmpuint(capab1, !=, vrand);
561e8a1faeSThomas Huth     g_assert_cmpuint(capab1, ==, capab0);
571e8a1faeSThomas Huth }
581e8a1faeSThomas Huth 
check_capab_baseclock(QSDHCI * s,uint8_t expec_freq)591e8a1faeSThomas Huth static void check_capab_baseclock(QSDHCI *s, uint8_t expec_freq)
601e8a1faeSThomas Huth {
611e8a1faeSThomas Huth     uint64_t capab, capab_freq;
621e8a1faeSThomas Huth 
631e8a1faeSThomas Huth     if (!expec_freq) {
641e8a1faeSThomas Huth         return;
651e8a1faeSThomas Huth     }
661e8a1faeSThomas Huth     capab = s->readq(s, SDHC_CAPAB);
671e8a1faeSThomas Huth     capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ);
681e8a1faeSThomas Huth     g_assert_cmpuint(capab_freq, ==, expec_freq);
691e8a1faeSThomas Huth }
701e8a1faeSThomas Huth 
check_capab_sdma(QSDHCI * s,bool supported)711e8a1faeSThomas Huth static void check_capab_sdma(QSDHCI *s, bool supported)
721e8a1faeSThomas Huth {
731e8a1faeSThomas Huth     uint64_t capab, capab_sdma;
741e8a1faeSThomas Huth 
751e8a1faeSThomas Huth     capab = s->readq(s, SDHC_CAPAB);
761e8a1faeSThomas Huth     capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA);
771e8a1faeSThomas Huth     g_assert_cmpuint(capab_sdma, ==, supported);
781e8a1faeSThomas Huth }
791e8a1faeSThomas Huth 
check_capab_v3(QSDHCI * s,uint8_t version)801e8a1faeSThomas Huth static void check_capab_v3(QSDHCI *s, uint8_t version)
811e8a1faeSThomas Huth {
821e8a1faeSThomas Huth     uint64_t capab, capab_v3;
831e8a1faeSThomas Huth 
841e8a1faeSThomas Huth     if (version < 3) {
851e8a1faeSThomas Huth         /* before v3 those fields are RESERVED */
861e8a1faeSThomas Huth         capab = s->readq(s, SDHC_CAPAB);
871e8a1faeSThomas Huth         capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR);
881e8a1faeSThomas Huth         g_assert_cmpuint(capab_v3, ==, 0);
891e8a1faeSThomas Huth         capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER);
901e8a1faeSThomas Huth         g_assert_cmpuint(capab_v3, ==, 0);
911e8a1faeSThomas Huth     }
921e8a1faeSThomas Huth }
931e8a1faeSThomas Huth 
test_registers(void * obj,void * data,QGuestAllocator * alloc)941e8a1faeSThomas Huth static void test_registers(void *obj, void *data, QGuestAllocator *alloc)
951e8a1faeSThomas Huth {
961e8a1faeSThomas Huth     QSDHCI *s = obj;
971e8a1faeSThomas Huth 
981e8a1faeSThomas Huth     check_specs_version(s, s->props.version);
991e8a1faeSThomas Huth     check_capab_capareg(s, s->props.capab.reg);
1001e8a1faeSThomas Huth     check_capab_readonly(s);
1011e8a1faeSThomas Huth     check_capab_v3(s, s->props.version);
1021e8a1faeSThomas Huth     check_capab_sdma(s, s->props.capab.sdma);
1031e8a1faeSThomas Huth     check_capab_baseclock(s, s->props.baseclock);
1041e8a1faeSThomas Huth }
1051e8a1faeSThomas Huth 
register_sdhci_test(void)1061e8a1faeSThomas Huth static void register_sdhci_test(void)
1071e8a1faeSThomas Huth {
1081e8a1faeSThomas Huth     qos_add_test("registers", "sdhci", test_registers, NULL);
1091e8a1faeSThomas Huth }
1101e8a1faeSThomas Huth 
1111e8a1faeSThomas Huth libqos_init(register_sdhci_test);
112