757c6eac8e
Convert tests/sdhci-test in first qgraph test node, sdhci-test. This test consumes an sdhci interface and checks that its function return the expected values. Note that this test does not allocate any sdhci structure, it's all done by the qtest walking graph mechanism Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
110 lines
2.9 KiB
C
110 lines
2.9 KiB
C
/*
|
|
* QTest testcase for SDHCI controllers
|
|
*
|
|
* Written by Philippe Mathieu-Daudé <f4bug@amsat.org>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
#include "hw/registerfields.h"
|
|
#include "libqtest.h"
|
|
#include "libqos/pci-pc.h"
|
|
#include "hw/pci/pci.h"
|
|
#include "libqos/qgraph.h"
|
|
#include "libqos/sdhci.h"
|
|
|
|
#define SDHC_CAPAB 0x40
|
|
FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8); /* since v2 */
|
|
FIELD(SDHC_CAPAB, SDMA, 22, 1);
|
|
FIELD(SDHC_CAPAB, SDR, 32, 3); /* since v3 */
|
|
FIELD(SDHC_CAPAB, DRIVER, 36, 3); /* since v3 */
|
|
#define SDHC_HCVER 0xFE
|
|
|
|
static void check_specs_version(QSDHCI *s, uint8_t version)
|
|
{
|
|
uint32_t v;
|
|
|
|
v = s->readw(s, SDHC_HCVER);
|
|
v &= 0xff;
|
|
v += 1;
|
|
g_assert_cmpuint(v, ==, version);
|
|
}
|
|
|
|
static void check_capab_capareg(QSDHCI *s, uint64_t expec_capab)
|
|
{
|
|
uint64_t capab;
|
|
|
|
capab = s->readq(s, SDHC_CAPAB);
|
|
g_assert_cmphex(capab, ==, expec_capab);
|
|
}
|
|
|
|
static void check_capab_readonly(QSDHCI *s)
|
|
{
|
|
const uint64_t vrand = 0x123456789abcdef;
|
|
uint64_t capab0, capab1;
|
|
|
|
capab0 = s->readq(s, SDHC_CAPAB);
|
|
g_assert_cmpuint(capab0, !=, vrand);
|
|
|
|
s->writeq(s, SDHC_CAPAB, vrand);
|
|
capab1 = s->readq(s, SDHC_CAPAB);
|
|
g_assert_cmpuint(capab1, !=, vrand);
|
|
g_assert_cmpuint(capab1, ==, capab0);
|
|
}
|
|
|
|
static void check_capab_baseclock(QSDHCI *s, uint8_t expec_freq)
|
|
{
|
|
uint64_t capab, capab_freq;
|
|
|
|
if (!expec_freq) {
|
|
return;
|
|
}
|
|
capab = s->readq(s, SDHC_CAPAB);
|
|
capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ);
|
|
g_assert_cmpuint(capab_freq, ==, expec_freq);
|
|
}
|
|
|
|
static void check_capab_sdma(QSDHCI *s, bool supported)
|
|
{
|
|
uint64_t capab, capab_sdma;
|
|
|
|
capab = s->readq(s, SDHC_CAPAB);
|
|
capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA);
|
|
g_assert_cmpuint(capab_sdma, ==, supported);
|
|
}
|
|
|
|
static void check_capab_v3(QSDHCI *s, uint8_t version)
|
|
{
|
|
uint64_t capab, capab_v3;
|
|
|
|
if (version < 3) {
|
|
/* before v3 those fields are RESERVED */
|
|
capab = s->readq(s, SDHC_CAPAB);
|
|
capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR);
|
|
g_assert_cmpuint(capab_v3, ==, 0);
|
|
capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER);
|
|
g_assert_cmpuint(capab_v3, ==, 0);
|
|
}
|
|
}
|
|
|
|
static void test_registers(void *obj, void *data, QGuestAllocator *alloc)
|
|
{
|
|
QSDHCI *s = obj;
|
|
|
|
check_specs_version(s, s->props.version);
|
|
check_capab_capareg(s, s->props.capab.reg);
|
|
check_capab_readonly(s);
|
|
check_capab_v3(s, s->props.version);
|
|
check_capab_sdma(s, s->props.capab.sdma);
|
|
check_capab_baseclock(s, s->props.baseclock);
|
|
}
|
|
|
|
static void register_sdhci_test(void)
|
|
{
|
|
qos_add_test("registers", "sdhci", test_registers, NULL);
|
|
}
|
|
|
|
libqos_init(register_sdhci_test);
|