From nobody Mon Sep 28 02:00:08 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1785326087; cv=none; d=zohomail.com; s=zohoarc; b=eMZ+uSZY7YAlI+nB4rBgXezgDzPfhAuLXisQZg3gis+usPXDZEIX98W8wZjw68LHiMVEZzHVFmOjYVBUrXRH5CUkOAZWOskjU1xqtYAoZSyLekVDWu3J5MPDqPD/PWmHPRS2Ekw/0pX2auAd9BWcSIPnRSu3C5NZT8rCoQz89u4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785326087; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=gQ5aFS2k3+LUcEAitcHN9BjMTSfVp18rofu2I0RU+Cw=; b=GC8tqiJgewKvx8HWwqftJus1hijYwoTt1ZafmV/cpkJhze0AVCsDyX1FnSMCSkNNRJYX7TZXgRyrBjTtr2EDeKfcJG1uDgs1kQS65ZRTrb+pZprIr7AaVAb1PYFlO04Ukq78m0bCEGo+YOm0o0FIWrYHqmsYBBSr7CkyJApPLnw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785326087539914.0929690031542; Wed, 29 Jul 2026 04:54:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wp2rk-0006BA-EX; Wed, 29 Jul 2026 07:54:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wp20f-000176-89 for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:38 -0400 Received: from mail-pj2-x00.google.com ([2607:f8b0:4864:39::]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wp20c-0004D7-Of for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:37 -0400 Received: by mail-pj2-x00.google.com with SMTP id d9443c01a7336-2cc7a345f51so6685225ad.0 for ; Wed, 29 Jul 2026 03:59:33 -0700 (PDT) Received: from LAPTOP-LOCIFOSI.localdomain ([123.127.39.254]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bfa240sm9627135ad.65.2026.07.29.03.59.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 03:59:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785322772; x=1785927572; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=gQ5aFS2k3+LUcEAitcHN9BjMTSfVp18rofu2I0RU+Cw=; b=fatFcBc/AasBu5t9zv4X3KfMG9QzjQMMSeRBI/g5NkG2B9InjPDqPDXX8Nhracg0eH b6a+Shzv9aFlNSQXNHawPmg1TUnNDO/6mddXgEbDZb5WQMdynt80a4UXNnF871LDqSY0 3usPb6pckTJe2iqohLpEa4X8+CXPQp43LuHDVag1l42Lb28Gv1syMyTb3KF8oxrMucg9 61blWiEsgP6JIXC12SrhV2Jy1P87ljdO+fBt7grTSEldkjIkvInnKb3rkDD57rjVTJ17 DAhD8G7Wb/do0V3p5Yu7yqHxR7U3ClZpeh4JlevfFyZJw8MdGCwflGXITKivpJUIZ+pZ kSZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785322772; x=1785927572; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=gQ5aFS2k3+LUcEAitcHN9BjMTSfVp18rofu2I0RU+Cw=; b=tFvSTmEc9m3l5xIbJ4n2VeTq6nRElFg3rnje2EB2BHPLRwVzMyKzr6zELyslQIzuql mSU3NlMlyk1ofvFwrzaBdQcHzakPbI7+TWQLQnfFG55cLmhX7ACQY26Ciutw+tk3I8Wd dNOllvnVM9C+LJNjNCa9IZ4Bc8mM2zO39vJObZE448SsqApTx4+5QiqXcXoiu9iQ6IJb ew2C1uetMA37go3yvWdUinq5g4euNZxGnSqJWEB/kB3UJ3vvtPErq/nP7Rvq0MhhxJji PQ5tQXfZcNcVhNG6p6uW/xMpqsOsvVXNi7w9Rse6gR11OadJ3WugK4S339ciwPK5nH8T w9TQ== X-Gm-Message-State: AOJu0Yy7wiw/EbDti1m0/aBfD6ZOgU9kmKnbDzNImIjMnb6D0sIAS63G ivcLpPtYmI+d0BU71xrtMuXTltKgdqUynSvAr8gAN9kkAEGiRqg7CPeRUzJein3E4knprw== X-Gm-Gg: AR+sD112ID3+zFDlVKnP7ZxRez751yUCPJt3tQUpwctPAhDOF9ibR2VlOFNoHKAAJtT OU4FE3gI7/jvdf+KiyLc85K6VPKgxLSxCxPZYDraonw583ZV2zoF7DWX+Hvk65kCHDjO2E0CmwN BSVWXalmaGWQNBy678QcLJSRsLxpJq3HcDQdOjcDNlLaF4To/rwXknr9FwJRw67LNLTOJdm6a/J aFfx1lLAut7iCRvtVkPHTVOSJhzwToxX9aSmTM3bxj6tLSS/c00hTsZuLGC5OLznJsHE/pcK6f6 lwh7NUpgqJli3EA+tHV3ZyJbpqrYuqxmabNkW4c8CZY7wOAU4xASEoRjGzRCE4Ox3g7qDMevtqw G7RhQauL6OffLX1SIRb3ZcE+hqR+m4dtgh1vRqDJffIhxJ29MvBqh9fI9Zb1qRaS5I1MsKlZ2rt CrOE41eKex53UYpKOhdnLRy7AuhMQn3Zeb51WYZZGYlp6kBxviiYf+fH7VEUlsRmGUE5dDZzqDP ysJXpLomg== X-Received: by 2002:a17:903:3583:b0:2c9:c991:3bf0 with SMTP id d9443c01a7336-2d015b148d4mr68977195ad.8.1785322772229; Wed, 29 Jul 2026 03:59:32 -0700 (PDT) From: Xin Xie To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, Chao Liu , Alistair Francis , Daniel Henrique Barboza , Fabiano Rosas , Laurent Vivier , Liu Zhiwei , Palmer Dabbelt , Paolo Bonzini , Pierrick Bouvier , Weiwei Li , Xin Xie Subject: [PATCH v1 1/3] hw/sd: add Kendryte K230 SDHCI controller Date: Wed, 29 Jul 2026 18:59:01 +0800 Message-ID: <20260729105904.272939-2-xinxie908@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260729105904.272939-1-xinxie908@gmail.com> References: <20260729105904.272939-1-xinxie908@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:39::; envelope-from=xinxie908@gmail.com; helo=mail-pj2-x00.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 29 Jul 2026 07:54:22 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1785326089612158500 Content-Type: text/plain; charset="utf-8" Add a minimal K230 SDHCI model based on the generic SDHCI model. Reuse the generic commands and data paths while providing the extended register layout and documented reset values. K230 SDHCI controller contains the standard SDHCI register block followed by preset, extension pointer, PHY and vendor-specific registers. This model implements the preset and extension pointer registers as read-only, retain writes to most PHY and vendor-specific registers, and keep PHY_PWRGOOD asserted so that the K230 SDK reset sequence can complete. The SDHCI version is set to 3 due to the absence of ADMA3 support in the generic model. Signed-off-by: Xin Xie Reviewed-by: Daniel Henrique Barboza --- MAINTAINERS | 2 + hw/sd/Kconfig | 4 + hw/sd/k230_sdhci.c | 311 +++++++++++++++++++++++++++++++++++++ hw/sd/meson.build | 1 + include/hw/sd/k230_sdhci.h | 82 ++++++++++ 5 files changed, 400 insertions(+) create mode 100644 hw/sd/k230_sdhci.c create mode 100644 include/hw/sd/k230_sdhci.h diff --git a/MAINTAINERS b/MAINTAINERS index 6171cc7494..06285352c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1826,8 +1826,10 @@ S: Maintained F: docs/system/riscv/k230.rst F: hw/riscv/k230.c F: hw/watchdog/k230_wdt.c +F: hw/sd/k230_sdhci.c F: include/hw/riscv/k230.h F: include/hw/watchdog/k230_wdt.h +F: include/hw/sd/k230_sdhci.h F: tests/qtest/k230-wdt-test.c =20 RX Machines diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig index 633b9afec9..e9a5d63b4d 100644 --- a/hw/sd/Kconfig +++ b/hw/sd/Kconfig @@ -23,3 +23,7 @@ config SDHCI_PCI config CADENCE_SDHCI bool select SDHCI + +config K230_SDHCI + bool + select SDHCI diff --git a/hw/sd/k230_sdhci.c b/hw/sd/k230_sdhci.c new file mode 100644 index 0000000000..34c972a2f7 --- /dev/null +++ b/hw/sd/k230_sdhci.c @@ -0,0 +1,311 @@ +/* + * Kendryte K230 SDHCI controller + * + * Copyright (c) 2026 Xin Xie + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/sd/k230_sdhci.h" +#include "hw/sd/sdhci-internal.h" +#include "migration/vmstate.h" + +/* + * The TRM describes an SDHCI v4.20 DWC MSHC, including the v4 block-count + * mode, ADMA3, and extension-area registers. QEMU's generic controller + * supports up to v3 and does not implement those v4 transfer semantics. + */ +#define K230_SDHCI_SPEC_VERSION 3 + +/* + * K230's Capabilities registers describe more functionality than the gene= ric + * QEMU SDHCI data path currently implements. Do not expose the following= TRM + * capabilities to the guest: + * + * - ASYNC_INT requires an SDIO card-interrupt input and asynchronous inte= rrupt + * signalling while the SD clock is stopped. SDBus has no such input. + * - TIMER_RETUNING and RETUNING_MODE require a re-tuning timer and genera= tion + * of a re-tuning request. The generic controller only completes an ini= tial + * command-based tuning operation; it never schedules periodic re-tuning. + * - ADMA3 requires the SDHCI v4.20 ADMA3 descriptor and command semantics, + * whereas the generic controller implements SDMA and ADMA2 only. + */ +#define K230_SDHCI_CAPABILITIES_UNSUPPORTED \ + (R_SDHC_CAPAB_ASYNC_INT_MASK | \ + R_SDHC_CAPAB_TIMER_RETUNING_MASK | \ + R_SDHC_CAPAB_RETUNING_MODE_MASK | \ + R_SDHC_CAPAB_ADMA3_MASK) +#define K230_SDHCI_CAPAREG_IMPLEMENTED \ + (K230_SDHCI_CAPAREG_RESET & ~K230_SDHCI_CAPABILITIES_UNSUPPORTED) + +#define K230_LO8(value) ((value) & 0xff) +#define K230_HI8(value) (((value) >> 8) & 0xff) + +static const uint8_t k230_sdhci_preset_reset[K230_SDHCI_PRESET_SIZE] =3D { + [K230_SDHCI_PRESET_INIT - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_INIT_RESET), + [K230_SDHCI_PRESET_INIT - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_INIT_RESET), + [K230_SDHCI_PRESET_DEFAULT_SPEED - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_DEFAULT_SPEED_RESET), + [K230_SDHCI_PRESET_DEFAULT_SPEED - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_DEFAULT_SPEED_RESET), + [K230_SDHCI_PRESET_HIGH_SPEED - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_HIGH_SPEED_RESET), + [K230_SDHCI_PRESET_HIGH_SPEED - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_HIGH_SPEED_RESET), + [K230_SDHCI_PRESET_SDR12 - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_SDR12_RESET), + [K230_SDHCI_PRESET_SDR12 - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_SDR12_RESET), + [K230_SDHCI_PRESET_SDR25 - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_SDR25_RESET), + [K230_SDHCI_PRESET_SDR25 - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_SDR25_RESET), + [K230_SDHCI_PRESET_SDR50 - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_SDR50_RESET), + [K230_SDHCI_PRESET_SDR50 - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_SDR50_RESET), + [K230_SDHCI_PRESET_SDR104 - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_SDR104_RESET), + [K230_SDHCI_PRESET_SDR104 - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_SDR104_RESET), + [K230_SDHCI_PRESET_DDR50 - K230_SDHCI_PRESET_BASE] =3D + K230_LO8(K230_SDHCI_PRESET_DDR50_RESET), + [K230_SDHCI_PRESET_DDR50 - K230_SDHCI_PRESET_BASE + 1] =3D + K230_HI8(K230_SDHCI_PRESET_DDR50_RESET), +}; + +static uint64_t k230_sdhci_preset_read(void *opaque, hwaddr addr, + unsigned int size) +{ + return ldn_le_p(&k230_sdhci_preset_reset[addr], size); +} + +static void k230_sdhci_preset_write(void *opaque, hwaddr addr, uint64_t va= lue, + unsigned int size) +{ + qemu_log_mask(LOG_GUEST_ERROR, + "K230 SDHCI: write to read-only Preset Value register " + "0x%03" HWADDR_PRIx "\n", + K230_SDHCI_PRESET_BASE + addr); +} + +static const MemoryRegionOps k230_sdhci_preset_ops =3D { + .read =3D k230_sdhci_preset_read, + .write =3D k230_sdhci_preset_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static const uint8_t k230_sdhci_pointer_reset[K230_SDHCI_POINTER_SIZE] =3D= { + [K230_SDHCI_P_UHS2_SETTINGS - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_UHS2_SETTINGS_RESET), + [K230_SDHCI_P_UHS2_SETTINGS - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_UHS2_SETTINGS_RESET), + [K230_SDHCI_P_UHS2_HOST_CAPAB - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_UHS2_HOST_CAPAB_RESET), + [K230_SDHCI_P_UHS2_HOST_CAPAB - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_UHS2_HOST_CAPAB_RESET), + [K230_SDHCI_P_UHS2_TEST - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_UHS2_TEST_RESET), + [K230_SDHCI_P_UHS2_TEST - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_UHS2_TEST_RESET), + [K230_SDHCI_P_EMBEDDED_CNTRL - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_EMBEDDED_CNTRL_RESET), + [K230_SDHCI_P_EMBEDDED_CNTRL - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_EMBEDDED_CNTRL_RESET), + [K230_SDHCI_P_VENDOR_AREA1 - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_VENDOR_AREA1_RESET), + [K230_SDHCI_P_VENDOR_AREA1 - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_VENDOR_AREA1_RESET), + [K230_SDHCI_P_VENDOR_AREA2 - K230_SDHCI_POINTER_BASE] =3D + K230_LO8(K230_SDHCI_P_VENDOR_AREA2_RESET), + [K230_SDHCI_P_VENDOR_AREA2 - K230_SDHCI_POINTER_BASE + 1] =3D + K230_HI8(K230_SDHCI_P_VENDOR_AREA2_RESET), +}; + +static uint64_t k230_sdhci_pointer_read(void *opaque, hwaddr addr, + unsigned int size) +{ + return ldn_le_p(&k230_sdhci_pointer_reset[addr], size); +} + +static void k230_sdhci_pointer_write(void *opaque, hwaddr addr, uint64_t v= alue, + unsigned int size) +{ + qemu_log_mask(LOG_GUEST_ERROR, + "K230 SDHCI: write to read-only pointer register " + "0x%03" HWADDR_PRIx "\n", + K230_SDHCI_POINTER_BASE + addr); +} + +static const MemoryRegionOps k230_sdhci_pointer_ops =3D { + .read =3D k230_sdhci_pointer_read, + .write =3D k230_sdhci_pointer_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +/* + * K230 uses the standard SDHCI register set at offset zero, followed by + * UHS-II, DWC MSHC PHY, Embedded Control, and vendor-specific blocks. Most + * side effects of analogue PHY behaviors not simulated. + * + * PHY_PWRGOOD is the sole synthesized status bit. Real hardware asserts = it + * after PHY power and reset sequencing; the SDK driver polls it during ev= ery + * full controller reset. A virtual PHY has no settling interval or failu= re + * condition, so the bit is permanently asserted and cannot be cleared by a + * guest write. + */ +static uint64_t k230_sdhci_fallback_read(void *opaque, hwaddr addr, + unsigned int size) +{ + K230SDHCIState *s =3D opaque; + uint64_t value =3D ldn_le_p(&s->fallback_regs[addr], size); + + if (ranges_overlap(addr, size, K230_SDHCI_PHY_CNFG, + sizeof(uint32_t)) && addr <=3D K230_SDHCI_PHY_CNFG)= { + unsigned int shift =3D (K230_SDHCI_PHY_CNFG - addr) * 8; + + value |=3D (uint64_t)K230_SDHCI_PHY_CNFG_PWRGOOD << shift; + } + + return value; +} + +static void k230_sdhci_fallback_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + K230SDHCIState *s =3D opaque; + + stn_le_p(&s->fallback_regs[addr], size, value); + + /* PWRGOOD reflects PHY state and is not software writable. */ + s->fallback_regs[K230_SDHCI_PHY_CNFG] |=3D + K230_SDHCI_PHY_CNFG_PWRGOOD; +} + +static const MemoryRegionOps k230_sdhci_fallback_ops =3D { + .read =3D k230_sdhci_fallback_read, + .write =3D k230_sdhci_fallback_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static void k230_sdhci_reset(DeviceState *dev) +{ + K230SDHCIState *s =3D K230_SDHCI(dev); + + memset(s->fallback_regs, 0, sizeof(s->fallback_regs)); + s->fallback_regs[K230_SDHCI_PHY_CNFG] =3D + K230_SDHCI_PHY_CNFG_PWRGOOD; + device_cold_reset(DEVICE(&s->sdhci)); +} + +static void k230_sdhci_realize(DeviceState *dev, Error **errp) +{ + K230SDHCIState *s =3D K230_SDHCI(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + SysBusDevice *sdhci_sbd =3D SYS_BUS_DEVICE(&s->sdhci); + + memory_region_init(&s->container, OBJECT(s), "k230.sdhci-container", + K230_SDHCI_REG_SIZE); + sysbus_init_mmio(sbd, &s->container); + + memory_region_init_io(&s->iomem_fallback, OBJECT(s), + &k230_sdhci_fallback_ops, s, + "k230.sdhci-fallback", + K230_SDHCI_REG_SIZE); + memory_region_add_subregion(&s->container, 0, &s->iomem_fallback); + + if (!sysbus_realize(sdhci_sbd, errp)) { + return; + } + memory_region_add_subregion_overlap( + &s->container, 0, sysbus_mmio_get_region(sdhci_sbd, 0), 1); + + memory_region_init_io(&s->iomem_preset, OBJECT(s), + &k230_sdhci_preset_ops, s, + "k230.sdhci-preset", K230_SDHCI_PRESET_SIZE); + memory_region_add_subregion_overlap(&s->container, + K230_SDHCI_PRESET_BASE, + &s->iomem_preset, 2); + + memory_region_init_io(&s->iomem_pointer, OBJECT(s), + &k230_sdhci_pointer_ops, s, + "k230.sdhci-pointers", K230_SDHCI_POINTER_SIZE); + memory_region_add_subregion_overlap(&s->container, + K230_SDHCI_POINTER_BASE, + &s->iomem_pointer, 2); + + sysbus_pass_irq(sbd, sdhci_sbd); + s->bus =3D qdev_get_child_bus(DEVICE(sdhci_sbd), "sd-bus"); +} + +static const VMStateDescription vmstate_k230_sdhci =3D { + .name =3D TYPE_K230_SDHCI, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT8_ARRAY(fallback_regs, K230SDHCIState, + K230_SDHCI_REG_SIZE), + VMSTATE_END_OF_LIST() + }, +}; + +static void k230_sdhci_instance_init(Object *obj) +{ + K230SDHCIState *s =3D K230_SDHCI(obj); + + object_initialize_child(obj, "generic-sdhci", &s->sdhci, + TYPE_SYSBUS_SDHCI); + + object_property_set_uint(OBJECT(&s->sdhci), "sd-spec-version", + K230_SDHCI_SPEC_VERSION, + &error_abort); + object_property_set_uint(OBJECT(&s->sdhci), "capareg", + K230_SDHCI_CAPAREG_IMPLEMENTED, + &error_abort); + object_property_set_uint(OBJECT(&s->sdhci), "uhs", UHS_I, &error_abort= ); +} + +static void k230_sdhci_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->desc =3D "Kendryte K230 SDHCI Controller"; + dc->realize =3D k230_sdhci_realize; + device_class_set_legacy_reset(dc, k230_sdhci_reset); + dc->vmsd =3D &vmstate_k230_sdhci; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +} + +static const TypeInfo k230_sdhci_type_info =3D { + .name =3D TYPE_K230_SDHCI, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(K230SDHCIState), + .instance_init =3D k230_sdhci_instance_init, + .class_init =3D k230_sdhci_class_init, +}; + +static void k230_sdhci_register_types(void) +{ + type_register_static(&k230_sdhci_type_info); +} + +type_init(k230_sdhci_register_types) diff --git a/hw/sd/meson.build b/hw/sd/meson.build index b43d45bc56..a109635233 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -10,3 +10,4 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('= aspeed_sdhci.c')) system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhos= t.c')) system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c')) system_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.= c')) +system_ss.add(when: 'CONFIG_K230_SDHCI', if_true: files('k230_sdhci.c')) diff --git a/include/hw/sd/k230_sdhci.h b/include/hw/sd/k230_sdhci.h new file mode 100644 index 0000000000..a8389f1de4 --- /dev/null +++ b/include/hw/sd/k230_sdhci.h @@ -0,0 +1,82 @@ +/* + * Kendryte K230 SDHCI controller + * + * Copyright (c) 2026 Xin Xie + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_SD_K230_SDHCI_H +#define HW_SD_K230_SDHCI_H + +#include "qemu/bitops.h" +#include "hw/sd/sdhci.h" +#include "qom/object.h" + +#define TYPE_K230_SDHCI "k230.sdhci" +OBJECT_DECLARE_SIMPLE_TYPE(K230SDHCIState, K230_SDHCI) + +#define K230_SDHCI_REG_SIZE 0x1000 + +/* K230 TRM reset values for Capabilities Registers 1 and 2. */ +#define K230_SDHCI_CAPABILITIES1_RESET 0x256ec881ULL +#define K230_SDHCI_CAPABILITIES2_RESET 0x0800a177ULL +#define K230_SDHCI_CAPAREG_RESET \ + ((K230_SDHCI_CAPABILITIES2_RESET << 32) \ + | K230_SDHCI_CAPABILITIES1_RESET) + +/* SDHCI Preset Value registers. */ +#define K230_SDHCI_PRESET_BASE 0x060 +#define K230_SDHCI_PRESET_SIZE 0x010 +#define K230_SDHCI_PRESET_INIT 0x060 +#define K230_SDHCI_PRESET_DEFAULT_SPEED 0x062 +#define K230_SDHCI_PRESET_HIGH_SPEED 0x064 +#define K230_SDHCI_PRESET_SDR12 0x066 +#define K230_SDHCI_PRESET_SDR25 0x068 +#define K230_SDHCI_PRESET_SDR50 0x06a +#define K230_SDHCI_PRESET_SDR104 0x06c +#define K230_SDHCI_PRESET_DDR50 0x06e +#define K230_SDHCI_PRESET_INIT_RESET 0x00fa +#define K230_SDHCI_PRESET_DEFAULT_SPEED_RESET 0x0004 +#define K230_SDHCI_PRESET_HIGH_SPEED_RESET 0x0002 +#define K230_SDHCI_PRESET_SDR12_RESET 0x0004 +#define K230_SDHCI_PRESET_SDR25_RESET 0x0002 +#define K230_SDHCI_PRESET_SDR50_RESET 0x0001 +#define K230_SDHCI_PRESET_SDR104_RESET 0x0000 +#define K230_SDHCI_PRESET_DDR50_RESET 0x0002 + +/* SDHCI v4 extension-area pointer registers. */ +#define K230_SDHCI_POINTER_BASE 0x0e0 +#define K230_SDHCI_POINTER_SIZE 0x00c +#define K230_SDHCI_P_UHS2_SETTINGS 0x0e0 +#define K230_SDHCI_P_UHS2_HOST_CAPAB 0x0e2 +#define K230_SDHCI_P_UHS2_TEST 0x0e4 +#define K230_SDHCI_P_EMBEDDED_CNTRL 0x0e6 +#define K230_SDHCI_P_VENDOR_AREA1 0x0e8 +#define K230_SDHCI_P_VENDOR_AREA2 0x0ea +#define K230_SDHCI_P_UHS2_SETTINGS_RESET 0x0000 +#define K230_SDHCI_P_UHS2_HOST_CAPAB_RESET 0x0f58 +#define K230_SDHCI_P_UHS2_TEST_RESET 0x0f68 +#define K230_SDHCI_P_EMBEDDED_CNTRL_RESET 0x0f6c +#define K230_SDHCI_P_VENDOR_AREA1_RESET 0x0500 +#define K230_SDHCI_P_VENDOR_AREA2_RESET 0x0384 + +/* DWC MSHC PHY register block. */ +#define K230_SDHCI_PHY_CNFG 0x300 +#define K230_SDHCI_PHY_CNFG_RSTN BIT(0) +#define K230_SDHCI_PHY_CNFG_PWRGOOD BIT(1) + +struct K230SDHCIState { + SysBusDevice parent_obj; + + MemoryRegion container; + MemoryRegion iomem_fallback; + MemoryRegion iomem_preset; + MemoryRegion iomem_pointer; + BusState *bus; + uint8_t fallback_regs[K230_SDHCI_REG_SIZE]; + + SDHCIState sdhci; +}; + +#endif --=20 2.43.0 From nobody Mon Sep 28 02:00:08 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1785326115; cv=none; d=zohomail.com; s=zohoarc; b=V4e2MUtVM1uzDsIKdMIAFLRPCPya/O4iENMUbmKDHuksXT5ZXoto1MChG2TqyhzO8rIGcWnNElUEyUkm5Zti82dZqSlcsmZFC8KZZEvz2RRBmlf9Tq7dDpMnIIcTphX10bLVuFU08gLA55WHLK9w28CSwdbEnkhVMEaVhTqedIc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785326114; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=AA4kbnvcGIDYoqgEXcU+45vYtoc2rnZEFSQgdt/3/7Y=; b=dwx5YsmdwfkX2sXlsRdyTdkePhHnw12X7LcuMmyv+DI7Hel7RpiW0Uwk1SwZstBCbzSBUa7wXNvIz0L2EhCF9+Quc7y13K5qUCBjjgHivWUU7nAYBfY5uiQ9nihwDgW1wS28HifKYAm/tJQiHLqH6xgVB5VzVfLbkO2ydir1L/o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785326114991458.3857402981304; Wed, 29 Jul 2026 04:55:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wp2ri-0006Ap-U3; Wed, 29 Jul 2026 07:54:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wp20j-00017z-5r for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:41 -0400 Received: from mail-pj2-x01.google.com ([2607:f8b0:4864:39::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wp20f-0004Dp-TX for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:40 -0400 Received: by mail-pj2-x01.google.com with SMTP id d9443c01a7336-2ce7ac92dfcso7097135ad.1 for ; Wed, 29 Jul 2026 03:59:37 -0700 (PDT) Received: from LAPTOP-LOCIFOSI.localdomain ([123.127.39.254]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bfa240sm9627135ad.65.2026.07.29.03.59.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 03:59:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785322776; x=1785927576; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=AA4kbnvcGIDYoqgEXcU+45vYtoc2rnZEFSQgdt/3/7Y=; b=RN/48wKRE2tgeu7wPFWccrzjq+imzseK4jqr3pt5lk2mMFxt+1WUF56h3HaeWYvHQS nzm+tSzmCzxVocibgupNqW1oFBXf9CufPqFiQMJ/28xsczoSNRJcMhffZgmN1QZskfyu m/8Facpgg6e37ZabJoyHD0za932Ugln4WtaexZ63oleDJ0TM+0pMCNlqrBiGPKG3cF4/ ExRTsBX/sl/mZuX5zl22ajogIf8ZkywGeUF0Yjub3kqOwqEa/fLFcggre83voP6ztcw+ 4WokBAPxKNZPT892qOKbEnmO9cpNu5K3nm4zI2pVCmxhV5scium5gJq5oww5vfC89sJq moFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785322776; x=1785927576; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=AA4kbnvcGIDYoqgEXcU+45vYtoc2rnZEFSQgdt/3/7Y=; b=bzAqXYWph+wmkIrrGjNKe3TZFpJeqYcAdgF4oIFIfW86ZfVd0kAg/cf4CcSaMK4E34 sxKAh17n5bu4Fuy58hYIRha+7DPG4CNk/sYNgNxNVKDFQtf7YNPZRcqXbixBZqmoleg4 bUDtjnyar3PNCqUVnekT0SoPNR41KNY+XxbsC3hlrMSvP0dZ5/ttNigEFFmhymnuwzkh cwZvS6Qqo7JMZjrNFdJJCYJhFu2PLMAtuUPZzJTh90KjzoadjUKu5iLlmlpoj2BOFcvr Mf9JjiHOl65LPpEaaqsfZORt3zRiQqN8rLi7cqc9Y9nVrIQ10XJYAbQagf4sDKfCbk54 huCw== X-Gm-Message-State: AOJu0YzdVZ2O7QfKPPPL1Y4g1Qy8NW5pW2DnxYtjwUmTIdplWiNK4HAm NfjzrUHHzAsNBzH03SWfLJ0uAPC5sRWeDIPrqaD60rbEEPUMfd3GX4axlaPcCXWKtu/+tQ== X-Gm-Gg: AR+sD100iN/k+tOpz62bDOS9NZVUJZejvDymv/Maf874W+p+X6JrX4JiI7j9NXSjc1v ypYoVrYaWpICSifHLsozT/ZVRhjdsEWLQzQEmuxjXyRAtuKEFgPjE78bx3FkDbwKwlxNmdwTlJo 2z1IwtvpUdDaHEqsreH4Ywcgldncb72r6WT5XDKof7CCtmQNZ5TNEqBYiz5QArpsQIiFzUN2DOY t5OohWdWuLtn+SDDmG+pAmwTF+OoGle/62fpFzsQUZrRUgk2zLINTGMr0q8J0/UvCp9nMOZVjPL P0jlbjOIV32+Hsvq+0nNZTM3fJ+/N8Uy1Nxam+iICrQEe34Rdtc4t59tz+qh2z6EcMdoQH3igE6 OqFkr1GQs5ioQ9OVfXv/87wIbBqBiY8Gx8ttV9Hm8F9ZacWj18twCaZGHeId4QTaFqfHT6eUtmS vUtojK+Zwv5k2jppp3ifve4ykx3NKSUTp88asoQrjyydxtPWoRlAeKXIgWlCJ9+6Lsh34hMZUTe ygCRl4zig== X-Received: by 2002:a17:903:166e:b0:2ce:fa3a:45f7 with SMTP id d9443c01a7336-2d015d1eb47mr65436735ad.16.1785322776228; Wed, 29 Jul 2026 03:59:36 -0700 (PDT) From: Xin Xie To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, Chao Liu , Alistair Francis , Daniel Henrique Barboza , Fabiano Rosas , Laurent Vivier , Liu Zhiwei , Palmer Dabbelt , Paolo Bonzini , Pierrick Bouvier , Weiwei Li , Xin Xie Subject: [PATCH v1 2/3] hw/riscv: enable SDHCI controllers on K230 Date: Wed, 29 Jul 2026 18:59:02 +0800 Message-ID: <20260729105904.272939-3-xinxie908@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260729105904.272939-1-xinxie908@gmail.com> References: <20260729105904.272939-1-xinxie908@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:39::1; envelope-from=xinxie908@gmail.com; helo=mail-pj2-x01.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 29 Jul 2026 07:54:23 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1785326117194158500 Content-Type: text/plain; charset="utf-8" Replace the two unimplemented K230 SD controller regions with K230 SDHCI devices. Map them at 0x91580000 and 0x91581000 and connect their interrupts to PLIC inputs 142 and 144 respectively. Create an SD card on each controller when a corresponding -drive if=3Dsd,index=3DN backend is provided. Update the K230 machine documentation to list the controllers as supported and remove the instructions that disabled the SDHCI device tree nodes before booting Linux. Signed-off-by: Xin Xie --- docs/system/riscv/k230.rst | 6 ++---- hw/riscv/Kconfig | 1 + hw/riscv/k230.c | 34 ++++++++++++++++++++++++++++++---- include/hw/riscv/k230.h | 4 ++++ 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/docs/system/riscv/k230.rst b/docs/system/riscv/k230.rst index cea8202e55..6e8286a0df 100644 --- a/docs/system/riscv/k230.rst +++ b/docs/system/riscv/k230.rst @@ -20,6 +20,7 @@ The ``k230`` machine supports the following devices: * Platform-Level Interrupt Controller (PLIC) * 2 K230 Watchdog Timer * 5 UART +* 2 SDHCI controllers =20 Boot options ------------ @@ -100,14 +101,11 @@ Press Enter to stop autoboot. At the U-Boot prompt, r= un these commands: K230# fdt resize 8192 K230# fdt set /chosen linux,initrd-start <0x0 0xa100000> K230# fdt set /chosen linux,initrd-end <0x0 ${INITRD_END}> - K230# fdt set /soc/sdhci0@91580000 status disabled - K230# fdt set /soc/sdhci1@91581000 status disabled K230# bootm 0xc100000 - 0xa000000 =20 Use ``setenv`` so ``bootm`` writes the kernel command line into ``/chosen/bootargs``. The ``fdt`` commands select the loaded DTB, add spac= e for -edits, describe the initrd range in ``/chosen``, and disable SDHCI nodes b= ecause -this machine does not emulate those controllers yet. Replace ``${INITRD_EN= D}`` +edits, and describe the initrd range in ``/chosen``. Replace ``${INITRD_EN= D}`` with the host-calculated value above when typing the command. ``cma=3D0`` = avoids the SDK kernel reserving too much of the little-core memory window for ini= tramfs boot. diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index de37c08cae..e4a0616c16 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -162,3 +162,4 @@ config K230 select SERIAL_MM select UNIMP select K230_WDT + select K230_SDHCI diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c index 656f28190c..7ea69084ae 100644 --- a/hw/riscv/k230.c +++ b/hw/riscv/k230.c @@ -110,6 +110,8 @@ static void k230_soc_init(Object *obj) object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY); object_initialize_child(obj, "k230-wdt0", &s->wdt[0], TYPE_K230_WDT); object_initialize_child(obj, "k230-wdt1", &s->wdt[1], TYPE_K230_WDT); + object_initialize_child(obj, "sdhci0", &s->sdhci[0], TYPE_K230_SDHCI); + object_initialize_child(obj, "sdhci1", &s->sdhci[1], TYPE_K230_SDHCI); =20 qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0); qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C9= 08); @@ -343,11 +345,21 @@ static void k230_soc_realize(DeviceState *dev, Error = **errp) create_unimplemented_device("usb1", memmap[K230_DEV_USB1].base, memmap[K230_DEV_USB1].size); =20 - create_unimplemented_device("sd0", memmap[K230_DEV_SD0].base, - memmap[K230_DEV_SD0].size); + for (int i =3D 0; i < 2; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci[i]), errp)) { + return; + } + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[0]), 0, + memmap[K230_DEV_SD0].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[0]), 0, + qdev_get_gpio_in(s->c908_plic, K230_SD0_IRQ)); =20 - create_unimplemented_device("sd1", memmap[K230_DEV_SD1].base, - memmap[K230_DEV_SD1].size); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[1]), 0, + memmap[K230_DEV_SD1].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[1]), 0, + qdev_get_gpio_in(s->c908_plic, K230_SD1_IRQ)); =20 create_unimplemented_device("qspi0", memmap[K230_DEV_QSPI0].base, memmap[K230_DEV_QSPI0].size); @@ -490,6 +502,20 @@ static void k230_machine_init(MachineState *machine) TYPE_RISCV_K230_SOC); qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); =20 + for (int i =3D 0; i < 2; i++) { + DriveInfo *dinfo =3D drive_get(IF_SD, 0, i); + DeviceState *card; + + if (!dinfo) { + continue; + } + + card =3D qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, s->soc.sdhci[i].bus, &error_fatal); + } + /* Data Memory */ memory_region_add_subregion(sys_mem, memmap[K230_DEV_DDRC].base, machine->ram); diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h index 592e1c26bf..8e73366e56 100644 --- a/include/hw/riscv/k230.h +++ b/include/hw/riscv/k230.h @@ -18,6 +18,7 @@ #include "hw/core/boards.h" #include "hw/riscv/riscv_hart.h" #include "hw/watchdog/k230_wdt.h" +#include "hw/sd/k230_sdhci.h" =20 #define C908_CPU_HARTID (0) =20 @@ -33,6 +34,7 @@ typedef struct K230SoCState { RISCVHartArrayState c908_cpu; /* Small core */ =20 K230WdtState wdt[2]; + K230SDHCIState sdhci[2]; MemoryRegion sram; MemoryRegion bootrom; =20 @@ -129,6 +131,8 @@ enum { K230_UART4_IRQ =3D 20, K230_WDT0_IRQ =3D 107, K230_WDT1_IRQ =3D 108, + K230_SD0_IRQ =3D 142, + K230_SD1_IRQ =3D 144, }; =20 #define K230_UART_COUNT 5 --=20 2.43.0 From nobody Mon Sep 28 02:00:08 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1785326135; cv=none; d=zohomail.com; s=zohoarc; b=QG2saxcJXf+Fwdht9LuVp6R00gww8jtlLG/FB77hfYQddiEnT00oM3q6tWTj/ET1K2QT3ITna6iLDbaVA6KdTkNf6MyQzjb69CpT8L2P8+AwWl+zetZdLuI9U5d84QLd5umLgmpLXEQd/qxh2vZvtxbNkK5Tcu4ZbeD82akZYgw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785326135; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=nCnQwREZ46dN0HG8gxHxD1hzR7ICebA42h1seeieyfA=; b=elEcdISmWsIwZ4EJe4xyQ2jt+N6OgNslGcfEN+9nVMpslZ6yEei8jj87ZacIcjpu/DqCaquhpf/7m1zf6RLQk6BANyZlFSlcJfyJwTKfXAc7jZ7wCYBNrIjlRqN1759P2vhYNpzduI1betXsxCbSdpUf3zIsOevjh0urpK5EPeQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785326135305135.57470456408043; Wed, 29 Jul 2026 04:55:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wp2rj-0006Aq-33; Wed, 29 Jul 2026 07:54:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wp20o-00019p-53 for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:47 -0400 Received: from mail-pj2-x0a.google.com ([2607:f8b0:4864:39::a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wp20j-0004Ed-S3 for qemu-devel@nongnu.org; Wed, 29 Jul 2026 06:59:43 -0400 Received: by mail-pj2-x0a.google.com with SMTP id d9443c01a7336-2cf5e516e67so4615125ad.1 for ; Wed, 29 Jul 2026 03:59:41 -0700 (PDT) Received: from LAPTOP-LOCIFOSI.localdomain ([123.127.39.254]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bfa240sm9627135ad.65.2026.07.29.03.59.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 03:59:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785322780; x=1785927580; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=nCnQwREZ46dN0HG8gxHxD1hzR7ICebA42h1seeieyfA=; b=qtH8/WtqL4PDwMlXHW3gc2bcpViR/g/0Gcwkzmunlwvo1QxRBQgNjrbZ6Y7tGCnkuv o0zNWGfYCs3GXzOoknY6Cag4pf/f3YGhQR/jlsnufT2gQfsCBfT/CCgdkqNcc1ByFzCX 3JwaZsAn8m/D+F02EEkgO7W/fQsK/kQl44QwycFo8te2AvxXmIcO4WrZIuS9WuKbuzlw vAokqduynREEcDk+ZhIN4BSEBlrqQILrfaLkKenb77dU7eLhPWuVh8NMI/94xn26/jk1 fBGt5jsbP3FFxbJDfqgZta4Bs9nAqryokJp71pdFPyBTbcDxFFl5jf52ZgoeHH9jduY8 8UnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785322780; x=1785927580; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=nCnQwREZ46dN0HG8gxHxD1hzR7ICebA42h1seeieyfA=; b=Cx9dzpxONW+kIPP3XAG96yrPpnKJ+SH85RVKNQVDwNR7gHz8y5b447670JoVvK9Vg3 gCQ2yR4j5v1XnU70pwaHQuDaEndi7haBFt2matyC5Jkpv5Fj4xezQyWk+k3s5B7jLVQi 6mM2z45eIV0bEMqzAFjgjZxLFVXWWKrid2t1W3848xdsEQ6zJSai++hcmi3mw/W/WWXz hQRcwJN+RgBKLNx43gQdf3Wn0dEOsdnL+aaq90o+Uk8kZfvVBa8zU7wY8/M5cv1/Hx3a SDzD9JsC0AnjKfWWc/k2p7mX61m8K+/ZRMDEBULyezWRL+/iZ3ou54xJJdE/s51ZWQxu fDLQ== X-Gm-Message-State: AOJu0Ywri+7KPQWTJBjo9AVxAfY+ix1WCosIpn7BdMuLsBw9FjjAR6yr BFkQOoGFngyM6N6Ij333Tia2JzmMkRRaIBjfdglcA2LXm/YI+1RK6NtqS08b47QWIxigow== X-Gm-Gg: AR+sD13yv8VkjNOYo3Q5o7Dks06uiXJ1ptUfzjR4jegto8rtKQQmDsYp+FI+LQe3w7K jYpzs41d/pvDFDloFUhi2YGZgUysBXKWQspVLnRQey2Ksm7ohkUyW7imgmD17G7LBim/YSZHqYn 3qa0wBR1XTTHKAXlWKCNP5tlj2skd3F/KffesS8qsAkjDOrzzJaKtuoku0D9hJmcWNwHIXsK3Ub k2ikqONHIGqfz0wmkX349hDq+Jm8RLkw70ECSsp/03cuwl0H2zBUHTml6bKtqxm2BRyBJdeI04l yiaq2l5tWiB8u22lLvJ5BLvti7oaJoQEeozhtNreH3fTOjoTnON9398EO7Ae5jGAUO4wQBe+RWf FOzruF+HzxvtG4GbQfvZ7SXUNT2B4YUbEPIeS0Dyf4o+YHpjSqHr0+VKBmcIvojsk5AlwzOVN+m oiC7QInUiu9ecR5U1VnLmAFe5NMGXmTUcfh/j7zI6quUFIQ9S0vmDRBlAU7tIWRvoF0hCptgjg9 y7B6p8/ZGOOcEmnKZ36 X-Received: by 2002:a17:902:ce05:b0:2ce:9c48:22d3 with SMTP id d9443c01a7336-2d015c3e0bbmr77503815ad.11.1785322780446; Wed, 29 Jul 2026 03:59:40 -0700 (PDT) From: Xin Xie To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, Chao Liu , Alistair Francis , Daniel Henrique Barboza , Fabiano Rosas , Laurent Vivier , Liu Zhiwei , Palmer Dabbelt , Paolo Bonzini , Pierrick Bouvier , Weiwei Li , Xin Xie Subject: [PATCH v1 3/3] tests/qtest: add K230 SDHCI tests Date: Wed, 29 Jul 2026 18:59:03 +0800 Message-ID: <20260729105904.272939-4-xinxie908@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260729105904.272939-1-xinxie908@gmail.com> References: <20260729105904.272939-1-xinxie908@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:39::a; envelope-from=xinxie908@gmail.com; helo=mail-pj2-x0a.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 29 Jul 2026 07:54:24 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1785326137394158500 Content-Type: text/plain; charset="utf-8" Add qtests covering the K230-specific SDHCI register layout, capability masking, preset values, extension pointers, PHY power status and per-controller vendor register storage. Verify card detection and interrupt delivery through the K230 PLIC. Exercise basic PIO reads and writes with an attached SD card image and check that written data reaches the backing file. Signed-off-by: Xin Xie Reviewed-by: Daniel Henrique Barboza --- MAINTAINERS | 1 + tests/qtest/k230-sdhci-test.c | 214 ++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 5 +- 3 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/k230-sdhci-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 06285352c4..99c4c3294b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1831,6 +1831,7 @@ F: include/hw/riscv/k230.h F: include/hw/watchdog/k230_wdt.h F: include/hw/sd/k230_sdhci.h F: tests/qtest/k230-wdt-test.c +F: tests/qtest/k230-sdhci-test.c =20 RX Machines ----------- diff --git a/tests/qtest/k230-sdhci-test.c b/tests/qtest/k230-sdhci-test.c new file mode 100644 index 0000000000..5eedb130c3 --- /dev/null +++ b/tests/qtest/k230-sdhci-test.c @@ -0,0 +1,214 @@ +/* + * QTest testcase for the Kendryte K230 SDHCI controllers + * + * Copyright (c) 2026 Xin Xie + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "libqtest.h" +#include "libqos/sdhci-cmd.h" +#include "hw/sd/k230_sdhci.h" +#include "hw/sd/sdhci-internal.h" + +#define K230_SD0_BASE 0x91580000 +#define K230_SD1_BASE 0x91581000 +#define K230_PLIC_PENDING 0xf00001000ULL +#define K230_SD1_IRQ 144 + +#define K230_SD_TEST_IMAGE_SIZE (2 * MiB) +#define K230_SD_TEST_BLOCK_SIZE 512 + +static void test_registers(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + uint64_t capabilities; + uint64_t expected =3D K230_SDHCI_CAPAREG_RESET; + + /* Only capabilities unsupported by the QEMU model are removed. */ + expected =3D FIELD_DP64(expected, SDHC_CAPAB, ASYNC_INT, 0); + expected =3D FIELD_DP64(expected, SDHC_CAPAB, TIMER_RETUNING, 0); + expected =3D FIELD_DP64(expected, SDHC_CAPAB, RETUNING_MODE, 0); + expected =3D FIELD_DP64(expected, SDHC_CAPAB, ADMA3, 0); + capabilities =3D qtest_readq(qts, K230_SD0_BASE + SDHC_CAPAB); + g_assert_cmphex(capabilities, =3D=3D, expected); + + /* Preset Value registers use the TRM reset values and are read-only. = */ + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_INIT) =3D= =3D + K230_SDHCI_PRESET_INIT_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + + K230_SDHCI_PRESET_DEFAULT_SPEED) =3D=3D + K230_SDHCI_PRESET_DEFAULT_SPEED_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + + K230_SDHCI_PRESET_HIGH_SPEED) =3D=3D + K230_SDHCI_PRESET_HIGH_SPEED_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR12) =3D= =3D + K230_SDHCI_PRESET_SDR12_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR25) =3D= =3D + K230_SDHCI_PRESET_SDR25_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR50) =3D= =3D + K230_SDHCI_PRESET_SDR50_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR104) = =3D=3D + K230_SDHCI_PRESET_SDR104_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_DDR50) =3D= =3D + K230_SDHCI_PRESET_DDR50_RESET); + + qtest_writew(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR50, 0xffff); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_PRESET_SDR50) =3D= =3D + K230_SDHCI_PRESET_SDR50_RESET); + + /* Extension-area pointers use their documented read-only reset values= . */ + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_UHS2_SETTINGS) = =3D=3D + K230_SDHCI_P_UHS2_SETTINGS_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_UHS2_HOST_CAPAB= ) =3D=3D + K230_SDHCI_P_UHS2_HOST_CAPAB_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_UHS2_TEST) =3D= =3D + K230_SDHCI_P_UHS2_TEST_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_EMBEDDED_CNTRL)= =3D=3D + K230_SDHCI_P_EMBEDDED_CNTRL_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_VENDOR_AREA1) = =3D=3D + K230_SDHCI_P_VENDOR_AREA1_RESET); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_VENDOR_AREA2) = =3D=3D + K230_SDHCI_P_VENDOR_AREA2_RESET); + + qtest_writew(qts, K230_SD0_BASE + K230_SDHCI_P_VENDOR_AREA1, 0xffff); + g_assert(qtest_readw(qts, K230_SD0_BASE + K230_SDHCI_P_VENDOR_AREA1) = =3D=3D + K230_SDHCI_P_VENDOR_AREA1_RESET); + + /* The virtual PHY is always ready and software cannot clear PWRGOOD. = */ + g_assert((qtest_readl(qts, K230_SD0_BASE + K230_SDHCI_PHY_CNFG) & + K230_SDHCI_PHY_CNFG_PWRGOOD) =3D=3D K230_SDHCI_PHY_CNFG_PWRG= OOD); + qtest_writel(qts, K230_SD0_BASE + K230_SDHCI_PHY_CNFG, 0); + g_assert(qtest_readl(qts, K230_SD0_BASE + K230_SDHCI_PHY_CNFG) =3D=3D + K230_SDHCI_PHY_CNFG_PWRGOOD); + + /* Vendor storage is writable and private to each controller instance.= */ + qtest_writel(qts, K230_SD0_BASE + K230_SDHCI_P_VENDOR_AREA1_RESET, + 0x89abcdef); + g_assert(qtest_readl(qts, K230_SD0_BASE + + K230_SDHCI_P_VENDOR_AREA1_RESET) =3D=3D + 0x89abcdef); + g_assert(qtest_readl(qts, K230_SD1_BASE + + K230_SDHCI_P_VENDOR_AREA1_RESET) =3D=3D 0); + + qtest_quit(qts); +} + +static void test_card_detect(void) +{ + g_autofree char *path =3D NULL; + int fd =3D g_file_open_tmp("k230-sd-XXXXXX.img", &path, NULL); + QTestState *qts; + + g_assert(fd >=3D 0); + g_assert(ftruncate(fd, K230_SD_TEST_IMAGE_SIZE) =3D=3D 0); + close(fd); + + qts =3D qtest_initf("-machine k230 " + "-drive if=3Dsd,index=3D1,format=3Draw,file=3D%s", p= ath); + + /* Card insertion becomes visible after the generic insertion delay. */ + qtest_clock_step(qts, NANOSECONDS_PER_SECOND); + g_assert((qtest_readl(qts, K230_SD1_BASE + SDHC_PRNSTS) & + SDHC_CARD_PRESENT) =3D=3D SDHC_CARD_PRESENT); + g_assert((qtest_readl(qts, K230_SD0_BASE + SDHC_PRNSTS) & + SDHC_CARD_PRESENT) =3D=3D 0); + + /* Route a command-complete event through SDHCI to the K230 PLIC. */ + qtest_writew(qts, K230_SD1_BASE + SDHC_NORINTSTSEN, + SDHC_NISEN_CMDCMP); + qtest_writew(qts, K230_SD1_BASE + SDHC_NORINTSIGEN, + SDHC_NISEN_CMDCMP); + g_assert((qtest_readw(qts, K230_SD1_BASE + SDHC_NORINTSTSEN) & + SDHC_NISEN_CMDCMP) !=3D 0); + g_assert((qtest_readw(qts, K230_SD1_BASE + SDHC_NORINTSIGEN) & + SDHC_NISEN_CMDCMP) !=3D 0); + qtest_writew(qts, K230_SD1_BASE + SDHC_CLKCON, + SDHC_CLOCK_INT_EN | SDHC_CLOCK_SDCLK_EN); + qtest_writew(qts, K230_SD1_BASE + SDHC_CMDREG, + SDHC_APP_CMD | SDHC_CMD_RESPONSE); + g_assert((qtest_readw(qts, K230_SD1_BASE + SDHC_NORINTSTS) & + SDHC_NIS_CMDCMP) !=3D 0); + g_assert((qtest_readl(qts, K230_PLIC_PENDING + + K230_SD1_IRQ / 32 * sizeof(uint32_t)) & + BIT(K230_SD1_IRQ % 32)) !=3D 0); + + qtest_quit(qts); + unlink(path); +} + +static void k230_sdhci_select_card(QTestState *qts) +{ + uint16_t rca; + + /* Reset the controller and enable its internal and SD clocks. */ + qtest_writeb(qts, K230_SD1_BASE + SDHC_SWRST, SDHC_RESET_ALL); + qtest_writew(qts, K230_SD1_BASE + SDHC_CLKCON, + SDHC_CLOCK_INT_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_SDCLK_EN); + + /* Run the SD identification sequence and select the assigned RCA. */ + sdhci_cmd_regs(qts, K230_SD1_BASE, 0, 0, 0, 0, SDHC_APP_CMD); + sdhci_cmd_regs(qts, K230_SD1_BASE, 0, 0, 0x41200000, 0, 41 << 8); + sdhci_cmd_regs(qts, K230_SD1_BASE, 0, 0, 0, 0, SDHC_ALL_SEND_CID); + sdhci_cmd_regs(qts, K230_SD1_BASE, 0, 0, 0, 0, + SDHC_SEND_RELATIVE_ADDR | SDHC_CMD_RESPONSE); + rca =3D qtest_readl(qts, K230_SD1_BASE + SDHC_RSPREG0) >> 16; + sdhci_cmd_regs(qts, K230_SD1_BASE, 0, 0, rca << 16, 0, + SDHC_SELECT_DESELECT_CARD); +} + +static void test_card_io(void) +{ + static const char read_data[] =3D "K230 SDHCI read"; + static const char write_data[] =3D "K230 SDHCI write"; + g_autofree char *path =3D NULL; + char buffer[K230_SD_TEST_BLOCK_SIZE]; + int fd =3D g_file_open_tmp("k230-sd-XXXXXX.img", &path, NULL); + QTestState *qts; + + /* Seed block zero so the controller read can be checked independently= . */ + g_assert(fd >=3D 0); + g_assert(ftruncate(fd, K230_SD_TEST_IMAGE_SIZE) =3D=3D 0); + g_assert(pwrite(fd, read_data, sizeof(read_data), 0) =3D=3D sizeof(rea= d_data)); + close(fd); + + qts =3D qtest_initf("-machine k230 " + "-drive if=3Dsd,index=3D1,format=3Draw,auto-read-onl= y=3Doff," + "file=3D%s", path); + k230_sdhci_select_card(qts); + + /* Read block zero through the SDHCI PIO data port. */ + memset(buffer, 0, sizeof(buffer)); + g_assert(sdhci_read_cmd(qts, K230_SD1_BASE, buffer, + sizeof(read_data)) =3D=3D sizeof(read_data)); + g_assert(memcmp(buffer, read_data, sizeof(read_data)) =3D=3D 0); + + /* Write through SDHCI, then verify the data reached the backing image= . */ + sdhci_write_cmd(qts, K230_SD1_BASE, write_data, sizeof(write_data), + K230_SD_TEST_BLOCK_SIZE); + qtest_quit(qts); + + fd =3D open(path, O_RDONLY); + g_assert(fd >=3D 0); + memset(buffer, 0, sizeof(buffer)); + g_assert(pread(fd, buffer, sizeof(write_data), 0) =3D=3D sizeof(write_= data)); + close(fd); + g_assert(memcmp(buffer, write_data, sizeof(write_data)) =3D=3D 0); + + unlink(path); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/k230-sdhci/registers", test_registers); + qtest_add_func("/k230-sdhci/card-detect", test_card_detect); + qtest_add_func("/k230-sdhci/card-io", test_card_io); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 56ff860e21..0600b1e807 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -297,7 +297,10 @@ qtests_riscv64 =3D ['riscv-csr-test'] + \ (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and config_all_devices.has_key('CONFIG_RISCV_IOMMU') ? ['iommu-riscv-test'] : []) + \ - (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test'] : []) + (config_all_devices.has_key('CONFIG_K230') ? [ + 'k230-wdt-test', + 'k230-sdhci-test', + ] : []) =20 qtests_hexagon =3D ['boot-serial-test'] =20 --=20 2.43.0