From nobody Wed Aug 26 02:53:45 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; arc=pass (i=1 dmarc=pass fromdomain=aspeedtech.com); dmarc=pass(p=quarantine dis=none) header.from=aspeedtech.com ARC-Seal: i=2; a=rsa-sha256; t=1780468787; cv=pass; d=zohomail.com; s=zohoarc; b=L9jIBrxco6ybgVd1UJsFaUqFubUPpwCimm27XajGzQWFbn/CUSEXBPxl4BNp6xtaqeTkqND9fh7GR6IrJWmj0IOEEi2qeXu2bjl9ETRfFAoTktVBzwRAkzVlOrJ58R2IOVIfm3v9vN80dU5Rk8MMdg6r1cIchHEpKZ4/j4RsKtM= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780468787; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=CfmzFh+8mkKZMhd9TBqC7CdNLesi+xSQeqfY2iSj32U=; b=gEHAl3A+hTdjPjbVyE3T1a22vthpGaCRqATm3KPPISDj6cpKi4EOT7J9KNxvZ73utqFb4fLJKGqjktID4wbWi/AqQgE8Spo9k1ufNfHj4HXafKSFqQgu7PWSm3bzM4ei70RfAmtb+neUc2//SQnRKLuY4Sa+M/3yZHqfblnaOks= ARC-Authentication-Results: i=2; 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; arc=pass (i=1 dmarc=pass fromdomain=aspeedtech.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1780468787575361.48560574479905; Tue, 2 Jun 2026 23:39:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wUfF4-00009J-FC; Wed, 03 Jun 2026 02:38:18 -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 1wUfF3-00008K-0b; Wed, 03 Jun 2026 02:38:17 -0400 Received: from mail-japanwestazlp170120003.outbound.protection.outlook.com ([2a01:111:f403:c406::3] helo=OS8PR02CU002.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wUfF0-0008HM-9z; Wed, 03 Jun 2026 02:38:16 -0400 Received: from TYZPR06MB4746.apcprd06.prod.outlook.com (2603:1096:400:129::9) by SEYPR06MB5859.apcprd06.prod.outlook.com (2603:1096:101:c0::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.92.7; Wed, 3 Jun 2026 06:38:01 +0000 Received: from TYZPR06MB4746.apcprd06.prod.outlook.com ([fe80::b6d5:b318:c4a6:d995]) by TYZPR06MB4746.apcprd06.prod.outlook.com ([fe80::b6d5:b318:c4a6:d995%6]) with mapi id 15.21.0092.006; Wed, 3 Jun 2026 06:38:00 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kpco4KNHZ9LazJHxjrbTsxg8n+oywHV467hhLsZPiiscQxGu205tMWE+u4C8n1jw+nJMc3opdCnIFgSJ2NIxiKVu3Mru/qVJAuIlEcNEfKRMvQxoi1AVJkxSF6LK0Ny4LPQk03cNdGPJvfOyF51ILqf6q18Ad8Fu0Yfu7cPDNtAAiJHb+4lt+UAuEFt9Fkhwa9RQ3dNB2HxtZJfeqsLL4nkfYzW4psajmUzrPvo0rW92PJu2fqd1Lf3t2L+c+QcK8hK5V/fhYmnWIEdR5/GFMvBId72f2v1otdPFBOML74kZoEonh5AnHzG2lM51l4eamId3VWJzmxc+kM3lffSIEQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=CfmzFh+8mkKZMhd9TBqC7CdNLesi+xSQeqfY2iSj32U=; b=Og5eLRatwTcO7dAYxcm54r54FAj0O/r3rgbW5lgRmrr95cNlvTPugjFJ6LKBytDzqho6wJT1PwWllK5cbTEk3STqSBmnSRSEXOZIxXhKu8cSMfh+rP9eSCWVK4prS4XGbGrLQuQA1d13TWN8nTvG5TrQ2rQFiCDSRr7WetigrjbRFQPZ+BsRQZDiuxgFA3MxCmO4vdqhOZIQuErNLgUQjXoqFi2BexQMzySGgXOhDyQTJXUsfwMRUgJWw35/s/bcmFFAt42JfkmHhynDaYfY5xO12kQMivfJWffU50IRiaLOChwdilNFUtH/3TbGyo982w7fdT+nJQAExghg8oPpag== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=aspeedtech.com; dmarc=pass action=none header.from=aspeedtech.com; dkim=pass header.d=aspeedtech.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aspeedtech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CfmzFh+8mkKZMhd9TBqC7CdNLesi+xSQeqfY2iSj32U=; b=V2DvNUeDNIDp9veAtbMg9gT1Oo0pUKtdRSg9xBuy6r5xKZ8kdahkfuKF2aihA63jfJDISzyFyVpqAUJ2LAW2jZKUIVBbYqOVSLgKVKLlW3jHbrq2VBtHfnHlx0SIpn45S1IBQY94+cAXXpAGDMDVrKQQm4qKdA2Z8EvurNXdYCuxR2nxFMPJPGxnsTfExQBuyxfRUdlHwrRvPUq9i9cmbEMNTNTM5Bh8Cc+WxXDOTgl3yRCI5W4z46G/f1GZNwgfD4cMoyy0Y+iYOdqvhQRVqoZPW1X9z/NSfJNhWUkBodxbRjLBsLb85UG5z3a1r/kC/86d9ZhU1VmxaiJLx0oZgA== From: Steven Lee To: =?iso-8859-1?Q?C=E9dric_Le_Goater?= , Peter Maydell , Steven Lee , Troy Lee , Jamin Lin , Kane Chen , Andrew Jeffery , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: Troy Lee , "longzl2@lenovo.com" , Yunlin Tang Subject: [RESEND PATCH 2/6] hw/misc: Add ASPEED Caliptra mailbox frontend Thread-Topic: [RESEND PATCH 2/6] hw/misc: Add ASPEED Caliptra mailbox frontend Thread-Index: AQHc8yOF8h7ze7L5ZkuRlaiJfE4lSA== Date: Wed, 3 Jun 2026 06:38:00 +0000 Message-ID: <20260603063756.1481524-3-steven_lee@aspeedtech.com> References: <20260603063756.1481524-1-steven_lee@aspeedtech.com> In-Reply-To: <20260603063756.1481524-1-steven_lee@aspeedtech.com> Accept-Language: zh-TW, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=aspeedtech.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: TYZPR06MB4746:EE_|SEYPR06MB5859:EE_ x-ms-office365-filtering-correlation-id: 0ea39cc6-47a8-4c2f-935b-08dec13aa847 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|1800799024|366016|376014|7416014|921020|6133799003|3023799007|18002099003|22082099003|56012099006|38070700021; x-microsoft-antispam-message-info: hGrO4pdCIL4ZZok/9nsJtPiHdxT85ogEyanbn9SOc42IXpYQAR+dl2dbduJgXbXDuoNEbyVi1lBDoeZ2A8LRZNtYRKSL+qnIEhZn2sWAUQb0r6d2aiv3GlfsmbojLwI5rvKcy5yZHLPyQcpcUClH4Oa8swqZ3uYqBniXsfYQOE498fx8eeY/HZB1DSImt8iu3EjHD3P+xDdmThTw3pqENmC/3Ky+POKlFkbM/MsK1Sqm+LdLJVUAXWleH5ARPGiP9vG5t41L0CMDMN+KjpA86pRDASNKC+2v9+IUr3R0PuDNddGt9p4lew19GDQMGqQpZEvp43MAwwZxloiePCHTq8yO8vaHWOHvBlHwz+Q3kLv9DHK9TDPLNyHZp/bl59EvJXswuWkUQOKcEeM15GnfDeGojsPNPxH/WhVv7oT776h6V5kpLdJCpeDiTL4JOgH/ZGKw54sd2NcnelfZh5JY0AQ9vQ2mh//KvgxlhpeQGvQKQzanszJNqpc2cA8SLraio0UDEZr4En0kTauV4ipW1UkyQbNwWGUhmIhdNVocgiuuYe78tSbFs6fc4SD/AZmIoTot2e/LFunispVPfQKtMn0vCUS2H/QnR5QRhdfyZ1EtOeL/R2Wa9AKdYPNNUybIRPXaMjGXOTmoHcklSYuDH5A/K+6Ng+tfnBcbo8RzYAAqGKUhxtJ3kQU6zrxhRi1PaTHiQ42wyQABAAzpG5rVpp1QMHJVxWwXOcQjCPQAKfGIrMmFD+BhXIZ/K3A4mxVchcETGv5LmFNLdwSXLAEn9A== x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:TYZPR06MB4746.apcprd06.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(376014)(7416014)(921020)(6133799003)(3023799007)(18002099003)(22082099003)(56012099006)(38070700021); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?0unYaqkrALPSGd9xLHUHVKr05Aw0XFM7B2Kj4CL2vL1lo1f3z/ygGBhMzu?= =?iso-8859-1?Q?vJiMLa5S/pwpFTvgqC2UJBLAw1V67YrtvRhPSP142PxBZOFVTfTb8H2/vL?= =?iso-8859-1?Q?EU9ereE1D0g9HtB+Xce+XwMLhrs525KphNOFsGEAmNW0TSXDKHasPOxgK/?= =?iso-8859-1?Q?GN26oqLg8kFySSkH8VUc3j1FMZnyukeuMjRUsc1dnP/d9X4TVfYy9hhcHk?= =?iso-8859-1?Q?GyovTFjQPsLXVLWlAveqW0PGyjnd1cFHx8X4fkpc67wrBo4nelPBB7/kd+?= =?iso-8859-1?Q?IQ7E0kRwLj9evMnnO3JQr5sp4MayQYQHxgcD82GOB4Ih8jorFBe4RFl2r8?= =?iso-8859-1?Q?xbCdDz/eLl+EClkQkVreYtYbl1U8UUND5ys7n/RXgdU/TvWZVICJnyB1RT?= =?iso-8859-1?Q?XJjYk9zhu/onMYgz3maWKhPSFTND1QIW8EuFBVljK6oB19jaszvsE6GTr3?= =?iso-8859-1?Q?ofAVJI6cHV8m0nWxsTLj3N1dWmR3N7hKCWIqsY1e0dz5T0meig/gO7uU9M?= =?iso-8859-1?Q?TTVfNhwHfG5J/d13IST6PkMR2wdgolK4rj2quK6KqZGhO6wbxHyVinytaF?= =?iso-8859-1?Q?9EABcuI2WIpLINNKKbCSwxUMVkYuEJriN8R4/lMF4aOy4+ouN7h44yOwpe?= =?iso-8859-1?Q?eV5YiuHkzGcugMkq4nwcbom1ydLwmeFj/F9eUpMQiHI0WZpf0hBYhYB6Rx?= =?iso-8859-1?Q?Sa6lw3dnqYK3WIvFfIh1Ko8qgx530Zj+QOztim3e/YmJI8FyJr4qto4xJ3?= =?iso-8859-1?Q?bfiG1mfwV/bWroQ9tjr9xu8f3dME8DnEe1bgiT+7sPLXhfwpUjflvHT7wu?= =?iso-8859-1?Q?w4Uhi/1t9blxGGUX+mSugq1DmnQTTUgU8C7XXAlA2bIiSGYej2BUU1fU7h?= =?iso-8859-1?Q?Icb4cL6EWUGe02RRr5ETb0tIff3IlLEiUSVAiOfc7mpyH/XpgnFhQQUTZD?= =?iso-8859-1?Q?iVLRVo5L8wYM3ghker4YYNkkQElFNMk7ZC1HEykv6mWdmnEfsy7T732m4n?= =?iso-8859-1?Q?dfZiCvHNOcGriygdILi3OCmq8heND+JIwbxSGT3p3SQIPfzajoijx7/Bzn?= =?iso-8859-1?Q?oI+qUyF31IfzYXp2L8fRPZuD5AVlU4ugya3VQUeTpKxk5PXLrZtzzAAGXH?= =?iso-8859-1?Q?vXVFsxXMsbcsMDrxaEEGDRq8QLZp8/nSB8185wcNHI4VqUWNdCPGO1KQZS?= =?iso-8859-1?Q?1tQsuuwzNGOaQDY2ChSZb8e1NUoNjcAO5eqB1KPTxuHw41sI7v0RY9MIB4?= =?iso-8859-1?Q?Xl+E9kdUIFu8/7toilrv9yO1iZyYc+qitShm1O6xpaY6DKrmb1NlYsctND?= =?iso-8859-1?Q?4X6B1aoa7ODuWv1tmdIXEQvv+q05Py7XufpDvjEK8qpDIlPjI6pOTGhRra?= =?iso-8859-1?Q?wkzdKwCrpUsuI92+qt+YP1Cirs/s6Q76hPnX0HQRkNDV6BaYJUPLz92e1z?= =?iso-8859-1?Q?ghcn5Cj5rII9kq4pQTLfM3KDnjkXiCp/E9eXqZGhBH4mP8QS24nJNG1s2H?= =?iso-8859-1?Q?ZThcWrOANhsg0pxB34vzmHm7OBFzfvvXzCabRnTghmXPVP/qdhSu1UsU1S?= =?iso-8859-1?Q?SXiIn6Tvqoic9Ckber64gg+pLHiBS0Hbhez3YUloZmMkz8aI2AsjRQD1wc?= =?iso-8859-1?Q?HieGydcAdtjD+m6ECqT3vmiFwN+OZbIuxLZiz8+5mLGGS5ju+X9GTVmWLr?= =?iso-8859-1?Q?hjP5zPvOL0A0JntZppPLG2gnnjkSO972xYIer0HY+FOnY1urjD7oem/jAC?= =?iso-8859-1?Q?ibjcr4IHB2Rxx84t07OST31oBpH15aV+NSFrWAdzq2/63sGTp0DbrbO4pi?= =?iso-8859-1?Q?8RkkNNtG9g=3D=3D?= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Exchange-RoutingPolicyChecked: TowlAB3U+TnkahWrh7Zx+jWKz1XUtBTSYsXXGg4GrFIMTp8Oabhz4YI9dcEDWQmsWmSy3vrGIfxM2+aL91JpJ6W7dmYi7xuu1+VFZFiqLctMKs1Jobo9LVfJd0u1/cP/8m6efc0DVxFkjs60QRj4rxYRWZ0hKTK+RQSH5swkLVeEhHkgYRx2zjODUhd2vgKh7LvBV5js/ZdizRGRZnhcAsQ6N8pY21jqB89gZpmKrXKKVyLxdtfRsVG33wLOyPcRjJVarPGK4znWjDONYBsweCTuR7qgSXpBePx7kAJRFa+HGHzrQeBAKzyu/VqBq0oQRGuju0js7l9Nf9hvS1q3rA== X-OriginatorOrg: aspeedtech.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: TYZPR06MB4746.apcprd06.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 0ea39cc6-47a8-4c2f-935b-08dec13aa847 X-MS-Exchange-CrossTenant-originalarrivaltime: 03 Jun 2026 06:38:00.8215 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 43d4aa98-e35b-4575-8939-080e90d5a249 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: bt+XB0Dzqc1kh3jP3PLm2526MkS9O0drcBMFDiR4OByApeg9IEVqnSfFJ7JwI1HC7o3qRjtyYwtgdQ0ehmmBFsjheyJss57YWCLYa+pvXVY= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SEYPR06MB5859 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=2a01:111:f403:c406::3; envelope-from=steven_lee@aspeedtech.com; helo=OS8PR02CU002.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 @aspeedtech.com) X-ZM-MESSAGEID: 1780468789660158500 Content-Type: text/plain; charset="utf-8" Add a Caliptra mailbox frontend device with SRAM and CSR regions for the AS= T1040 MCI mailbox window. Model the mailbox lock, command registers, execute flow and completion path= through a pluggable peer interface so backends can service commands synchr= onously or asynchronously. Signed-off-by: Steven Lee --- include/hw/misc/aspeed_cptra_mbox.h | 133 ++++++++++ hw/misc/aspeed_cptra_mbox.c | 380 ++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/misc/trace-events | 4 + 4 files changed, 518 insertions(+) create mode 100644 include/hw/misc/aspeed_cptra_mbox.h create mode 100644 hw/misc/aspeed_cptra_mbox.c diff --git a/include/hw/misc/aspeed_cptra_mbox.h b/include/hw/misc/aspeed_c= ptra_mbox.h new file mode 100644 index 0000000000..470e91597f --- /dev/null +++ b/include/hw/misc/aspeed_cptra_mbox.h @@ -0,0 +1,133 @@ +/* + * ASPEED Caliptra mailbox model (Caliptra 2.x subsystem mode) + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_ASPEED_CPTRA_MBOX_H +#define HW_MISC_ASPEED_CPTRA_MBOX_H + +#include "qom/object.h" +#include "hw/core/sysbus.h" + +typedef struct Error Error; + +/* SRAM size: 2 MiB (matches MCU_MAILBOX0_SRAM_SIZE in caliptra-mcu-sw) */ +#define CPTRA_MBOX0_SRAM_SIZE (2u * 1024u * 1024u) +#define CPTRA_MBOX0_SRAM_WORDS (CPTRA_MBOX0_SRAM_SIZE / 4) + +/* CSR window: 4 KiB (covers all defined registers) */ +#define CPTRA_MBOX0_CSR_SIZE 0x1000u + +/* CSR register offsets (relative to CSR BAR) */ +#define CPTRA_MBOX0_LOCK_OFF 0x000 +#define CPTRA_MBOX0_USER_OFF 0x004 +#define CPTRA_MBOX0_TARGET_USER_OFF 0x008 +#define CPTRA_MBOX0_TARGET_USER_VAL_OFF 0x00C +#define CPTRA_MBOX0_CMD_OFF 0x010 +#define CPTRA_MBOX0_DLEN_OFF 0x014 +#define CPTRA_MBOX0_EXECUTE_OFF 0x018 +#define CPTRA_MBOX0_TARGET_STATUS_OFF 0x01C +#define CPTRA_MBOX0_CMD_STATUS_OFF 0x020 +#define CPTRA_MBOX0_HW_STATUS_OFF 0x024 + +/* CMD_STATUS values */ +#define CPTRA_MBOX0_STATUS_BUSY 0 +#define CPTRA_MBOX0_STATUS_DATA_READY 1 +#define CPTRA_MBOX0_STATUS_COMPLETE 2 +#define CPTRA_MBOX0_STATUS_CMD_FAILURE 3 + +/* SoC agent ID reported in the USER register when the lock is acquired */ +#define CPTRA_MBOX0_SOC_USER_ID 1u + +/* + * Caliptra mailbox interface (frontend), implemented as a QOM interface so + * that backends can deliver an asynchronous response without depending on= the + * concrete frontend device type. + */ +#define TYPE_CPTRA_MBOX_IF "cptra-mbox-if" +typedef struct CptraMboxIfClass CptraMboxIfClass; +DECLARE_CLASS_CHECKERS(CptraMboxIfClass, CPTRA_MBOX_IF, TYPE_CPTRA_MBOX_IF) +typedef struct CptraMboxIf CptraMboxIf; +#define CPTRA_MBOX_IF(obj) \ + INTERFACE_CHECK(CptraMboxIf, (obj), TYPE_CPTRA_MBOX_IF) + +struct CptraMboxIfClass { + InterfaceClass parent; + + /* + * Called by the peer when a command submitted via handle_execute() has + * completed. @status is a CPTRA_MBOX0_STATUS_* value; @data/@len carr= y the + * response payload to be written back into the mailbox SRAM (@len byt= es, + * @dlen is the reported DLEN). + */ + void (*complete)(CptraMboxIf *s, uint32_t status, uint32_t dlen, + const uint8_t *data, uint32_t len); +}; + +/* + * Caliptra mailbox peer (backend) base class. + */ +#define TYPE_CPTRA_MBOX_PEER "cptra-mbox-peer" +OBJECT_DECLARE_TYPE(CptraMboxPeer, CptraMboxPeerClass, CPTRA_MBOX_PEER) + +struct CptraMboxPeer { + DeviceState parent; + + /* Set by the frontend when this peer is linked to it. */ + CptraMboxIf *intf; +}; + +struct CptraMboxPeerClass { + DeviceClass parent; + + /* + * Process a command. @data/@len is a copy of the request payload from= the + * mailbox SRAM. The peer must eventually report completion by calling= the + * interface's complete() method (synchronously or asynchronously). + */ + void (*handle_execute)(CptraMboxPeer *p, uint32_t cmd, uint32_t dlen, + const uint8_t *data, uint32_t len); + + /* Optional: notify the peer of a mailbox reset. */ + void (*handle_reset)(CptraMboxPeer *p); +}; + +/* Concrete frontend device type. */ +#define TYPE_ASPEED_CPTRA_MBOX "aspeed-cptra-mbox" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedCptraMboxState, ASPEED_CPTRA_MBOX) + +struct AspeedCptraMboxState { + SysBusDevice parent_obj; + + /* Linked backend; NULL means no Caliptra peer is present. */ + CptraMboxPeer *peer; + + bool locked; + bool command_pending; + bool release_pending; + uint32_t user; + uint32_t target_user; + uint32_t target_user_valid; + uint32_t cmd; + uint32_t dlen; + uint32_t execute; + uint32_t target_status; + uint32_t cmd_status; + uint32_t hw_status; + + uint32_t sram[CPTRA_MBOX0_SRAM_WORDS]; + + MemoryRegion sram_mr; + MemoryRegion csr_mr; +}; + +bool aspeed_cptra_mbox_set_peer(AspeedCptraMboxState *s, CptraMboxPeer *pe= er, + Error **errp); + +/* Concrete external (chardev) peer type. */ +#define TYPE_CPTRA_MBOX_PEER_EXTERN "cptra-mbox-peer-extern" + +#endif /* HW_MISC_ASPEED_CPTRA_MBOX_H */ diff --git a/hw/misc/aspeed_cptra_mbox.c b/hw/misc/aspeed_cptra_mbox.c new file mode 100644 index 0000000000..8c1faf69df --- /dev/null +++ b/hw/misc/aspeed_cptra_mbox.c @@ -0,0 +1,380 @@ +/* + * ASPEED Caliptra mailbox host interface (frontend) and peer base class. + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/aspeed_cptra_mbox.h" +#include "hw/core/qdev-properties.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "system/memory.h" +#include "trace.h" + +static size_t cptra_mbox_padded_len(uint32_t dlen) +{ + return (size_t)((dlen + 3) / 4) * 4; +} + +static void cptra_mbox_clear(AspeedCptraMboxState *s) +{ + s->locked =3D false; + s->release_pending =3D false; + s->user =3D 0; + s->target_user =3D 0; + s->target_user_valid =3D 0; + s->cmd =3D 0; + s->dlen =3D 0; + s->execute =3D 0; + s->target_status =3D 0; + s->cmd_status =3D 0; + s->hw_status =3D 0; + memset(s->sram, 0, sizeof(s->sram)); +} + +static void cptra_mbox_submit(AspeedCptraMboxState *s) +{ + CptraMboxPeerClass *pc; + g_autofree uint8_t *data =3D NULL; + size_t len; + + if (s->dlen > CPTRA_MBOX0_SRAM_SIZE) { + s->cmd_status =3D CPTRA_MBOX0_STATUS_CMD_FAILURE; + qemu_log_mask(LOG_GUEST_ERROR, + "%s: DLEN 0x%x exceeds SRAM size\n", __func__, s->dl= en); + return; + } + + if (!s->peer) { + /* No Caliptra peer present: the command cannot be serviced. */ + s->cmd_status =3D CPTRA_MBOX0_STATUS_CMD_FAILURE; + return; + } + + len =3D cptra_mbox_padded_len(s->dlen); + if (len) { + data =3D g_malloc(len); + for (size_t i =3D 0; i < len / 4; i++) { + stl_le_p(data + i * 4, s->sram[i]); + } + } + + s->command_pending =3D true; + s->release_pending =3D false; + trace_cptra_mbox_execute(s->cmd, s->dlen); + + pc =3D CPTRA_MBOX_PEER_GET_CLASS(s->peer); + pc->handle_execute(s->peer, s->cmd, s->dlen, data, len); +} + +/* CptraMboxIf::complete - called by the peer when a command finishes. */ +static void cptra_mbox_complete(CptraMboxIf *iface, uint32_t status, + uint32_t dlen, const uint8_t *data, + uint32_t len) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(iface); + + s->command_pending =3D false; + trace_cptra_mbox_complete(status, dlen); + + if (s->release_pending) { + cptra_mbox_clear(s); + return; + } + + /* + * Report the peer's status verbatim and write back whatever response + * payload it returned. The peer signals a transport/command failure w= ith + * CPTRA_MBOX0_STATUS_CMD_FAILURE and no data. + */ + s->cmd_status =3D status; + s->dlen =3D dlen; + if (data && len) { + size_t words =3D MIN(len, CPTRA_MBOX0_SRAM_SIZE) / 4; + + for (size_t i =3D 0; i < words; i++) { + s->sram[i] =3D ldl_le_p(data + i * 4); + } + } +} + +static uint64_t cptra_mbox_sram_read(void *opaque, hwaddr offset, unsigned= size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t idx =3D offset / 4; + + if (idx >=3D CPTRA_MBOX0_SRAM_WORDS) { + return 0; + } + return s->sram[idx]; +} + +static void cptra_mbox_sram_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t idx =3D offset / 4; + + if (idx < CPTRA_MBOX0_SRAM_WORDS) { + s->sram[idx] =3D (uint32_t)value; + } +} + +static const MemoryRegionOps cptra_mbox_sram_ops =3D { + .read =3D cptra_mbox_sram_read, + .write =3D cptra_mbox_sram_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, +}; + +static uint64_t cptra_mbox_csr_read(void *opaque, hwaddr offset, unsigned = size) +{ + AspeedCptraMboxState *s =3D opaque; + + switch (offset) { + case CPTRA_MBOX0_LOCK_OFF: + if (!s->locked) { + s->locked =3D true; + s->user =3D CPTRA_MBOX0_SOC_USER_ID; + return 0; + } + return 1; + case CPTRA_MBOX0_USER_OFF: + return s->user; + case CPTRA_MBOX0_TARGET_USER_OFF: + return s->target_user; + case CPTRA_MBOX0_TARGET_USER_VAL_OFF: + return s->target_user_valid; + case CPTRA_MBOX0_CMD_OFF: + return s->cmd; + case CPTRA_MBOX0_DLEN_OFF: + return s->dlen; + case CPTRA_MBOX0_EXECUTE_OFF: + return s->execute; + case CPTRA_MBOX0_TARGET_STATUS_OFF: + return s->target_status; + case CPTRA_MBOX0_CMD_STATUS_OFF: + return s->cmd_status; + case CPTRA_MBOX0_HW_STATUS_OFF: + return s->hw_status; + default: + return 0; + } +} + +static void cptra_mbox_csr_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t val =3D (uint32_t)value; + + switch (offset) { + case CPTRA_MBOX0_LOCK_OFF: + case CPTRA_MBOX0_USER_OFF: + case CPTRA_MBOX0_HW_STATUS_OFF: + break; + case CPTRA_MBOX0_TARGET_USER_OFF: + s->target_user =3D val; + break; + case CPTRA_MBOX0_TARGET_USER_VAL_OFF: + s->target_user_valid =3D val; + break; + case CPTRA_MBOX0_CMD_OFF: + s->cmd =3D val; + break; + case CPTRA_MBOX0_DLEN_OFF: + if (val > CPTRA_MBOX0_SRAM_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: DLEN 0x%x exceeds SRAM size, clamped\n", + __func__, val); + val =3D CPTRA_MBOX0_SRAM_SIZE; + } + s->dlen =3D val; + break; + case CPTRA_MBOX0_EXECUTE_OFF: + if (val =3D=3D 1 && s->execute !=3D 1 && !s->command_pending) { + s->execute =3D 1; + s->cmd_status =3D CPTRA_MBOX0_STATUS_BUSY; + cptra_mbox_submit(s); + } else if (val =3D=3D 0 && s->execute !=3D 0) { + if (s->command_pending) { + s->release_pending =3D true; + } else { + cptra_mbox_clear(s); + } + } + break; + case CPTRA_MBOX0_TARGET_STATUS_OFF: + s->target_status =3D val; + break; + case CPTRA_MBOX0_CMD_STATUS_OFF: + s->cmd_status =3D val; + break; + default: + break; + } +} + +static const MemoryRegionOps cptra_mbox_csr_ops =3D { + .read =3D cptra_mbox_csr_read, + .write =3D cptra_mbox_csr_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, +}; + +static void cptra_mbox_reset_hold(Object *obj, ResetType type) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(obj); + + if (s->command_pending) { + /* Defer the clear until the in-flight command completes. */ + s->release_pending =3D true; + return; + } + cptra_mbox_clear(s); + + if (s->peer) { + CptraMboxPeerClass *pc =3D CPTRA_MBOX_PEER_GET_CLASS(s->peer); + if (pc->handle_reset) { + pc->handle_reset(s->peer); + } + } +} + +static void cptra_mbox_peer_check(const Object *obj, const char *name, + Object *val, Error **errp) +{ + CptraMboxPeer *peer; + + if (!val) { + return; + } + + peer =3D CPTRA_MBOX_PEER(val); + if (peer->intf) { + error_setg(errp, "Caliptra mailbox peer is already in use"); + } +} + +bool aspeed_cptra_mbox_set_peer(AspeedCptraMboxState *s, CptraMboxPeer *pe= er, + Error **errp) +{ + CptraMboxPeer *old_peer =3D s->peer; + + if (old_peer =3D=3D peer) { + if (s->peer) { + s->peer->intf =3D CPTRA_MBOX_IF(s); + } + return true; + } + if (!object_property_set_link(OBJECT(s), "peer", + peer ? OBJECT(peer) : NULL, errp)) { + return false; + } + if (old_peer) { + old_peer->intf =3D NULL; + } + if (s->peer) { + s->peer->intf =3D CPTRA_MBOX_IF(s); + } + return true; +} + +static void cptra_mbox_init(Object *obj) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(obj); + + object_property_add_link(obj, "peer", TYPE_CPTRA_MBOX_PEER, + (Object **)&s->peer, cptra_mbox_peer_check, + OBJ_PROP_LINK_STRONG); +} + +static void cptra_mbox_realize(DeviceState *dev, Error **errp) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + if (s->peer) { + if (!aspeed_cptra_mbox_set_peer(s, s->peer, errp)) { + return; + } + } + + memory_region_init_io(&s->sram_mr, OBJECT(s), &cptra_mbox_sram_ops, s, + "cptra-mbox.sram", CPTRA_MBOX0_SRAM_SIZE); + sysbus_init_mmio(sbd, &s->sram_mr); + + memory_region_init_io(&s->csr_mr, OBJECT(s), &cptra_mbox_csr_ops, s, + "cptra-mbox.csr", CPTRA_MBOX0_CSR_SIZE); + sysbus_init_mmio(sbd, &s->csr_mr); +} + +static const VMStateDescription vmstate_cptra_mbox =3D { + .name =3D TYPE_ASPEED_CPTRA_MBOX, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_BOOL(locked, AspeedCptraMboxState), + VMSTATE_UINT32(user, AspeedCptraMboxState), + VMSTATE_UINT32(target_user, AspeedCptraMboxState), + VMSTATE_UINT32(target_user_valid, AspeedCptraMboxState), + VMSTATE_UINT32(cmd, AspeedCptraMboxState), + VMSTATE_UINT32(dlen, AspeedCptraMboxState), + VMSTATE_UINT32(execute, AspeedCptraMboxState), + VMSTATE_UINT32(target_status, AspeedCptraMboxState), + VMSTATE_UINT32(cmd_status, AspeedCptraMboxState), + VMSTATE_UINT32(hw_status, AspeedCptraMboxState), + VMSTATE_UINT32_ARRAY(sram, AspeedCptraMboxState, + CPTRA_MBOX0_SRAM_WORDS), + VMSTATE_END_OF_LIST() + }, +}; + +static void cptra_mbox_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + ResettableClass *rc =3D RESETTABLE_CLASS(oc); + CptraMboxIfClass *ic =3D CPTRA_MBOX_IF_CLASS(oc); + + dc->desc =3D "Caliptra mailbox host interface"; + dc->realize =3D cptra_mbox_realize; + dc->vmsd =3D &vmstate_cptra_mbox; + rc->phases.hold =3D cptra_mbox_reset_hold; + ic->complete =3D cptra_mbox_complete; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo cptra_mbox_types[] =3D { + { + .name =3D TYPE_CPTRA_MBOX_IF, + .parent =3D TYPE_INTERFACE, + .class_size =3D sizeof(CptraMboxIfClass), + }, + { + .name =3D TYPE_CPTRA_MBOX_PEER, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(CptraMboxPeer), + .class_size =3D sizeof(CptraMboxPeerClass), + .abstract =3D true, + }, + { + .name =3D TYPE_ASPEED_CPTRA_MBOX, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(AspeedCptraMboxState), + .instance_init =3D cptra_mbox_init, + .class_init =3D cptra_mbox_class_init, + .interfaces =3D (const InterfaceInfo[]) { + { TYPE_CPTRA_MBOX_IF }, + { } + }, + }, +}; + +DEFINE_TYPES(cptra_mbox_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index fa6a961ac9..d23045c4b5 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -135,6 +135,7 @@ system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: file= s('pvpanic-pci.c')) system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: files('pvpanic-mmio.c'= )) system_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( + 'aspeed_cptra_mbox.c', 'aspeed_hace.c', 'aspeed_lpc.c', 'aspeed_ltpi.c', diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 82ddbf4d15..9fe2d27fef 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -106,6 +106,10 @@ aspeed_ast2700_scuio_read(uint64_t offset, unsigned si= ze, uint32_t data) "To 0x% aspeed_ast1040_scu_write(uint64_t offset, unsigned size, uint32_t data) "T= o 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_ast1040_scu_read(uint64_t offset, unsigned size, uint32_t data) "To= 0x%" PRIx64 " of size %u: 0x%" PRIx32 =20 +# aspeed_cptra_mbox.c +cptra_mbox_execute(uint32_t cmd, uint32_t dlen) "EXECUTE cmd 0x%" PRIx32 "= dlen 0x%" PRIx32 +cptra_mbox_complete(uint32_t status, uint32_t dlen) "complete status %u dl= en 0x%" PRIx32 + # mps2-scc.c mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC rea= d: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC wr= ite: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" --=20 2.43.0