From nobody Sun Feb 8 00:26:18 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=1768885189; cv=none; d=zohomail.com; s=zohoarc; b=Y+g/KV1ivvq0bAjWcuTLT8NweigDVeNL5AGMcLnoNHVuGIfHG/Qm3uRdlswegiap/veO5CggkTeA8FGQA5VF6w3+TGsDHvBfJPOGBNS/5XN/daM3b9ibXEk+HhP4GJPUNj6Ys9vVR8eq4zqKXBAksoR/FKCt5DT4LyHBw67gs+M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768885189; 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=X5Gzpl9PAetQsWG3CaRP7rZC8ptvuBg78yLrcUDJ4Ck=; b=JFx11g3TfmRYU2aKBaJc4IwOuUJ7wMRxSimD6rDdlJlsWYxr0gmSKMYqyHA7mA/pNAIxsdNvuJDSdR1fuTzIz1cymo6BbQhN5t917Vvy75jFYAsSyQ1rEYuseiF3ssBszGkpCtEPWDlPxv84zGrE6CgRyVXhrUZVtjjfvZ7/zsg= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176888518932712.3516300574272; Mon, 19 Jan 2026 20:59:49 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vi3pP-0002RM-Gi; Mon, 19 Jan 2026 23:58:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vi3p9-0002Jm-8U for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:40 -0500 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vi3p6-0000Ar-AS for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:39 -0500 Received: by mail-pl1-x643.google.com with SMTP id d9443c01a7336-2a0d6f647e2so48420305ad.1 for ; Mon, 19 Jan 2026 20:58:35 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([183.195.21.180]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm110703045ad.38.2026.01.19.20.58.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 20:58:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768885115; x=1769489915; 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; bh=X5Gzpl9PAetQsWG3CaRP7rZC8ptvuBg78yLrcUDJ4Ck=; b=MlzCnBJVrOq0Vfz1RG2lR4VFdyzcO3B8erZfj0dW611EE5UgW/z5eoAXbu2e2QvZqv vZ1dq9oWqtYSB3QX9nfFWRi7uGPUP8z33Jygx1iF/bpUYCW86iV9+dlu7mZX2EPmyC+T OECDWWF81nnoA9v38IfMO+AZWGvQi61REW6+rLOFH7kD5tic4m8ewYpRldLjI59hFG9x jBzfFxZUCVCpwbmlP5Js2oLhXmWp6/qhf8RU2joaMh5cxvZE6sMscEhv7L8xPFwznc8w LAPFQYGeAbmm4vKYc+nLuvGjv29dEnsPGz1TpxIr9GQrc7r3bm2k4FwWxOM+cvDZphcK gufA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768885115; x=1769489915; 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; bh=X5Gzpl9PAetQsWG3CaRP7rZC8ptvuBg78yLrcUDJ4Ck=; b=U0GINz6z7SmS+3JLWsflKVlZX9J+UxJvziCyWc749nSpn3315IZPIfCkb7/1soJ4QQ nVdJTGCb+24zGF56W11Xr0loqAun7KMjXvp/w/Qz1tTvup0bEkdcVstt8mazs1Z9SiYJ /1EnckmNx5fnIeuPa66n9LKrm5jrOZm7fEAstOVlR4WSV5UKtpDCjslDu8ihFmlPPENl fZtmIxVGK2XW1e0lnVMMbenf7+Pinxi88HjqG96Xfff9NwefnWRFPNEaHapF4elxkFv+ YwjDh3itP7VoH2rnpuIkk8JsV0mYfeF7arRofdQdzom8vn8n+4aZEikm+9aV1huCEr++ f5rQ== X-Gm-Message-State: AOJu0YzgbOEQAWzQNhd8n1ssdYqqV0FUZe7UsuQVBaVCbRhAVaJA1bDu 0YFoFhRSPBRFNwTPWPDtK+Td6ejUJg87wqqm5MhZ/46OMe+gqn5TerJT X-Gm-Gg: AZuq6aKPrWX44pOVJiygzhaMHO+7qLclR6aAIkfCy3LdscXU0udybWmiNO6sSQZWeM6 kIqxSS83Jl4s3+rVPcXyiOmrAvbopKBigjtOMz/dRxpleJdu2vYXDKJIhzXZXdhD/8TjlD395ra REDbxamBDqBmaXG/yelkQ35s/UYFJ0tOn6K5oBRKLeFxi8AP1Iz5zoruMRS9W+Zu9YQzgNbEEtj V/3sgJkOcxIm2BPdUP46WMkh9Tpu9eqSTj2rKFxDwNG9MF1TyRxvO14xAxjmn1Ms7CwQAMOKD9s 0yUb3zHGlh1wzcZyoNIR85e+EP7YfZCeR5G7uIzLmVUaOYy8TSJpVlwYvVigIjYv1RDMWSDjqpn UJ4GhMDXQWG8zgOJ6go0ksiw6XRjSOW2/frTW5JLYe5JWZspHotCfIqcc0P0lNjFI5UJGlQ0ys5 +y8gd6QiVAPj04wEcoAscE/aHNw5iGvKfzSUsZaAQGFSa2Z2OqIeUKiAeVV50= X-Received: by 2002:a17:903:1b25:b0:295:9e4e:4092 with SMTP id d9443c01a7336-2a76b1696c2mr6497145ad.56.1768885114693; Mon, 19 Jan 2026 20:58:34 -0800 (PST) From: Chao Liu To: Alistair Francis , Daniel Henrique Barboza , Palmer Dabbelt , Weiwei Li , Liu Zhiwei Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, wangjingwei@iscas.ac.cn, Chao Liu , Chao Liu , Conor Dooley , Peng Jiang <3160104094@zju.edu.cn> Subject: [PATCH v4 1/5] target/riscv: add thead-c908 cpu support Date: Tue, 20 Jan 2026 12:56:51 +0800 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::643; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-pl1-x643.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-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: 1768885193460154100 Content-Type: text/plain; charset="utf-8" From: Chao Liu The C908 processor is based on the RV64GCB[V] instruction set, compatible to RVA22 Profile and implements the XIE (XuanTie Instruction Extension) technology. Signed-off-by: Chao Liu Suggested-by: LIU Zhiwei Reviewed-by: Daniel Henrique Barboza Reviewed-by: Conor Dooley Reported-by: Peng Jiang <3160104094@zju.edu.cn> --- target/riscv/cpu-qom.h | 2 + target/riscv/cpu.c | 51 ++++++ target/riscv/th_csr.c | 380 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 432 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 30dcdcfaae..1a28f1369c 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -52,6 +52,8 @@ #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") #define TYPE_RISCV_CPU_THEAD_C906 RISCV_CPU_TYPE_NAME("thead-c906") +#define TYPE_RISCV_CPU_THEAD_C908 RISCV_CPU_TYPE_NAME("thead-c908") +#define TYPE_RISCV_CPU_THEAD_C908V RISCV_CPU_TYPE_NAME("thead-c908v") #define TYPE_RISCV_CPU_VEYRON_V1 RISCV_CPU_TYPE_NAME("veyron-v1") #define TYPE_RISCV_CPU_TT_ASCALON RISCV_CPU_TYPE_NAME("tt-ascalon") #define TYPE_RISCV_CPU_XIANGSHAN_NANHU RISCV_CPU_TYPE_NAME("xiangshan-nan= hu") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e95eea0249..ed21570199 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3133,6 +3133,57 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { #endif ), =20 + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C908, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max =3D MXL_RV64, + .misa_ext =3D RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU, + .priv_spec =3D PRIV_VERSION_1_12_0, + + /* ISA extensions */ + .cfg.ext_xtheadba =3D true, + .cfg.ext_xtheadbb =3D true, + .cfg.ext_xtheadbs =3D true, + .cfg.ext_xtheadcmo =3D true, + .cfg.ext_xtheadcondmov =3D true, + .cfg.ext_xtheadfmv =3D true, + .cfg.ext_xtheadfmemidx =3D true, + .cfg.ext_xtheadmac =3D true, + .cfg.ext_xtheadmemidx =3D true, + .cfg.ext_xtheadmempair =3D true, + .cfg.ext_xtheadsync =3D true, + .cfg.ext_smepmp =3D true, + .cfg.ext_sscofpmf =3D true, + .cfg.ext_sstc =3D true, + .cfg.ext_svpbmt =3D true, + .cfg.ext_svinval =3D true, + .cfg.ext_svnapot =3D true, + .cfg.ext_zba =3D true, + .cfg.ext_zbb =3D true, + .cfg.ext_zbc =3D true, + .cfg.ext_zbs =3D true, + .cfg.ext_zkt =3D true, + .cfg.ext_zbkc =3D true, + .cfg.ext_zicsr =3D true, + .cfg.ext_zifencei =3D true, + .cfg.ext_zihintpause =3D true, + .cfg.ext_zicbom =3D true, + .cfg.ext_zicboz =3D true, + + .cfg.pmp =3D true, + .cfg.mmu =3D true, + .cfg.max_satp_mode =3D VM_1_10_SV48, + + .cfg.marchid =3D 0x8d143000, + .cfg.mvendorid =3D THEAD_VENDOR_ID, +#ifndef CONFIG_USER_ONLY + .custom_csrs =3D th_csr_list, +#endif + ), + + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C908V, TYPE_RISCV_CPU_THEAD_C908, + .misa_ext =3D RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU | RVV, + .vext_spec =3D VEXT_VERSION_1_00_0, + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_TT_ASCALON, TYPE_RISCV_VENDOR_CPU, .misa_mxl_max =3D MXL_RV64, .misa_ext =3D RVG | RVC | RVS | RVU | RVH | RVV, diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c index 49eb7bbab5..3b59939f05 100644 --- a/target/riscv/th_csr.c +++ b/target/riscv/th_csr.c @@ -2,6 +2,9 @@ * T-Head-specific CSRs. * * Copyright (c) 2024 VRULL GmbH + * Copyright (c) 2025 Chao Liu + * + * For more information, see XuanTie-C908-UserManual_xrvm_20240530.pdf * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,13 +23,88 @@ #include "cpu.h" #include "cpu_vendorid.h" =20 -#define CSR_TH_SXSTATUS 0x5c0 +/* Extended M-mode control registers of T-Head */ +#define CSR_TH_MXSTATUS 0x7c0 +#define CSR_TH_MHCR 0x7c1 +#define CSR_TH_MCOR 0x7c2 +#define CSR_TH_MCCR2 0x7c3 +#define CSR_TH_MHINT 0x7c5 +#define CSR_TH_MRVBR 0x7c7 +#define CSR_TH_MCOUNTERWEN 0x7c9 +#define CSR_TH_MCOUNTERINTEN 0x7ca +#define CSR_TH_MCOUNTEROF 0x7cb +#define CSR_TH_MCINS 0x7d2 +#define CSR_TH_MCINDEX 0x7d3 +#define CSR_TH_MCDATA0 0x7d4 +#define CSR_TH_MCDATA1 0x7d5 +#define CSR_TH_MSMPR 0x7f3 +#define CSR_TH_CPUID 0xfc0 +#define CSR_TH_MAPBADDR 0xfc1 + +/* TH_MXSTATUS bits */ +#define TH_MXSTATUS_UCME BIT(16) +#define TH_MXSTATUS_MAEE BIT(21) +#define TH_MXSTATUS_THEADISAEE BIT(22) + +/* Extended S-mode control registers of T-Head */ +#define CSR_TH_SXSTATUS 0x5c0 +#define CSR_TH_SHCR 0x5c1 +#define CSR_TH_SCER2 0x5c2 +#define CSR_TH_SCER 0x5c3 +#define CSR_TH_SCOUNTERINTEN 0x5c4 +#define CSR_TH_SCOUNTEROF 0x5c5 +#define CSR_TH_SCYCLE 0x5e0 +#define CSR_TH_SHPMCOUNTER3 0x5e3 +#define CSR_TH_SHPMCOUNTER4 0x5e4 +#define CSR_TH_SHPMCOUNTER5 0x5e5 +#define CSR_TH_SHPMCOUNTER6 0x5e6 +#define CSR_TH_SHPMCOUNTER7 0x5e7 +#define CSR_TH_SHPMCOUNTER8 0x5e8 +#define CSR_TH_SHPMCOUNTER9 0x5e9 +#define CSR_TH_SHPMCOUNTER10 0x5ea +#define CSR_TH_SHPMCOUNTER11 0x5eb +#define CSR_TH_SHPMCOUNTER12 0x5ec +#define CSR_TH_SHPMCOUNTER13 0x5ed +#define CSR_TH_SHPMCOUNTER14 0x5ee +#define CSR_TH_SHPMCOUNTER15 0x5ef +#define CSR_TH_SHPMCOUNTER16 0x5f0 +#define CSR_TH_SHPMCOUNTER17 0x5f1 +#define CSR_TH_SHPMCOUNTER18 0x5f2 +#define CSR_TH_SHPMCOUNTER19 0x5f3 +#define CSR_TH_SHPMCOUNTER20 0x5f4 +#define CSR_TH_SHPMCOUNTER21 0x5f5 +#define CSR_TH_SHPMCOUNTER22 0x5f6 +#define CSR_TH_SHPMCOUNTER23 0x5f7 +#define CSR_TH_SHPMCOUNTER24 0x5f8 +#define CSR_TH_SHPMCOUNTER25 0x5f9 +#define CSR_TH_SHPMCOUNTER26 0x5fa +#define CSR_TH_SHPMCOUNTER27 0x5fb +#define CSR_TH_SHPMCOUNTER28 0x5fc +#define CSR_TH_SHPMCOUNTER29 0x5fd +#define CSR_TH_SHPMCOUNTER30 0x5fe +#define CSR_TH_SHPMCOUNTER31 0x5ff +#define CSR_TH_SMIR 0x9c0 +#define CSR_TH_SMLO0 0x9c1 +#define CSR_TH_SMEH 0x9c2 +#define CSR_TH_SMCIR 0x9c3 + +/* Extended U-mode control registers of T-Head */ +#define CSR_TH_FXCR 0x800 =20 /* TH_SXSTATUS bits */ #define TH_SXSTATUS_UCME BIT(16) #define TH_SXSTATUS_MAEE BIT(21) #define TH_SXSTATUS_THEADISAEE BIT(22) =20 +static RISCVException mmode(CPURISCVState *env, int csrno) +{ + if (riscv_has_ext(env, RVM)) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} + static RISCVException smode(CPURISCVState *env, int csrno) { if (riscv_has_ext(env, RVS)) { @@ -36,11 +114,31 @@ static RISCVException smode(CPURISCVState *env, int cs= rno) return RISCV_EXCP_ILLEGAL_INST; } =20 +static RISCVException any(CPURISCVState *env, int csrno) +{ + return RISCV_EXCP_NONE; +} + static bool test_thead_mvendorid(RISCVCPU *cpu) { return cpu->cfg.mvendorid =3D=3D THEAD_VENDOR_ID; } =20 +static RISCVException read_th_mxstatus(CPURISCVState *env, int csrno, + target_ulong *val) +{ + /* We don't set MAEE here, because QEMU does not implement MAEE. */ + *val =3D TH_MXSTATUS_UCME | TH_MXSTATUS_THEADISAEE; + return RISCV_EXCP_NONE; +} + +static RISCVException read_unimp_th_csr(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D 0; + return RISCV_EXCP_NONE; +} + static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno, target_ulong *val) { @@ -50,10 +148,290 @@ static RISCVException read_th_sxstatus(CPURISCVState = *env, int csrno, } =20 const RISCVCSR th_csr_list[] =3D { + { + .csrno =3D CSR_TH_MXSTATUS, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mxstatus", mmode, read_th_mxstatus } + }, + { + .csrno =3D CSR_TH_MHCR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mhcr", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCOR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcor", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCCR2, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mccr2", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MHINT, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mhint", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MRVBR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mrvbr", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCOUNTERWEN, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcounterwen", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCOUNTERINTEN, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcounterinten", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCOUNTEROF, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcounterof", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCINS, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcins", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCINDEX, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcindex", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCDATA0, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcdata0", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MCDATA1, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mcdata1", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MSMPR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.msmpr", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_CPUID, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.cpuid", mmode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_MAPBADDR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.mapbaddr", mmode, read_unimp_th_csr } + }, { .csrno =3D CSR_TH_SXSTATUS, .insertion_test =3D test_thead_mvendorid, .csr_ops =3D { "th.sxstatus", smode, read_th_sxstatus } }, + { + .csrno =3D CSR_TH_SHCR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shcr", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SCER2, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.scer2", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SCER, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.scer", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SCOUNTERINTEN, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.scounterinten", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SCOUNTEROF, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.scounterof", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SCYCLE, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.scycle", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER3, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter3", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER4, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter4", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER5, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter5", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER6, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter6", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER7, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter7", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER8, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter8", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER9, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter9", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER10, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter10", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER11, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter11", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER12, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter12", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER13, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter13", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER14, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter14", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER15, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter15", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER16, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter16", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER17, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter17", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER18, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter18", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER19, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter19", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER20, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter20", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER21, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter21", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER22, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter22", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER23, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter23", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER24, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter24", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER25, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter25", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER26, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter26", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER27, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter27", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER28, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter28", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER29, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter29", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER30, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter30", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SHPMCOUNTER31, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.shpmcounter31", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SMIR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.smir", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SMLO0, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.smlo0", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SMEH, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.smeh", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_SMCIR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.smcir", smode, read_unimp_th_csr } + }, + { + .csrno =3D CSR_TH_FXCR, + .insertion_test =3D test_thead_mvendorid, + .csr_ops =3D { "th.fxcr", any, read_unimp_th_csr } + }, { } }; --=20 2.52.0 From nobody Sun Feb 8 00:26:18 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=1768885164; cv=none; d=zohomail.com; s=zohoarc; b=aNKF8pxCqvyFnIuavoiHXMB4snBx1Q6bCk8aA27wUDr5Xkc1b0SPOnjGmJ4Y/uQOVSV1QMg41AbApMxC+Pol3HgaCQ7z2RTyi9Rhq8l6NI1OD3spq/8gUKo6t7fgPx1d2/DUMAfbcMKjyK9m+K93+eYCnAgYJq1HzVXjOjCWV08= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768885164; 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=6jqHi4lzZwLH0ukgOcb+3Xk2B26rS4L/sbgqYHHALIE=; b=nT+FkiMcGP5sdpVnoKIdmfM8lOD3l2FzqpPlLBns54Hbzl7nOH2ZU0gtBtacFuyKnuY3jgztr0jJ5QCFhGCneXIXuiyEnxR1c2G0fRdIJ1MizqdHOluNR7Q8puQ8ktBPX4j+uzARnaVL16THq/e4l9Hz6pJ0P/mhldHvGMcK/So= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768885164536167.99471515686503; Mon, 19 Jan 2026 20:59:24 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vi3pS-0002UU-9R; Mon, 19 Jan 2026 23:58:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vi3pG-0002Mh-69 for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:47 -0500 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vi3pC-0000DP-Q8 for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:45 -0500 Received: by mail-pl1-x643.google.com with SMTP id d9443c01a7336-29f2676bb21so49804745ad.0 for ; Mon, 19 Jan 2026 20:58:42 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([183.195.21.180]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm110703045ad.38.2026.01.19.20.58.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 20:58:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768885121; x=1769489921; 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; bh=6jqHi4lzZwLH0ukgOcb+3Xk2B26rS4L/sbgqYHHALIE=; b=Xu0ULm3fRZYyjzEc10+Lw6NrQq9DHiWRGmO5XLTEQFH4oX3GJXg0/wjjIlte0o5ttH ijv3ylaDpZkxdEs8+56mDLme/ZUBv/SCLBriywqYKxKOF77Rdr6g68MHrP2mqdtM0HNU 9NitZt+VtylalSIPd2Mk58HqFhWncCI+MLyuLvwySxaW81meUEJs2uKBbrWqsTGaZv5c Zi+5X83vF2HbSFWHZUExxyC9xYSGv14Fnk3Aj6XH0E82nSO0WN+dOi/iThRnQMr8ksKK k3KOeMK857oNFtHgt3Wmqmk6sW63SOHAzuQx1z+I76kaSUNqNI9oIkQADYezsZmOxnVl aNAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768885121; x=1769489921; 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; bh=6jqHi4lzZwLH0ukgOcb+3Xk2B26rS4L/sbgqYHHALIE=; b=Mhrz0INHxvb1m+ZCsNAw7lEUDqtVYOFOJwFX5/Ff4p6F8R6nAa5xadzM1aDojT5jHC Zty4K3/LOQUkMKKNW6yEMGIOvYZzFGnzcP6gj88QgUVVKWfXNwLlZIDrwmLi1wHrKdKJ GzWA5h1LuxyOd1SWMiraLpVNC8czJp9cVDVMXN3ilnIqKI/wyKSw2CVBsKPM2DBKu6LN L2HCg+9x6CshR7J7o7Or8vce7Xhc4LArkIxzEZVpwAYf1VrFhLe8ymgMpNXCqCD/CUGV jVatrCj3OhgtB4hjZKAwBRT07eHRk9ljxBNZCs8lKjss1Hph7lyumXPurgAUSLbQsW+Z u3fA== X-Gm-Message-State: AOJu0YypQf7NlMI+kzuu8jdCU0Uqc8jpV5RnFsqxcaM9pfKZY41PkHIv WrTzw5qaZB2H4ddeMM7lI9sO2SfmhfeKS3vJ0W/8ptF3OiVAl5dM2Js8ruTLn0m/A0Yv6w== X-Gm-Gg: AZuq6aJLCTj1tinqt9pO5/iDJOteXSy2cgUijs7N9KFKZKJRNNTPKpTTRONps0d4Yui hJUJM92gaHUmY2680IZvhtG3Eues3MEzzdWQCgjRimUVTlwhS/DwiOdaZYTxUETD7Tov6921qXj JA/nars3Z5Eq9wZYdPhGyOdKN8ef+6zEEGBf9pFjhxPx0gydJsK4slqxk8JyyOtz7Pv65mTkaCN GQDzVhER/JJOQon43R4BGOYFxJwHft41ZBewbqFcPg4/1GjgEGBjayY0mk85bYZVkgHoa1KMYCZ mG2uxXZUvUQF06gpmChxCqUlI7rCEiN0forUEGdhvLk2Q/AEYqehOhdqyqslcl/+al2SVo52bzn x+dlzx1zsBZZ4gArKtAnXuCUGawy5JaqTy3zxh94//z0oYVc5wadsa9JX5s1LJnLpAyFru2Epvb Pgx2Y2tbELM0FQmpUSjb8nnzkSsKcTIanNCOlLvwmA1KOfsOWMyG3iNwKw3dk= X-Received: by 2002:a17:903:2ed0:b0:2a0:9081:8a6 with SMTP id d9443c01a7336-2a71887c864mr121184275ad.20.1768885121315; Mon, 19 Jan 2026 20:58:41 -0800 (PST) From: Chao Liu To: Alistair Francis , Daniel Henrique Barboza , Palmer Dabbelt , Weiwei Li , Liu Zhiwei Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, wangjingwei@iscas.ac.cn, Chao Liu , Chao Liu , Peng Jiang <3160104094@zju.edu.cn> Subject: [PATCH v4 2/5] hw/riscv: add k230 board initial support Date: Tue, 20 Jan 2026 12:56:52 +0800 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::643; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-pl1-x643.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-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: 1768885166928154100 Content-Type: text/plain; charset="utf-8" From: Chao Liu K230 Board Compatible with kendryte K230 SDK. Preliminarily supports the C908 small core, which can run the U-Boot and Linux kernel compiled by the K230 SDK. Signed-off-by: Chao Liu Reviewed-by: Daniel Henrique Barboza Reported-by: Peng Jiang <3160104094@zju.edu.cn> --- MAINTAINERS | 8 +- hw/riscv/Kconfig | 10 + hw/riscv/k230.c | 483 ++++++++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 2 +- include/hw/riscv/k230.h | 149 +++++++++++++ 5 files changed, 650 insertions(+), 2 deletions(-) create mode 100644 hw/riscv/k230.c create mode 100644 include/hw/riscv/k230.h diff --git a/MAINTAINERS b/MAINTAINERS index c1e586c58f..6c8391186d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1758,6 +1758,12 @@ F: docs/system/riscv/xiangshan-kunminghu.rst F: hw/riscv/xiangshan_kmh.c F: include/hw/riscv/xiangshan_kmh.h =20 +K230 Machines +M: Chao Liu +S: Maintained +F: hw/riscv/k230.c +F: include/hw/riscv/k230.h + RX Machines ----------- rx-gdbsim @@ -3576,7 +3582,7 @@ M: Alexander Bulekov R: Paolo Bonzini R: Stefan Hajnoczi R: Fabiano Rosas -R: Darren Kenny =20 +R: Darren Kenny R: Qiuhao Li S: Maintained F: tests/qtest/fuzz/ diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0222c93f87..b1a7357866 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -134,3 +134,13 @@ config MIPS_BOSTON_AIA default y select PCI_EXPRESS select PCI_EXPRESS_XILINX + +config K230 + bool + default y + depends on RISCV64 + select RISCV_ACLINT + select RISCV_APLIC + select RISCV_IMSIC + select SERIAL_MM + select UNIMP diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c new file mode 100644 index 0000000000..e1780e4f0b --- /dev/null +++ b/hw/riscv/k230.c @@ -0,0 +1,483 @@ +/* + * QEMU RISC-V Virt Board Compatible with Kendryte K230 SDK + * + * Copyright (c) 2025 Chao Liu + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Provides a board compatible with the Kendryte K230 SDK + * + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf + * + * For more information, see + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "cpu-qom.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "system/system.h" +#include "system/memory.h" +#include "target/riscv/cpu.h" +#include "chardev/char.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/riscv/k230.h" +#include "hw/riscv/boot.h" +#include "hw/intc/riscv_aclint.h" +#include "hw/intc/sifive_plic.h" +#include "hw/char/serial-mm.h" +#include "hw/misc/unimp.h" + +static const MemMapEntry memmap[] =3D { + [K230_DEV_DDRC] =3D { 0x00000000, 0x80000000 }, + [K230_DEV_KPU_L2_CACHE] =3D { 0x80000000, 0x00200000 }, + [K230_DEV_SRAM] =3D { 0x80200000, 0x00200000 }, + [K230_DEV_KPU_CFG] =3D { 0x80400000, 0x00000800 }, + [K230_DEV_FFT] =3D { 0x80400800, 0x00000400 }, + [K230_DEV_AI_2D_ENGINE] =3D { 0x80400C00, 0x00000800 }, + [K230_DEV_GSDMA] =3D { 0x80800000, 0x00004000 }, + [K230_DEV_DMA] =3D { 0x80804000, 0x00004000 }, + [K230_DEV_DECOMP_GZIP] =3D { 0x80808000, 0x00004000 }, + [K230_DEV_NON_AI_2D] =3D { 0x8080C000, 0x00004000 }, + [K230_DEV_ISP] =3D { 0x90000000, 0x00008000 }, + [K230_DEV_DEWARP] =3D { 0x90008000, 0x00001000 }, + [K230_DEV_RX_CSI] =3D { 0x90009000, 0x00002000 }, + [K230_DEV_H264] =3D { 0x90400000, 0x00010000 }, + [K230_DEV_2P5D] =3D { 0x90800000, 0x00040000 }, + [K230_DEV_VO] =3D { 0x90840000, 0x00010000 }, + [K230_DEV_VO_CFG] =3D { 0x90850000, 0x00001000 }, + [K230_DEV_3D_ENGINE] =3D { 0x90A00000, 0x00000800 }, + [K230_DEV_PMU] =3D { 0x91000000, 0x00000C00 }, + [K230_DEV_RTC] =3D { 0x91000C00, 0x00000400 }, + [K230_DEV_CMU] =3D { 0x91100000, 0x00001000 }, + [K230_DEV_RMU] =3D { 0x91101000, 0x00001000 }, + [K230_DEV_BOOT] =3D { 0x91102000, 0x00001000 }, + [K230_DEV_PWR] =3D { 0x91103000, 0x00001000 }, + [K230_DEV_MAILBOX] =3D { 0x91104000, 0x00001000 }, + [K230_DEV_IOMUX] =3D { 0x91105000, 0x00000800 }, + [K230_DEV_TIMER] =3D { 0x91105800, 0x00000800 }, + [K230_DEV_WDT0] =3D { 0x91106000, 0x00000800 }, + [K230_DEV_WDT1] =3D { 0x91106800, 0x00000800 }, + [K230_DEV_TS] =3D { 0x91107000, 0x00000800 }, + [K230_DEV_HDI] =3D { 0x91107800, 0x00000800 }, + [K230_DEV_STC] =3D { 0x91108000, 0x00000800 }, + [K230_DEV_BOOTROM] =3D { 0x91200000, 0x00010000 }, + [K230_DEV_SECURITY] =3D { 0x91210000, 0x00008000 }, + [K230_DEV_UART0] =3D { 0x91400000, 0x00001000 }, + [K230_DEV_UART1] =3D { 0x91401000, 0x00001000 }, + [K230_DEV_UART2] =3D { 0x91402000, 0x00001000 }, + [K230_DEV_UART3] =3D { 0x91403000, 0x00001000 }, + [K230_DEV_UART4] =3D { 0x91404000, 0x00001000 }, + [K230_DEV_I2C0] =3D { 0x91405000, 0x00001000 }, + [K230_DEV_I2C1] =3D { 0x91406000, 0x00001000 }, + [K230_DEV_I2C2] =3D { 0x91407000, 0x00001000 }, + [K230_DEV_I2C3] =3D { 0x91408000, 0x00001000 }, + [K230_DEV_I2C4] =3D { 0x91409000, 0x00001000 }, + [K230_DEV_PWM] =3D { 0x9140A000, 0x00001000 }, + [K230_DEV_GPIO0] =3D { 0x9140B000, 0x00001000 }, + [K230_DEV_GPIO1] =3D { 0x9140C000, 0x00001000 }, + [K230_DEV_ADC] =3D { 0x9140D000, 0x00001000 }, + [K230_DEV_CODEC] =3D { 0x9140E000, 0x00001000 }, + [K230_DEV_I2S] =3D { 0x9140F000, 0x00001000 }, + [K230_DEV_USB0] =3D { 0x91500000, 0x00010000 }, + [K230_DEV_USB1] =3D { 0x91540000, 0x00010000 }, + [K230_DEV_SD0] =3D { 0x91580000, 0x00001000 }, + [K230_DEV_SD1] =3D { 0x91581000, 0x00001000 }, + [K230_DEV_QSPI0] =3D { 0x91582000, 0x00001000 }, + [K230_DEV_QSPI1] =3D { 0x91583000, 0x00001000 }, + [K230_DEV_SPI] =3D { 0x91584000, 0x00001000 }, + [K230_DEV_HI_SYS_CFG] =3D { 0x91585000, 0x00000400 }, + [K230_DEV_DDRC_CFG] =3D { 0x98000000, 0x02000000 }, + [K230_DEV_FLASH] =3D { 0xC0000000, 0x08000000 }, + [K230_DEV_PLIC] =3D { 0xF00000000, 0x00400000 }, + [K230_DEV_CLINT] =3D { 0xF04000000, 0x00400000 }, +}; + +static void k230_soc_init(Object *obj) +{ + K230SoCState *s =3D RISCV_K230_SOC(obj); + RISCVHartArrayState *cpu0 =3D &s->c908_cpu; + + object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY); + qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0); + qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C9= 08); + qdev_prop_set_uint64(DEVICE(cpu0), "resetvec", + memmap[K230_DEV_BOOTROM].base); +} + +static DeviceState *k230_create_plic(int base_hartid, int hartid_count) +{ + g_autofree char *plic_hart_config =3D NULL; + + /* Per-socket PLIC hart topology configuration string */ + plic_hart_config =3D riscv_plic_hart_config_string(hartid_count); + + /* Per-socket PLIC */ + return sifive_plic_create(memmap[K230_DEV_PLIC].base, + plic_hart_config, hartid_count, base_hartid, + K230_PLIC_NUM_SOURCES, + K230_PLIC_NUM_PRIORITIES, + K230_PLIC_PRIORITY_BASE, K230_PLIC_PENDING_B= ASE, + K230_PLIC_ENABLE_BASE, K230_PLIC_ENABLE_STRI= DE, + K230_PLIC_CONTEXT_BASE, + K230_PLIC_CONTEXT_STRIDE, + memmap[K230_DEV_PLIC].size); +} + +static void k230_soc_realize(DeviceState *dev, Error **errp) +{ + K230SoCState *s =3D RISCV_K230_SOC(dev); + MemoryRegion *sys_mem =3D get_system_memory(); + int c908_cpus; + + sysbus_realize(SYS_BUS_DEVICE(&s->c908_cpu), &error_fatal); + + c908_cpus =3D s->c908_cpu.num_harts; + + /* SRAM */ + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", + memmap[K230_DEV_SRAM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[K230_DEV_SRAM].base, + &s->sram); + + /* BootROM */ + memory_region_init_rom(&s->bootrom, OBJECT(dev), "bootrom", + memmap[K230_DEV_BOOTROM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[K230_DEV_BOOTROM].base, + &s->bootrom); + + /* PLIC */ + s->c908_plic =3D k230_create_plic(C908_CPU_HARTID, c908_cpus); + + /* CLINT */ + riscv_aclint_swi_create(memmap[K230_DEV_CLINT].base, + C908_CPU_HARTID, c908_cpus, false); + riscv_aclint_mtimer_create(memmap[K230_DEV_CLINT].base + 0x4000, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, + C908_CPU_HARTID, c908_cpus, + RISCV_ACLINT_DEFAULT_MTIMECMP, + RISCV_ACLINT_DEFAULT_MTIME, + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + + /* UART */ + serial_mm_init(sys_mem, memmap[K230_DEV_UART0].base, 2, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART0_IRQ), + 399193, serial_hd(0), DEVICE_LITTLE_ENDIAN); + serial_mm_init(sys_mem, memmap[K230_DEV_UART1].base, 2, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART1_IRQ), + 399193, serial_hd(1), DEVICE_LITTLE_ENDIAN); + serial_mm_init(sys_mem, memmap[K230_DEV_UART2].base, 2, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART2_IRQ), + 399193, serial_hd(2), DEVICE_LITTLE_ENDIAN); + serial_mm_init(sys_mem, memmap[K230_DEV_UART3].base, 2, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART3_IRQ), + 399193, serial_hd(3), DEVICE_LITTLE_ENDIAN); + serial_mm_init(sys_mem, memmap[K230_DEV_UART4].base, 2, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART4_IRQ), + 399193, serial_hd(4), DEVICE_LITTLE_ENDIAN); + + /* unimplemented devices */ + create_unimplemented_device("kpu.l2-cache", + memmap[K230_DEV_KPU_L2_CACHE].base, + memmap[K230_DEV_KPU_L2_CACHE].size); + + create_unimplemented_device("kpu_cfg", memmap[K230_DEV_KPU_CFG].base, + memmap[K230_DEV_KPU_CFG].size); + + create_unimplemented_device("fft", memmap[K230_DEV_FFT].base, + memmap[K230_DEV_FFT].size); + + create_unimplemented_device("2d-engine.ai", + memmap[K230_DEV_AI_2D_ENGINE].base, + memmap[K230_DEV_AI_2D_ENGINE].size); + + create_unimplemented_device("gsdma", memmap[K230_DEV_GSDMA].base, + memmap[K230_DEV_GSDMA].size); + + create_unimplemented_device("dma", memmap[K230_DEV_DMA].base, + memmap[K230_DEV_DMA].size); + + create_unimplemented_device("decomp-gzip", + memmap[K230_DEV_DECOMP_GZIP].base, + memmap[K230_DEV_DECOMP_GZIP].size); + + create_unimplemented_device("2d-engine.non-ai", + memmap[K230_DEV_NON_AI_2D].base, + memmap[K230_DEV_NON_AI_2D].size); + + create_unimplemented_device("isp", memmap[K230_DEV_ISP].base, + memmap[K230_DEV_ISP].size); + + create_unimplemented_device("dewarp", memmap[K230_DEV_DEWARP].base, + memmap[K230_DEV_DEWARP].size); + + create_unimplemented_device("rx-csi", memmap[K230_DEV_RX_CSI].base, + memmap[K230_DEV_RX_CSI].size); + + create_unimplemented_device("vpu", memmap[K230_DEV_H264].base, + memmap[K230_DEV_H264].size); + + create_unimplemented_device("gpu", memmap[K230_DEV_2P5D].base, + memmap[K230_DEV_2P5D].size); + + create_unimplemented_device("vo", memmap[K230_DEV_VO].base, + memmap[K230_DEV_VO].size); + + create_unimplemented_device("vo_cfg", memmap[K230_DEV_VO_CFG].base, + memmap[K230_DEV_VO_CFG].size); + + create_unimplemented_device("3d-engine", memmap[K230_DEV_3D_ENGINE].ba= se, + memmap[K230_DEV_3D_ENGINE].size); + + create_unimplemented_device("pmu", memmap[K230_DEV_PMU].base, + memmap[K230_DEV_PMU].size); + + create_unimplemented_device("rtc", memmap[K230_DEV_RTC].base, + memmap[K230_DEV_RTC].size); + + create_unimplemented_device("cmu", memmap[K230_DEV_CMU].base, + memmap[K230_DEV_CMU].size); + + create_unimplemented_device("rmu", memmap[K230_DEV_RMU].base, + memmap[K230_DEV_RMU].size); + + create_unimplemented_device("boot", memmap[K230_DEV_BOOT].base, + memmap[K230_DEV_BOOT].size); + + create_unimplemented_device("pwr", memmap[K230_DEV_PWR].base, + memmap[K230_DEV_PWR].size); + + create_unimplemented_device("ipcm", memmap[K230_DEV_MAILBOX].base, + memmap[K230_DEV_MAILBOX].size); + + create_unimplemented_device("iomux", memmap[K230_DEV_IOMUX].base, + memmap[K230_DEV_IOMUX].size); + + create_unimplemented_device("timer", memmap[K230_DEV_TIMER].base, + memmap[K230_DEV_TIMER].size); + + create_unimplemented_device("wdt0", memmap[K230_DEV_WDT0].base, + memmap[K230_DEV_WDT0].size); + + create_unimplemented_device("wdt1", memmap[K230_DEV_WDT1].base, + memmap[K230_DEV_WDT1].size); + + create_unimplemented_device("ts", memmap[K230_DEV_TS].base, + memmap[K230_DEV_TS].size); + + create_unimplemented_device("hdi", memmap[K230_DEV_HDI].base, + memmap[K230_DEV_HDI].size); + + create_unimplemented_device("stc", memmap[K230_DEV_STC].base, + memmap[K230_DEV_STC].size); + + create_unimplemented_device("security", memmap[K230_DEV_SECURITY].base, + memmap[K230_DEV_SECURITY].size); + + create_unimplemented_device("i2c0", memmap[K230_DEV_I2C0].base, + memmap[K230_DEV_I2C0].size); + + create_unimplemented_device("i2c1", memmap[K230_DEV_I2C1].base, + memmap[K230_DEV_I2C1].size); + + create_unimplemented_device("i2c2", memmap[K230_DEV_I2C2].base, + memmap[K230_DEV_I2C2].size); + + create_unimplemented_device("i2c3", memmap[K230_DEV_I2C3].base, + memmap[K230_DEV_I2C3].size); + + create_unimplemented_device("i2c4", memmap[K230_DEV_I2C4].base, + memmap[K230_DEV_I2C4].size); + + create_unimplemented_device("pwm", memmap[K230_DEV_PWM].base, + memmap[K230_DEV_PWM].size); + + create_unimplemented_device("gpio0", memmap[K230_DEV_GPIO0].base, + memmap[K230_DEV_GPIO0].size); + + create_unimplemented_device("gpio1", memmap[K230_DEV_GPIO1].base, + memmap[K230_DEV_GPIO1].size); + + create_unimplemented_device("adc", memmap[K230_DEV_ADC].base, + memmap[K230_DEV_ADC].size); + + create_unimplemented_device("codec", memmap[K230_DEV_CODEC].base, + memmap[K230_DEV_CODEC].size); + + create_unimplemented_device("i2s", memmap[K230_DEV_I2S].base, + memmap[K230_DEV_I2S].size); + + create_unimplemented_device("usb0", memmap[K230_DEV_USB0].base, + memmap[K230_DEV_USB0].size); + + create_unimplemented_device("usb1", memmap[K230_DEV_USB1].base, + memmap[K230_DEV_USB1].size); + + create_unimplemented_device("sd0", memmap[K230_DEV_SD0].base, + memmap[K230_DEV_SD0].size); + + create_unimplemented_device("sd1", memmap[K230_DEV_SD1].base, + memmap[K230_DEV_SD1].size); + + create_unimplemented_device("qspi0", memmap[K230_DEV_QSPI0].base, + memmap[K230_DEV_QSPI0].size); + + create_unimplemented_device("qspi1", memmap[K230_DEV_QSPI1].base, + memmap[K230_DEV_QSPI1].size); + + create_unimplemented_device("spi", memmap[K230_DEV_SPI].base, + memmap[K230_DEV_SPI].size); + + create_unimplemented_device("hi_sys_cfg", memmap[K230_DEV_HI_SYS_CFG].= base, + memmap[K230_DEV_HI_SYS_CFG].size); + + create_unimplemented_device("ddrc_cfg", memmap[K230_DEV_DDRC_CFG].base, + memmap[K230_DEV_DDRC_CFG].size); + + create_unimplemented_device("flash", memmap[K230_DEV_FLASH].base, + memmap[K230_DEV_FLASH].size); +} + +static void k230_soc_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D k230_soc_realize; +} + +static const TypeInfo k230_soc_type_info =3D { + .name =3D TYPE_RISCV_K230_SOC, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(K230SoCState), + .instance_init =3D k230_soc_init, + .class_init =3D k230_soc_class_init, +}; + +static void k230_soc_register_types(void) +{ + type_register_static(&k230_soc_type_info); +} + +type_init(k230_soc_register_types) + +static void k230_machine_done(Notifier *notifier, void *data) +{ + K230MachineState *s =3D container_of(notifier, K230MachineState, + machine_done); + MachineState *machine =3D MACHINE(s); + hwaddr start_addr =3D memmap[K230_DEV_DDRC].base; + target_ulong firmware_end_addr, kernel_start_addr; + const char *firmware_name =3D riscv_default_firmware_name(&s->soc.c908= _cpu); + uint64_t kernel_entry =3D 0; + RISCVBootInfo boot_info; + + firmware_end_addr =3D riscv_find_and_load_firmware(machine, firmware_n= ame, + &start_addr, NULL); + + /* Mask ROM reset vector */ + uint32_t reset_vec[] =3D { + /* 0x91200000: auipc t0, 0x0 */ 0x00000297, + /* 0x91200004: addi t0, t0, 36 # */ 0x02428293, + /* 0x91200008: csrw mtvec, t0 */ 0x30529073, + /* 0x9120000C: csrr a0, misa */ 0x301012F3, + /* 0x91200010: lui t0, 0x1 */ 0x000012B7, + /* 0x91200014: slli t0, t0, 1 */ 0x00129293, + /* 0x91200018: and t0, a0, t0 */ 0x005572B3, + /* 0x9120001C: bnez t0, loop */ 0x00511063, + /* entry: */ + /* 0x91200020: addiw t0, zero, 1 */ 0x0010029b, + /* 0x91200024: slli t0, t0, 0x1b */ 0x01b29293, + /* 0x91200028: jr t0 # uboot 0x8000000 */ 0x00028067, + /* loop: */ + /* 0x9120002C: j 0x9120002C # */ 0x0000006f, + /* trap: */ + /* 0x91200030: j 0x91200030 # */ 0x0000006f, + }; + + /* copy in the reset vector in little_endian byte order */ + for (int i =3D 0; i < sizeof(reset_vec) >> 2; i++) { + reset_vec[i] =3D cpu_to_le32(reset_vec[i]); + } + rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), + memmap[K230_DEV_BOOTROM].base, &address_space_me= mory); + + riscv_boot_info_init(&boot_info, &s->soc.c908_cpu); + + if (machine->kernel_filename && !kernel_entry) { + kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, + firmware_end_addr= ); + riscv_load_kernel(machine, &boot_info, kernel_start_addr, + true, NULL); + kernel_entry =3D boot_info.image_low_addr; + } +} + +static void k230_machine_init(MachineState *machine) +{ + MachineClass *mc =3D MACHINE_GET_CLASS(machine); + + K230MachineState *s =3D RISCV_K230_MACHINE(machine); + MemoryRegion *sys_mem =3D get_system_memory(); + + if (machine->ram_size < mc->default_ram_size) { + char *sz =3D size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be %s", sz); + g_free(sz); + exit(EXIT_FAILURE); + } + + /* Initialize SoC */ + object_initialize_child(OBJECT(machine), "soc", &s->soc, + TYPE_RISCV_K230_SOC); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); + + /* Data Memory */ + memory_region_add_subregion(sys_mem, memmap[K230_DEV_DDRC].base, + machine->ram); + + s->machine_done.notify =3D k230_machine_done; + qemu_add_machine_init_done_notifier(&s->machine_done); +} + +static void k230_machine_instance_init(Object *obj) +{ +} + +static void k230_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "RISC-V Board compatible with Kendryte K230 SDK"; + mc->init =3D k230_machine_init; + mc->default_cpus =3D 2; + mc->default_ram_id =3D "riscv.K230.ram"; /* DDR */ + mc->default_ram_size =3D memmap[K230_DEV_DDRC].size; +} + +static const TypeInfo k230_machine_typeinfo =3D { + .name =3D TYPE_RISCV_K230_MACHINE, + .parent =3D TYPE_MACHINE, + .class_init =3D k230_machine_class_init, + .instance_init =3D k230_machine_instance_init, + .instance_size =3D sizeof(K230MachineState), +}; + +static void k230_machine_init_register_types(void) +{ + type_register_static(&k230_machine_typeinfo); +} + +type_init(k230_machine_init_register_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 533472e22a..09cf855984 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -14,8 +14,8 @@ riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files( 'riscv-iommu.c', 'riscv-iommu-pci.c', 'riscv-iommu-sys.c', 'riscv-iommu-h= pm.c')) riscv_ss.add(when: 'CONFIG_MICROBLAZE_V', if_true: files('microblaze-v-gen= eric.c')) riscv_ss.add(when: 'CONFIG_XIANGSHAN_KUNMINGHU', if_true: files('xiangshan= _kmh.c')) - riscv_ss.add(when: 'CONFIG_RISCV_MIPS_CPS', if_true: files('cps.c')) riscv_ss.add(when: 'CONFIG_MIPS_BOSTON_AIA', if_true: files('boston-aia.c'= )) +riscv_ss.add(when: 'CONFIG_K230', if_true: files('k230.c')) =20 hw_arch +=3D {'riscv': riscv_ss} diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h new file mode 100644 index 0000000000..3158381e8f --- /dev/null +++ b/include/hw/riscv/k230.h @@ -0,0 +1,149 @@ +/* + * QEMU RISC-V Virt Board Compatible with kendryte K230 SDK + * + * Copyright (c) 2025 Chao Liu + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Provides a board compatible with the kendryte K230 SDK + * + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf + * + * For more information, see + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ +#ifndef HW_K230_H +#define HW_K230_H + +#include "hw/boards.h" +#include "hw/riscv/riscv_hart.h" + +#define C908_CPU_HARTID (0) + +#define TYPE_RISCV_K230_SOC "riscv.k230.soc" +#define RISCV_K230_SOC(obj) \ + OBJECT_CHECK(K230SoCState, (obj), TYPE_RISCV_K230_SOC) + +typedef struct K230SoCState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + RISCVHartArrayState c908_cpu; /* Small core */ + + MemoryRegion sram; + MemoryRegion bootrom; + + DeviceState *c908_plic; +} K230SoCState; + +#define TYPE_RISCV_K230_MACHINE MACHINE_TYPE_NAME("k230") +#define RISCV_K230_MACHINE(obj) \ + OBJECT_CHECK(K230MachineState, (obj), TYPE_RISCV_K230_MACHINE) + +typedef struct K230MachineState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + K230SoCState soc; + Notifier machine_done; +} K230MachineState; + +enum { + K230_DEV_DDRC, + K230_DEV_KPU_L2_CACHE, + K230_DEV_SRAM, + K230_DEV_KPU_CFG, + K230_DEV_FFT, + K230_DEV_AI_2D_ENGINE, + K230_DEV_GSDMA, + K230_DEV_DMA, + K230_DEV_DECOMP_GZIP, + K230_DEV_NON_AI_2D, + K230_DEV_ISP, + K230_DEV_DEWARP, + K230_DEV_RX_CSI, + K230_DEV_H264, + K230_DEV_2P5D, + K230_DEV_VO, + K230_DEV_VO_CFG, + K230_DEV_3D_ENGINE, + K230_DEV_PMU, + K230_DEV_RTC, + K230_DEV_CMU, + K230_DEV_RMU, + K230_DEV_BOOT, + K230_DEV_PWR, + K230_DEV_MAILBOX, + K230_DEV_IOMUX, + K230_DEV_TIMER, + K230_DEV_WDT0, + K230_DEV_WDT1, + K230_DEV_TS, + K230_DEV_HDI, + K230_DEV_STC, + K230_DEV_BOOTROM, + K230_DEV_SECURITY, + K230_DEV_UART0, + K230_DEV_UART1, + K230_DEV_UART2, + K230_DEV_UART3, + K230_DEV_UART4, + K230_DEV_I2C0, + K230_DEV_I2C1, + K230_DEV_I2C2, + K230_DEV_I2C3, + K230_DEV_I2C4, + K230_DEV_PWM, + K230_DEV_GPIO0, + K230_DEV_GPIO1, + K230_DEV_ADC, + K230_DEV_CODEC, + K230_DEV_I2S, + K230_DEV_USB0, + K230_DEV_USB1, + K230_DEV_SD0, + K230_DEV_SD1, + K230_DEV_QSPI0, + K230_DEV_QSPI1, + K230_DEV_SPI, + K230_DEV_HI_SYS_CFG, + K230_DEV_DDRC_CFG, + K230_DEV_FLASH, + K230_DEV_PLIC, + K230_DEV_CLINT, +}; + +enum { + K230_UART0_IRQ =3D 16, + K230_UART1_IRQ =3D 17, + K230_UART2_IRQ =3D 18, + K230_UART3_IRQ =3D 19, + K230_UART4_IRQ =3D 20, +}; + +/* + * Integrates with the interrupt controller (PLIC), + * which can process 208 interrupt external sources + */ +#define K230_PLIC_NUM_SOURCES 208 +#define K230_PLIC_NUM_PRIORITIES 7 +#define K230_PLIC_PRIORITY_BASE 0x00 +#define K230_PLIC_PENDING_BASE 0x1000 +#define K230_PLIC_ENABLE_BASE 0x2000 +#define K230_PLIC_ENABLE_STRIDE 0x80 +#define K230_PLIC_CONTEXT_BASE 0x200000 +#define K230_PLIC_CONTEXT_STRIDE 0x1000 + +#endif --=20 2.52.0 From nobody Sun Feb 8 00:26:18 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=1768885230; cv=none; d=zohomail.com; s=zohoarc; b=ZL2QnHZ9TZOge9U5pJqYRs7ARA0ZwT3IcLocQ8h4PFy7tJuJUOVlnTf8dvtCki01fzwcH4BErg/gvH4IUh4hH+4SQuuklPlo1eunderfGOvmoyJrnHIPpm1+i2YQ7oj/POVCd5q90OQcM7RsZqpWov7InkLU7uf4g7XE3njQz1E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768885230; 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=Os00p2/mdwB+iqetTp5LfIuJaWdSjIgYcH4zv0vHSc0=; b=FCts2RiFHknXDj23DnH4AP/ulT0sVSjcSoes370ghlko5FaKldptIk8zlq8x4DD2RPh1AyLUG9HL1oS8YgKio6GJq3+N0MnOZqpBLPRAnrbM4UH0DMJ9Zv2suBKaIY1367yeZMw1k9Dl7eIgrLVzHrolfs0U9NKtY9wLjbj2Wgs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768885230347773.8896510824976; Mon, 19 Jan 2026 21:00:30 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vi3pV-0002aN-UH; Mon, 19 Jan 2026 23:59:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vi3pM-0002PY-W9 for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:53 -0500 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vi3pJ-0000EI-Dg for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:51 -0500 Received: by mail-pf1-x444.google.com with SMTP id d2e1a72fcca58-81f4ba336b4so4505111b3a.1 for ; Mon, 19 Jan 2026 20:58:49 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([183.195.21.180]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm110703045ad.38.2026.01.19.20.58.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 20:58:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768885128; x=1769489928; 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; bh=Os00p2/mdwB+iqetTp5LfIuJaWdSjIgYcH4zv0vHSc0=; b=OhMvQ//RqRS6s7SLHY+MsdlgAXihgSL93X9ek+yrHtSEo/iedb9taXVjxdXONPrWTe 3hSdhpjA1QWjX+2e+yX4/t2HiwEAhpf65fKmidnD6/KXlCBKod0X7SmOQ/zAwfkpMCoc Vx1+AAYBxVAUC84/5S7XI4qOH3Dxp3DlNLIMqe1g4GBbrv7lNOl2H/heP29kL8MDSQWf VpHXGfBHIxJw95FH2IdSzf4VwHv210F72YbpB15L2p2oBuO5D/FmoqtbDP5tz70L/aDv VY9MvjNjVIegX34bdewkU1VLDg3ejTfL0o3Re+HRKeIXpCctzK58MYMrfmUjy/7faGTP AQZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768885128; x=1769489928; 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; bh=Os00p2/mdwB+iqetTp5LfIuJaWdSjIgYcH4zv0vHSc0=; b=tuUfcraCw82XYTeHNx+m2NmjX5WyNr70V+2PeIq7CFwP9Ufu57ar8dJj/i8vvFyZUL GI1DFFrPOxpoQD9AgZlTIQ/ktCWVKLBXEgtQUqpRdV8QOnszUTkx6kVMeQlhDquA2fcx IVt7hQnP/rg862XJpUrbYZTjQJQRH4ydDBmL/kmCWz7Ntq/6YCwOvMRvXo/YIWic5+R3 EA/129XqBLyYwAurkXwNxaGpNrzmoyezZEfPnBlAV2ecIU9dqH7EmKp75JQ61LqsmZr/ WErRHoFydX7yWRBYqpB3beOhLM9b20/wE0rgJzSh+WwQ3v1QKj9nse7s/rWtf88Ttbtb gt1Q== X-Gm-Message-State: AOJu0Ywib1L1PS3l/ZlRditb+tLo0/QtvJHxRlqhPVgglCdxsGMwZK07 Y1fVZIcIISdVzY2i2XCAHGD9yWtC7gcczU+CQZRVP6Ol8Yq1Zuskpg2z X-Gm-Gg: AY/fxX4R6lC6qjruT/vfIVbPOvBKjlxxWctIGORHKL+D4P6N0QigmcDXa+sgE0zqh2d 91eGzV5HYh31G2GCDd1Ly0M6souvMQxXSoZqge3poRl6hJSk8zh0B3DKXPlXvNGA/l3pDhQrcGH ZMcOkDCU/10/wqLrA9rM79Cya9PqlxW0CKtsMpvUI0/Q/oya7auGu5PuTHNVm+UfShuU/GJs6S1 P11IUv9gfIV6FUvyBKvOgvt7nCN7TlyliqpKuuyMESm27z7GDp/uSLJP4eAS1zfVN1xprRjKKL6 jfggrSBdZFl+7yNvwveLHUWvOd1+f/8MaEPx5K12QyGw/RJeqggzOhztK3B/kI/y5zLT1KbXUwm 6fucc4v9ggpXsiFAtK/fGhDLTCn/bq2OP4kWodvrH2CEJtNCG7KNcHTKAL1MGDe9hGqo/naeZXY n8Aq5VpGPLJKBChCGAaWNRECNebdY+3FxEVJqkzDnyXjoVC64PTIGORKMoTffL8G1CgLMWlQ== X-Received: by 2002:a05:6a21:9d48:b0:371:53a7:a4ba with SMTP id adf61e73a8af0-38dfe67beafmr11933471637.30.1768885127748; Mon, 19 Jan 2026 20:58:47 -0800 (PST) From: Chao Liu To: Alistair Francis , Daniel Henrique Barboza , Palmer Dabbelt , Weiwei Li , Liu Zhiwei Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, wangjingwei@iscas.ac.cn, Chao Liu , Mig Yang , Chao Liu Subject: [PATCH v4 3/5] hw/watchdog: add k230 watchdog initial support Date: Tue, 20 Jan 2026 12:56:53 +0800 Message-ID: <0e8179aa4d09fe857effa05a6fecd309817ab1ee.1768884546.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::444; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-pf1-x444.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-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: 1768885233338154100 Content-Type: text/plain; charset="utf-8" From: Chao Liu Add programmable Watchdog Timer (WDT) peripheral for K230 machine. Signed-off-by: Mig Yang Signed-off-by: Chao Liu Reviewed-by: Daniel Henrique Barboza --- MAINTAINERS | 2 + hw/riscv/Kconfig | 1 + hw/riscv/k230.c | 18 ++ hw/watchdog/Kconfig | 4 + hw/watchdog/k230_wdt.c | 307 +++++++++++++++++++++++++++++++++ hw/watchdog/meson.build | 1 + hw/watchdog/trace-events | 9 + include/hw/riscv/k230.h | 4 + include/hw/watchdog/k230_wdt.h | 130 ++++++++++++++ 9 files changed, 476 insertions(+) create mode 100644 hw/watchdog/k230_wdt.c create mode 100644 include/hw/watchdog/k230_wdt.h diff --git a/MAINTAINERS b/MAINTAINERS index 6c8391186d..5b7edf4ec6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1762,7 +1762,9 @@ K230 Machines M: Chao Liu S: Maintained F: hw/riscv/k230.c +F: hw/watchdog/k230_wdt.c F: include/hw/riscv/k230.h +F: include/hw/watchdog/k230_wdt.h =20 RX Machines ----------- diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index b1a7357866..5f8511cb92 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -144,3 +144,4 @@ config K230 select RISCV_IMSIC select SERIAL_MM select UNIMP + select K230_WDT diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c index e1780e4f0b..6817aa7d3e 100644 --- a/hw/riscv/k230.c +++ b/hw/riscv/k230.c @@ -112,6 +112,9 @@ static void k230_soc_init(Object *obj) RISCVHartArrayState *cpu0 =3D &s->c908_cpu; =20 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); + qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0); qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C9= 08); qdev_prop_set_uint64(DEVICE(cpu0), "resetvec", @@ -189,6 +192,21 @@ static void k230_soc_realize(DeviceState *dev, Error *= *errp) qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART4_IRQ), 399193, serial_hd(4), DEVICE_LITTLE_ENDIAN); =20 + /* Watchdog */ + for (int i =3D 0; i < 2; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { + return; + } + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[0]), 0, memmap[K230_DEV_WDT0].b= ase); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[0]), 0, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT0_IR= Q)); + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[1]), 0, memmap[K230_DEV_WDT1].b= ase); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[1]), 0, + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT1_IR= Q)); + /* unimplemented devices */ create_unimplemented_device("kpu.l2-cache", memmap[K230_DEV_KPU_L2_CACHE].base, diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig index 861fd00334..55f77c5c84 100644 --- a/hw/watchdog/Kconfig +++ b/hw/watchdog/Kconfig @@ -18,6 +18,10 @@ config WDT_DIAG288 config WDT_IMX2 bool =20 +config K230_WDT + bool + select PTIMER + config WDT_SBSA bool =20 diff --git a/hw/watchdog/k230_wdt.c b/hw/watchdog/k230_wdt.c new file mode 100644 index 0000000000..f385319836 --- /dev/null +++ b/hw/watchdog/k230_wdt.c @@ -0,0 +1,307 @@ +/* + * * K230 Watchdog Compatible with kendryte K230 SDK + * + * Copyright (c) 2025 Mig Yang + * Copyright (c) 2025 Chao Liu + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Provides a board compatible with the kendryte K230 SDK + * + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf + * + * For more information, see + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/module.h" +#include "system/watchdog.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#include "hw/watchdog/k230_wdt.h" +#include "trace.h" + +static void k230_wdt_timeout(void *opaque) +{ + K230WdtState *s =3D K230_WDT(opaque); + + trace_k230_wdt_timeout(); + + /* Set interrupt status if in interrupt mode */ + if (s->cr & K230_WDT_CR_RMOD) { + s->stat |=3D K230_WDT_STAT_INT; + s->interrupt_pending =3D true; + qemu_set_irq(s->irq, 1); + trace_k230_wdt_interrupt(); + } else { + /* Direct reset mode */ + trace_k230_wdt_reset(); + watchdog_perform_action(); + } + + /* Restart counter */ + s->current_count =3D s->timeout_value; + ptimer_set_count(s->timer, s->current_count); + ptimer_run(s->timer, 1); +} + +static void k230_wdt_reset(DeviceState *dev) +{ + K230WdtState *s =3D K230_WDT(dev); + + trace_k230_wdt_reset_device(); + + ptimer_transaction_begin(s->timer); + ptimer_stop(s->timer); + ptimer_transaction_commit(s->timer); + + /* Reset registers to default values */ + s->cr =3D 0; + s->torr =3D 0; + s->ccvr =3D 0xFFFFFFFF; + s->stat =3D 0; + s->prot_level =3D 0x2; + + s->interrupt_pending =3D false; + s->enabled =3D false; + s->timeout_value =3D 0; + s->current_count =3D 0xFFFFFFFF; +} + +static uint64_t k230_wdt_read(void *opaque, hwaddr addr, unsigned int size) +{ + K230WdtState *s =3D K230_WDT(opaque); + uint32_t value =3D 0; + + switch (addr) { + case K230_WDT_CR: + value =3D s->cr; + break; + case K230_WDT_TORR: + value =3D s->torr; + break; + case K230_WDT_CCVR: + if (s->enabled) { + value =3D ptimer_get_count(s->timer); + } else { + value =3D s->current_count; + } + break; + case K230_WDT_STAT: + value =3D s->stat; + break; + case K230_WDT_PROT_LEVEL: + value =3D s->prot_level; + break; + case K230_WDT_COMP_PARAM_5: + value =3D 0; /* Upper limit of Timeout Period parameters */ + break; + case K230_WDT_COMP_PARAM_4: + value =3D 0; /* Upper limit of Initial Timeout Period parameters */ + break; + case K230_WDT_COMP_PARAM_3: + value =3D 0; /* Derived from WDT_TOP_RST parameter */ + break; + case K230_WDT_COMP_PARAM_2: + value =3D 0xFFFFFFFF; /* Derived from WDT_RST_CNT parameter */ + break; + case K230_WDT_COMP_PARAM_1: + /* Component parameters */ + value =3D (32 << K230_WDT_CNT_WIDTH_SHIFT) | /* 32-bit counter */ + (0 << K230_WDT_DFLT_TOP_INIT_SHIFT) | + (0 << K230_WDT_DFLT_TOP_SHIFT) | + (K230_WDT_RPL_16_CYCLES << K230_WDT_DFLT_RPL_SHIFT) | + (2 << K230_WDT_APB_DATA_WIDTH_SHIFT) | /* 32-bit APB */ + K230_WDT_USE_FIX_TOP; /* Use fixed timeout values */ + break; + case K230_WDT_COMP_VERSION: + value =3D K230_WDT_COMP_VERSION_VAL; + break; + case K230_WDT_COMP_TYPE: + value =3D K230_WDT_COMP_TYPE_VAL; + break; + default: + /* Other registers return 0 */ + break; + } + + trace_k230_wdt_read(addr, value); + return value; +} + +static void k230_wdt_update_timer(K230WdtState *s) +{ + ptimer_transaction_begin(s->timer); + + if (s->enabled && s->timeout_value > 0) { + ptimer_set_count(s->timer, s->current_count); + ptimer_run(s->timer, 1); + } else { + ptimer_stop(s->timer); + } + + ptimer_transaction_commit(s->timer); +} + +static uint32_t k230_wdt_calculate_timeout(uint32_t top_value) +{ + /* Calculate timeout based on TOP value */ + /* For fixed timeout mode: 2^(16 + top_value) */ + if (top_value <=3D 15) { + return 1 << (16 + top_value); + } + return 1 << 31; /* Maximum value for 32-bit counter */ +} + +static void k230_wdt_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + K230WdtState *s =3D K230_WDT(opaque); + + trace_k230_wdt_write(addr, value); + + switch (addr) { + case K230_WDT_CR: + s->cr =3D value & (K230_WDT_CR_RPL_MASK << K230_WDT_CR_RPL_SHIFT | + K230_WDT_CR_RMOD | K230_WDT_CR_WDT_EN); + + /* Update enabled state */ + s->enabled =3D (s->cr & K230_WDT_CR_WDT_EN) !=3D 0; + + /* Update timer */ + k230_wdt_update_timer(s); + break; + + case K230_WDT_TORR: + s->torr =3D value & K230_WDT_TORR_TOP_MASK; + + /* Calculate new timeout value */ + s->timeout_value =3D k230_wdt_calculate_timeout(s->torr); + s->current_count =3D s->timeout_value; + + /* Update timer if enabled */ + if (s->enabled) { + k230_wdt_update_timer(s); + } + break; + + case K230_WDT_CRR: + /* Restart counter with magic value 0x76 */ + if ((value & 0xFF) =3D=3D K230_WDT_CRR_RESTART) { + trace_k230_wdt_restart(); + s->current_count =3D s->timeout_value; + + /* Clear interrupt if pending */ + if (s->interrupt_pending) { + s->stat &=3D ~K230_WDT_STAT_INT; + s->interrupt_pending =3D false; + qemu_set_irq(s->irq, 0); + } + + /* Update timer */ + k230_wdt_update_timer(s); + } + break; + + case K230_WDT_EOI: + /* Clear interrupt */ + s->stat &=3D ~K230_WDT_STAT_INT; + s->interrupt_pending =3D false; + qemu_set_irq(s->irq, 0); + break; + + case K230_WDT_PROT_LEVEL: + s->prot_level =3D value & 0x7; + break; + + default: + /* Read-only registers, ignore writes */ + break; + } +} + +static const MemoryRegionOps k230_wdt_ops =3D { + .read =3D k230_wdt_read, + .write =3D k230_wdt_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static const VMStateDescription vmstate_k230_wdt =3D { + .name =3D "k230.wdt", + .fields =3D (const VMStateField[]) { + VMSTATE_PTIMER(timer, K230WdtState), + VMSTATE_UINT32(cr, K230WdtState), + VMSTATE_UINT32(torr, K230WdtState), + VMSTATE_UINT32(ccvr, K230WdtState), + VMSTATE_UINT32(stat, K230WdtState), + VMSTATE_UINT32(prot_level, K230WdtState), + VMSTATE_BOOL(interrupt_pending, K230WdtState), + VMSTATE_BOOL(enabled, K230WdtState), + VMSTATE_UINT32(timeout_value, K230WdtState), + VMSTATE_UINT32(current_count, K230WdtState), + VMSTATE_END_OF_LIST() + } +}; + +static void k230_wdt_realize(DeviceState *dev, Error **errp) +{ + K230WdtState *s =3D K230_WDT(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), + &k230_wdt_ops, s, + TYPE_K230_WDT, + K230_WDT_MMIO_SIZE); + sysbus_init_mmio(sbd, &s->mmio); + sysbus_init_irq(sbd, &s->irq); + + s->timer =3D ptimer_init(k230_wdt_timeout, s, + PTIMER_POLICY_NO_IMMEDIATE_TRIGGER | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD | + PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); + + ptimer_transaction_begin(s->timer); + ptimer_set_freq(s->timer, K230_WDT_DEFAULT_FREQ); + ptimer_transaction_commit(s->timer); +} + +static void k230_wdt_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D k230_wdt_realize; + device_class_set_legacy_reset(dc, k230_wdt_reset); + dc->vmsd =3D &vmstate_k230_wdt; + dc->desc =3D "K230 watchdog timer"; + set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories); +} + +static const TypeInfo k230_wdt_info =3D { + .name =3D TYPE_K230_WDT, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(K230WdtState), + .class_init =3D k230_wdt_class_init, +}; + +static void k230_wdt_register_type(void) +{ + type_register_static(&k230_wdt_info); +} +type_init(k230_wdt_register_type) diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build index 15370565bd..5edae65a36 100644 --- a/hw/watchdog/meson.build +++ b/hw/watchdog/meson.build @@ -6,5 +6,6 @@ system_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt= _ib700.c')) system_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c')) system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c')) system_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c')) +system_ss.add(when: 'CONFIG_K230_WDT', if_true: files('k230_wdt.c')) system_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_watchdog.c')) diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events index ad3be1e9bd..d85b3ca769 100644 --- a/hw/watchdog/trace-events +++ b/hw/watchdog/trace-events @@ -33,3 +33,12 @@ spapr_watchdog_expired(uint64_t num, unsigned action) "n= um=3D%" PRIu64 " action=3D%u # watchdog.c watchdog_perform_action(unsigned int action) "action=3D%u" watchdog_set_action(unsigned int action) "action=3D%u" + +# k230_wdt.c +k230_wdt_read(uint64_t addr, uint32_t data) "K230 WDT read: [0x%" PRIx64 "= ] -> 0x%" PRIx32 +k230_wdt_write(uint64_t addr, uint64_t data) "K230 WDT write: [0x%" PRIx64= "] <- 0x%" PRIx64 +k230_wdt_timeout(void) "K230 WDT timeout" +k230_wdt_interrupt(void) "K230 WDT interrupt" +k230_wdt_reset(void) "K230 WDT system reset" +k230_wdt_restart(void) "K230 WDT restart" +k230_wdt_reset_device(void) "K230 WDT device reset" diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h index 3158381e8f..f2eedd5f70 100644 --- a/include/hw/riscv/k230.h +++ b/include/hw/riscv/k230.h @@ -27,6 +27,7 @@ =20 #include "hw/boards.h" #include "hw/riscv/riscv_hart.h" +#include "hw/watchdog/k230_wdt.h" =20 #define C908_CPU_HARTID (0) =20 @@ -41,6 +42,7 @@ typedef struct K230SoCState { /*< public >*/ RISCVHartArrayState c908_cpu; /* Small core */ =20 + K230WdtState wdt[2]; MemoryRegion sram; MemoryRegion bootrom; =20 @@ -131,6 +133,8 @@ enum { K230_UART2_IRQ =3D 18, K230_UART3_IRQ =3D 19, K230_UART4_IRQ =3D 20, + K230_WDT0_IRQ =3D 32, + K230_WDT1_IRQ =3D 33, }; =20 /* diff --git a/include/hw/watchdog/k230_wdt.h b/include/hw/watchdog/k230_wdt.h new file mode 100644 index 0000000000..9371602387 --- /dev/null +++ b/include/hw/watchdog/k230_wdt.h @@ -0,0 +1,130 @@ +/* + * K230 Watchdog Timer + * + * Based on K230 technical documentation + * + * Copyright (c) 2025 Mig Yang + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef K230_WDT_H +#define K230_WDT_H + +#include "qemu/bitops.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/ptimer.h" +#include "qom/object.h" + +#define TYPE_K230_WDT "riscv.k230.wdt" +OBJECT_DECLARE_SIMPLE_TYPE(K230WdtState, K230_WDT) + +#define K230_WDT_DEFAULT_FREQ (32768) + +/* K230 Watchdog Register Map */ +enum K230WdtRegisters { + K230_WDT_CR =3D 0x00, /* Control Register */ + K230_WDT_TORR =3D 0x04, /* Timeout Range Register */ + K230_WDT_CCVR =3D 0x08, /* Current Counter Value Register */ + K230_WDT_CRR =3D 0x0c, /* Counter Restart Register */ + K230_WDT_STAT =3D 0x10, /* Interrupt Status Register */ + K230_WDT_EOI =3D 0x14, /* Interrupt Clear Register */ + K230_WDT_PROT_LEVEL =3D 0x1c, /* Protection Level Register */ + K230_WDT_COMP_PARAM_5 =3D 0xe4, /* Component Parameters Register 5 */ + K230_WDT_COMP_PARAM_4 =3D 0xe8, /* Component Parameters Register 4 */ + K230_WDT_COMP_PARAM_3 =3D 0xec, /* Component Parameters Register 3 */ + K230_WDT_COMP_PARAM_2 =3D 0xf0, /* Component Parameters Register 2 */ + K230_WDT_COMP_PARAM_1 =3D 0xf4, /* Component Parameters Register 1 */ + K230_WDT_COMP_VERSION =3D 0xf8, /* Component Version Register */ + K230_WDT_COMP_TYPE =3D 0xfc, /* Component Type Register */ +}; + +#define K230_WDT_MMIO_SIZE 0x100 + +/* Control Register (WDT_CR) definitions */ +#define K230_WDT_CR_RPL_MASK 0x7 /* Reset Pulse Length */ +#define K230_WDT_CR_RPL_SHIFT 2 +#define K230_WDT_CR_RMOD BIT(1) /* Response Mode */ +#define K230_WDT_CR_WDT_EN BIT(0) /* Watchdog Enable */ + +/* Reset Pulse Length values */ +#define K230_WDT_RPL_2_CYCLES 0x0 +#define K230_WDT_RPL_4_CYCLES 0x1 +#define K230_WDT_RPL_8_CYCLES 0x2 +#define K230_WDT_RPL_16_CYCLES 0x3 +#define K230_WDT_RPL_32_CYCLES 0x4 +#define K230_WDT_RPL_64_CYCLES 0x5 +#define K230_WDT_RPL_128_CYCLES 0x6 +#define K230_WDT_RPL_256_CYCLES 0x7 + +/* Timeout Range Register (WDT_TORR) definitions */ +#define K230_WDT_TORR_TOP_MASK 0xf /* Timeout Period */ + +/* Interrupt Status Register (WDT_STAT) definitions */ +#define K230_WDT_STAT_INT BIT(0) /* Interrupt Status */ + +/* Counter Restart Register (WDT_CRR) magic value */ +#define K230_WDT_CRR_RESTART 0x76 /* Restart command */ + +/* Component Parameters Register 1 (WDT_COMP_PARAM_1) definitions */ +#define K230_WDT_CNT_WIDTH_MASK 0x1f000000 /* Counter Width */ +#define K230_WDT_CNT_WIDTH_SHIFT 24 +#define K230_WDT_DFLT_TOP_INIT_MASK 0xf00000 /* Default Initial Timeout */ +#define K230_WDT_DFLT_TOP_INIT_SHIFT 20 +#define K230_WDT_DFLT_TOP_MASK 0xf0000 /* Default Timeout */ +#define K230_WDT_DFLT_TOP_SHIFT 16 +#define K230_WDT_DFLT_RPL_MASK 0x7 /* Default Reset Pulse Length */ +#define K230_WDT_DFLT_RPL_SHIFT 10 +#define K230_WDT_APB_DATA_WIDTH_MASK 0x3 /* APB Data Width */ +#define K230_WDT_APB_DATA_WIDTH_SHIFT 8 +#define K230_WDT_USE_FIX_TOP BIT(6) /* Use Fixed Timeout Values */ +#define K230_WDT_HC_TOP BIT(5) /* Hard-coded Timeout */ +#define K230_WDT_HC_RPL BIT(4) /* Hard-coded Reset Pulse Lengt= h */ +#define K230_WDT_HC_RMOD BIT(3) /* Hard-coded Response Mode */ +#define K230_WDT_DUAL_TOP BIT(2) /* Dual Timeout Period */ +#define K230_WDT_DFLT_RMOD BIT(1) /* Default Response Mode */ +#define K230_WDT_ALWAYS_EN BIT(0) /* Always Enabled */ + +/* Component Type Register value */ +#define K230_WDT_COMP_TYPE_VAL 0x44570120 + +/* Component Version Register value */ +#define K230_WDT_COMP_VERSION_VAL 0x3131302a /* "110*" */ + +struct K230WdtState { + /* */ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + qemu_irq irq; + + struct ptimer_state *timer; + + /* Register state */ + uint32_t cr; /* Control Register */ + uint32_t torr; /* Timeout Range Register */ + uint32_t ccvr; /* Current Counter Value Register */ + uint32_t stat; /* Interrupt Status Register */ + uint32_t prot_level; /* Protection Level Register */ + + /* Internal state */ + bool interrupt_pending; + bool enabled; + uint32_t timeout_value; + uint32_t current_count; +}; + +#endif /* K230_WDT_H */ --=20 2.52.0 From nobody Sun Feb 8 00:26:18 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=1768885179; cv=none; d=zohomail.com; s=zohoarc; b=R8JyZeMFjq0yZtuidHfB+h15puclIm19zc0nsQUxUgNCf2dx1ng7fNnWAFfd5xs14VmYw9bpTPXCU/MpyrAehQvwwdlEtlvgaxodaEjauCUvDB+PpsqwKfJ/RpFJPJwHHGweOhZe5DK4oA3vmnjUxTW88BN7P97rXvBnrqv4btE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768885179; 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=CQ7R+SfXzKgQZUjTnUgKdicDt1/sFenEIossTHOnfPg=; b=FdxdpKfuDO04e4M+8ciy3En5JrM86d3AaGLnb7efM5dT8p8wLEBPMrHS8AFxj1UzHafD4ddZW6N0aHO81t0ukeErzp+gGXRNa9EmeqA4nF9AGH9xgSnlM89MkfcDcx9/Ut4uG4nCR+4sWdps1biXBTRTpGtU8Nu/HlLhUJXVZG8= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768885179200245.7699396450082; Mon, 19 Jan 2026 20:59:39 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vi3pT-0002Uu-ON; Mon, 19 Jan 2026 23:58:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vi3pR-0002SF-8B for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:57 -0500 Received: from mail-pf1-x441.google.com ([2607:f8b0:4864:20::441]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vi3pP-0000Es-6q for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:58:57 -0500 Received: by mail-pf1-x441.google.com with SMTP id d2e1a72fcca58-81f46b5e2ccso2520198b3a.0 for ; Mon, 19 Jan 2026 20:58:54 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([183.195.21.180]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm110703045ad.38.2026.01.19.20.58.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 20:58:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768885134; x=1769489934; 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; bh=CQ7R+SfXzKgQZUjTnUgKdicDt1/sFenEIossTHOnfPg=; b=KbUgQcZDDNw+11HZzjkFGeeEldPnG62+3cqIuOVz7fqOJ02ejrcEP9XRld+nRciIyC MXF8SD4/9N6C+YNu9kDgC3Xqnw6GILkwYoUBDhXu3DpNS7a8E6kd5aS+H4Xcwlrf7Syd 2v5r93fUELPd0EpuDiD39WBRGEJzlv18s79Fq8lomgBSEYeZqmD6IrW9UZx8AdblXyLz HppKKuEN9c8FYeJP94ssZWHuMJnMhTSuV7wb3PR0Xxq7yUznteTD4Al8TJPW3tc/P/uj 41LgiwjZnXyuad9smrjngTz91KA096Ht1F5oj+7+O2/p0PYM2b5ytmQ81lkEVd7EzgYN YnvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768885134; x=1769489934; 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; bh=CQ7R+SfXzKgQZUjTnUgKdicDt1/sFenEIossTHOnfPg=; b=dyQtqgHvo2MBUWP3bVACJ4cc/SKaKHa9wnZy7CXE2kIVgKHIeRe2bXEHDBFbJeYicL ATgyUshjpjQtt0a5YvP3iXVGUwy5Qb3x87rtl0kcr4vphu4+lwq3CCvxOKjbeoBh2fsX 0jdojJDNgPtD1+0DPEzY6UsKWR2ZGZ4SjIdp4fyo7dNi4+nCLe35XlBoyyXDY6yUqmun Re2RkJsxj8K2rnPQAnDQ10PtgCkAzcrS8IlG4YcevhSUEM7bmmtGl3OjqHFkyTQ1rLql 7B5GSa0cCcCiuRF27wRJAiLFnUg6t22qMByLtYqVmFVNrQeyDAr6FCF79OP35ehx03g5 rp7A== X-Gm-Message-State: AOJu0Yx8idl80zzdaOsZWr3BHfTtKCavRJxxOAmpDTc5uOh11y7vmX6a IRKKDvIl0awkdLBgerbW6ngr9tN1Qonul98MZNdZe+Cw5NhU0UlV3C0T X-Gm-Gg: AY/fxX5G00nWN3BqV5Wtbb0Ot4ID6qTngkUkanWvfkIrPJGIi7sXG/8M0fAWSggOdfF kyahDF4FfGEGbz8aF5/VQ9ATLPmlXCKkZ0TrIeieGtWlxy0tGJ6VQwtqsUvD4ZksTlHwqqCjzcd qwqKZwR07tDhXmrKnHenTV+qb9j74O6F2morq1Ib4NqJfXQEMrX9zZSeZC2SPIqEL3E74uhlvIQ l6oo+OWV7bLS9bfSJbTG5OKnzXGhOgb9DMHR2JUdi7FKPGC58+8myN+H2GALE2AJjF3MadbbWd6 MM7Ku1p56yyliX1h6l2l5gSZh1dsKd40/DuBkusAS2jocJPSCqda9roe99BjA4Y7OoHjPHO1W8Y xWrIjofzYhSoR/rsoHUI/Q6T0IN3sCsxrpa1WsKZH8ivg49bf0fWei5vW2UsN2BsmwupGanoDe3 T6GrSR66j+cMN7BbyAkEeUvLhXnh8KszCFiuok2XPUQgsRDfTMhXBw2vViy5w= X-Received: by 2002:a05:6a21:32a6:b0:252:2bfe:b65a with SMTP id adf61e73a8af0-38e45d0eaffmr836215637.7.1768885133742; Mon, 19 Jan 2026 20:58:53 -0800 (PST) From: Chao Liu To: Alistair Francis , Daniel Henrique Barboza , Palmer Dabbelt , Weiwei Li , Liu Zhiwei Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, wangjingwei@iscas.ac.cn, Chao Liu , Mig Yang Subject: [PATCH v4 4/5] tests/qtest: add test for K230 watchdog Date: Tue, 20 Jan 2026 12:56:54 +0800 Message-ID: <512d772a7dfb84d8a729cf3ac2ef58a82766af47.1768884546.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::441; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-pf1-x441.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-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: 1768885180722158500 Content-Type: text/plain; charset="utf-8" From: Chao Liu Testing the Basic Functions of K230 WDT: 1. Reset Function 2. Timeout Check 3. Interrupt Function Signed-off-by: Mig Yang Reviewed-by: Daniel Henrique Barboza --- MAINTAINERS | 1 + tests/qtest/k230-wdt-test.c | 199 ++++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 3 +- 3 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/k230-wdt-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 5b7edf4ec6..5464e7fb5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1765,6 +1765,7 @@ F: hw/riscv/k230.c F: hw/watchdog/k230_wdt.c F: include/hw/riscv/k230.h F: include/hw/watchdog/k230_wdt.h +F: tests/qtest/k230-wdt-test.c =20 RX Machines ----------- diff --git a/tests/qtest/k230-wdt-test.c b/tests/qtest/k230-wdt-test.c new file mode 100644 index 0000000000..2550cebd10 --- /dev/null +++ b/tests/qtest/k230-wdt-test.c @@ -0,0 +1,199 @@ +/* + * QTest testcase for K230 Watchdog + * + * Copyright (c) 2025 Mig Yang + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Provides a board compatible with the kendryte K230 SDK + * + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf + * + * For more information, see + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/timer.h" +#include "qemu/bitops.h" +#include "libqtest.h" +#include "hw/watchdog/k230_wdt.h" + +/* K230 WDT0 base address */ +#define K230_WDT0_BASE 0x91106000 +#define K230_WDT1_BASE 0x91106800 + +/* Test WDT0 by default */ +#define WDT_BASE K230_WDT0_BASE + +static void test_register_read_write(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* Test Control Register (CR) read/write */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, 0xFFFFFFFF); + g_assert_cmphex(qtest_readl(qts, WDT_BASE + K230_WDT_CR), =3D=3D, + (K230_WDT_CR_RPL_MASK << K230_WDT_CR_RPL_SHIFT) | + K230_WDT_CR_RMOD | K230_WDT_CR_WDT_EN); + + /* Test Timeout Range Register (TORR) read/write */ + qtest_writel(qts, WDT_BASE + K230_WDT_TORR, 0xFFFFFFFF); + g_assert_cmphex(qtest_readl(qts, WDT_BASE + K230_WDT_TORR), =3D=3D, + K230_WDT_TORR_TOP_MASK); + + /* Test Protection Level Register read/write */ + qtest_writel(qts, WDT_BASE + K230_WDT_PROT_LEVEL, 0xFFFFFFFF); + g_assert_cmphex(qtest_readl(qts, WDT_BASE + K230_WDT_PROT_LEVEL), =3D= =3D, 0x7); + + qtest_quit(qts); +} + +static void test_counter_restart(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* Enable watchdog and set timeout */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, K230_WDT_CR_WDT_EN); + qtest_writel(qts, WDT_BASE + K230_WDT_TORR, 0x5); /* TOP =3D 5 */ + + /* Read current counter value */ + uint32_t initial_count =3D qtest_readl(qts, WDT_BASE + K230_WDT_CCVR); + g_assert_cmpuint(initial_count, >, 0); + + /* Restart counter with magic value */ + qtest_writel(qts, WDT_BASE + K230_WDT_CRR, K230_WDT_CRR_RESTART); + + /* Wait for time */ + qtest_clock_step(qts, NANOSECONDS_PER_SECOND * 2); + + /* Counter should be reset to timeout value */ + uint32_t new_count =3D qtest_readl(qts, WDT_BASE + K230_WDT_CCVR); + g_assert_cmpuint(new_count, >, 0); + g_assert_cmpuint(new_count, !=3D, initial_count); + + qtest_quit(qts); +} + +static void test_interrupt_mode(void) +{ + QTestState *qts =3D qtest_init("-machine k230 --trace k230_*,file=3Dk2= 30.log"); + + /* Set interrupt mode and enable watchdog */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, + K230_WDT_CR_RMOD | K230_WDT_CR_WDT_EN); + qtest_writel(qts, WDT_BASE + K230_WDT_TORR, 0x1); /* Short timeout */ + + /* Wait for timeout to trigger interrupt */ + qtest_clock_step(qts, NANOSECONDS_PER_SECOND * 10); + + /* Check interrupt status */ + uint32_t stat =3D qtest_readl(qts, WDT_BASE + K230_WDT_STAT); + g_assert_cmphex(stat & K230_WDT_STAT_INT, =3D=3D, K230_WDT_STAT_INT); + + /* Clear interrupt */ + qtest_writel(qts, WDT_BASE + K230_WDT_EOI, 0x1); + stat =3D qtest_readl(qts, WDT_BASE + K230_WDT_STAT); + g_assert_cmphex(stat & K230_WDT_STAT_INT, =3D=3D, 0); + + qtest_quit(qts); +} + +static void test_reset_mode(void) +{ + QTestState *qts =3D qtest_init("-machine k230 -no-reboot"); + + /* Set reset mode and enable watchdog */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, K230_WDT_CR_WDT_EN); + qtest_writel(qts, WDT_BASE + K230_WDT_TORR, 0x1); /* Short timeout */ + + /* Wait for timeout to trigger reset */ + qtest_clock_step(qts, NANOSECONDS_PER_SECOND * 2); + + /* In reset mode, the system should reset */ + /* This test verifies that reset mode is properly configured */ + + qtest_quit(qts); +} + +static void test_timeout_calculation(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* Test different timeout values */ + for (uint32_t top =3D 0; top <=3D 15; top++) { + qtest_writel(qts, WDT_BASE + K230_WDT_TORR, top); + qtest_writel(qts, WDT_BASE + K230_WDT_CR, K230_WDT_CR_WDT_EN); + + /* Read current counter value */ + uint32_t count =3D qtest_readl(qts, WDT_BASE + K230_WDT_CCVR); + g_assert_cmpuint(count, >, 0); + + /* Disable watchdog for next iteration */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, 0); + } + + qtest_quit(qts); +} + +static void test_wdt1_registers(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* Test WDT1 registers (second watchdog) */ + qtest_writel(qts, K230_WDT1_BASE + K230_WDT_CR, 0xFFFFFFFF); + g_assert_cmphex(qtest_readl(qts, K230_WDT1_BASE + K230_WDT_CR), =3D=3D, + (K230_WDT_CR_RPL_MASK << K230_WDT_CR_RPL_SHIFT) | + K230_WDT_CR_RMOD | K230_WDT_CR_WDT_EN); + + qtest_writel(qts, K230_WDT1_BASE + K230_WDT_TORR, 0xFFFFFFFF); + g_assert_cmphex(qtest_readl(qts, K230_WDT1_BASE + K230_WDT_TORR), =3D= =3D, + K230_WDT_TORR_TOP_MASK); + + qtest_quit(qts); +} + +static void test_enable_disable(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* Initially disabled */ + uint32_t cr =3D qtest_readl(qts, WDT_BASE + K230_WDT_CR); + g_assert_cmphex(cr & K230_WDT_CR_WDT_EN, =3D=3D, 0); + + /* Enable watchdog */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, K230_WDT_CR_WDT_EN); + cr =3D qtest_readl(qts, WDT_BASE + K230_WDT_CR); + g_assert_cmphex(cr & K230_WDT_CR_WDT_EN, =3D=3D, K230_WDT_CR_WDT_EN); + + /* Disable watchdog */ + qtest_writel(qts, WDT_BASE + K230_WDT_CR, 0); + cr =3D qtest_readl(qts, WDT_BASE + K230_WDT_CR); + g_assert_cmphex(cr & K230_WDT_CR_WDT_EN, =3D=3D, 0); + + qtest_quit(qts); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/k230-wdt/register_read_write", test_register_read_wri= te); + qtest_add_func("/k230-wdt/counter_restart", test_counter_restart); + qtest_add_func("/k230-wdt/interrupt_mode", test_interrupt_mode); + qtest_add_func("/k230-wdt/reset_mode", test_reset_mode); + qtest_add_func("/k230-wdt/timeout_calculation", test_timeout_calculati= on); + qtest_add_func("/k230-wdt/wdt1_registers", test_wdt1_registers); + qtest_add_func("/k230-wdt/enable_disable", test_enable_disable); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 0f053fb56d..54c3ba5dea 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -283,7 +283,8 @@ qtests_riscv32 =3D \ (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watc= hdog-test'] : []) =20 qtests_riscv64 =3D ['riscv-csr-test'] + \ - (unpack_edk2_blobs ? ['bios-tables-test'] : []) + (unpack_edk2_blobs ? ['bios-tables-test'] : []) + \ + (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test'] : []) =20 qos_test_ss =3D ss.source_set() qos_test_ss.add( --=20 2.52.0 From nobody Sun Feb 8 00:26:18 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=1768885164; cv=none; d=zohomail.com; s=zohoarc; b=IgeaBjjDvZpt/SPnsvuRooDhwN+Zu7dvRlgqEadhT/FYC8FPFviU0nqittqr1cs3RZgtdpcfIO3A3LNESo9wkQM6b2lFGjozJJEHTC9IXYPq1jR3X8+/UuH9SIq1bXnZ4cWyJWNeBcJ9ASMN7EK4YoQYq2b4O/G0yDXodUyBXsE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768885164; h=Content-Type: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=iHPPQtLsBrf6SxxB3IwlY/gIhjLfsrdUl251mQ5AQeg=; b=K5Ty9OcVCFMT0Hn17v1UXaGy5GDfhHA+WonGCMH6zPW6aHUakWGdSmxKOgF5tGhRRykk/BNJNlZJSvuOPexMUiTOpuZsbBj87r3Lc/GAU15u2ljxQrCmbUBeIp1Tmzd09YWIMeAFbLvby1KGTQD5a2HAOSXYmpPITEq7H4FX6uY= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768885164715972.7424055900102; Mon, 19 Jan 2026 20:59:24 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vi3pY-0002cv-I3; Mon, 19 Jan 2026 23:59:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vi3pW-0002bi-NS for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:59:03 -0500 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vi3pV-0000FX-1R for qemu-devel@nongnu.org; Mon, 19 Jan 2026 23:59:02 -0500 Received: by mail-pl1-x642.google.com with SMTP id d9443c01a7336-2a1022dda33so30201195ad.2 for ; Mon, 19 Jan 2026 20:59:00 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([183.195.21.180]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm110703045ad.38.2026.01.19.20.58.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 20:58:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768885140; x=1769489940; 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; bh=iHPPQtLsBrf6SxxB3IwlY/gIhjLfsrdUl251mQ5AQeg=; b=msnJj/ZN1IK94GlglrmGJYYXnmH/sB8uzr2yf9QYgGeDMuCnZO9aNq+QpFLRMYb0gF Ao+YGPrcZUzvmY2JjUN4i/Y/6kKXPyE2UDRXCgEKYBCkMtpkX0sPtfmsKXs0b1YuwWyv 5IJ2r67xe3q09/nm6x+lrC/EeOCpRqVbxHD3N5jdYP0glZJecuHWVu6Pi0dxCVt8Bl6H jp7XXkQJUpbU5XF9unYvSRiMVu9aP0cmq421EHg9bDfJsoPX4TfEtmoQCQss6Ldd32CW Yszwh9I7K3F8yuWFWp9hI/vSVHEQeThAiqLCVfyaghs7FjH4jmPz1p1Nl3H+zcEoTbM3 ArGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768885140; x=1769489940; 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; bh=iHPPQtLsBrf6SxxB3IwlY/gIhjLfsrdUl251mQ5AQeg=; b=ZPm76dI3Wnugn+VwDmD+B2Lg/GD6HHiwi9OukxCmQWbKh7+EUbgQJROjN3VYBoG5jJ 0oC9rb4dzPwsnut5aeUvzCExdoTBybEXlAl6klIod/tvScUAtAk/R0sAwy1alKq4WGxs djRGu/Ixfgi4T0Jlj7vESLDUKOPgBV5SiipHPSfc7Kzcisknv6YWMWPqZH7kw4erUibI 5An9UccpFLEqlj3drQ0uUks3C0L7OOQQfmiW+OINJJMm2Y+d/X/I4z8VeSvZYpWtao3o 8jrKfd3oJjUHyVVfZWfeq3ppzRE3l68OYaWzEPhgmolNB15uEYCzY/zro6A/3Hr8uZY9 9PuQ== X-Gm-Message-State: AOJu0YzbFqYBkQYYPTW3sHwMULaChmuIPdNWlM+o20tz61NXVa/QFQu+ i3nJXc3fJGwig6cW433UXvQgG69lh4x7pM+5pGCJPCJg9ffSmqWlHmBV X-Gm-Gg: AZuq6aKE/L+RCz+aDCqOc7+MlKdVmrSlIRpSk5B6lFzR5PlD70C/cYqFdudeYeXE+E2 sld+bWJy4eh3hMj0qFvgV8ORXnJ78z3l1oQ9ZOTOPueQn8PGv5HPuj8TZr6JNTz0t78iCc9EdFf vZm3LjQFrmX/37kWQLTqBTVr8W/5oj9K1W1LiM4bIWdSwMH6gGXkBG0o+qkAKKvYiOWnXyypTgn 6044mUFxRVRsA89TCOF27ERU3yG5NpR6RQweKYpqLBAttozvVmPnSbQrlnp8+OL409QN/2jvEu7 oTlMnj1xRlf8oyrN0JcZBuYGwc7tMkfL8BpACguoafJwnAmnr4TkvUDuNRHIq85nM+ueDx0yXTq KNWHXhXlv61Hpdcg0fESG1Mis7+BXn6z8CVd+iIW7+ubIP9o2RB0/K9ZmMTfx+a/Ggu1GaZrfwu x/EqWtzA0IYOo2yOOHIIOMc77CQUfA9kRL+bKpluiRXsRkqVvUbLZtCJXddcA= X-Received: by 2002:a17:903:22c5:b0:2a0:9eed:5182 with SMTP id d9443c01a7336-2a7698f99e1mr6136605ad.20.1768885139717; Mon, 19 Jan 2026 20:58:59 -0800 (PST) From: Chao Liu To: Alistair Francis , Daniel Henrique Barboza , Palmer Dabbelt , Weiwei Li , Liu Zhiwei Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, wangjingwei@iscas.ac.cn, Chao Liu , Chao Liu Subject: [PATCH v4 5/5] docs/system/riscv: add documentation for k230 machine Date: Tue, 20 Jan 2026 12:56:55 +0800 Message-ID: <03fd30a68eae5d850953fef26f9b69294ff00048.1768884546.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::642; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-pl1-x642.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-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: 1768885166844154100 From: Chao Liu Add documentation for k230 virt reference platform. Signed-off-by: Chao Liu Reviewed-by: Daniel Henrique Barboza --- MAINTAINERS | 1 + docs/system/riscv/k230.rst | 48 ++++++++++++++++++++++++++++++++++++ docs/system/target-riscv.rst | 1 + 3 files changed, 50 insertions(+) create mode 100644 docs/system/riscv/k230.rst diff --git a/MAINTAINERS b/MAINTAINERS index 5464e7fb5c..80d6bd6e90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1761,6 +1761,7 @@ F: include/hw/riscv/xiangshan_kmh.h K230 Machines M: Chao Liu S: Maintained +F: docs/system/riscv/k230.rst F: hw/riscv/k230.c F: hw/watchdog/k230_wdt.c F: include/hw/riscv/k230.h diff --git a/docs/system/riscv/k230.rst b/docs/system/riscv/k230.rst new file mode 100644 index 0000000000..3e6ca295df --- /dev/null +++ b/docs/system/riscv/k230.rst @@ -0,0 +1,48 @@ +Kendryte K230 virt reference platform (``k230``) +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The ``k230`` machine is compatible with with Kendryte K230 SDK. + +The K230 is a chip from the AIoT SoC series made by Kendryte =C2=AE =E2=80= =94 a part of +Canaan Inc. It uses a brand-new multi-heterogeneous unit accelerated compu= ting +structure. + +This chip has 2 RISC-V computing cores and a new-generation KPU (Knowledge +Process Unit) smart computing unit. + +It has multi-precision AI computing ability, works with many common AI com= puting +frameworks, and for some typical networks, its usage rate is over 70%. Bes= ides, +the K230 chip supports many peripheral connections and has several special +hardware acceleration units (like 2D and 2.5D accelerators). It can speed = up +different tasks (such as image processing, video processing, audio process= ing +and AI computing). It also has many good features: low delay, high perform= ance, +low power use and fast start-up. + +For more information, see + +Supported devices +----------------- +The ``k230`` machine supports the following devices: + +* 1 c908 cores +* Core Local Interruptor (CLINT) +* Incoming MSI Controller (IMSIC) +* 2 K230 Watchdog Timer +* 4 UART + +Boot options +------------ +The ``k230`` machine can start using the standard ``-bios`` +functionality for loading the boot image. You need to compile and link +the firmware, kernel, and Device Tree (FDT) into a single binary file with +K230 SDK(k230_canmv_defconfig), such as ``uboot``. + +Running +------- +Below is an example command line for running the ``k230`` +machine: + +.. code-block:: bash + + $ qemu-system-riscv64 -machine k230 \ + -bios k230_sdk/output/k230_canmv_defconfig/little/uboot/u-boot \ + -nographic diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 3ad5d1ddaf..b0b2f9584f 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -66,6 +66,7 @@ undocumented; you can get a complete list by running .. toctree:: :maxdepth: 1 =20 + riscv/k230 riscv/microblaze-v-generic riscv/microchip-icicle-kit riscv/mips --=20 2.52.0