From nobody Mon Sep 28 02:05:47 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=1785418707; cv=none; d=zohomail.com; s=zohoarc; b=W2+qDeIvRX9/PRDijVv0FIkWawccMt0sWJeOnkwWXtWdykz/PQ6m3sej3xH7KuwZrJ8UdQWRjdqQB/Jx3w1O7tCeuE0KfuD17TZfMQ3mFhX28RsUZBC5GZ99fUFzJ5KKxsbZsco/6wxf6f/v5hHReoLCBBSnldcNKqHGZqArC3g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785418707; 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=VXeXaSmB/86trqyinsTj9cvA0T4G9xJkeVkYlBDivtA=; b=NPPNPlvehjsKslAnVJkLCYZy6jJYpb1tqV8SnN9DY8NL/gnoynbfN0yjbUip2f9J2QzLUB0MB7VVMJGRsBDxtjmHAGqSRQ91z2xXU49oORIp//X4Md8Pf4nARk7k3xGibM+jMUTGgeRli5RGduSXSIIBuypIb8hpftMWO8OzQmY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785418707294893.2490936352448; Thu, 30 Jul 2026 06:38:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wpQxO-0006Rp-9r; Thu, 30 Jul 2026 09:37:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpQx7-0006Gr-G8 for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:39 -0400 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wpQx4-0005y3-NH for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:37 -0400 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-2cab973140bso28812275ad.3 for ; Thu, 30 Jul 2026 06:37:34 -0700 (PDT) Received: from DESKTOP-DFGP8OG.lan ([120.230.138.58]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bf845asm26757745ad.60.2026.07.30.06.37.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jul 2026 06:37:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785418653; x=1786023453; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=VXeXaSmB/86trqyinsTj9cvA0T4G9xJkeVkYlBDivtA=; b=lTjk+BheNYIVGtq6Kc4Bd7iIyvfpi4Vbs/P+a6Vehhq2xcpKchdbhvtJrxdiN0QukO KSOK6/Xw1kplaPHrUHs6dTn7K8VT+fe7YIql0csq+V8hA3e2KlnwRlisxwl2NjKJRUd+ RcbHGR/+lW2G32uMpk9qrQkfiT4cC+q27KwjH5U0WvIRCUqgqkpEnTsIqjVZlgKM5yzr 8onale5i0XQQugguJ6lPMZ7luJNHKefkFTiB8eYglOHBAuV+7YqPGU/+hwPYYIdYsHjw 3JEz2ekc49vdEk1zi/wgeI43FIBSzS/X+iBwAOY3/WuWCK9aPt9fPxplBo/1Gsr4FgPC UAOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785418653; x=1786023453; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=VXeXaSmB/86trqyinsTj9cvA0T4G9xJkeVkYlBDivtA=; b=Lxf22NWRylYyiwMtO7D+7Qx6bG37JqEUwTvBqatPyhGAzpbFq+o0PEmtKr11KWEAbY enMZze1duc+71DQS+yfUe2phDv6o0rNE5NL++ad1sXODLWUlGbbApdntiJWX9n3URVm2 R7PVwd5NGCWcj1VMbE7pj9sRbpq+ATlw/6otnAoD+lnAxrq+rp0Rm4Idz835IV1Yqr+2 CWGMDtorLx3XrWrbPZrgNCU84sh9leYoyYH/Gwa9xOaWPdQSnjgEC4MeHoU/Hs21MEpt T5oylqowWxoOz+ieDBZk5V/hYNEKtPBQikoZhaezqNVpGC1e//dO3K5JArOzkDL86avs JvYA== X-Gm-Message-State: AOJu0YyjDXr44qITa6lhE4yXB6O3EUF/i56+cXV9qLL2/9uRUCw/TyFw fjc9BcM4PzBgZ73R7L1aJTJ8TQHr2ztV8BbzzwqzKKxAuqPFWmkFn+3S8uMiRgQEJMM= X-Gm-Gg: AR+sD13i2rNp8dTRzW1bnu78HS5RAjieWZSzEqrpfZQtB9fvdggpsxzyeOYL+XQISbn 9qR9klkIxQK5v2a4jlGpbg8aR/tsQFmikeVHpguQZfHaEpCunFBcPQS2mWL/HFYrE61nq7JwfhW zfo2BLDqBIXAQE3U5WedqfxHCm8HG/jjtuNNjjgV4xy2sMShzId40brcRMAmGmRsDRsq1pmrhdg L60XoBljVLY3SHHoKJjXoN6AbZJLoB4Xf4k2U+TwDg58zJpXXdJKul1eJ4dB/xVSdtjy6sUcyek S2A1LTEN+le/LoEYV+TvcA3wlzphr1FXoPn0r6fgqeqtYfBhQKiSRULWEZejAvw33QpBNdSct6q CH8UPpGO3mwMs2VE5wLNkWTXWo4K8j5xScHf2VxhJmBZ2IK3lY3oioUzpDVFwqmjn9LXznsAh9G duZYzx7+apmAXGi+iGyJIGpwvO5P47xjR8ZqhNXEFZnSL/7Egd0ffRcEojOPRpa25kWYFQXuc= X-Received: by 2002:a17:902:cf4b:b0:2ca:e0ff:e696 with SMTP id d9443c01a7336-2d035b80aedmr27463865ad.9.1785418653146; Thu, 30 Jul 2026 06:37:33 -0700 (PDT) From: raoyi To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, pbonzini@redhat.com, palmer@dabbelt.com, alistair.francis@wdc.com, liwei1518@gmail.com, daniel.barboza@oss.qualcomm.com, zhiwei_liu@linux.alibaba.com, chao.liu@processmission.com, farosas@suse.de, lvivier@redhat.com, caojunze424@gmail.com, raoyi Subject: [PATCH v2 1/3] hw/timer: add k230 dwapb timer model Date: Thu, 30 Jul 2026 21:37:09 +0800 Message-ID: <20260730133713.3253-2-rao232328@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260730133713.3253-1-rao232328@gmail.com> References: <20260730133713.3253-1-rao232328@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::629; envelope-from=rao232328@gmail.com; helo=mail-pl1-x629.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-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: 1785418708010158500 Content-Type: text/plain; charset="utf-8" Add DesignWare APB timer model for K230 machine. The timer uses the Clock framework for frequency input, preparing for future CMU integration. Signed-off-by: raoyi --- hw/timer/Kconfig | 4 + hw/timer/k230_dwapb_timer.c | 317 ++++++++++++++++++++++++++++ hw/timer/meson.build | 1 + hw/timer/trace-events | 9 + include/hw/timer/k230_dwapb_timer.h | 72 +++++++ 5 files changed, 403 insertions(+) create mode 100644 hw/timer/k230_dwapb_timer.c create mode 100644 include/hw/timer/k230_dwapb_timer.h diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index b3d823ce2c..9d1f20f5cd 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -65,3 +65,7 @@ config STELLARIS_GPTM =20 config AVR_TIMER16 bool + +config K230_TIMER + bool + select PTIMER diff --git a/hw/timer/k230_dwapb_timer.c b/hw/timer/k230_dwapb_timer.c new file mode 100644 index 0000000000..623f84cafd --- /dev/null +++ b/hw/timer/k230_dwapb_timer.c @@ -0,0 +1,317 @@ +/* + * K230 DW APB timer + * + * Copyright (c) 2026 raoyi + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * K230 Technical Reference Manual V0.3.1 (2024-11-18): + * https://github.com/revyos/external-docs/blob/master/K230/en-us/K230_Tec= hnical_Reference_Manual_V0.3.1_20241118.pdf + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/core/sysbus.h" +#include "hw/core/ptimer.h" +#include "hw/core/qdev-clock.h" +#include "hw/timer/k230_dwapb_timer.h" +#include "trace.h" + +static void k230_timer_clk_update(void *opaque, ClockEvent event) +{ + K230TimerState *s =3D K230_TIMER(opaque); + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + if (!s->timers[i].ptimer) { + continue; + } + ptimer_transaction_begin(s->timers[i].ptimer); + ptimer_set_period_from_clock(s->timers[i].ptimer, s->pclk, 1); + ptimer_transaction_commit(s->timers[i].ptimer); + } +} + +static void k230_timer_enable(K230Timer *t) +{ + ptimer_transaction_begin(t->ptimer); + ptimer_set_limit(t->ptimer, t->load ? t->load : 1, 1); + ptimer_run(t->ptimer, 1); + ptimer_transaction_commit(t->ptimer); + + trace_k230_timer_enable(t->id, t->load); +} + +static void k230_timer_disable(K230Timer *t) +{ + ptimer_transaction_begin(t->ptimer); + ptimer_stop(t->ptimer); + ptimer_transaction_commit(t->ptimer); + + t->int_status =3D 0; + qemu_set_irq(t->irq, 0); + + trace_k230_timer_disable(t->id); +} + +static void k230_timer_tick(void *opaque) +{ + K230Timer *t =3D opaque; + uint32_t reload; + + trace_k230_timer_tick(t->id); + + t->int_status =3D 1; + + if (!(t->control & K230_APBTMR_CONTROL_INT)) { + qemu_set_irq(t->irq, 1); + trace_k230_timer_interrupt(t->id); + } + + if (t->control & K230_APBTMR_CONTROL_MODE_PERIODIC) { + reload =3D t->load ? t->load : 1; + } else { + reload =3D UINT32_MAX; + } + + ptimer_set_limit(t->ptimer, reload, 1); + ptimer_run(t->ptimer, 1); +} + +static uint64_t k230_timer_read(void *opaque, hwaddr addr, unsigned int si= ze) +{ + K230TimerState *s =3D K230_TIMER(opaque); + uint32_t value =3D 0; + + addr &=3D 0xfff; + + if (addr < K230_APBTMRS_INT_STATUS) { + int idx =3D addr / K230_APBTMR_STRIDE; + int reg =3D addr % K230_APBTMR_STRIDE; + + if (idx < K230_APBTMR_NUM_TIMERS) { + switch (reg) { + case K230_APBTMR_N_LOAD_COUNT: + value =3D s->timers[idx].load; + break; + case K230_APBTMR_N_CURRENT_VALUE: + if (s->timers[idx].control & K230_APBTMR_CONTROL_ENABLE) { + value =3D ptimer_get_count(s->timers[idx].ptimer); + } else { + value =3D 0; + } + break; + case K230_APBTMR_N_CONTROL: + value =3D s->timers[idx].control; + break; + case K230_APBTMR_N_EOI: + s->timers[idx].int_status =3D 0; + qemu_set_irq(s->timers[idx].irq, 0); + trace_k230_timer_irq_clear(s->timers[idx].id); + value =3D 0; + break; + case K230_APBTMR_N_INT_STATUS: + if (s->timers[idx].control & K230_APBTMR_CONTROL_INT) { + value =3D 0; + } else { + value =3D s->timers[idx].int_status; + } + break; + } + } + } else if (addr >=3D K230_APBTMR_N_LOAD2 && + addr < K230_APBTMR_N_LOAD2 + + K230_APBTMR_NUM_TIMERS * K230_APBTMR_LOAD2_STRIDE) { + int idx =3D (addr - K230_APBTMR_N_LOAD2) / K230_APBTMR_LOAD2_STRID= E; + value =3D s->timers[idx].load2; + } else { + switch (addr) { + case K230_APBTMRS_INT_STATUS: + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + if (!(s->timers[i].control & K230_APBTMR_CONTROL_INT)) { + value |=3D s->timers[i].int_status << i; + } + } + break; + case K230_APBTMRS_EOI: + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + s->timers[i].int_status =3D 0; + qemu_set_irq(s->timers[i].irq, 0); + } + value =3D 0; + break; + case K230_APBTMRS_RAW_INT_STATUS: + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + value |=3D s->timers[i].int_status << i; + } + break; + case K230_APBTMRS_COMP_VERSION: + value =3D K230_APBTMR_COMP_VERSION_VAL; + break; + } + } + + trace_k230_timer_read(addr, value); + return value; +} + +static void k230_timer_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + K230TimerState *s =3D K230_TIMER(opaque); + + addr &=3D 0xfff; + + if (addr < K230_APBTMRS_INT_STATUS) { + int idx =3D addr / K230_APBTMR_STRIDE; + int reg =3D addr % K230_APBTMR_STRIDE; + + if (idx < K230_APBTMR_NUM_TIMERS) { + switch (reg) { + case K230_APBTMR_N_LOAD_COUNT: + s->timers[idx].load =3D value; + break; + case K230_APBTMR_N_CONTROL: { + uint32_t old_ctrl =3D s->timers[idx].control; + s->timers[idx].control =3D value & K230_APBTMR_CONTROL_RW_= MASK; + if ((value ^ old_ctrl) & K230_APBTMR_CONTROL_ENABLE) { + if (value & K230_APBTMR_CONTROL_ENABLE) { + k230_timer_enable(&s->timers[idx]); + } else { + k230_timer_disable(&s->timers[idx]); + } + } + if ((value ^ old_ctrl) & K230_APBTMR_CONTROL_INT) { + if (value & K230_APBTMR_CONTROL_INT) { + qemu_set_irq(s->timers[idx].irq, 0); + } else if (s->timers[idx].int_status) { + qemu_set_irq(s->timers[idx].irq, 1); + } + } + break; + } + default: + break; + } + } + } else if (addr >=3D K230_APBTMR_N_LOAD2 && + addr < K230_APBTMR_N_LOAD2 + + K230_APBTMR_NUM_TIMERS * K230_APBTMR_LOAD2_STRIDE) { + int idx =3D (addr - K230_APBTMR_N_LOAD2) / K230_APBTMR_LOAD2_STRID= E; + s->timers[idx].load2 =3D value; + } + + trace_k230_timer_write(addr, value); +} + +static const MemoryRegionOps k230_timer_ops =3D { + .read =3D k230_timer_read, + .write =3D k230_timer_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void k230_timer_realize(DeviceState *dev, Error **errp) +{ + K230TimerState *s =3D K230_TIMER(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + if (!clock_has_source(s->pclk)) { + error_setg(errp, "K230 DW APB timer: pclk clock must be connected"= ); + return; + } + + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + s->timers[i].id =3D i; + s->timers[i].ptimer =3D ptimer_init(k230_timer_tick, &s->timers[i], + PTIMER_POLICY_NO_IMMEDIATE_TRIGGER | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD | + PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); + ptimer_transaction_begin(s->timers[i].ptimer); + ptimer_set_limit(s->timers[i].ptimer, UINT32_MAX, 1); + ptimer_transaction_commit(s->timers[i].ptimer); + sysbus_init_irq(sbd, &s->timers[i].irq); + } + + k230_timer_clk_update(s, ClockUpdate); + + memory_region_init_io(&s->mmio, OBJECT(dev), &k230_timer_ops, + s, TYPE_K230_TIMER, K230_APBTMR_MMIO_SIZE); + sysbus_init_mmio(sbd, &s->mmio); +} + +static void k230_timer_reset(DeviceState *dev) +{ + K230TimerState *s =3D K230_TIMER(dev); + + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + K230Timer *t =3D &s->timers[i]; + + ptimer_transaction_begin(t->ptimer); + ptimer_stop(t->ptimer); + ptimer_transaction_commit(t->ptimer); + + t->load =3D 0; + t->load2 =3D 0; + t->control =3D 0; + t->int_status =3D 0; + qemu_set_irq(t->irq, 0); + } +} + +static const VMStateDescription vmstate_k230_timer_channel =3D { + .name =3D "k230-dwapb-timer-channel", + .fields =3D (const VMStateField[]) { + VMSTATE_PTIMER(ptimer, K230Timer), + VMSTATE_UINT32(load, K230Timer), + VMSTATE_UINT32(load2, K230Timer), + VMSTATE_UINT32(control, K230Timer), + VMSTATE_UINT32(int_status, K230Timer), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_k230_timer =3D { + .name =3D "k230-dwapb-timer", + .fields =3D (const VMStateField[]) { + VMSTATE_CLOCK(pclk, K230TimerState), + VMSTATE_STRUCT_ARRAY(timers, K230TimerState, + K230_APBTMR_NUM_TIMERS, 0, + vmstate_k230_timer_channel, K230Timer), + VMSTATE_END_OF_LIST() + } +}; + +static void k230_timer_init(Object *obj) +{ + K230TimerState *s =3D K230_TIMER(obj); + s->pclk =3D qdev_init_clock_in(DEVICE(obj), "pclk", k230_timer_clk_upd= ate, + s, ClockUpdate); +} + +static void k230_timer_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + dc->realize =3D k230_timer_realize; + dc->vmsd =3D &vmstate_k230_timer; + dc->desc =3D "K230 DW APB timer"; + device_class_set_legacy_reset(dc, k230_timer_reset); +} + +static const TypeInfo k230_timer_info =3D { + .name =3D TYPE_K230_TIMER, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(K230TimerState), + .instance_init =3D k230_timer_init, + .class_init =3D k230_timer_class_init, +}; + +static void k230_timer_register_type(void) +{ + type_register_static(&k230_timer_info); +} +type_init(k230_timer_register_type) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 201b5d8316..d0a834e127 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -34,3 +34,4 @@ specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex= _timer.c')) system_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) =20 system_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) +system_ss.add(when: 'CONFIG_K230_TIMER', if_true: files('k230_dwapb_timer.= c')) diff --git a/hw/timer/trace-events b/hw/timer/trace-events index 634ba1da27..89c619bc87 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -1,5 +1,14 @@ # See docs/devel/tracing.rst for syntax documentation. =20 +# k230_dwapb_timer.c +k230_timer_read(uint64_t addr, uint32_t val) "K230 timer read: [0x%" PRIx6= 4 "] -> 0x%" PRIx32 +k230_timer_write(uint64_t addr, uint64_t val) "K230 timer write: [0x%" PRI= x64 "] <- 0x%" PRIx64 +k230_timer_tick(int idx) "K230 timer %d tick" +k230_timer_interrupt(int idx) "K230 timer %d IRQ asserted" +k230_timer_irq_clear(int idx) "K230 timer %d IRQ cleared" +k230_timer_enable(int idx, uint32_t load) "K230 timer %d enabled load=3D0x= %" PRIx32 +k230_timer_disable(int idx) "K230 timer %d disabled" + # slavio_timer.c slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "= limit 0x%"PRIx64" count 0x%x0x%08x" slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count 0x%x= 0x%08x" diff --git a/include/hw/timer/k230_dwapb_timer.h b/include/hw/timer/k230_dw= apb_timer.h new file mode 100644 index 0000000000..3aba178dfa --- /dev/null +++ b/include/hw/timer/k230_dwapb_timer.h @@ -0,0 +1,72 @@ +/* + * K230 DW APB timer + * + * Copyright (c) 2026 raoyi + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * K230 Technical Reference Manual V0.3.1 (2024-11-18): + * https://github.com/revyos/external-docs/blob/master/K230/en-us/K230_Tec= hnical_Reference_Manual_V0.3.1_20241118.pdf + */ + +#ifndef K230_DWAPB_TIMER_H +#define K230_DWAPB_TIMER_H + +#include "qemu/bitops.h" +#include "hw/core/sysbus.h" +#include "hw/core/irq.h" +#include "hw/core/clock.h" +#include "qom/object.h" + +#define TYPE_K230_TIMER "riscv.k230.timer" +OBJECT_DECLARE_SIMPLE_TYPE(K230TimerState, K230_TIMER) + +#define K230_APBTMR_MMIO_SIZE 0x800 +#define K230_APBTMR_NUM_TIMERS 6 +#define K230_APBTMR_STRIDE 0x14 +#define K230_APBTMR_DEFAULT_FREQ 6250000 +#define K230_APBTMR_COMP_VERSION_VAL 0x3231312A +#define K230_APBTMR_LOAD2_STRIDE 0x04 + +/* Per-timer register offsets */ +#define K230_APBTMR_N_LOAD_COUNT 0x00 +#define K230_APBTMR_N_CURRENT_VALUE 0x04 +#define K230_APBTMR_N_CONTROL 0x08 +#define K230_APBTMR_N_EOI 0x0c +#define K230_APBTMR_N_INT_STATUS 0x10 +/* Global register offsets */ +#define K230_APBTMRS_INT_STATUS 0xa0 +#define K230_APBTMRS_EOI 0xa4 +#define K230_APBTMRS_RAW_INT_STATUS 0xa8 +#define K230_APBTMRS_COMP_VERSION 0xac +/* PWM LoadCount2 registers */ +#define K230_APBTMR_N_LOAD2 0xb0 + +/* Control register bits */ +#define K230_APBTMR_CONTROL_ENABLE BIT(0) +#define K230_APBTMR_CONTROL_MODE_PERIODIC BIT(1) +#define K230_APBTMR_CONTROL_INT BIT(2) +#define K230_APBTMR_CONTROL_PWM BIT(3) +#define K230_APBTMR_CONTROL_RW_MASK 0xf + +typedef struct K230Timer { + struct ptimer_state *ptimer; + qemu_irq irq; + int id; + uint32_t load; + uint32_t load2; + uint32_t control; + uint32_t int_status; +} K230Timer; + +struct K230TimerState { + /* */ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + K230Timer timers[K230_APBTMR_NUM_TIMERS]; + Clock *pclk; +}; + +#endif --=20 2.53.0 From nobody Mon Sep 28 02:05:47 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=1785418705; cv=none; d=zohomail.com; s=zohoarc; b=I2stetr9oHrNLQItGNRGsBv1j1rkVe1jBHekz4U/PbKU8DVCFp769SyDYKBpKsT3rjxKLRsM6/5w20lO2NTyzz2FkuUJQlg+Bki6xwfmNBU9l9EYeIiHPKevjBMs0vbFJtjkyMQWu4kdTr16AiPb9DF0PtLUL9QnxXZwffW0j2w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785418705; 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=hGVPXsOP9uyqFKFA6uavYqfpocB6qSsHNa9L6NkdoEU=; b=KsHmEyIWRRPC93TQEX85zfMDNqFGm8f7FYrX7irzPNBeh8g0F2kfrIcrTEfFV39d22uklYhk1DNOryd1WrkbOZe5SDW+qEufafH9HbLlknQt7SCgpLJgze2AAUGyPz6Un6ipDKZlrilyM/nxy7vxmsHbvKY8EImTohqru14yMXg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785418705420734.8708502448862; Thu, 30 Jul 2026 06:38:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wpQxP-0006X4-5m; Thu, 30 Jul 2026 09:37:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpQxD-0006K1-Ua for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:47 -0400 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wpQxC-0005yZ-6j for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:43 -0400 Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-2cab973140bso28813725ad.3 for ; Thu, 30 Jul 2026 06:37:41 -0700 (PDT) Received: from DESKTOP-DFGP8OG.lan ([120.230.138.58]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bf845asm26757745ad.60.2026.07.30.06.37.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jul 2026 06:37:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785418660; x=1786023460; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=hGVPXsOP9uyqFKFA6uavYqfpocB6qSsHNa9L6NkdoEU=; b=LTniMEPAs19xuC8J/iq0ErJdby9MIkIGjCgQUacYlXSDWqbaI2wAo+GkaPomtCJ7+L 4axtSaOzb/RQ7KoWQha3jq/5w9pOz5pKvznyuxyyZEV9SQFWkgfKOl5p9csAOrqs57XI tN/WxbNlv1KKr1XXfChLOUxKoZ9KLmj5CgbpMk9PMp1tSeRnrGyEvIb2SSPHJ15PLQri uaJArH3S/Le+Ud9eFQRTnHbbhc6kyykomBiGxdZQhEQ+qxhy0KchdoYvnmoJiXQgN29j jnDbRS9/d4/H+2nh4SrWQqbFlqMK5IqDgcZig+GQ+XiuEh/OHOUvyJpq7KQsfiNodOb3 f4sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785418660; x=1786023460; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=hGVPXsOP9uyqFKFA6uavYqfpocB6qSsHNa9L6NkdoEU=; b=FE4+on9obKkyMhA8pcwrJ77pDIJXv2DwJ/n1a9LgycsKtX9Uk4v2wavIIZoNC4JikH IuxJtINuiXV5aSzMJl8Yqug3oBRyqR2b9YZw+wxPCRYPiS9MEzX6pol5AsHHUpgQAVBL gHbK3ZyDRNivtRSodnVXpxbfp9rxP5u0j329heqigUmgee8wapRCVFWzSIuqgpHUsbi9 GOYEzRKZgtCKWbJQgFTq7LDGLdKDFj0kswoDDdCb80C1IPkNvWfYKtIu6dzdGyej79rE 1fgs2XMm+uQ3FqI4awhN8FAJCJnncs2IQBqYkFHZdxjQ918kurvWJi0I75dfAfTyKgkR rV7A== X-Gm-Message-State: AOJu0Yyrk92ARMsBwxH3DMlaEChGCpM6pQrcU8bN/iAg8Ego0V/OnBkJ 91u99wg+IK78DldoQvzzGKmz5vzpeTImNWfgcuF4LvqLRczV5/P/PzlsNpzMqNU19JI= X-Gm-Gg: AR+sD12u4Up3vJ4olYt0kk6iavPZKxf89bbSi9YeKuc8Z++v1C4R4OGxEsWUkxjyZav 4eEcxFslx4J18Yjb7qP4SncP2RsY1oQK2KUBFyjsNDMfSMCZUTQL19HFVbudZNutnfc/wbhbTt6 UiizKE/0rD7F5CYUyOyC1ByBgW9kwAd4W1JHsMVNdRNgcdIVgrf3ZDDAkgDY/p7Pjl/9O5BUkr7 w8mlnmGFS1H5s2LDnRJ3PLd/439XF2MLJuM2x0UPoh1nSwo3xu6y0lInYb4A413/kngKGQGPsQE iXTCSl0w/OzPlAVj+Lt7MQrrPZARLbQPitneGEEgR3/NHdt+9fs2MWebaP6KaV64OEniNZ8BygH LHFip6XKe8y3xoNd1CswmTkW8PUr4kxrvuNQYOD/Uoxm4sQJUTS4R1Efcck9HM7oP22g9C1/B2N PkmA3PTsdxbjweiaO+Aw9VNhwSCj5i5X45WGOPdOEWahBSHypwF02ccDEwWs6fJXhhiq7xBsk= X-Received: by 2002:a17:903:2444:b0:2cf:82e6:a5 with SMTP id d9443c01a7336-2d035bb12e3mr24469355ad.13.1785418659834; Thu, 30 Jul 2026 06:37:39 -0700 (PDT) From: raoyi To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, pbonzini@redhat.com, palmer@dabbelt.com, alistair.francis@wdc.com, liwei1518@gmail.com, daniel.barboza@oss.qualcomm.com, zhiwei_liu@linux.alibaba.com, chao.liu@processmission.com, farosas@suse.de, lvivier@redhat.com, caojunze424@gmail.com, raoyi Subject: [PATCH v2 2/3] hw/riscv: integrate k230 dwapb timer into k230 board Date: Thu, 30 Jul 2026 21:37:10 +0800 Message-ID: <20260730133713.3253-3-rao232328@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260730133713.3253-1-rao232328@gmail.com> References: <20260730133713.3253-1-rao232328@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::62c; envelope-from=rao232328@gmail.com; helo=mail-pl1-x62c.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-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: 1785418706010158500 Content-Type: text/plain; charset="utf-8" Wire up the K230 DW APB timer to the K230 SoC, including PLIC IRQ connections and memory mapping. Remove the previous unimplemented timer stub. Signed-off-by: raoyi --- hw/riscv/Kconfig | 1 + hw/riscv/k230.c | 23 ++++++++++++++++++++--- include/hw/riscv/k230.h | 8 ++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index de37c08cae..c86968f759 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -162,3 +162,4 @@ config K230 select SERIAL_MM select UNIMP select K230_WDT + select K230_TIMER diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c index 656f28190c..214fb3525e 100644 --- a/hw/riscv/k230.c +++ b/hw/riscv/k230.c @@ -24,6 +24,8 @@ #include "target/riscv/cpu.h" #include "hw/core/loader.h" #include "hw/core/sysbus.h" +#include "hw/core/clock.h" +#include "hw/core/qdev-clock.h" #include "hw/riscv/k230.h" #include "hw/riscv/boot.h" #include "hw/riscv/machines-qom.h" @@ -110,6 +112,12 @@ static void k230_soc_init(Object *obj) object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY); object_initialize_child(obj, "k230-wdt0", &s->wdt[0], TYPE_K230_WDT); object_initialize_child(obj, "k230-wdt1", &s->wdt[1], TYPE_K230_WDT); + object_initialize_child(obj, "k230-dwapb-timer", &s->timer, + TYPE_K230_TIMER); + + Clock *timer_clk =3D clock_new(OBJECT(s), "timer-clk"); + clock_set_hz(timer_clk, K230_APBTMR_DEFAULT_FREQ); + qdev_connect_clock_in(DEVICE(&s->timer), "pclk", timer_clk); =20 qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0); qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C9= 08); @@ -191,6 +199,18 @@ static void k230_soc_realize(DeviceState *dev, Error *= *errp) k230_create_uart(sys_mem, DEVICE(s->c908_plic), i); } =20 + /* Timer */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, memmap[K230_DEV_TIMER].b= ase); + + for (int i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), i, + qdev_get_gpio_in(DEVICE(s->c908_plic), + K230_TIMER0_IRQ + i)); + } + /* Watchdog */ for (int i =3D 0; i < 2; i++) { if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { @@ -283,9 +303,6 @@ static void k230_soc_realize(DeviceState *dev, Error **= errp) create_unimplemented_device("iomux", memmap[K230_DEV_IOMUX].base, memmap[K230_DEV_IOMUX].size); =20 - 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); =20 diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h index 592e1c26bf..3de3b7e765 100644 --- a/include/hw/riscv/k230.h +++ b/include/hw/riscv/k230.h @@ -18,6 +18,7 @@ #include "hw/core/boards.h" #include "hw/riscv/riscv_hart.h" #include "hw/watchdog/k230_wdt.h" +#include "hw/timer/k230_dwapb_timer.h" =20 #define C908_CPU_HARTID (0) =20 @@ -33,6 +34,7 @@ typedef struct K230SoCState { RISCVHartArrayState c908_cpu; /* Small core */ =20 K230WdtState wdt[2]; + K230TimerState timer; MemoryRegion sram; MemoryRegion bootrom; =20 @@ -127,6 +129,12 @@ enum { K230_UART2_IRQ =3D 18, K230_UART3_IRQ =3D 19, K230_UART4_IRQ =3D 20, + K230_TIMER0_IRQ =3D 101, + K230_TIMER1_IRQ =3D 102, + K230_TIMER2_IRQ =3D 103, + K230_TIMER3_IRQ =3D 104, + K230_TIMER4_IRQ =3D 105, + K230_TIMER5_IRQ =3D 106, K230_WDT0_IRQ =3D 107, K230_WDT1_IRQ =3D 108, }; --=20 2.53.0 From nobody Mon Sep 28 02:05:47 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=1785418716; cv=none; d=zohomail.com; s=zohoarc; b=bWyjIp4rt9jCsqD5Qp7jP3joDEhTmOOgYVoxXeXRu2gVLAWSaipi7B5qqAj5oVe83pUj51k6k2sism5oUMYnTtlFnXX7wMvK1h7ktTailXF9d17XtqzmUsqYmO2hGcOVVwYjosQcVXxXUs1tXj3xrVbwnce11bh+5HpdesKmiUQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785418716; 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=YBIc7qU1l7UiaSisuLpSrifHwV7mtioEOP66kgKIfac=; b=a+ZqY3jYlMQ2ORkyiZDlAPlbdMu96rusoxrWitKeyMgxotoijQC4gBtnA2aAtckTUcM/aBooOe10Rvb9AEeAX1kWZv9KWDiammccMce75d7ILlYdLTyD6vz/Y9C5qe8t77ifMP3yBw+lXVSgAmUdc6OH5xsuKQ50G2j5aXuX+xU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785418716840619.9020111971657; Thu, 30 Jul 2026 06:38:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wpQxP-0006a4-Kc; Thu, 30 Jul 2026 09:37:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpQxK-0006Pq-1b for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:51 -0400 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wpQxH-0005z7-VQ for qemu-devel@nongnu.org; Thu, 30 Jul 2026 09:37:49 -0400 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-2ceab75934dso25174605ad.2 for ; Thu, 30 Jul 2026 06:37:47 -0700 (PDT) Received: from DESKTOP-DFGP8OG.lan ([120.230.138.58]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022bf845asm26757745ad.60.2026.07.30.06.37.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jul 2026 06:37:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785418667; x=1786023467; darn=nongnu.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=YBIc7qU1l7UiaSisuLpSrifHwV7mtioEOP66kgKIfac=; b=YSEbrPafuka08Sgj4R3+1HRILrVV8G/WSCeWlskpLO3XNeOGUNxgW3dv/3rwzqB3T6 aC5uFVxXFOwYQvJb5uA949KvUi+mQU/QdOE6SQxkoNcK+FSODU465xiJCvjTglwUZiVa zItPwhg28UrgpKaUnMcqn3bFQdFR+kaafZInLOyOyhg5ciAN6oA4I23r1+vM+DyW2fiF B0UaIjFO9LZ8i5/MZYQPyCrHMcboPIK4QffguoUNMgLUd/0R9NJGlR9zpjXMp9rhk8/l SwM/as8YVUe9sAzh8HBPQxHdtgKgdJGYaBtdmJDILgDAPBlD9Q4kGqAOHcq5iPYBPO0R rdtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785418667; x=1786023467; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=YBIc7qU1l7UiaSisuLpSrifHwV7mtioEOP66kgKIfac=; b=BigVCs9y7BzFMN2scGL/P881ggSaOg+fSe7ziFwHoZe8aJsQaniPxRVCABPCafSedd /LITe++1zKj0zZCEGk1i1m9gZl2MsDQfctmMYjjIKVopl8fJ/QWjoS+4Q91ORtC2w9zQ xC7TEftOe9MPNDT1jJuOP/bXQ4Gel2p/77EAk6oZwFXrVujRxvsBjiRzavu9SYYyhBvJ ir6z5heTuW8FviC6ySGjjkM9x06rOapHrFXmJN0hcIbmGbbBplTo/BA4+9czEsGUDfFR PydOfqb/LcbI2mqLvlfuDv7ZzBaziwcgaFA/Bp/Ic4lwEHBlT1pZcq6hF8IhA+SkiT5i +7rw== X-Gm-Message-State: AOJu0YwLcYGcS2v8u1l1CX69YLlhDGyHys412gQh8XzWtJkNBex2Zfzr dL8vP4NoreDsnlX2ry7ekSSa9qdPrTZQEA4A6NVltPO5KsvwgwW6wsizGdaUU3H1feg= X-Gm-Gg: AR+sD10PcXC9ifVSUXCGFGtoKAkeQ1OZFQTWs4CLoj8GHCgUAP9bH9ncc53aAIguLch YTfRKuYMeOseB6d7q9L2Vx4jE5SqyPB05CZP/RgsPuewQOw4YzsPaaT5kDAyA23n3WO3ube49d1 6gHnMJXBR//aD9KliQpZ7s58Vm0gBPVKygV9lCxsYZaTBYq3oeTefkGgh0QqCd3jiurPXPRWOpX 0U6M1ErnZBaVjumKUHu9DCd4TS0JbvkrkMXCU2cWBnxrya/xu1jC5Lyx7oFVFZIRASgfAESh+59 acOMWZbNIw/L8//8YWXbC1ELE1S2LJHUMOAmHdvG6hGqO9LaZCbzuKCUeJr5LYU7XPK+GnXfpSj xy4WMcXDkMUKcRiwUfPekgDg00NWmTOYJKZbd/0mJdRxc3BaHUsW3nYcrczphxS3wrzqrj0JMHK pAhIN4CHyp/OiMKo9+RnjwWhW9pKruSQDUqfPasjXvcFAkr2lHqgf79odOR663uvKtvX/0B4Y= X-Received: by 2002:a17:902:cf41:b0:2c9:df1b:e948 with SMTP id d9443c01a7336-2d035b94236mr28369805ad.4.1785418666530; Thu, 30 Jul 2026 06:37:46 -0700 (PDT) From: raoyi To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, pbonzini@redhat.com, palmer@dabbelt.com, alistair.francis@wdc.com, liwei1518@gmail.com, daniel.barboza@oss.qualcomm.com, zhiwei_liu@linux.alibaba.com, chao.liu@processmission.com, farosas@suse.de, lvivier@redhat.com, caojunze424@gmail.com, raoyi Subject: [PATCH v2 3/3] tests/qtest: add k230 dwapb timer test Date: Thu, 30 Jul 2026 21:37:11 +0800 Message-ID: <20260730133713.3253-4-rao232328@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260730133713.3253-1-rao232328@gmail.com> References: <20260730133713.3253-1-rao232328@gmail.com> 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=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=rao232328@gmail.com; helo=mail-pl1-x634.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-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: 1785418718042158500 Add qtest coverage for K230 DW APB timer including free-running, periodic, interrupt mask, disable behavior, current value, dynamic reload, and multi-channel scenarios. Add timer files to MAINTAINERS. Signed-off-by: raoyi --- MAINTAINERS | 3 + tests/qtest/k230-dwapb-timer-test.c | 227 ++++++++++++++++++++++++++++ tests/qtest/meson.build | 2 +- 3 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/k230-dwapb-timer-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 6171cc7494..ed2ba7c58a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1826,9 +1826,12 @@ S: Maintained F: docs/system/riscv/k230.rst F: hw/riscv/k230.c F: hw/watchdog/k230_wdt.c +F: hw/timer/k230_dwapb_timer.c F: include/hw/riscv/k230.h F: include/hw/watchdog/k230_wdt.h +F: include/hw/timer/k230_dwapb_timer.h F: tests/qtest/k230-wdt-test.c +F: tests/qtest/k230-dwapb-timer-test.c =20 RX Machines ----------- diff --git a/tests/qtest/k230-dwapb-timer-test.c b/tests/qtest/k230-dwapb-t= imer-test.c new file mode 100644 index 0000000000..7fe380bb61 --- /dev/null +++ b/tests/qtest/k230-dwapb-timer-test.c @@ -0,0 +1,227 @@ +/* + * QTest testcase for K230 Timer + * + * Copyright (c) 2026 raoyi + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "qemu/timer.h" +#include "libqtest.h" +#include "hw/timer/k230_dwapb_timer.h" + +#define TIMER_BASE 0x91105800 +#define TIMER_REG(n, reg) (TIMER_BASE + (n) * K230_APBTMR_STRIDE + (reg)) +#define TIMER_TICK_NS (NANOSECONDS_PER_SECOND / K230_APBTMR_DEFAULT_FREQ) + +static void timer_load(QTestState *qts, int n, uint32_t value) +{ + qtest_writel(qts, TIMER_REG(n, K230_APBTMR_N_LOAD_COUNT), value); +} + +static void timer_enable(QTestState *qts, int n, uint32_t ctrl) +{ + qtest_writel(qts, TIMER_REG(n, K230_APBTMR_N_CONTROL), ctrl); +} + +static void timer_disable(QTestState *qts, int n) +{ + qtest_writel(qts, TIMER_REG(n, K230_APBTMR_N_CONTROL), 0); +} + +static uint32_t timer_get_and_clear_irq(QTestState *qts, int n) +{ + uint32_t int_status =3D qtest_readl(qts, + TIMER_REG(n, K230_APBTMR_N_INT_STATUS)); + + if (int_status) { + qtest_readl(qts, TIMER_REG(n, K230_APBTMR_N_EOI)); + } + + return int_status; +} + +static void test_timer_free_running(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + timer_load(qts, 0, 100); + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE); + + qtest_clock_step(qts, 101ULL * TIMER_TICK_NS + 1); + g_assert_cmphex(timer_get_and_clear_irq(qts, 0), =3D=3D, 1); + + qtest_clock_step(qts, 10ULL * TIMER_TICK_NS); + uint32_t cur =3D qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)); + g_assert_cmphex(cur, <, UINT32_MAX); + g_assert_cmphex(cur, >, 0); + + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_INT_STATUS)), =3D=3D, 0); + + qtest_quit(qts); +} + +static void test_timer_periodic(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + int i; + + timer_load(qts, 0, 100); + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE | + K230_APBTMR_CONTROL_MODE_PERIODIC); + + for (i =3D 0; i < 3; i++) { + qtest_clock_step(qts, 101ULL * TIMER_TICK_NS + 1); + g_assert_cmphex(timer_get_and_clear_irq(qts, 0), =3D=3D, 1); + uint32_t cur =3D qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)); + g_assert_cmphex(cur, <=3D, 100); + } + + qtest_quit(qts); +} + +static void test_timer_int_mask(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + timer_load(qts, 0, 100); + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE | + K230_APBTMR_CONTROL_MODE_PERIODIC | + K230_APBTMR_CONTROL_INT); + + qtest_clock_step(qts, 101ULL * TIMER_TICK_NS + 1); + + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_INT_STATUS)) & 1, =3D=3D,= 0); + g_assert_cmphex(qtest_readl(qts, + TIMER_BASE + K230_APBTMRS_INT_STATUS), =3D=3D, 0); + g_assert_cmphex(qtest_readl(qts, + TIMER_BASE + K230_APBTMRS_RAW_INT_STATUS) & 1, =3D= =3D, 1); + + qtest_quit(qts); +} + +static void test_timer_disable_clears_irq(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + timer_load(qts, 0, 100); + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE | + K230_APBTMR_CONTROL_MODE_PERIODIC); + + qtest_clock_step(qts, 101ULL * TIMER_TICK_NS + 1); + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_INT_STATUS)) & 1, =3D=3D,= 1); + + timer_disable(qts, 0); + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_INT_STATUS)) & 1, =3D=3D,= 0); + + qtest_quit(qts); +} + +static void test_timer_current_disabled(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + + /* TRM: "A '0' is always read back when the timer is not enabled" */ + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)), =3D=3D, = 0); + + timer_load(qts, 0, 9999); + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)), =3D=3D, = 0); + + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE); + qtest_clock_step(qts, 10ULL * TIMER_TICK_NS); + uint32_t cur_enabled =3D qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)); + g_assert_cmphex(cur_enabled, >, 0); + g_assert_cmphex(cur_enabled, <, UINT32_MAX); + + timer_disable(qts, 0); + g_assert_cmphex(qtest_readl(qts, + TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)), =3D=3D, = 0); + + qtest_quit(qts); +} + +static void test_timer_dynamic_reload(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + uint32_t cur; + + timer_load(qts, 0, 1000); + timer_enable(qts, 0, K230_APBTMR_CONTROL_ENABLE | + K230_APBTMR_CONTROL_MODE_PERIODIC); + + qtest_clock_step(qts, 100ULL * TIMER_TICK_NS); + + timer_load(qts, 0, 200); + + qtest_clock_step(qts, 901ULL * TIMER_TICK_NS + 1); + g_assert_cmphex(timer_get_and_clear_irq(qts, 0), =3D=3D, 1); + + qtest_clock_step(qts, 100ULL * TIMER_TICK_NS); + cur =3D qtest_readl(qts, TIMER_REG(0, K230_APBTMR_N_CURRENT_VALUE)); + g_assert_cmphex(cur, =3D=3D, 99); + + qtest_quit(qts); +} + +static void test_timer_all_channels(void) +{ + QTestState *qts =3D qtest_init("-machine k230"); + int i; + + for (i =3D 0; i < K230_APBTMR_NUM_TIMERS; i++) { + timer_load(qts, i, 100 + i * 50); + timer_enable(qts, i, K230_APBTMR_CONTROL_ENABLE | + K230_APBTMR_CONTROL_MODE_PERIODIC); + } + + /* Step past timer 0 expiry (load=3D100) =E2=80=94 only timer 0 should= fire */ + qtest_clock_step(qts, 101ULL * TIMER_TICK_NS + 1); + uint32_t sts =3D qtest_readl(qts, TIMER_BASE + K230_APBTMRS_INT_STATUS= ); + g_assert_cmphex(sts & 1, =3D=3D, 1); + g_assert_cmphex(sts & 0x3e, =3D=3D, 0); + + /* Step to timer 1 expiry (another 50 ticks) */ + qtest_clock_step(qts, 50ULL * TIMER_TICK_NS + 1); + sts =3D qtest_readl(qts, TIMER_BASE + K230_APBTMRS_INT_STATUS); + g_assert_cmphex(sts & 0x3, =3D=3D, 0x3); + g_assert_cmphex(sts & 0x3c, =3D=3D, 0); + + /* Step to expiry of all remaining timers (another 200 ticks) */ + qtest_clock_step(qts, 200ULL * TIMER_TICK_NS + 1); + sts =3D qtest_readl(qts, TIMER_BASE + K230_APBTMRS_INT_STATUS); + g_assert_cmphex(sts, =3D=3D, 0x3f); + + /* EOI_ALL clears all */ + qtest_readl(qts, TIMER_BASE + K230_APBTMRS_EOI); + sts =3D qtest_readl(qts, TIMER_BASE + K230_APBTMRS_INT_STATUS); + g_assert_cmphex(sts, =3D=3D, 0); + + qtest_quit(qts); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/k230-dwapb-timer/free_running", test_timer_free_runni= ng); + qtest_add_func("/k230-dwapb-timer/periodic", test_timer_periodic); + qtest_add_func("/k230-dwapb-timer/int_mask", test_timer_int_mask); + qtest_add_func("/k230-dwapb-timer/disable_clears_irq", + test_timer_disable_clears_irq); + qtest_add_func("/k230-dwapb-timer/current_disabled", + test_timer_current_disabled); + qtest_add_func("/k230-dwapb-timer/dynamic_reload", + test_timer_dynamic_reload); + qtest_add_func("/k230-dwapb-timer/all_channels", test_timer_all_channe= ls); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 56ff860e21..db95099481 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -297,7 +297,7 @@ qtests_riscv64 =3D ['riscv-csr-test'] + \ (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and config_all_devices.has_key('CONFIG_RISCV_IOMMU') ? ['iommu-riscv-test'] : []) + \ - (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test'] : []) + (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test', 'k230-dw= apb-timer-test'] : []) =20 qtests_hexagon =3D ['boot-serial-test'] =20 --=20 2.53.0