From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824393; cv=none; d=zohomail.com; s=zohoarc; b=f91XREcuDgUKQT4P1vh46TsLWjp0AEkiZQ0DMMQN3Dw+5hzfMN36vA+4aFWko5i/QukugMWz7lemIAwp5m+ycE6V76ii8Ra9HPBV7IVOQN6ZvNhliVXex3YQ+x1O2B3IU/21ztfKf52gFvaIbTI6VzBAaDZnKg4ygbGvN2MqwGA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824393; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8YhXGObb9R7y4NQD16UzBKhs9n3aO4Y8czE9nfrcr5Q=; b=H/ErvHhVfmeVd1d8T0x+fPVNunTHgkmJAI5whVCZC+8CV095SI/BXXqOAMASHLdgA0nTA6xSVDVcRQ4sCM9MnYqnea9vAzX1bWzt63z1Io/jASo1BamRXy7VBddcjMzmchdw/gqJA7+5POnhwFM1eaxg6o9UuNzLFRd1MJAMn34= 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 1791824393177272.20414726589; Mon, 12 Oct 2026 09:59:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJN5-0008CB-Qy; Mon, 12 Oct 2026 12:59:33 -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 1xGJMN-0007ym-4D; Mon, 12 Oct 2026 12:58:49 -0400 Received: from smtp-out-1.univ-lille.fr ([194.254.129.82]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMK-0006BP-W2; Mon, 12 Oct 2026 12:58:46 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-1.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw135JdzBqdB; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw11wCTz83nb; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824321; bh=8YhXGObb9R7y4NQD16UzBKhs9n3aO4Y8czE9nfrcr5Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VChLSd4MyD6XgFpzIigfXVefaM8Vm1gzazXlMMiwY2Hi6CXtEq0M1eAFIPJ7y11Z6 JSq6piOUiU0tul8hIPbVPp7a1KGHtbrg4TOYEJw0kQqjlxlxYHmE5nC/SdtVytyZWr X1VKldqcDF434hLqX3edWDvzX3Qm3UQWokd66yAjlCZ0PHrXhY33ap51UT/e3Z/aTZ N/xt22c8DNTChYRqG2C8Oi9hpqBT1BayeE6xmcI15Ztbn+sd0psO2T0eHJm4Ia+W66 mDMY2kAAF7mmCBU1zj54slkKNJuUzRpEucLgyDuRGIaRukPOakRslawJal+cobWwc+ OgK7KNMrs3q2Q== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 1/9] target/arm: add Cortex-M0+ CPU type Date: Mon, 12 Oct 2026 18:58:31 +0200 Message-ID: <20261012165840.99050-2-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.82; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-1.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824394781158500 Content-Type: text/plain; charset="utf-8" The Armv6-M Unprivileged/Privileged Extension is optional. While the Cortex-M0 does not implement it, the Cortex-M0+ may - and the RP2040 Cortex-M0+ configuration in particular provides this extension. Add the cortex-m0plus CPU type, with explicit initialization of all architectural state. Enable ARM_FEATURE_M_UNPRIV (introduced by commit 285e929908) and set the MIDR used by the RP2040. All ID registers are initialized explicitly, and their values inherited from Cortex-M0 have been verified to be appropriate for Cortex-M0+. Note: The MPU is optional on Cortex-M0+, so we do not configure the default 8 regions in the CPU type. The RP2040 machine correctly sets mpu-ns-regions =3D 8. Signed-off-by: Gilles Grimaud --- target/arm/tcg/cpu-v7m.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c index 48b31d5eac..975c712b61 100644 --- a/target/arm/tcg/cpu-v7m.c +++ b/target/arm/tcg/cpu-v7m.c @@ -76,6 +76,37 @@ static void cortex_m0_initfn(Object *obj) SET_IDREG(isar, ID_ISAR6, 0x00000000); } =20 +static void cortex_m0plus_initfn(Object *obj) +{ + ARMCPU *cpu =3D ARM_CPU(obj); + ARMISARegisters *isar =3D &cpu->isar; + + /* Architectural state: M-profile, v6-M, with unprivileged extension */ + set_feature(&cpu->env, ARM_FEATURE_V6); + set_feature(&cpu->env, ARM_FEATURE_M); + set_feature(&cpu->env, ARM_FEATURE_M_UNPRIV); + + /* MIDR for Cortex-M0+, RP2040 variant */ + cpu->midr =3D 0x410cc601; + + /* ID registers: same as Cortex-M0, verified to be appropriate */ + SET_IDREG(isar, ID_PFR0, 0x00000030); + SET_IDREG(isar, ID_PFR1, 0x00000200); + SET_IDREG(isar, ID_DFR0, 0x00100000); + SET_IDREG(isar, ID_AFR0, 0x00000000); + SET_IDREG(isar, ID_MMFR0, 0x00000030); + SET_IDREG(isar, ID_MMFR1, 0x00000000); + SET_IDREG(isar, ID_MMFR2, 0x00000000); + SET_IDREG(isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); + SET_IDREG(isar, ID_ISAR3, 0x01111110); + SET_IDREG(isar, ID_ISAR4, 0x01310102); + SET_IDREG(isar, ID_ISAR5, 0x00000000); + SET_IDREG(isar, ID_ISAR6, 0x00000000); +} + static void cortex_m3_initfn(Object *obj) { ARMCPU *cpu =3D ARM_CPU(obj); @@ -325,6 +356,8 @@ static void arm_v7m_class_init(ObjectClass *oc, const v= oid *data) static const ARMCPUInfo arm_v7m_cpus[] =3D { { .name =3D "cortex-m0", .initfn =3D cortex_m0_initfn, .class_init =3D arm_v7m_class_init }, + { .name =3D "cortex-m0plus", .initfn =3D cortex_m0plus_initfn, + .class_init =3D arm_v7m_class_init }, { .name =3D "cortex-m3", .initfn =3D cortex_m3_initfn, .class_init =3D arm_v7m_class_init }, { .name =3D "cortex-m4", .initfn =3D cortex_m4_initfn, --=20 2.55.0 From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824507; cv=none; d=zohomail.com; s=zohoarc; b=dy5dyt6JD+/8QWpOTDsE4Yiq1UW/6s24ee/hrc2b76RVc56EeMZmXeFjmmuY1W4zoNa3wYBmXVDHya5lNXj2zul2e07KeETzEBU8JVw/HB9zazYaHsFMcQSTFdyIgO7vcxHWrdyKdBb/QLwswrLzEhnyk70IFL9+sReQuCZNPjg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824507; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=uqTbvuo/zJtXTe+rLQT9ZSufS6hh+dOK1T9kqU6JZMU=; b=EN+qujt0ZJrNxTHfAQgSKDse9vuph3ZbEv24PFwVoQYG4px9EYBQ7+mln/N0r5KeqGEBiFifvnys1QG+NubIDqEhWfU/W58lHe2KeqnLVmpVaMpB2ugUKIAXaiA259964skRdpY6uBadeeM7sjbyZQu7cvSz0nF6mYbDMLu8D5Q= 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 1791824507695102.98739555504585; Mon, 12 Oct 2026 10:01:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJMv-00085J-1C; Mon, 12 Oct 2026 12:59:23 -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 1xGJMR-0007yz-H7 for qemu-devel@nongnu.org; Mon, 12 Oct 2026 12:58:52 -0400 Received: from smtp-out-1.univ-lille.fr ([194.254.129.82]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMO-0006CJ-Rj for qemu-devel@nongnu.org; Mon, 12 Oct 2026 12:58:51 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-1.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw13jnTzBqfW; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw12ztDz83nY; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824321; bh=uqTbvuo/zJtXTe+rLQT9ZSufS6hh+dOK1T9kqU6JZMU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oVG4TEBXSbqHadUom3zQl9B+tcufIqCA0DPeAcSaQcikbKjrtE//7Sv4qxURDmM7N 6iEY2T1PUorh4FG58nSReHD07A1xgNumGQtG2yqAIpQcjJB8TRGyBeSht/SMlfqjfj xsUE4rLqNHnzTJchCw+Mjo31EJAw/p46BH81lDUhza56EOs0oZPKAQnpSe0DU5bsNX sfr7D4tTTO+VrhbQASeE5MxUZUm//rMAHYl13Asd6qJxZNyX8tykkgxm81+by9xr7t W7RI3WJ7W1hfw2XpXJ2RTgxayM9XjzEIKh90lB9T4VNXfVg9XaPKJ3A27/C3rIQrPE ztHRLvz1YLF/Q== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud Subject: [RFC PATCH 2/9] hw/misc: add common RP2040 peripheral definitions Date: Mon, 12 Oct 2026 18:58:32 +0200 Message-ID: <20261012165840.99050-3-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.82; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-1.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824508808158500 Content-Type: text/plain; charset="utf-8" RP2040 APB peripherals share atomic XOR, SET and CLEAR alias windows. Add common constants and an inline update helper so individual device models do not duplicate this behavior. Signed-off-by: Gilles Grimaud --- include/hw/misc/rp2040.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/hw/misc/rp2040.h diff --git a/include/hw/misc/rp2040.h b/include/hw/misc/rp2040.h new file mode 100644 index 0000000000..13e05c9526 --- /dev/null +++ b/include/hw/misc/rp2040.h @@ -0,0 +1,32 @@ +/* + * RP2040 common peripheral helpers + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_RP2040_H +#define HW_MISC_RP2040_H + +#include "exec/hwaddr.h" + +#define RP2040_ATOMIC_ALIAS_MASK 0x3000 +#define RP2040_ATOMIC_XOR 0x1000 +#define RP2040_ATOMIC_SET 0x2000 +#define RP2040_ATOMIC_CLR 0x3000 + +static inline uint32_t rp2040_atomic_update(uint32_t old, uint32_t value, + hwaddr alias) +{ + switch (alias) { + case RP2040_ATOMIC_XOR: + return old ^ value; + case RP2040_ATOMIC_SET: + return old | value; + case RP2040_ATOMIC_CLR: + return old & ~value; + default: + return value; + } +} + +#endif --=20 2.55.0 From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824407; cv=none; d=zohomail.com; s=zohoarc; b=UaZ0TvUc3jvV/MmY7mjilyRpu/keXyDzpNt3x4oGRresMcOz6/2I30dGCWi436M4E9nMOqk2E6z585UKdpx3Lavgv2Z1BnqaihLnBbvgaNQFXgXPx8TR2bEtPJmm7nZMbsN/Of+3/HfuijoDQH2kfLv/Lt/zrIwMPvH6m2JXIyM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824407; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Y4dIddh8wrXNQIag2FJxhCu0Ew2R8fkEe1PbPB0nr1E=; b=LllrLNnLN/ord52TP3kfca4fc6YNM1zgD4wD+v/Q9JzbFfvOGzqWSzNSUvyZO8NdMz/ki4AU/Ok9I0mKP/1qYFRP9LrC8EfOS8CHwvhzKOw02Mdg5TRUeOxH44nBv1tekCmPAUlNPfgTrdF6lyvK1X83sAlKhw4/nyEX4Ldn5/s= 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 1791824406987608.1846502553555; Mon, 12 Oct 2026 10:00:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNJ-00005P-O6; Mon, 12 Oct 2026 12:59:45 -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 1xGJMW-00080b-ML; Mon, 12 Oct 2026 12:59:01 -0400 Received: from smtp-out-2.univ-lille.fr ([194.254.129.106]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMU-0006D5-2T; Mon, 12 Oct 2026 12:58:56 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-2.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw15VJ9z8BMd; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw13zzdz83nb; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824321; bh=Y4dIddh8wrXNQIag2FJxhCu0Ew2R8fkEe1PbPB0nr1E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kY1JQc4dS1522jPy11gmUEF1Fr1vCTy3U+xDeDcMdTJPQw5ziuNVI5++xD7iqN/BY 9DTvYYxvrzH6Nxa8adS7pB42WStso+/cVWtE3X4y5ddBecJJEvVhMmfLiE6CwX5HXI 48qcg6NFamsV4Jts95ACLyoKNjfUdDwCG+4g9A+EeKrDk4bAz4vSG4n5fqJEbCFxNL HZZtbW8spa37eLq+vJxHFAdLuZvuczofx5QvV6shB0kX9OLxbBl2QPUZtBB34eJmNG QNj+V0H21fWZv99Vv0RgQ/+XZJJxtAwIaq7QCrCKF5KUZzTnRXbkiPzkb0j65pVODP Fx1XjpyDJCHpw== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Paolo Bonzini , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 3/9] hw/arm: add RP2040 SoC and Raspberry Pi Pico machine Date: Mon, 12 Oct 2026 18:58:33 +0200 Message-ID: <20261012165840.99050-4-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.106; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-2.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824409180158500 Continue the Raspberry Pi Pico machine model introduced by Alex Benn=C3=A9e= 's 2022 RFC on current QEMU APIs. Add the RP2040 QOM skeleton, internal ROM and SRAM map, the board XIP window, two PL011-backed UARTs, and explicit unimplemented-device placeholders for the remaining MMIO blocks. Instantiate both Cortex-M0+ cores from the initial machine model. Give each core a separate memory container over the shared SoC address map so later patches can add per-core views for banked peripherals. Keep core 1 powered off until SIO and the boot ROM launch protocol are implemented. Signed-off-by: gilles grimaud --- configs/devices/arm-softmmu/default.mak | 1 + hw/arm/Kconfig | 12 ++ hw/arm/meson.build | 2 + hw/arm/raspi_pico.c | 83 ++++++++ hw/arm/rp2040.c | 263 ++++++++++++++++++++++++ include/hw/arm/rp2040.h | 49 +++++ 6 files changed, 410 insertions(+) create mode 100644 hw/arm/raspi_pico.c create mode 100644 hw/arm/rp2040.c create mode 100644 include/hw/arm/rp2040.h diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-= softmmu/default.mak index 22caa6a63e..11a5cac093 100644 --- a/configs/devices/arm-softmmu/default.mak +++ b/configs/devices/arm-softmmu/default.mak @@ -32,6 +32,7 @@ # CONFIG_OLIMEX_STM32_H405=3Dn # CONFIG_MPS2=3Dn # CONFIG_RASPI=3Dn +CONFIG_RASPI_PICO=3Dy # CONFIG_DIGIC=3Dn # CONFIG_SABRELITE=3Dn # CONFIG_EMCRAFT_SF2=3Dn diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 4445f16f45..73faefb1d7 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -353,6 +353,18 @@ config RASPI select BCM2835_SPI select BCM2835_I2C =20 +config RASPI_PICO + bool + default y + depends on TCG && ARM + select RP2040 + +config RP2040 + bool + select ARM_V7M + select PL011 + select UNIMP + config STM32F100_SOC bool select ARM_V7M diff --git a/hw/arm/meson.build b/hw/arm/meson.build index bcc068de04..a61a45840b 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -31,6 +31,8 @@ arm_common_ss.add(when: 'CONFIG_RASPI', if_true: files( 'raspi.c', 'raspi4b.c' )) +arm_common_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040.c')) +arm_common_ss.add(when: 'CONFIG_RASPI_PICO', if_true: files('raspi_pico.c'= )) arm_common_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_= soc.c')) arm_common_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_= soc.c')) arm_common_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_= soc.c')) diff --git a/hw/arm/raspi_pico.c b/hw/arm/raspi_pico.c new file mode 100644 index 0000000000..dff897085a --- /dev/null +++ b/hw/arm/raspi_pico.c @@ -0,0 +1,83 @@ +/* + * Raspberry Pi Pico machine + * + * Copyright (c) 2021 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/arm/boot.h" +#include "hw/arm/rp2040.h" +#include "hw/core/boards.h" +#include "hw/core/qdev-properties.h" +#include "system/address-spaces.h" +#include "system/system.h" +#include "qom/object.h" + +#define TYPE_RASPI_PICO_MACHINE MACHINE_TYPE_NAME("raspi-pico") +OBJECT_DECLARE_SIMPLE_TYPE(RaspiPicoMachineState, RASPI_PICO_MACHINE) + +#define PICO_FLASH_SIZE (2 * MiB) + +struct RaspiPicoMachineState { + MachineState parent_obj; + + RP2040State soc; + MemoryRegion flash; +}; + +static void raspi_pico_init(MachineState *machine) +{ + RaspiPicoMachineState *s =3D RASPI_PICO_MACHINE(machine); + MemoryRegion *system_memory =3D get_system_memory(); + + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RP2040); + qdev_prop_set_chr(DEVICE(&s->soc), "serial0", serial_hd(0)); + qdev_prop_set_chr(DEVICE(&s->soc), "serial1", serial_hd(1)); + if (machine->firmware) { + qdev_prop_set_string(DEVICE(&s->soc), "bootrom-file", + machine->firmware); + } + object_property_set_link(OBJECT(&s->soc), "memory", + OBJECT(system_memory), &error_fatal); + + memory_region_init_rom(&s->flash, NULL, "raspi-pico.flash", + PICO_FLASH_SIZE, &error_fatal); + memory_region_add_subregion(system_memory, RP2040_XIP_BASE, &s->flash); + + sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); + + armv7m_load_kernel(s->soc.armv7m[0].cpu, machine->kernel_filename, + RP2040_XIP_BASE, PICO_FLASH_SIZE); +} + +static void raspi_pico_machine_class_init(ObjectClass *oc, const void *dat= a) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "Raspberry Pi Pico (Cortex-M0+)"; + mc->init =3D raspi_pico_init; + mc->default_cpus =3D RP2040_NUM_CORES; + mc->min_cpus =3D RP2040_NUM_CORES; + mc->max_cpus =3D RP2040_NUM_CORES; + mc->default_ram_size =3D 0; + mc->no_parallel =3D 1; + mc->no_floppy =3D 1; + mc->no_cdrom =3D 1; +} + +static const TypeInfo raspi_pico_machine_info =3D { + .name =3D TYPE_RASPI_PICO_MACHINE, + .parent =3D TYPE_MACHINE, + .instance_size =3D sizeof(RaspiPicoMachineState), + .class_init =3D raspi_pico_machine_class_init, +}; + +static void raspi_pico_machine_init(void) +{ + type_register_static(&raspi_pico_machine_info); +} +type_init(raspi_pico_machine_init) diff --git a/hw/arm/rp2040.c b/hw/arm/rp2040.c new file mode 100644 index 0000000000..d5398e67e4 --- /dev/null +++ b/hw/arm/rp2040.c @@ -0,0 +1,263 @@ +/* + * RP2040 SoC emulation + * + * Copyright (c) 2021 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/arm/rp2040.h" +#include "hw/core/loader.h" +#include "hw/core/qdev-clock.h" +#include "hw/core/qdev-properties.h" +#include "hw/misc/unimp.h" +#include "qemu/datadir.h" +#include "target/arm/cpu-qom.h" + +#define RP2040_SYSCLK_FRQ 125000000 + +#define RP2040_UART0_BASE 0x40034000 +#define RP2040_UART0_IRQ 20 +#define RP2040_UART1_BASE 0x40038000 +#define RP2040_UART1_IRQ 21 + +/* + * Temporary boot ROM used until the synthetic ROM is introduced. It loads + * the reset handler from a vector table at the base of the XIP window. + */ +static const uint8_t rp2040_bootrom[] =3D { + 0x00, 0x20, 0x04, 0x20, /* initial SP: 0x20042000 */ + 0x09, 0x00, 0x00, 0x00, /* reset handler: 0x00000009 */ + 0x03, 0x48, /* ldr r0, vtor */ + 0x04, 0x49, /* ldr r1, xip_base */ + 0x01, 0x60, /* str r1, [r0] */ + 0x04, 0x48, /* ldr r0, xip_reset_vector */ + 0x01, 0x68, /* ldr r1, [r0] */ + 0x08, 0x47, /* bx r1 */ + 0xfe, 0xe7, /* b . */ + 0xc0, 0x46, /* nop */ + 0x08, 0xed, 0x00, 0xe0, /* VTOR: 0xe000ed08 */ + 0x00, 0x00, 0x00, 0x10, /* XIP base: 0x10000000 */ + 0x04, 0x00, 0x00, 0x10, /* XIP reset vector: 0x10000004 */ +}; + +static const struct { + const char *name; + hwaddr base; + hwaddr size; +} rp2040_unimplemented[] =3D { + { "rp2040.sysinfo", 0x40000000, 0x4000 }, + { "rp2040.syscfg", 0x40004000, 0x4000 }, + { "rp2040.clocks", 0x40008000, 0x4000 }, + { "rp2040.resets", 0x4000c000, 0x4000 }, + { "rp2040.psm", 0x40010000, 0x4000 }, + { "rp2040.iobank0", 0x40014000, 0x4000 }, + { "rp2040.ioqspi", 0x40018000, 0x4000 }, + { "rp2040.padsbank0", 0x4001c000, 0x4000 }, + { "rp2040.padsqspi", 0x40020000, 0x4000 }, + { "rp2040.xosc", 0x40024000, 0x4000 }, + { "rp2040.pll_sys", 0x40028000, 0x4000 }, + { "rp2040.pll_usb", 0x4002c000, 0x4000 }, + { "rp2040.busctrl", 0x40030000, 0x4000 }, + { "rp2040.uart0_aliases", 0x40035000, 0x3000 }, + { "rp2040.uart1_aliases", 0x40039000, 0x3000 }, + { "rp2040.spi0", 0x4003c000, 0x4000 }, + { "rp2040.spi1", 0x40040000, 0x4000 }, + { "rp2040.i2c0", 0x40044000, 0x4000 }, + { "rp2040.i2c1", 0x40048000, 0x4000 }, + { "rp2040.adc", 0x4004c000, 0x4000 }, + { "rp2040.pwm", 0x40050000, 0x4000 }, + { "rp2040.timer", 0x40054000, 0x4000 }, + { "rp2040.watchdog", 0x40058000, 0x4000 }, + { "rp2040.rtc", 0x4005c000, 0x4000 }, + { "rp2040.rosc", 0x40060000, 0x4000 }, + { "rp2040.vreg_and_chip_reset", 0x40064000, 0x4000 }, + { "rp2040.tbman", 0x4006c000, 0x4000 }, + { "rp2040.dma", 0x50000000, 0x1000 }, + { "rp2040.usbctrl_dpram", 0x50100000, 0x10000 }, + { "rp2040.usbctrl_regs", 0x50110000, 0x10000 }, + { "rp2040.pio0", 0x50200000, 0x10000 }, + { "rp2040.pio1", 0x50300000, 0x10000 }, + { "rp2040.sio", 0xd0000000, 0x1000 }, +}; + +static void rp2040_soc_init(Object *obj) +{ + RP2040State *s =3D RP2040(obj); + int i; + + for (i =3D 0; i < RP2040_NUM_CORES; i++) { + g_autofree char *name =3D g_strdup_printf("proc%d", i); + + object_initialize_child(obj, name, &s->armv7m[i], TYPE_ARMV7M); + qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type", + ARM_CPU_TYPE_NAME("cortex-m0plus")); + qdev_prop_set_uint32(DEVICE(&s->armv7m[i]), "num-irq", + RP2040_NUM_IRQS); + qdev_prop_set_uint32(DEVICE(&s->armv7m[i]), "mpu-ns-regions", 8); + } + qdev_prop_set_bit(DEVICE(&s->armv7m[1]), "start-powered-off", true); + + for (i =3D 0; i < ARRAY_SIZE(s->uart); i++) { + g_autofree char *name =3D g_strdup_printf("uart%d", i); + g_autofree char *property =3D g_strdup_printf("serial%d", i); + + object_initialize_child(obj, name, &s->uart[i], TYPE_PL011); + object_property_add_alias(obj, property, OBJECT(&s->uart[i]), + "chardev"); + } + + s->sysclk =3D clock_new(obj, "sysclk"); + clock_set_hz(s->sysclk, RP2040_SYSCLK_FRQ); +} + +static bool rp2040_init_memory(RP2040State *s, Error **errp) +{ + int i; + + if (!memory_region_init_rom(&s->rom, OBJECT(s), "rp2040.rom", + RP2040_ROM_SIZE, errp)) { + return false; + } + memory_region_add_subregion(s->board_memory, RP2040_ROM_BASE, &s->rom); + + for (i =3D 0; i < 4; i++) { + g_autofree char *name =3D g_strdup_printf("rp2040.sram%d", i); + + if (!memory_region_init_ram(&s->sram[i], OBJECT(s), name, + RP2040_SRAM_BANK_SIZE, errp)) { + return false; + } + memory_region_add_subregion(s->board_memory, + RP2040_SRAM_BASE + + i * RP2040_SRAM_BANK_SIZE, + &s->sram[i]); + } + + if (!memory_region_init_ram(&s->sram[4], OBJECT(s), "rp2040.sram4", + RP2040_SRAM_HI_SIZE, errp)) { + return false; + } + memory_region_add_subregion(s->board_memory, RP2040_SRAM4_BASE, + &s->sram[4]); + + if (!memory_region_init_ram(&s->sram[5], OBJECT(s), "rp2040.sram5", + RP2040_SRAM_HI_SIZE, errp)) { + return false; + } + memory_region_add_subregion(s->board_memory, RP2040_SRAM5_BASE, + &s->sram[5]); + + return true; +} + +static bool rp2040_load_bootrom(RP2040State *s, Error **errp) +{ + g_autofree char *filename =3D NULL; + + if (!s->bootrom_file) { + rom_add_blob_fixed("rp2040.bootrom", rp2040_bootrom, + sizeof(rp2040_bootrom), RP2040_ROM_BASE); + return true; + } + + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bootrom_file); + if (!filename) { + error_setg(errp, "could not find RP2040 boot ROM image '%s'", + s->bootrom_file); + return false; + } + + return load_image_targphys(filename, RP2040_ROM_BASE, + RP2040_ROM_SIZE, errp) >=3D 0; +} + +static void rp2040_soc_realize(DeviceState *dev, Error **errp) +{ + RP2040State *s =3D RP2040(dev); + static const hwaddr uart_base[] =3D { RP2040_UART0_BASE, RP2040_UART1_= BASE }; + static const int uart_irq[] =3D { RP2040_UART0_IRQ, RP2040_UART1_IRQ }; + Error *err =3D NULL; + int i; + + if (!s->board_memory) { + error_setg(errp, "memory property was not set"); + return; + } + if (!rp2040_init_memory(s, errp) || !rp2040_load_bootrom(s, errp)) { + return; + } + + for (i =3D 0; i < ARRAY_SIZE(rp2040_unimplemented); i++) { + create_unimplemented_device(rp2040_unimplemented[i].name, + rp2040_unimplemented[i].base, + rp2040_unimplemented[i].size); + } + + for (i =3D 0; i < RP2040_NUM_CORES; i++) { + g_autofree char *memory_name =3D + g_strdup_printf("rp2040.proc%d-memory", i); + g_autofree char *alias_name =3D + g_strdup_printf("rp2040.proc%d-board-memory", i); + + memory_region_init(&s->cpu_memory[i], OBJECT(dev), memory_name, + UINT64_C(1) << 32); + memory_region_init_alias(&s->cpu_board_alias[i], OBJECT(dev), + alias_name, s->board_memory, 0, + UINT64_C(1) << 32); + memory_region_add_subregion(&s->cpu_memory[i], 0, + &s->cpu_board_alias[i]); + qdev_connect_clock_in(DEVICE(&s->armv7m[i]), "cpuclk", s->sysclk); + object_property_set_link(OBJECT(&s->armv7m[i]), "memory", + OBJECT(&s->cpu_memory[i]), &err); + if (err) { + error_propagate(errp, err); + return; + } + if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m[i]), errp)) { + return; + } + } + + for (i =3D 0; i < ARRAY_SIZE(s->uart); i++) { + qdev_connect_clock_in(DEVICE(&s->uart[i]), "clk", s->sysclk); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, uart_base[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, + qdev_get_gpio_in(DEVICE(&s->armv7m[0]), + uart_irq[i])); + } +} + +static const Property rp2040_soc_properties[] =3D { + DEFINE_PROP_LINK("memory", RP2040State, board_memory, TYPE_MEMORY_REGI= ON, + MemoryRegion *), + DEFINE_PROP_STRING("bootrom-file", RP2040State, bootrom_file), +}; + +static void rp2040_soc_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D rp2040_soc_realize; + device_class_set_props(dc, rp2040_soc_properties); +} + +static const TypeInfo rp2040_soc_info =3D { + .name =3D TYPE_RP2040, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RP2040State), + .instance_init =3D rp2040_soc_init, + .class_init =3D rp2040_soc_class_init, +}; + +static void rp2040_soc_types(void) +{ + type_register_static(&rp2040_soc_info); +} +type_init(rp2040_soc_types) diff --git a/include/hw/arm/rp2040.h b/include/hw/arm/rp2040.h new file mode 100644 index 0000000000..ccab548275 --- /dev/null +++ b/include/hw/arm/rp2040.h @@ -0,0 +1,49 @@ +/* + * RP2040 SoC emulation + * + * Copyright (c) 2021 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_ARM_RP2040_H +#define HW_ARM_RP2040_H + +#include "hw/arm/armv7m.h" +#include "hw/char/pl011.h" +#include "hw/core/clock.h" +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_RP2040 "rp2040" +OBJECT_DECLARE_SIMPLE_TYPE(RP2040State, RP2040) + +#define RP2040_ROM_BASE 0x00000000 +#define RP2040_ROM_SIZE (16 * KiB) +#define RP2040_XIP_BASE 0x10000000 +#define RP2040_SRAM_BASE 0x20000000 +#define RP2040_SRAM_BANK_SIZE (64 * KiB) +#define RP2040_SRAM4_BASE 0x20040000 +#define RP2040_SRAM5_BASE 0x20041000 +#define RP2040_SRAM_HI_SIZE (4 * KiB) + +#define RP2040_NUM_CORES 2 +#define RP2040_NUM_IRQS 32 + +struct RP2040State { + SysBusDevice parent_obj; + + ARMv7MState armv7m[RP2040_NUM_CORES]; + PL011State uart[2]; + + MemoryRegion *board_memory; + MemoryRegion cpu_memory[RP2040_NUM_CORES]; + MemoryRegion cpu_board_alias[RP2040_NUM_CORES]; + MemoryRegion rom; + MemoryRegion sram[6]; + char *bootrom_file; + + Clock *sysclk; +}; + +#endif --=20 2.55.0 From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824390; cv=none; d=zohomail.com; s=zohoarc; b=ggGW5FgathbJUSbL278iLc65YPy8Tdk4/H/GmRO18vpOJy/BA44HvudctCnF3MxUetYeJVbr58ugESFWb5q7nciKu+Pi/NHTzl+A/om6nVzs06N1mCHKod5hrIF7zCEjVIQ5iM5/GjRnn/T+TaxftMe0RXJQcbbWhw9k9Adz0QM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824390; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=n/Rh9NOT0tf2DdviPPLi8SSJK4fnxZ0dt0bXhGsBWso=; b=YIIrwBt9vSxwUHiYrJyhDqwwAtp6jIr/7l1mxUy5UH6GmYB18kMchS2+FynncrSWMT9ZiDv30ZzrK6wSsFpYKCkgr92E9TzAPGMdonzz6RpmuWkM0GMLOH9eATPBALSNjtgK2QYiLxG2PlN/FFo0Eq4T2+ySkwwQjenUcjZchMI= 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 1791824390332879.0336687634813; Mon, 12 Oct 2026 09:59:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNJ-00007R-U1; Mon, 12 Oct 2026 12:59:45 -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 1xGJMn-00084n-Ma; Mon, 12 Oct 2026 12:59:15 -0400 Received: from smtp-out-2.univ-lille.fr ([194.254.129.106]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMd-0006ES-Vl; Mon, 12 Oct 2026 12:59:12 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-2.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw16dW0z8BNx; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw15YZNz83nc; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824321; bh=n/Rh9NOT0tf2DdviPPLi8SSJK4fnxZ0dt0bXhGsBWso=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kOLkPSIbzxlNsAvrpyWo7JI3ZL7BANs+gKEqB33sLOX/CzXn8BwLIarimqk5FvOjF /6Gh3gt+uyPcK5EScd/AihovH7XX6nzEWQ5+gfyqSEO2942flfcXU0axz68GIqeRmO xyvg+kTwOKOQ4q7J4UjtzVuANMk8XTaTxc3oIzunROouR0pbhYUDrFKAoQefJ8JgGY 1A5Jzxy6ocqT60o65lX3ZYSSzEE9O8FGttEGwAOihNZNELPmlG+7N0DX2DJIqmWRge dwa51Rfu1z4zWY6fQ2uG8K2YLOC4DBr6MUAh0MH54413EC+doISwm2RvrsLHPG/Syg SBXUgKxyV2kaA== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 4/9] tests/tcg/arm: add Raspberry Pi Pico smoke tests Date: Mon, 12 Oct 2026 18:58:34 +0200 Message-ID: <20261012165840.99050-5-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.106; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-2.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824392803158500 Content-Type: text/plain; charset="utf-8" Build Cortex-M0+ guest programs from assembly sources to exercise the minimal Pico boot path, UART0 output, and the Cortex-M0+ MPU. Keep the vector table at the XIP base so these tests match the initial synthetic boot stub without depending on boot2 or the later flash controller model. Signed-off-by: gilles grimaud --- tests/tcg/arm/system/meson.build | 14 +++++++ tests/tcg/arm/system/rp2040-boot.S | 30 +++++++++++++++ tests/tcg/arm/system/rp2040-minimal.ld | 40 +++++++++++++++++++ tests/tcg/arm/system/rp2040-uart.S | 53 ++++++++++++++++++++++++++ tests/tcg/arm/system/rp2040-uart.ref | 1 + 5 files changed, 138 insertions(+) create mode 100644 tests/tcg/arm/system/rp2040-boot.S create mode 100644 tests/tcg/arm/system/rp2040-minimal.ld create mode 100644 tests/tcg/arm/system/rp2040-uart.S create mode 100644 tests/tcg/arm/system/rp2040-uart.ref diff --git a/tests/tcg/arm/system/meson.build b/tests/tcg/arm/system/meson.= build index 80c5461e62..29b03b64d0 100644 --- a/tests/tcg/arm/system/meson.build +++ b/tests/tcg/arm/system/meson.build @@ -15,6 +15,11 @@ qemu_base_args =3D ['-display', 'none', '-semihosting-config', 'enable=3Don', '-kernel'] qemu_def_args =3D ['-M', 'virt', '-cpu', 'max', qemu_base_args] +rp2040_cflags =3D ['-mcpu=3Dcortex-m0plus', '-mthumb', '-mfloat-abi=3Dsoft= ', + '-nostdlib', '-Wl,--build-id=3Dnone', + '-T', files('rp2040-minimal.ld')] +rp2040_qemu_args =3D ['-M', 'raspi-pico', '-monitor', 'none', + qemu_base_args] =20 # Multi arch tests multi_src =3D [] @@ -51,6 +56,15 @@ tests +=3D { '-T', files('test-armv6m-undef.ld')], 'qemu_args': ['-M', 'microbit', qemu_base_args], }, + 'rp2040-boot.S': { + 'cflags': rp2040_cflags, + 'qemu_args': rp2040_qemu_args, + }, + 'rp2040-uart.S': { + 'cflags': rp2040_cflags, + 'qemu_args': ['-serial', 'stdio', rp2040_qemu_args], + 'expected_output': 'rp2040-uart.ref', + }, 'semiconsole.c': { 'cflags': cflags, 'qemu_args': ['-serial', 'none', '-chardev', 'stdio,mux=3Don,id=3Dstdi= o0', diff --git a/tests/tcg/arm/system/rp2040-boot.S b/tests/tcg/arm/system/rp20= 40-boot.S new file mode 100644 index 0000000000..0537a54d44 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-boot.S @@ -0,0 +1,30 @@ +/* + * Raspberry Pi Pico boot smoke test. + * + * Copyright 2026 Gilles Grimaud + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +.syntax unified +.cpu cortex-m0plus +.thumb + +#define SRAM_END 0x20042000 +#define SYS_EXIT 0x18 +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +.section .vectors, "a", %progbits +vector_table: + .word SRAM_END + .word reset_handler + 1 + +.section .text, "ax", %progbits +.thumb_func +.global reset_handler +reset_handler: + movs r0, SYS_EXIT + ldr r1, =3DADP_STOPPED_APPLICATION_EXIT + bkpt 0xab + +1: + b 1b diff --git a/tests/tcg/arm/system/rp2040-minimal.ld b/tests/tcg/arm/system/= rp2040-minimal.ld new file mode 100644 index 0000000000..ebfbac8cf2 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-minimal.ld @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +ENTRY(reset_handler) + +MEMORY +{ + FLASH (rx) : ORIGIN =3D 0x10000000, LENGTH =3D 2M + SRAM (rwx) : ORIGIN =3D 0x20000000, LENGTH =3D 264K +} + +SECTIONS +{ + .vectors ORIGIN(FLASH) : + { + KEEP(*(.vectors)) + } > FLASH + + .text : + { + *(.text*) + *(.rodata*) + } > FLASH + + .data : + { + *(.data*) + } > SRAM AT > FLASH + + .bss (NOLOAD) : + { + *(.bss*) + *(COMMON) + } > SRAM + + /DISCARD/ : + { + *(.ARM.attributes) + *(.comment) + } +} diff --git a/tests/tcg/arm/system/rp2040-uart.S b/tests/tcg/arm/system/rp20= 40-uart.S new file mode 100644 index 0000000000..bdb58cc7f2 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-uart.S @@ -0,0 +1,53 @@ +/* + * Raspberry Pi Pico UART boot smoke test. + * + * Copyright 2026 Gilles Grimaud + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +.syntax unified +.cpu cortex-m0plus +.thumb + +#define SRAM_END 0x20042000 +#define UART0_DR 0x40034000 +#define SYS_EXIT 0x18 +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +.section .vectors, "a", %progbits +vector_table: + .word SRAM_END + .word reset_handler + 1 + .word default_handler + 1 + .word default_handler + 1 + +.section .text, "ax", %progbits +.thumb_func +.global reset_handler +reset_handler: + ldr r0, =3DUART0_DR + ldr r1, =3Dmessage + +1: + ldrb r2, [r1] + cmp r2, 0 + beq 2f + str r2, [r0] + adds r1, 1 + b 1b + +2: + movs r0, SYS_EXIT + ldr r1, =3DADP_STOPPED_APPLICATION_EXIT + bkpt 0xab + +3: + b 3b + +.thumb_func +default_handler: + b default_handler + +.section .rodata, "a", %progbits +message: + .asciz "PICO TCG UART OK\n" diff --git a/tests/tcg/arm/system/rp2040-uart.ref b/tests/tcg/arm/system/rp= 2040-uart.ref new file mode 100644 index 0000000000..1ef16e8299 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-uart.ref @@ -0,0 +1 @@ +PICO TCG UART OK --=20 2.55.0 From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824458; cv=none; d=zohomail.com; s=zohoarc; b=dtEObGCZR5MU2mtAhJzvRbABsZkO7lQPxcSvKbwjPUf2uFT4ht2A8FqZDeAmyhIxiYsr3xrsz3IHepd1eIb9rNnZn/4xbXn+NqJSv/FdPL9MpfM7zY6HshVP6sHqXFBJe++Jl+nhPfRT7jLxl9KRR5Wj4irvfMWO2INl5KbMACM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824458; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=nKDqbM830VGPWv4COxRiwMRIrPyjpp9xZrU2XT8YZHg=; b=jIOxfLdOAKTdzSPy/PSBmRs6+jEqB374Qjv3RLvAbqCy4UhEVFI1LFp5Ki9l65xwiQj6WTPAtmPYjScsr+x8aU9KmuGlXnUI3ujApGRGm34BJ87S1X2t3jvH8XksRc1uznYGzy8qinAafdrgkdnlyNJ4snsWI+0jBF/Mn1Lo0dM= 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 1791824458824920.0422812141886; Mon, 12 Oct 2026 10:00:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNR-0000ZG-9g; Mon, 12 Oct 2026 12:59:53 -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 1xGJMx-000898-9R; Mon, 12 Oct 2026 12:59:24 -0400 Received: from smtp-out-2.univ-lille.fr ([194.254.129.106]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMv-0006IG-3w; Mon, 12 Oct 2026 12:59:23 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-2.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw20ZDpz8BS9; Mon, 12 Oct 2026 18:58:42 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw16f0Qz83nY; Mon, 12 Oct 2026 18:58:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824322; bh=nKDqbM830VGPWv4COxRiwMRIrPyjpp9xZrU2XT8YZHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vlxgCnK91TRlu6U0tQGbqrZdLVBJcuTdBJywgIGVi9aRa1AoAbXTrNtUXF2qSKWjb sZojpXyH50ap1I9qAd+2WxWwzKJIRYv+2nOyRvyysxEMaWLTBuptC5EU75kiSenYQk u0Kyr8aCkAesZ7zjCXYAHXUW9h2zTpvI0TNZGGuSO3UWr9EKTutAIEOwS4BlQXNTzR bkuq8WiTuTDOTyJtUbzj+lIoo04JQHE3UfXjyP7YFQtVMgtWKDQfIjAp0NifMFsnYI Ki6fF3wXgQsjEfUOCFQyDecrvwL6ubfxsZgtvNAvIOLj6Er/0aPDxa1E7Dqgo/B4jM QK8EYtB5LxYDg== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 5/9] tests/tcg/arm: test the RP2040 Cortex-M0+ MPU Date: Mon, 12 Oct 2026 18:58:35 +0200 Message-ID: <20261012165840.99050-6-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.106; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-2.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824460079158501 Content-Type: text/plain; charset="utf-8" Add focused execution tests for the optional Armv6-M MPU exposed by the RP2040 Cortex-M0+ cores. Check register reset and readback, privileged and unprivileged accesses, the 256-byte minimum region size, overlapping-region priority, subregion disabling, and escalation of an MPU violation to HardFault. The test runs after the generic Armv6-M CONTROL.nPRIV prerequisite and the RP2040 machine have both been introduced. Signed-off-by: gilles grimaud --- tests/tcg/arm/system/meson.build | 5 + tests/tcg/arm/system/rp2040-mpu.S | 356 ++++++++++++++++++++++++++++ tests/tcg/arm/system/rp2040-mpu.ref | 10 + 3 files changed, 371 insertions(+) create mode 100644 tests/tcg/arm/system/rp2040-mpu.S create mode 100644 tests/tcg/arm/system/rp2040-mpu.ref diff --git a/tests/tcg/arm/system/meson.build b/tests/tcg/arm/system/meson.= build index 29b03b64d0..6de149fa32 100644 --- a/tests/tcg/arm/system/meson.build +++ b/tests/tcg/arm/system/meson.build @@ -65,6 +65,11 @@ tests +=3D { 'qemu_args': ['-serial', 'stdio', rp2040_qemu_args], 'expected_output': 'rp2040-uart.ref', }, + 'rp2040-mpu.S': { + 'cflags': rp2040_cflags, + 'qemu_args': ['-serial', 'stdio', rp2040_qemu_args], + 'expected_output': 'rp2040-mpu.ref', + }, 'semiconsole.c': { 'cflags': cflags, 'qemu_args': ['-serial', 'none', '-chardev', 'stdio,mux=3Don,id=3Dstdi= o0', diff --git a/tests/tcg/arm/system/rp2040-mpu.S b/tests/tcg/arm/system/rp204= 0-mpu.S new file mode 100644 index 0000000000..5cc98f3d0e --- /dev/null +++ b/tests/tcg/arm/system/rp2040-mpu.S @@ -0,0 +1,356 @@ +/* + * Raspberry Pi Pico Cortex-M0+ MPU test. + * + * Copyright 2026 Gilles Grimaud + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +.syntax unified +.cpu cortex-m0plus +.thumb + +#define SRAM_END 0x20042000 +#define TEST_ADDRESS 0x20001000 +#define TEST_VALUE 0x12345678 +#define UART0_DR 0x40034000 +#define MPU_TYPE 0xe000ed90 +#define MPU_CTRL 0xe000ed94 +#define MPU_RNR 0xe000ed98 +#define MPU_RBAR 0xe000ed9c +#define MPU_RASR 0xe000eda0 +#define MPU_TYPE_DREGION_MASK 0x0000ff00 +#define MPU_TYPE_DREGION_SHIFT 8 +#define MPU_CTRL_ENABLE_PRIVDEFENA 0x05 +#define MPU_RASR_SRAM_FULL_ACCESS 0x03000025 +#define MPU_RASR_XIP_READ_ONLY 0x06000039 +#define MPU_RASR_TEST_PRIV_RW 0x0100000f +#define MPU_RASR_TEST_NO_ACCESS_32B 0x00000009 +#define MPU_RASR_TEST_NO_ACCESS_256B 0x0000000f +#define MPU_RASR_TEST_SUBREGION0_OFF 0x0000010f +#define SYS_EXIT 0x18 +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 +#define ADP_STOPPED_RUNTIME_ERROR 0x20023 + +.section .vectors, "a", %progbits +vector_table: + .word SRAM_END + .word reset_handler + 1 + .word default_handler + 1 + .word hardfault_handler + 1 + +.section .text, "ax", %progbits +.thumb_func +.global reset_handler +reset_handler: + ldr r0, =3Dstart_message + bl puts + + ldr r0, =3DMPU_TYPE + ldr r0, [r0] + ldr r1, =3DMPU_TYPE_DREGION_MASK + ands r0, r1 + lsrs r0, r0, MPU_TYPE_DREGION_SHIFT + cmp r0, 8 + beq 1f + b fail_type +1: + + ldr r0, =3Dtype_message + bl puts + + ldr r0, =3DMPU_CTRL + ldr r1, [r0] + cmp r1, 0 + beq 1f + b fail_reset +1: + ldr r0, =3DMPU_RNR + ldr r1, [r0] + cmp r1, 0 + beq 1f + b fail_reset +1: + ldr r0, =3DMPU_RBAR + ldr r1, [r0] + cmp r1, 0 + beq 1f + b fail_reset +1: + ldr r0, =3DMPU_RASR + ldr r1, [r0] + cmp r1, 0 + beq 1f + b fail_reset +1: + + ldr r0, =3Dreset_message + bl puts + + ldr r4, =3DTEST_ADDRESS + ldr r5, =3DTEST_VALUE + str r5, [r4] + ldr r0, [r4] + cmp r0, r5 + beq 1f + b fail_plain +1: + + ldr r0, =3Dplain_message + bl puts + + movs r0, 0 + ldr r1, =3D0x20000000 + ldr r2, =3DMPU_RASR_SRAM_FULL_ACCESS + bl configure_region + + movs r0, 1 + movs r1, 0 + ldr r2, =3DMPU_RASR_XIP_READ_ONLY + bl configure_region + + movs r0, 2 + ldr r1, =3DTEST_ADDRESS + ldr r2, =3DMPU_RASR_TEST_PRIV_RW + bl configure_region + + ldr r0, =3DMPU_RNR + ldr r0, [r0] + cmp r0, 2 + beq 1f + b fail_registers +1: + ldr r0, =3DMPU_RBAR + ldr r0, [r0] + ldr r1, =3D(TEST_ADDRESS | 2) + cmp r0, r1 + beq 1f + b fail_registers +1: + ldr r0, =3DMPU_RASR + ldr r0, [r0] + ldr r1, =3DMPU_RASR_TEST_PRIV_RW + cmp r0, r1 + beq 1f + b fail_registers +1: + + ldr r0, =3Dregisters_message + bl puts + + ldr r0, =3DMPU_CTRL + movs r1, MPU_CTRL_ENABLE_PRIVDEFENA + str r1, [r0] + dsb + isb + + ldr r0, [r4] + cmp r0, r5 + beq 1f + b fail_privileged +1: + + ldr r0, =3Dprivileged_message + bl puts + + movs r0, 3 + ldr r1, =3DTEST_ADDRESS + ldr r2, =3DMPU_RASR_TEST_NO_ACCESS_32B + bl configure_region + dsb + isb + ldr r0, [r4] + cmp r0, r5 + beq 1f + b fail_min_size +1: + + ldr r0, =3Dmin_size_message + bl puts + + ldr r0, =3Dfault_phase + movs r1, 1 + str r1, [r0] + movs r0, 3 + ldr r1, =3DTEST_ADDRESS + ldr r2, =3DMPU_RASR_TEST_NO_ACCESS_256B + bl configure_region + dsb + isb + ldr r0, [r4] + ldr r1, =3Dfault_phase + ldr r1, [r1] + cmp r1, 0 + beq 1f + b fail_priority +1: + + ldr r0, =3Dpriority_message + bl puts + + movs r0, 3 + ldr r1, =3DTEST_ADDRESS + ldr r2, =3DMPU_RASR_TEST_SUBREGION0_OFF + bl configure_region + dsb + isb + ldr r0, [r4] + cmp r0, r5 + beq 1f + b fail_subregion +1: + + ldr r0, =3Dsubregion_message + bl puts + + movs r0, 1 + msr control, r0 + isb + + ldr r0, [r4] + ldr r0, =3Dfail_no_fault_message + b test_failed + +.thumb_func +configure_region: + ldr r3, =3DMPU_RNR + str r0, [r3] + ldr r3, =3DMPU_RBAR + str r1, [r3] + ldr r3, =3DMPU_RASR + str r2, [r3] + bx lr + +fail_type: + ldr r0, =3Dfail_type_message + b test_failed + +fail_reset: + ldr r0, =3Dfail_reset_message + b test_failed + +fail_registers: + ldr r0, =3Dfail_registers_message + b test_failed + +fail_plain: + ldr r0, =3Dfail_plain_message + b test_failed + +fail_privileged: + ldr r0, =3Dfail_privileged_message + b test_failed + +fail_min_size: + ldr r0, =3Dfail_min_size_message + b test_failed + +fail_priority: + ldr r0, =3Dfail_priority_message + b test_failed + +fail_subregion: + ldr r0, =3Dfail_subregion_message + +test_failed: + bl puts + movs r0, SYS_EXIT + ldr r1, =3DADP_STOPPED_RUNTIME_ERROR + bkpt 0xab + +1: + b 1b + +.thumb_func +hardfault_handler: + ldr r0, =3Dfault_phase + ldr r1, [r0] + cmp r1, 0 + beq hardfault_done + movs r1, 0 + str r1, [r0] + ldr r0, =3DMPU_RNR + movs r1, 3 + str r1, [r0] + ldr r0, =3DMPU_RASR + movs r1, 0 + str r1, [r0] + dsb + isb + bx lr + +hardfault_done: + ldr r0, =3Dok_message + bl puts + movs r0, SYS_EXIT + ldr r1, =3DADP_STOPPED_APPLICATION_EXIT + bkpt 0xab + +2: + b 2b + +.thumb_func +default_handler: + ldr r0, =3Dfail_exception_message + b test_failed + +.thumb_func +puts: + ldr r2, =3DUART0_DR + +3: + ldrb r1, [r0] + cmp r1, 0 + beq 4f + str r1, [r2] + adds r0, 1 + b 3b + +4: + bx lr + +.section .rodata, "a", %progbits +start_message: + .asciz "PICO TCG MPU START\n" +type_message: + .asciz "PICO TCG MPU TYPE\n" +reset_message: + .asciz "PICO TCG MPU RESET\n" +plain_message: + .asciz "PICO TCG MPU PLAIN\n" +registers_message: + .asciz "PICO TCG MPU REGISTERS\n" +privileged_message: + .asciz "PICO TCG MPU PRIV\n" +min_size_message: + .asciz "PICO TCG MPU MIN SIZE\n" +priority_message: + .asciz "PICO TCG MPU PRIORITY\n" +subregion_message: + .asciz "PICO TCG MPU SUBREGION\n" +ok_message: + .asciz "PICO TCG MPU OK\n" +fail_type_message: + .asciz "PICO TCG MPU FAIL: TYPE\n" +fail_reset_message: + .asciz "PICO TCG MPU FAIL: RESET\n" +fail_plain_message: + .asciz "PICO TCG MPU FAIL: PLAIN\n" +fail_registers_message: + .asciz "PICO TCG MPU FAIL: REGISTERS\n" +fail_privileged_message: + .asciz "PICO TCG MPU FAIL: PRIV\n" +fail_min_size_message: + .asciz "PICO TCG MPU FAIL: MIN SIZE\n" +fail_priority_message: + .asciz "PICO TCG MPU FAIL: PRIORITY\n" +fail_subregion_message: + .asciz "PICO TCG MPU FAIL: SUBREGION\n" +fail_no_fault_message: + .asciz "PICO TCG MPU FAIL: NOFAULT\n" +fail_exception_message: + .asciz "PICO TCG MPU FAIL: EXCEPTION\n" + +.section .bss, "aw", %nobits +.align 2 +fault_phase: + .word 0 diff --git a/tests/tcg/arm/system/rp2040-mpu.ref b/tests/tcg/arm/system/rp2= 040-mpu.ref new file mode 100644 index 0000000000..d3938add02 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-mpu.ref @@ -0,0 +1,10 @@ +PICO TCG MPU START +PICO TCG MPU TYPE +PICO TCG MPU RESET +PICO TCG MPU PLAIN +PICO TCG MPU REGISTERS +PICO TCG MPU PRIV +PICO TCG MPU MIN SIZE +PICO TCG MPU PRIORITY +PICO TCG MPU SUBREGION +PICO TCG MPU OK --=20 2.55.0 From nobody Thu Oct 22 19:28:17 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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824462; cv=none; d=zohomail.com; s=zohoarc; b=LxObOV2WEifFijAgiUoNcWvmrX8sc9ghJn1eri4+I650/sZ3/9xjp/abo7W/yaIyTmOjmwzQYCl+Fi/k8Zy3l50NMJQZ9ShwuWZ64r13A07iBNF+K2+28+MmLde91MvMvLCCPhfFWpe07xfi1QrXfHB6Ys0mDS5MvTX95JS2bNw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824462; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GdzwaCUEbqkr6BJ+PYfkIGMYuR2E6mJzYvUTYXJ8ue0=; b=eePm7bOtXb9SURE9643SzKbw0PSMzn5pC/mM/SLTGtdHnP5xkBnWdNzUaiTeayavwLQ2TZPT+WuiutNYgnmqU5/oeE42o+FtYoNf/9uIL78v1MpTGpekH7i5Y/CrKIgsYtXJGoryfa8ZobGHICTqCq4su6ydLoGAd9WgT3QOlpQ= 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 1791824462047490.32757349793167; Mon, 12 Oct 2026 10:01:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNP-0000MX-7R; Mon, 12 Oct 2026 12:59:51 -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 1xGJMV-00080N-Vm; Mon, 12 Oct 2026 12:58:58 -0400 Received: from smtp-out-1.univ-lille.fr ([194.254.129.82]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMT-0006D6-T7; Mon, 12 Oct 2026 12:58:55 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-1.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw22n5JzBqmm; Mon, 12 Oct 2026 18:58:42 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw20tsJz83nb; Mon, 12 Oct 2026 18:58:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824322; bh=GdzwaCUEbqkr6BJ+PYfkIGMYuR2E6mJzYvUTYXJ8ue0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FrtBXjnhD2YcbFwo1du0k3vFY3Fcm95IrgTa1kEWI8XwZJ/xmhlRvDaBANi5dfuij o1gi/efG6F5y1eNGFzPDQx3VLqG0ISFZ5vNzg9BjjXJVzTzARQfZkSbYM4doxHL2Vp bpMJ6YfIKcT4FZWpQfJFGuFzo884r7KeHg8Fhgzr4G3uUGrXS9xQz5+eC6FIFSeirT Q+DJKqjVUMHzgg0nUF9E/kQ4nqQUf8DAebiRle/o1K/yLwE8ns6/KSPvrxrMOtn+GB gFhryCaH41j0YMVtyNLB/wBk1mCvaIM8wXZ9KHV1xv2XLYdY6ujyyjMvHZrs2sOXEP FRc3kRz4tz/xA== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 6/9] hw/misc: add RP2040 SYSINFO Date: Mon, 12 Oct 2026 18:58:36 +0200 Message-ID: <20261012165840.99050-7-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.82; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-1.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824464176158500 Content-Type: text/plain; charset="utf-8" Model the read-only RP2040 identification and platform registers. The platform register reports an ASIC implementation, while CHIP_ID and the Git revision retain stable zero values. Add a focused qtest for the documented register values. Signed-off-by: Gilles Grimaud --- hw/arm/rp2040.c | 8 ++- hw/misc/meson.build | 1 + hw/misc/rp2040_sysinfo.c | 102 ++++++++++++++++++++++++++++++ include/hw/arm/rp2040.h | 2 + include/hw/misc/rp2040_sysinfo.h | 25 ++++++++ tests/qtest/meson.build | 2 + tests/qtest/rp2040-sysinfo-test.c | 37 +++++++++++ 7 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 hw/misc/rp2040_sysinfo.c create mode 100644 include/hw/misc/rp2040_sysinfo.h create mode 100644 tests/qtest/rp2040-sysinfo-test.c diff --git a/hw/arm/rp2040.c b/hw/arm/rp2040.c index d5398e67e4..55554f72e9 100644 --- a/hw/arm/rp2040.c +++ b/hw/arm/rp2040.c @@ -49,7 +49,6 @@ static const struct { hwaddr base; hwaddr size; } rp2040_unimplemented[] =3D { - { "rp2040.sysinfo", 0x40000000, 0x4000 }, { "rp2040.syscfg", 0x40004000, 0x4000 }, { "rp2040.clocks", 0x40008000, 0x4000 }, { "rp2040.resets", 0x4000c000, 0x4000 }, @@ -110,6 +109,8 @@ static void rp2040_soc_init(Object *obj) "chardev"); } =20 + object_initialize_child(obj, "sysinfo", &s->sysinfo, TYPE_RP2040_SYSIN= FO); + s->sysclk =3D clock_new(obj, "sysclk"); clock_set_hz(s->sysclk, RP2040_SYSCLK_FRQ); } @@ -222,6 +223,11 @@ static void rp2040_soc_realize(DeviceState *dev, Error= **errp) } } =20 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, RP2040_SYSINFO_BASE); + for (i =3D 0; i < ARRAY_SIZE(s->uart); i++) { qdev_connect_clock_in(DEVICE(&s->uart[i]), "clk", s->sysclk); if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 9790afa104..ca9b951e3e 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -98,6 +98,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files( 'bcm2835_cprman.c', 'bcm2835_powermgt.c', )) +system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_sysinfo.c')) system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) system_ss.add(when: 'CONFIG_XLNX_ZYNQ_DDRC', if_true: files('xlnx-zynq-ddr= c.c')) diff --git a/hw/misc/rp2040_sysinfo.c b/hw/misc/rp2040_sysinfo.c new file mode 100644 index 0000000000..a35b867698 --- /dev/null +++ b/hw/misc/rp2040_sysinfo.c @@ -0,0 +1,102 @@ +/* + * RP2040 sysinfo emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040_sysinfo.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +#define SYSINFO_CHIP_ID 0x00 +#define SYSINFO_PLATFORM 0x04 +#define SYSINFO_GITREF_RP2040 0x40 + +#define SYSINFO_PLATFORM_ASIC BIT(1) + +static uint64_t rp2040_sysinfo_read(void *opaque, hwaddr addr, unsigned si= ze) +{ + hwaddr offset =3D addr & 0xfff; + uint64_t value; + + switch (offset) { + case SYSINFO_CHIP_ID: + case SYSINFO_GITREF_RP2040: + value =3D 0; + break; + case SYSINFO_PLATFORM: + value =3D SYSINFO_PLATFORM_ASIC; + break; + default: + value =3D 0; + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented read at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } + + return value; +} + +static void rp2040_sysinfo_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + hwaddr offset =3D addr & 0xfff; + + qemu_log_mask(LOG_GUEST_ERROR, "rp2040.sysinfo: write to read-only " + "register (size %d, addr 0x%08" HWADDR_PRIx + ", offset 0x%04" HWADDR_PRIx + ", value 0x%0*" PRIx64 ")\n", + size, RP2040_SYSINFO_BASE + addr, offset, size << 1, val= ue); +} + +static const MemoryRegionOps rp2040_sysinfo_ops =3D { + .read =3D rp2040_sysinfo_read, + .write =3D rp2040_sysinfo_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void rp2040_sysinfo_init(Object *obj) +{ + RP2040SysInfoState *s =3D RP2040_SYSINFO(obj); + + memory_region_init_io(&s->iomem, obj, &rp2040_sysinfo_ops, s, + "rp2040.sysinfo", RP2040_SYSINFO_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static const VMStateDescription rp2040_sysinfo_vmstate =3D { + .name =3D TYPE_RP2040_SYSINFO, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static void rp2040_sysinfo_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &rp2040_sysinfo_vmstate; +} + +static const TypeInfo rp2040_sysinfo_info =3D { + .name =3D TYPE_RP2040_SYSINFO, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RP2040SysInfoState), + .instance_init =3D rp2040_sysinfo_init, + .class_init =3D rp2040_sysinfo_class_init, +}; + +static void rp2040_sysinfo_register_types(void) +{ + type_register_static(&rp2040_sysinfo_info); +} +type_init(rp2040_sysinfo_register_types) diff --git a/include/hw/arm/rp2040.h b/include/hw/arm/rp2040.h index ccab548275..7e7d8f5c95 100644 --- a/include/hw/arm/rp2040.h +++ b/include/hw/arm/rp2040.h @@ -13,6 +13,7 @@ #include "hw/char/pl011.h" #include "hw/core/clock.h" #include "hw/core/sysbus.h" +#include "hw/misc/rp2040_sysinfo.h" #include "qom/object.h" =20 #define TYPE_RP2040 "rp2040" @@ -35,6 +36,7 @@ struct RP2040State { =20 ARMv7MState armv7m[RP2040_NUM_CORES]; PL011State uart[2]; + RP2040SysInfoState sysinfo; =20 MemoryRegion *board_memory; MemoryRegion cpu_memory[RP2040_NUM_CORES]; diff --git a/include/hw/misc/rp2040_sysinfo.h b/include/hw/misc/rp2040_sysi= nfo.h new file mode 100644 index 0000000000..d521659488 --- /dev/null +++ b/include/hw/misc/rp2040_sysinfo.h @@ -0,0 +1,25 @@ +/* + * RP2040 sysinfo emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_RP2040_SYSINFO_H +#define HW_MISC_RP2040_SYSINFO_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_RP2040_SYSINFO "rp2040-sysinfo" +OBJECT_DECLARE_SIMPLE_TYPE(RP2040SysInfoState, RP2040_SYSINFO) + +#define RP2040_SYSINFO_BASE 0x40000000 +#define RP2040_SYSINFO_SIZE 0x4000 + +struct RP2040SysInfoState { + SysBusDevice parent_obj; + + MemoryRegion iomem; +}; + +#endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 200abf6f36..8079fcee28 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -253,6 +253,8 @@ qtests_exynos4210 =3D \ ['exynos4210_uart_fifo-test'] =20 qtests_arm =3D \ + (config_all_devices.has_key('CONFIG_RP2040') ? + ['rp2040-sysinfo-test'] : []) + \ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-= dualtimer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-time= r-test'] : []) + \ diff --git a/tests/qtest/rp2040-sysinfo-test.c b/tests/qtest/rp2040-sysinfo= -test.c new file mode 100644 index 0000000000..7775842420 --- /dev/null +++ b/tests/qtest/rp2040-sysinfo-test.c @@ -0,0 +1,37 @@ +/* + * QTest testcase for the RP2040 SYSINFO block. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu/bitops.h" + +#define SYSINFO_BASE 0x40000000 +#define SYSINFO_CHIP_ID 0x00 +#define SYSINFO_PLATFORM 0x04 +#define SYSINFO_GITREF_RP2040 0x40 +#define SYSINFO_PLATFORM_ASIC BIT(1) + +static void test_sysinfo_read_values(void) +{ + QTestState *qts =3D qtest_init("-machine raspi-pico"); + + g_assert_cmphex(qtest_readl(qts, SYSINFO_BASE + SYSINFO_CHIP_ID), =3D= =3D, 0); + g_assert_cmphex(qtest_readl(qts, SYSINFO_BASE + SYSINFO_PLATFORM), =3D= =3D, + SYSINFO_PLATFORM_ASIC); + g_assert_cmphex(qtest_readl(qts, SYSINFO_BASE + SYSINFO_GITREF_RP2040), + =3D=3D, 0); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/rp2040-sysinfo/read-values", test_sysinfo_read_values= ); + + return g_test_run(); +} --=20 2.55.0 From nobody Thu Oct 22 19:28: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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824406; cv=none; d=zohomail.com; s=zohoarc; b=kLLDhJABblj37AJUOHdE/WQR2dHOCl9nE6PTCRI+SCWVOm5HClrcm/TUfP0K+Mw64FoV/LPy/GekIQlTfOhlzK+atyOhgqFPkhMtfKrODtLW0fS4WxeI42pjMdwcMEZpPEJ+d+VlEqoBNZNNbxONH2jqsRfrrTFBKi+zgo2/7WQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824406; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=4nMCyH95a9yeNXw/h8rLUbU/Orduycph7hf1HolxLDc=; b=Bnx4yIDhQY6mM/MIjDpyWeA4j+CRO1d0E7tY0nNOWZQzfqcNSsOQ52Qm4Vx9V6xLZZ8TN5JSr7f3s6XtqDtLPFn2JHEKUr+lLkjOmfNTC5AdBkf6FIkopopNQNPGCrRcoxYluJ60qISUw5fQjqxwIiz8usk88uzeO5K4NeQWWyM= 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 1791824406986126.90747667633434; Mon, 12 Oct 2026 10:00:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNQ-0000WT-L5; Mon, 12 Oct 2026 12:59:52 -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 1xGJMc-00081H-6K; Mon, 12 Oct 2026 12:59:12 -0400 Received: from smtp-out-1.univ-lille.fr ([194.254.129.82]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMY-0006De-44; Mon, 12 Oct 2026 12:59:00 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-1.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw321G1zBqmn; Mon, 12 Oct 2026 18:58:43 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw22zzsz83nY; Mon, 12 Oct 2026 18:58:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824323; bh=4nMCyH95a9yeNXw/h8rLUbU/Orduycph7hf1HolxLDc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oZHqxF/QUN2qenYpga0YmUWnkEJUlzRGQfcJvCwQKfL2Fuh5nvj2d2Fxo4zrkcDoC MhAnOQKhCAfijU4tWgWVITrFltKErTphMf6EYE8RwhbTDG6WSH5ueClKMwo/Kxffs6 al+9s5M0D1p7HqPnmrPPMPCpKLPQtR15/9JDfZiLcWF5UlM/Dkmvx8lfc6F0ovwblH dk33gLJr6gIL9IKeZu8Pbh2UMj0n0mxE9sqeeDE0AcMDlRaEYJ10yRmXbXOV9042Rq c5eRQw0WhWr/v0BszHLWaeBfmiG9PJtyxu36AQdfmzMxshjQCb+0Cy2BkFg/c+OXiV XZzU7qGhWBpTA== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 7/9] hw/misc: add RP2040 SYSCFG Date: Mon, 12 Oct 2026 18:58:37 +0200 Message-ID: <20261012165840.99050-8-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.82; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-1.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824409075158500 Content-Type: text/plain; charset="utf-8" Model the RP2040 system configuration registers, documented reset and write masks, and APB atomic aliases. Route each peripheral interrupt to the normal IRQ input or NMI input of each Cortex-M0+ according to PROC0_NMI_MASK and PROC1_NMI_MASK. MEMPOWERDOWN retains its documented register state without inventing behavior for accesses to powered-down memory banks. Add focused qtests for reset values, write masks, and atomic aliases. Signed-off-by: Gilles Grimaud --- hw/arm/rp2040.c | 57 +++++++- hw/misc/meson.build | 1 + hw/misc/rp2040_syscfg.c | 220 +++++++++++++++++++++++++++++++ include/hw/arm/rp2040.h | 7 + include/hw/misc/rp2040_syscfg.h | 41 ++++++ tests/qtest/meson.build | 2 +- tests/qtest/rp2040-syscfg-test.c | 97 ++++++++++++++ 7 files changed, 421 insertions(+), 4 deletions(-) create mode 100644 hw/misc/rp2040_syscfg.c create mode 100644 include/hw/misc/rp2040_syscfg.h create mode 100644 tests/qtest/rp2040-syscfg-test.c diff --git a/hw/arm/rp2040.c b/hw/arm/rp2040.c index 55554f72e9..47a0ef220f 100644 --- a/hw/arm/rp2040.c +++ b/hw/arm/rp2040.c @@ -13,6 +13,7 @@ #include "hw/core/loader.h" #include "hw/core/qdev-clock.h" #include "hw/core/qdev-properties.h" +#include "hw/core/irq.h" #include "hw/misc/unimp.h" #include "qemu/datadir.h" #include "target/arm/cpu-qom.h" @@ -49,7 +50,6 @@ static const struct { hwaddr base; hwaddr size; } rp2040_unimplemented[] =3D { - { "rp2040.syscfg", 0x40004000, 0x4000 }, { "rp2040.clocks", 0x40008000, 0x4000 }, { "rp2040.resets", 0x4000c000, 0x4000 }, { "rp2040.psm", 0x40010000, 0x4000 }, @@ -83,6 +83,40 @@ static const struct { { "rp2040.sio", 0xd0000000, 0x1000 }, }; =20 +static void rp2040_update_nmi(RP2040State *s) +{ + unsigned core; + + for (core =3D 0; core < RP2040_NUM_CORES; core++) { + uint32_t nmi_mask =3D rp2040_syscfg_get_nmi_mask(&s->syscfg, core); + bool nmi_level =3D false; + int irq; + + for (irq =3D 0; irq < RP2040_NUM_IRQS; irq++) { + bool route_to_nmi =3D nmi_mask & BIT(irq); + + qemu_set_irq(s->cpu_irq[core][irq], + s->irq_level[irq] && !route_to_nmi); + nmi_level |=3D s->irq_level[irq] && route_to_nmi; + } + qemu_set_irq(s->nmi_irq[core], nmi_level); + } +} + +static void rp2040_syscfg_update(void *opaque) +{ + rp2040_update_nmi(opaque); +} + +static void rp2040_set_irq(void *opaque, int irq, int level) +{ + RP2040State *s =3D opaque; + + assert(irq >=3D 0 && irq < RP2040_NUM_IRQS); + s->irq_level[irq] =3D level; + rp2040_update_nmi(s); +} + static void rp2040_soc_init(Object *obj) { RP2040State *s =3D RP2040(obj); @@ -109,8 +143,11 @@ static void rp2040_soc_init(Object *obj) "chardev"); } =20 + object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_RP2040_SYSCFG); object_initialize_child(obj, "sysinfo", &s->sysinfo, TYPE_RP2040_SYSIN= FO); =20 + s->irq =3D qemu_allocate_irqs(rp2040_set_irq, s, RP2040_NUM_IRQS); + s->sysclk =3D clock_new(obj, "sysclk"); clock_set_hz(s->sysclk, RP2040_SYSCLK_FRQ); } @@ -221,8 +258,21 @@ static void rp2040_soc_realize(DeviceState *dev, Error= **errp) if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m[i]), errp)) { return; } + + for (int irq =3D 0; irq < RP2040_NUM_IRQS; irq++) { + s->cpu_irq[i][irq] =3D + qdev_get_gpio_in(DEVICE(&s->armv7m[i]), irq); + } + s->nmi_irq[i] =3D qdev_get_gpio_in_named(DEVICE(&s->armv7m[i]), + "NMI", 0); } =20 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->syscfg), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->syscfg), 0, RP2040_SYSCFG_BASE); + rp2040_syscfg_set_update_callback(&s->syscfg, rp2040_syscfg_update, s); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) { return; } @@ -235,9 +285,10 @@ static void rp2040_soc_realize(DeviceState *dev, Error= **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, uart_base[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, - qdev_get_gpio_in(DEVICE(&s->armv7m[0]), - uart_irq[i])); + s->irq[uart_irq[i]]); } + + rp2040_update_nmi(s); } =20 static const Property rp2040_soc_properties[] =3D { diff --git a/hw/misc/meson.build b/hw/misc/meson.build index ca9b951e3e..c26442fdcc 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -98,6 +98,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files( 'bcm2835_cprman.c', 'bcm2835_powermgt.c', )) +system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_syscfg.c')) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_sysinfo.c')) system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) diff --git a/hw/misc/rp2040_syscfg.c b/hw/misc/rp2040_syscfg.c new file mode 100644 index 0000000000..9f907194ed --- /dev/null +++ b/hw/misc/rp2040_syscfg.c @@ -0,0 +1,220 @@ +/* + * RP2040 syscfg emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040.h" +#include "hw/misc/rp2040_syscfg.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +#define SYSCFG_PROC0_NMI_MASK 0x00 +#define SYSCFG_PROC1_NMI_MASK 0x04 +#define SYSCFG_PROC_CONFIG 0x08 +#define SYSCFG_PROC_IN_SYNC_BYPASS 0x0c +#define SYSCFG_PROC_IN_SYNC_BYPASS_HI 0x10 +#define SYSCFG_DBGFORCE 0x14 +#define SYSCFG_MEMPOWERDOWN 0x18 + +#define PROC_CONFIG_RW_MASK 0xff000000 +#define PROC_CONFIG_RESET 0x10000000 +#define PROC_IN_SYNC_BYPASS_MASK 0x3fffffff +#define PROC_IN_SYNC_BYPASS_HI_MASK 0x0000003f +#define DBGFORCE_RW_MASK 0x000000ee +#define DBGFORCE_RESET 0x00000066 +#define MEMPOWERDOWN_MASK 0x000000ff + +static void rp2040_syscfg_update(RP2040SysCfgState *s) +{ + if (s->update) { + s->update(s->update_opaque); + } +} + +void rp2040_syscfg_set_update_callback(RP2040SysCfgState *s, + RP2040SysCfgUpdateFn update, + void *opaque) +{ + s->update =3D update; + s->update_opaque =3D opaque; +} + +uint32_t rp2040_syscfg_get_nmi_mask(RP2040SysCfgState *s, unsigned core) +{ + assert(core < 2); + return core ? s->proc1_nmi_mask : s->proc0_nmi_mask; +} + +static uint64_t rp2040_syscfg_read(void *opaque, hwaddr addr, unsigned siz= e) +{ + RP2040SysCfgState *s =3D opaque; + hwaddr offset =3D addr & 0xfff; + uint64_t value; + + switch (offset) { + case SYSCFG_PROC0_NMI_MASK: + value =3D s->proc0_nmi_mask; + break; + case SYSCFG_PROC1_NMI_MASK: + value =3D s->proc1_nmi_mask; + break; + case SYSCFG_PROC_CONFIG: + value =3D s->proc_config; + break; + case SYSCFG_PROC_IN_SYNC_BYPASS: + value =3D s->proc_in_sync_bypass; + break; + case SYSCFG_PROC_IN_SYNC_BYPASS_HI: + value =3D s->proc_in_sync_bypass_hi; + break; + case SYSCFG_DBGFORCE: + value =3D s->dbgforce; + break; + case SYSCFG_MEMPOWERDOWN: + value =3D s->mempowerdown; + break; + default: + value =3D 0; + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented read at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } + + return value; +} + +static void rp2040_syscfg_write(void *opaque, hwaddr addr, + uint64_t value64, unsigned size) +{ + RP2040SysCfgState *s =3D opaque; + hwaddr alias =3D addr & RP2040_ATOMIC_ALIAS_MASK; + hwaddr offset =3D addr & 0xfff; + uint32_t value =3D value64; + + switch (offset) { + case SYSCFG_PROC0_NMI_MASK: + s->proc0_nmi_mask =3D + rp2040_atomic_update(s->proc0_nmi_mask, value, alias); + rp2040_syscfg_update(s); + break; + case SYSCFG_PROC1_NMI_MASK: + s->proc1_nmi_mask =3D + rp2040_atomic_update(s->proc1_nmi_mask, value, alias); + rp2040_syscfg_update(s); + break; + case SYSCFG_PROC_CONFIG: + s->proc_config =3D + rp2040_atomic_update(s->proc_config, value, alias) & + PROC_CONFIG_RW_MASK; + break; + case SYSCFG_PROC_IN_SYNC_BYPASS: + s->proc_in_sync_bypass =3D + rp2040_atomic_update(s->proc_in_sync_bypass, value, alias) & + PROC_IN_SYNC_BYPASS_MASK; + break; + case SYSCFG_PROC_IN_SYNC_BYPASS_HI: + s->proc_in_sync_bypass_hi =3D + rp2040_atomic_update(s->proc_in_sync_bypass_hi, value, alias) & + PROC_IN_SYNC_BYPASS_HI_MASK; + break; + case SYSCFG_DBGFORCE: + s->dbgforce =3D + rp2040_atomic_update(s->dbgforce, value, alias) & + DBGFORCE_RW_MASK; + break; + case SYSCFG_MEMPOWERDOWN: + s->mempowerdown =3D + rp2040_atomic_update(s->mempowerdown, value, alias) & + MEMPOWERDOWN_MASK; + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented write at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } +} + +static const MemoryRegionOps rp2040_syscfg_ops =3D { + .read =3D rp2040_syscfg_read, + .write =3D rp2040_syscfg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void rp2040_syscfg_reset(DeviceState *dev) +{ + RP2040SysCfgState *s =3D RP2040_SYSCFG(dev); + + s->proc0_nmi_mask =3D 0; + s->proc1_nmi_mask =3D 0; + s->proc_config =3D PROC_CONFIG_RESET; + s->proc_in_sync_bypass =3D 0; + s->proc_in_sync_bypass_hi =3D 0; + s->dbgforce =3D DBGFORCE_RESET; + s->mempowerdown =3D 0; + rp2040_syscfg_update(s); +} + +static int rp2040_syscfg_post_load(void *opaque, int version_id) +{ + RP2040SysCfgState *s =3D opaque; + + rp2040_syscfg_update(s); + return 0; +} + +static void rp2040_syscfg_init(Object *obj) +{ + RP2040SysCfgState *s =3D RP2040_SYSCFG(obj); + + memory_region_init_io(&s->iomem, obj, &rp2040_syscfg_ops, s, + "rp2040.syscfg", RP2040_SYSCFG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static const VMStateDescription rp2040_syscfg_vmstate =3D { + .name =3D TYPE_RP2040_SYSCFG, + .version_id =3D 1, + .minimum_version_id =3D 1, + .post_load =3D rp2040_syscfg_post_load, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32(proc0_nmi_mask, RP2040SysCfgState), + VMSTATE_UINT32(proc1_nmi_mask, RP2040SysCfgState), + VMSTATE_UINT32(proc_config, RP2040SysCfgState), + VMSTATE_UINT32(proc_in_sync_bypass, RP2040SysCfgState), + VMSTATE_UINT32(proc_in_sync_bypass_hi, RP2040SysCfgState), + VMSTATE_UINT32(dbgforce, RP2040SysCfgState), + VMSTATE_UINT32(mempowerdown, RP2040SysCfgState), + VMSTATE_END_OF_LIST() + } +}; + +static void rp2040_syscfg_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, rp2040_syscfg_reset); + dc->vmsd =3D &rp2040_syscfg_vmstate; +} + +static const TypeInfo rp2040_syscfg_info =3D { + .name =3D TYPE_RP2040_SYSCFG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RP2040SysCfgState), + .instance_init =3D rp2040_syscfg_init, + .class_init =3D rp2040_syscfg_class_init, +}; + +static void rp2040_syscfg_register_types(void) +{ + type_register_static(&rp2040_syscfg_info); +} +type_init(rp2040_syscfg_register_types) diff --git a/include/hw/arm/rp2040.h b/include/hw/arm/rp2040.h index 7e7d8f5c95..f6050f255d 100644 --- a/include/hw/arm/rp2040.h +++ b/include/hw/arm/rp2040.h @@ -14,6 +14,7 @@ #include "hw/core/clock.h" #include "hw/core/sysbus.h" #include "hw/misc/rp2040_sysinfo.h" +#include "hw/misc/rp2040_syscfg.h" #include "qom/object.h" =20 #define TYPE_RP2040 "rp2040" @@ -36,6 +37,7 @@ struct RP2040State { =20 ARMv7MState armv7m[RP2040_NUM_CORES]; PL011State uart[2]; + RP2040SysCfgState syscfg; RP2040SysInfoState sysinfo; =20 MemoryRegion *board_memory; @@ -45,6 +47,11 @@ struct RP2040State { MemoryRegion sram[6]; char *bootrom_file; =20 + qemu_irq *irq; + qemu_irq cpu_irq[RP2040_NUM_CORES][RP2040_NUM_IRQS]; + qemu_irq nmi_irq[RP2040_NUM_CORES]; + bool irq_level[RP2040_NUM_IRQS]; + Clock *sysclk; }; =20 diff --git a/include/hw/misc/rp2040_syscfg.h b/include/hw/misc/rp2040_syscf= g.h new file mode 100644 index 0000000000..0e02e4ad81 --- /dev/null +++ b/include/hw/misc/rp2040_syscfg.h @@ -0,0 +1,41 @@ +/* + * RP2040 syscfg emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_RP2040_SYSCFG_H +#define HW_MISC_RP2040_SYSCFG_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_RP2040_SYSCFG "rp2040-syscfg" +OBJECT_DECLARE_SIMPLE_TYPE(RP2040SysCfgState, RP2040_SYSCFG) + +#define RP2040_SYSCFG_BASE 0x40004000 +#define RP2040_SYSCFG_SIZE 0x4000 + +typedef void (*RP2040SysCfgUpdateFn)(void *opaque); + +struct RP2040SysCfgState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + RP2040SysCfgUpdateFn update; + void *update_opaque; + uint32_t proc0_nmi_mask; + uint32_t proc1_nmi_mask; + uint32_t proc_config; + uint32_t proc_in_sync_bypass; + uint32_t proc_in_sync_bypass_hi; + uint32_t dbgforce; + uint32_t mempowerdown; +}; + +void rp2040_syscfg_set_update_callback(RP2040SysCfgState *s, + RP2040SysCfgUpdateFn update, + void *opaque); +uint32_t rp2040_syscfg_get_nmi_mask(RP2040SysCfgState *s, unsigned core); + +#endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 8079fcee28..dbd2e4f4a7 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -254,7 +254,7 @@ qtests_exynos4210 =3D \ =20 qtests_arm =3D \ (config_all_devices.has_key('CONFIG_RP2040') ? - ['rp2040-sysinfo-test'] : []) + \ + ['rp2040-syscfg-test', 'rp2040-sysinfo-test'] : []) + \ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-= dualtimer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-time= r-test'] : []) + \ diff --git a/tests/qtest/rp2040-syscfg-test.c b/tests/qtest/rp2040-syscfg-t= est.c new file mode 100644 index 0000000000..b1a0738bd2 --- /dev/null +++ b/tests/qtest/rp2040-syscfg-test.c @@ -0,0 +1,97 @@ +/* + * QTest testcase for the RP2040 SYSCFG block. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "hw/misc/rp2040.h" +#include "qemu/bitops.h" + +#define SYSCFG_BASE 0x40004000 +#define SYSCFG_PROC0_NMI_MASK 0x00 +#define SYSCFG_PROC1_NMI_MASK 0x04 +#define SYSCFG_PROC_CONFIG 0x08 +#define SYSCFG_PROC_IN_SYNC_BYPASS 0x0c +#define SYSCFG_PROC_IN_SYNC_BYPASS_HI 0x10 +#define SYSCFG_DBGFORCE 0x14 +#define SYSCFG_MEMPOWERDOWN 0x18 + +#define PROC_CONFIG_RESET 0x10000000 +#define DBGFORCE_RESET 0x00000066 + +static QTestState *rp2040_start(void) +{ + return qtest_init("-machine raspi-pico"); +} + +static void test_syscfg_reset_values(void) +{ + QTestState *qts =3D rp2040_start(); + + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC0_NMI_MASK), + =3D=3D, 0); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC1_NMI_MASK), + =3D=3D, 0); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC_CONFIG), = =3D=3D, + PROC_CONFIG_RESET); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_DBGFORCE), =3D= =3D, + DBGFORCE_RESET); + + qtest_quit(qts); +} + +static void test_syscfg_rw_masks(void) +{ + QTestState *qts =3D rp2040_start(); + + qtest_writel(qts, SYSCFG_BASE + SYSCFG_PROC0_NMI_MASK, 0xa5a5a5a5); + qtest_writel(qts, SYSCFG_BASE + SYSCFG_PROC1_NMI_MASK, 0x5a5a5a5a); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC0_NMI_MASK), + =3D=3D, 0xa5a5a5a5); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC1_NMI_MASK), + =3D=3D, 0x5a5a5a5a); + + qtest_writel(qts, SYSCFG_BASE + SYSCFG_PROC_IN_SYNC_BYPASS, 0xffffffff= ); + qtest_writel(qts, SYSCFG_BASE + SYSCFG_PROC_IN_SYNC_BYPASS_HI, + 0xffffffff); + qtest_writel(qts, SYSCFG_BASE + SYSCFG_MEMPOWERDOWN, 0xffffffff); + g_assert_cmphex(qtest_readl(qts, + SYSCFG_BASE + SYSCFG_PROC_IN_SYNC_BYPASS), + =3D=3D, 0x3fffffff); + g_assert_cmphex(qtest_readl(qts, + SYSCFG_BASE + SYSCFG_PROC_IN_SYNC_BYPASS_H= I), + =3D=3D, 0x0000003f); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_MEMPOWERDOWN), = =3D=3D, + 0x000000ff); + + qtest_quit(qts); +} + +static void test_syscfg_atomic_aliases(void) +{ + QTestState *qts =3D rp2040_start(); + + qtest_writel(qts, SYSCFG_BASE + SYSCFG_PROC0_NMI_MASK, 0); + qtest_writel(qts, SYSCFG_BASE + RP2040_ATOMIC_SET + + SYSCFG_PROC0_NMI_MASK, 0x0000000f); + qtest_writel(qts, SYSCFG_BASE + RP2040_ATOMIC_CLR + + SYSCFG_PROC0_NMI_MASK, 0x00000003); + g_assert_cmphex(qtest_readl(qts, SYSCFG_BASE + SYSCFG_PROC0_NMI_MASK), + =3D=3D, 0x0000000c); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/rp2040-syscfg/reset-values", test_syscfg_reset_values= ); + qtest_add_func("/rp2040-syscfg/rw-masks", test_syscfg_rw_masks); + qtest_add_func("/rp2040-syscfg/atomic-aliases", + test_syscfg_atomic_aliases); + + return g_test_run(); +} --=20 2.55.0 From nobody Thu Oct 22 19:28: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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824449; cv=none; d=zohomail.com; s=zohoarc; b=K7bbkfCQsbfikyP/AmO7EpQ+y1AYS6bykS0WLDPusDdbijjmZjj90Fiest93ghJSnXjWPfRMQEc4hpIER0G8ybaZoPLRemowlDctqlQgpA4sCdo5YbGMcYW15T4/1xktE4IGk7qm9LyNxoh+WBfXfMOQm7fm2dOFVog7CZ19NHE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824449; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/QnzBLaPi29cfAK622DcsenVTGZKD4K2Pku8zU1gJC4=; b=Xe8zNjeMvU/prYh6NQrYehh5TowY5hbIYDQrUlZn8kCKA/cPGWNVhgXnK+cbjAmVVhmWpByBD9+NIove8dK/2pd6vDrls46OdVoiR+me32Gd2FeKo3TZ16ZXYMuNjLuwsjUNsev+V1Xoxebv6RC2662+1hSSD1wU8zQolOoWagE= 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 1791824449721609.852954511508; Mon, 12 Oct 2026 10:00:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNR-0000bW-Qo; Mon, 12 Oct 2026 12:59:53 -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 1xGJMn-00084m-Ll; Mon, 12 Oct 2026 12:59:15 -0400 Received: from smtp-out-1.univ-lille.fr ([194.254.129.82]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJMe-0006EW-Bq; Mon, 12 Oct 2026 12:59:12 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-1.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw34WHMzBqmr; Mon, 12 Oct 2026 18:58:43 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw32b6jz83nc; Mon, 12 Oct 2026 18:58:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824323; bh=/QnzBLaPi29cfAK622DcsenVTGZKD4K2Pku8zU1gJC4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mybcsavC2095F4Bw/apOxUjnCIiocEJRFC/Luo/hqOqc8Pp2fYN1F79TVp+lV1FwY dY+ToriSgAdIuUfYgsePozlst8PgF+v+hqOcmfjZXgvgxtCbaC8OGV0dxaKCUvjnMI A9EXHiDVrRF0vMuIWvtg1+z7v/YWyQFSsH+THvy9J/yxPFNCk5gdgBTZ4pTueUwIpN TRu1zNsQD9VsmGWTcp79O4bm0PGXRVorBnc56gOPU/9iIjJLV976yBWnw40lK8qwiM sxOaxJdjksTX27l+F/ajdpB9lSkPz/Q/66Mn8Xdytg7NAVOgBaRZptzQTF1QyNanE0 Ede0oLxxBHMMg== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 8/9] hw/misc: add RP2040 voltage regulator Date: Mon, 12 Oct 2026 18:58:38 +0200 Message-ID: <20261012165840.99050-9-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.82; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-1.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824451919158500 Content-Type: text/plain; charset="utf-8" Model the RP2040 voltage regulator, brown-out detector, and chip reset. Include documented reset values, writable masks, and APB atomic aliases. Signed-off-by: Gilles Grimaud --- hw/arm/rp2040.c | 8 +- hw/misc/meson.build | 1 + hw/misc/rp2040_vreg.c | 149 +++++++++++++++++++++++++++++++++ include/hw/arm/rp2040.h | 2 + include/hw/misc/rp2040_vreg.h | 46 ++++++++++ tests/qtest/meson.build | 6 +- tests/qtest/rp2040-vreg-test.c | 79 +++++++++++++++++ 7 files changed, 287 insertions(+), 4 deletions(-) create mode 100644 hw/misc/rp2040_vreg.c create mode 100644 include/hw/misc/rp2040_vreg.h create mode 100644 tests/qtest/rp2040-vreg-test.c diff --git a/hw/arm/rp2040.c b/hw/arm/rp2040.c index 47a0ef220f..0af99aed7e 100644 --- a/hw/arm/rp2040.c +++ b/hw/arm/rp2040.c @@ -73,8 +73,6 @@ static const struct { { "rp2040.watchdog", 0x40058000, 0x4000 }, { "rp2040.rtc", 0x4005c000, 0x4000 }, { "rp2040.rosc", 0x40060000, 0x4000 }, - { "rp2040.vreg_and_chip_reset", 0x40064000, 0x4000 }, - { "rp2040.tbman", 0x4006c000, 0x4000 }, { "rp2040.dma", 0x50000000, 0x1000 }, { "rp2040.usbctrl_dpram", 0x50100000, 0x10000 }, { "rp2040.usbctrl_regs", 0x50110000, 0x10000 }, @@ -145,6 +143,7 @@ static void rp2040_soc_init(Object *obj) =20 object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_RP2040_SYSCFG); object_initialize_child(obj, "sysinfo", &s->sysinfo, TYPE_RP2040_SYSIN= FO); + object_initialize_child(obj, "vreg", &s->vreg, TYPE_RP2040_VREG); =20 s->irq =3D qemu_allocate_irqs(rp2040_set_irq, s, RP2040_NUM_IRQS); =20 @@ -278,6 +277,11 @@ static void rp2040_soc_realize(DeviceState *dev, Error= **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, RP2040_SYSINFO_BASE); =20 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->vreg), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->vreg), 0, RP2040_VREG_BASE); + for (i =3D 0; i < ARRAY_SIZE(s->uart); i++) { qdev_connect_clock_in(DEVICE(&s->uart[i]), "clk", s->sysclk); if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { diff --git a/hw/misc/meson.build b/hw/misc/meson.build index c26442fdcc..ea89f26b88 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -100,6 +100,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files( )) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_syscfg.c')) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_sysinfo.c')) +system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_vreg.c')) system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) system_ss.add(when: 'CONFIG_XLNX_ZYNQ_DDRC', if_true: files('xlnx-zynq-ddr= c.c')) diff --git a/hw/misc/rp2040_vreg.c b/hw/misc/rp2040_vreg.c new file mode 100644 index 0000000000..2745bddd50 --- /dev/null +++ b/hw/misc/rp2040_vreg.c @@ -0,0 +1,149 @@ +/* + * RP2040 voltage regulator and chip reset emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040.h" +#include "hw/misc/rp2040_vreg.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +#define VREG_RW_MASK \ + (R_RP2040_VREG_VREG_VSEL_MASK | R_RP2040_VREG_VREG_HIZ_MASK | \ + R_RP2040_VREG_VREG_EN_MASK) +#define BOD_RW_MASK \ + (R_RP2040_VREG_BOD_VSEL_MASK | R_RP2040_VREG_BOD_EN_MASK) +#define CHIP_RESET_RW_MASK R_RP2040_VREG_CHIP_RESET_PSM_RESTART_FLAG_MASK + +static uint32_t rp2040_vreg_read_vreg(RP2040VregState *s) +{ + uint32_t value =3D s->vreg; + + if (FIELD_EX32(value, RP2040_VREG_VREG, EN) && + !FIELD_EX32(value, RP2040_VREG_VREG, HIZ)) { + value |=3D R_RP2040_VREG_VREG_ROK_MASK; + } + + return value; +} + +static uint64_t rp2040_vreg_read(void *opaque, hwaddr addr, unsigned size) +{ + RP2040VregState *s =3D opaque; + hwaddr offset =3D addr & 0xfff; + uint64_t value; + + switch (offset) { + case A_RP2040_VREG_VREG: + value =3D rp2040_vreg_read_vreg(s); + break; + case A_RP2040_VREG_BOD: + value =3D s->bod; + break; + case A_RP2040_VREG_CHIP_RESET: + value =3D s->chip_reset; + break; + default: + value =3D 0; + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented read at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } + + return value; +} + +static void rp2040_vreg_write(void *opaque, hwaddr addr, + uint64_t value64, unsigned size) +{ + RP2040VregState *s =3D opaque; + hwaddr alias =3D addr & RP2040_ATOMIC_ALIAS_MASK; + hwaddr offset =3D addr & 0xfff; + uint32_t value =3D value64; + + switch (offset) { + case A_RP2040_VREG_VREG: + s->vreg =3D rp2040_atomic_update(s->vreg, value, alias) & + VREG_RW_MASK; + break; + case A_RP2040_VREG_BOD: + s->bod =3D rp2040_atomic_update(s->bod, value, alias) & BOD_RW_MAS= K; + break; + case A_RP2040_VREG_CHIP_RESET: + s->chip_reset =3D + rp2040_atomic_update(s->chip_reset, value, alias) & + CHIP_RESET_RW_MASK; + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented write at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } +} + +static const MemoryRegionOps rp2040_vreg_ops =3D { + .read =3D rp2040_vreg_read, + .write =3D rp2040_vreg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void rp2040_vreg_reset(DeviceState *dev) +{ + RP2040VregState *s =3D RP2040_VREG(dev); + + s->vreg =3D RP2040_VREG_VREG_RESET; + s->bod =3D RP2040_VREG_BOD_RESET; + s->chip_reset =3D 0; +} + +static void rp2040_vreg_init(Object *obj) +{ + RP2040VregState *s =3D RP2040_VREG(obj); + + memory_region_init_io(&s->iomem, obj, &rp2040_vreg_ops, s, + "rp2040.vreg_and_chip_reset", RP2040_VREG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static const VMStateDescription rp2040_vreg_vmstate =3D { + .name =3D TYPE_RP2040_VREG, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32(vreg, RP2040VregState), + VMSTATE_UINT32(bod, RP2040VregState), + VMSTATE_UINT32(chip_reset, RP2040VregState), + VMSTATE_END_OF_LIST() + } +}; + +static void rp2040_vreg_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, rp2040_vreg_reset); + dc->vmsd =3D &rp2040_vreg_vmstate; +} + +static const TypeInfo rp2040_vreg_info =3D { + .name =3D TYPE_RP2040_VREG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RP2040VregState), + .instance_init =3D rp2040_vreg_init, + .class_init =3D rp2040_vreg_class_init, +}; + +static void rp2040_vreg_register_types(void) +{ + type_register_static(&rp2040_vreg_info); +} +type_init(rp2040_vreg_register_types) diff --git a/include/hw/arm/rp2040.h b/include/hw/arm/rp2040.h index f6050f255d..4b6f7c2faa 100644 --- a/include/hw/arm/rp2040.h +++ b/include/hw/arm/rp2040.h @@ -15,6 +15,7 @@ #include "hw/core/sysbus.h" #include "hw/misc/rp2040_sysinfo.h" #include "hw/misc/rp2040_syscfg.h" +#include "hw/misc/rp2040_vreg.h" #include "qom/object.h" =20 #define TYPE_RP2040 "rp2040" @@ -39,6 +40,7 @@ struct RP2040State { PL011State uart[2]; RP2040SysCfgState syscfg; RP2040SysInfoState sysinfo; + RP2040VregState vreg; =20 MemoryRegion *board_memory; MemoryRegion cpu_memory[RP2040_NUM_CORES]; diff --git a/include/hw/misc/rp2040_vreg.h b/include/hw/misc/rp2040_vreg.h new file mode 100644 index 0000000000..eab6cd8221 --- /dev/null +++ b/include/hw/misc/rp2040_vreg.h @@ -0,0 +1,46 @@ +/* + * RP2040 voltage regulator and chip reset emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_RP2040_VREG_H +#define HW_MISC_RP2040_VREG_H + +#include "hw/core/registerfields.h" +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_RP2040_VREG "rp2040-vreg" +OBJECT_DECLARE_SIMPLE_TYPE(RP2040VregState, RP2040_VREG) + +#define RP2040_VREG_BASE 0x40064000 +#define RP2040_VREG_SIZE 0x4000 + +REG32(RP2040_VREG_VREG, 0x00) + FIELD(RP2040_VREG_VREG, ROK, 12, 1) + FIELD(RP2040_VREG_VREG, VSEL, 4, 4) + FIELD(RP2040_VREG_VREG, HIZ, 1, 1) + FIELD(RP2040_VREG_VREG, EN, 0, 1) +REG32(RP2040_VREG_BOD, 0x04) + FIELD(RP2040_VREG_BOD, VSEL, 4, 4) + FIELD(RP2040_VREG_BOD, EN, 0, 1) +REG32(RP2040_VREG_CHIP_RESET, 0x08) + FIELD(RP2040_VREG_CHIP_RESET, PSM_RESTART_FLAG, 24, 1) + FIELD(RP2040_VREG_CHIP_RESET, HAD_PSM_RESTART, 20, 1) + FIELD(RP2040_VREG_CHIP_RESET, HAD_RUN, 16, 1) + FIELD(RP2040_VREG_CHIP_RESET, HAD_POR, 8, 1) + +#define RP2040_VREG_VREG_RESET 0x000000b1 +#define RP2040_VREG_BOD_RESET 0x00000091 + +struct RP2040VregState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint32_t vreg; + uint32_t bod; + uint32_t chip_reset; +}; + +#endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index dbd2e4f4a7..4e8b753536 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -253,8 +253,6 @@ qtests_exynos4210 =3D \ ['exynos4210_uart_fifo-test'] =20 qtests_arm =3D \ - (config_all_devices.has_key('CONFIG_RP2040') ? - ['rp2040-syscfg-test', 'rp2040-sysinfo-test'] : []) + \ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-= dualtimer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-time= r-test'] : []) + \ @@ -267,6 +265,10 @@ qtests_arm =3D \ (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test',= 'tpm-tis-i2c-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : = []) + \ (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : [])= + \ + (config_all_devices.has_key('CONFIG_RP2040') ? + ['rp2040-syscfg-test', + 'rp2040-sysinfo-test', + 'rp2040-vreg-test'] : []) + \ (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 := []) + \ (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-= test'] : []) + \ (config_all_devices.has_key('CONFIG_CAN_FLEXCAN') ? ['flexcan-test'] : [= ]) + \ diff --git a/tests/qtest/rp2040-vreg-test.c b/tests/qtest/rp2040-vreg-test.c new file mode 100644 index 0000000000..cb47d7d527 --- /dev/null +++ b/tests/qtest/rp2040-vreg-test.c @@ -0,0 +1,79 @@ +/* + * QTest testcase for the RP2040 vreg_and_chip_reset block. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040.h" +#include "hw/misc/rp2040_vreg.h" +#include "libqtest.h" + +static QTestState *rp2040_start(void) +{ + return qtest_init("-machine raspi-pico"); +} + +static void test_vreg_reset_values(void) +{ + QTestState *qts =3D rp2040_start(); + + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_VREG), =3D=3D, + RP2040_VREG_VREG_RESET | + R_RP2040_VREG_VREG_ROK_MASK); + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_BOD), =3D=3D, + RP2040_VREG_BOD_RESET); + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_CHIP_RESET), =3D=3D, = 0); + + qtest_quit(qts); +} + +static void test_vreg_rw_masks(void) +{ + QTestState *qts =3D rp2040_start(); + + qtest_writel(qts, RP2040_VREG_BASE + A_RP2040_VREG_VREG, 0xffffffff); + qtest_writel(qts, RP2040_VREG_BASE + A_RP2040_VREG_BOD, 0xffffffff); + qtest_writel(qts, RP2040_VREG_BASE + A_RP2040_VREG_CHIP_RESET, + 0xffffffff); + + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_VREG), =3D=3D, 0x0000= 00f3); + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_BOD), =3D=3D, 0x00000= 0f1); + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_CHIP_RESET), =3D=3D, + R_RP2040_VREG_CHIP_RESET_PSM_RESTART_FLAG_MASK); + + qtest_quit(qts); +} + +static void test_vreg_atomic_aliases(void) +{ + QTestState *qts =3D rp2040_start(); + + qtest_writel(qts, RP2040_VREG_BASE + A_RP2040_VREG_BOD, 0); + qtest_writel(qts, RP2040_VREG_BASE + RP2040_ATOMIC_SET + + A_RP2040_VREG_BOD, 0x00000011); + qtest_writel(qts, RP2040_VREG_BASE + RP2040_ATOMIC_CLR + + A_RP2040_VREG_BOD, 0x00000010); + + g_assert_cmphex(qtest_readl(qts, + RP2040_VREG_BASE + A_RP2040_VREG_BOD), =3D=3D, 0x00000= 001); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/rp2040-vreg/reset-values", test_vreg_reset_values); + qtest_add_func("/rp2040-vreg/rw-masks", test_vreg_rw_masks); + qtest_add_func("/rp2040-vreg/atomic-aliases", test_vreg_atomic_aliases= ); + + return g_test_run(); +} --=20 2.55.0 From nobody Thu Oct 22 19:28: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=univ-lille.fr ARC-Seal: i=1; a=rsa-sha256; t=1791824470; cv=none; d=zohomail.com; s=zohoarc; b=KTbK5opuRGVZIJqX6MBJaQiJStgPWlSM6Y8JEgH1Cd5AyNmKE0Vz09q9LXHMjb0o5+VbkOfeqFVNcRK++wZRhlonrWMemqwQa56xsuZu33G0IXM3niC3qdByVp2kGxDXVa6/st9O8npZrTaPIBNYR+Lz3tEBETCQlgKT1qsuJ9k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1791824470; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=vz13J9qe9FL7TAPGBQHYiICwl3Y6kaxotqUC9vUcfmw=; b=YZBvQzzzRAA0R6eRE28BPZUygcv4nFmAv9vb38OUE2zrvPebGqhDSMwt6YhNTj4+YYtMTNcWhGTRVavQEKnlT6/1D7Ei5PJCg+kAarc5xHZJesj19SJ0Whvg+43Wv0tTKGT107kyanpTWUvf43OSkIAd0Ia4rD5E/Lpv50vtkdQ= 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 1791824470186796.5680152330294; Mon, 12 Oct 2026 10:01:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xGJNL-0000CQ-J0; Mon, 12 Oct 2026 12:59:47 -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 1xGJN7-0008Fd-NE; Mon, 12 Oct 2026 12:59:34 -0400 Received: from smtp-out-2.univ-lille.fr ([194.254.129.106]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xGJN4-0006JP-Hg; Mon, 12 Oct 2026 12:59:32 -0400 Received: from smtp01.univ-lille.fr (smtp01.univ-lille.fr [194.254.129.95]) by smtp-out-2.univ-lille.fr (Postfix) with ESMTPS id 4j3Nw36C6qz8BVL; Mon, 12 Oct 2026 18:58:43 +0200 (CEST) Received: from localhost.localdomain (unknown [134.206.205.113]) (Authenticated sender: gilles.grimaud) by smtp01.univ-lille.fr (Postfix) with ESMTPSA id 4j3Nw34ljHz83nY; Mon, 12 Oct 2026 18:58:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=univ-lille.fr; s=dkim; t=1791824323; bh=vz13J9qe9FL7TAPGBQHYiICwl3Y6kaxotqUC9vUcfmw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vQpHiybypuDa9gLEY2dGD/bcomR56NX/Naz8MyEqqf9ybfZPreuSR7KT+2sjEu6A6 BdvPlH1dHymiy9FyU9ADHCmtWh+yEiFDJiPG2v49iPncw84ztsC9akjtV0rn0amodl 3sCWadh4r22r/eF9I8ULxSUb1JK56WSZcP8DMpVJW+8rOkoWHQHGFVkN7S1tWzQ6s1 /BpHBHXshkK4gXLs5PuNl+uz9L9HWuutN7JLpd3bUpZEWjdaFjR6fkPr1u5TPU8JlK Qd3pMN4fFCb7A41uAqkbIQ1k+RD2uLws100o/ufbEL1VBfxtw7L8hJxvd2i4OaTLbv tcoCAOYQ3tShw== From: Gilles Grimaud To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, Gilles Grimaud , Peter Maydell , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , qemu-arm@nongnu.org (open list:ARM TCG CPUs) Subject: [RFC PATCH 9/9] hw/misc: add RP2040 testbench manager Date: Mon, 12 Oct 2026 18:58:39 +0200 Message-ID: <20261012165840.99050-10-gilles.grimaud@univ-lille.fr> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> References: <20261012165840.99050-1-gilles.grimaud@univ-lille.fr> 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=194.254.129.106; envelope-from=gilles.grimaud@univ-lille.fr; helo=smtp-out-2.univ-lille.fr X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, 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 @univ-lille.fr) X-ZM-MESSAGEID: 1791824472349158500 Content-Type: text/plain; charset="utf-8" Model the RP2040 testbench manager PLATFORM register. Return the documented ASIC platform value. Signed-off-by: Gilles Grimaud --- hw/arm/rp2040.c | 6 +++ hw/misc/meson.build | 1 + hw/misc/rp2040_tbman.c | 88 +++++++++++++++++++++++++++++++++ include/hw/arm/rp2040.h | 2 + include/hw/misc/rp2040_tbman.h | 29 +++++++++++ tests/qtest/meson.build | 1 + tests/qtest/rp2040-tbman-test.c | 29 +++++++++++ 7 files changed, 156 insertions(+) create mode 100644 hw/misc/rp2040_tbman.c create mode 100644 include/hw/misc/rp2040_tbman.h create mode 100644 tests/qtest/rp2040-tbman-test.c diff --git a/hw/arm/rp2040.c b/hw/arm/rp2040.c index 0af99aed7e..f5ee31392e 100644 --- a/hw/arm/rp2040.c +++ b/hw/arm/rp2040.c @@ -143,6 +143,7 @@ static void rp2040_soc_init(Object *obj) =20 object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_RP2040_SYSCFG); object_initialize_child(obj, "sysinfo", &s->sysinfo, TYPE_RP2040_SYSIN= FO); + object_initialize_child(obj, "tbman", &s->tbman, TYPE_RP2040_TBMAN); object_initialize_child(obj, "vreg", &s->vreg, TYPE_RP2040_VREG); =20 s->irq =3D qemu_allocate_irqs(rp2040_set_irq, s, RP2040_NUM_IRQS); @@ -277,6 +278,11 @@ static void rp2040_soc_realize(DeviceState *dev, Error= **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, RP2040_SYSINFO_BASE); =20 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->tbman), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->tbman), 0, RP2040_TBMAN_BASE); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->vreg), errp)) { return; } diff --git a/hw/misc/meson.build b/hw/misc/meson.build index ea89f26b88..349b6c126e 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -100,6 +100,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files( )) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_syscfg.c')) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_sysinfo.c')) +system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_tbman.c')) system_ss.add(when: 'CONFIG_RP2040', if_true: files('rp2040_vreg.c')) system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) diff --git a/hw/misc/rp2040_tbman.c b/hw/misc/rp2040_tbman.c new file mode 100644 index 0000000000..f55a80e514 --- /dev/null +++ b/hw/misc/rp2040_tbman.c @@ -0,0 +1,88 @@ +/* + * RP2040 testbench manager emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040_tbman.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +static uint64_t rp2040_tbman_read(void *opaque, hwaddr addr, unsigned size) +{ + hwaddr offset =3D addr & 0xfff; + uint64_t value; + + switch (offset) { + case A_RP2040_TBMAN_PLATFORM: + value =3D R_RP2040_TBMAN_PLATFORM_ASIC_MASK; + break; + default: + value =3D 0; + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented read at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); + break; + } + + return value; +} + +static void rp2040_tbman_write(void *opaque, hwaddr addr, + uint64_t value64, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented write at offset 0x%" + HWADDR_PRIx "\n", __func__, addr & 0xfff); +} + +static const MemoryRegionOps rp2040_tbman_ops =3D { + .read =3D rp2040_tbman_read, + .write =3D rp2040_tbman_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void rp2040_tbman_init(Object *obj) +{ + RP2040TbmanState *s =3D RP2040_TBMAN(obj); + + memory_region_init_io(&s->iomem, obj, &rp2040_tbman_ops, s, + "rp2040.tbman", RP2040_TBMAN_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static const VMStateDescription rp2040_tbman_vmstate =3D { + .name =3D TYPE_RP2040_TBMAN, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static void rp2040_tbman_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &rp2040_tbman_vmstate; +} + +static const TypeInfo rp2040_tbman_info =3D { + .name =3D TYPE_RP2040_TBMAN, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RP2040TbmanState), + .instance_init =3D rp2040_tbman_init, + .class_init =3D rp2040_tbman_class_init, +}; + +static void rp2040_tbman_register_types(void) +{ + type_register_static(&rp2040_tbman_info); +} +type_init(rp2040_tbman_register_types) diff --git a/include/hw/arm/rp2040.h b/include/hw/arm/rp2040.h index 4b6f7c2faa..e4370b90fd 100644 --- a/include/hw/arm/rp2040.h +++ b/include/hw/arm/rp2040.h @@ -15,6 +15,7 @@ #include "hw/core/sysbus.h" #include "hw/misc/rp2040_sysinfo.h" #include "hw/misc/rp2040_syscfg.h" +#include "hw/misc/rp2040_tbman.h" #include "hw/misc/rp2040_vreg.h" #include "qom/object.h" =20 @@ -40,6 +41,7 @@ struct RP2040State { PL011State uart[2]; RP2040SysCfgState syscfg; RP2040SysInfoState sysinfo; + RP2040TbmanState tbman; RP2040VregState vreg; =20 MemoryRegion *board_memory; diff --git a/include/hw/misc/rp2040_tbman.h b/include/hw/misc/rp2040_tbman.h new file mode 100644 index 0000000000..d89deb726c --- /dev/null +++ b/include/hw/misc/rp2040_tbman.h @@ -0,0 +1,29 @@ +/* + * RP2040 testbench manager emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_RP2040_TBMAN_H +#define HW_MISC_RP2040_TBMAN_H + +#include "hw/core/registerfields.h" +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_RP2040_TBMAN "rp2040-tbman" +OBJECT_DECLARE_SIMPLE_TYPE(RP2040TbmanState, RP2040_TBMAN) + +#define RP2040_TBMAN_BASE 0x4006c000 +#define RP2040_TBMAN_SIZE 0x4000 + +REG32(RP2040_TBMAN_PLATFORM, 0x00) + FIELD(RP2040_TBMAN_PLATFORM, ASIC, 0, 1) + +struct RP2040TbmanState { + SysBusDevice parent_obj; + + MemoryRegion iomem; +}; + +#endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 4e8b753536..ad5c877bb5 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -268,6 +268,7 @@ qtests_arm =3D \ (config_all_devices.has_key('CONFIG_RP2040') ? ['rp2040-syscfg-test', 'rp2040-sysinfo-test', + 'rp2040-tbman-test', 'rp2040-vreg-test'] : []) + \ (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 := []) + \ (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-= test'] : []) + \ diff --git a/tests/qtest/rp2040-tbman-test.c b/tests/qtest/rp2040-tbman-tes= t.c new file mode 100644 index 0000000000..d654aabba3 --- /dev/null +++ b/tests/qtest/rp2040-tbman-test.c @@ -0,0 +1,29 @@ +/* + * QTest testcase for the RP2040 testbench manager block. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/rp2040_tbman.h" +#include "libqtest.h" + +static void test_tbman_platform(void) +{ + QTestState *qts =3D qtest_init("-machine raspi-pico"); + + g_assert_cmphex(qtest_readl(qts, + RP2040_TBMAN_BASE + A_RP2040_TBMAN_PLATFORM), =3D=3D, + R_RP2040_TBMAN_PLATFORM_ASIC_MASK); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/rp2040-tbman/platform", test_tbman_platform); + + return g_test_run(); +} --=20 2.55.0