From nobody Sun Sep 28 16:34:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1758274481; cv=none; d=zohomail.com; s=zohoarc; b=YYU1FN/8kGpi94ByJNryUvPUASWSlnTxlWZ6xlytw/RvNiYooznt3zDJIJO2bS1Bd6UBrNNPKaMFVn5gm5Oboq9UKoOuWobOe9dzS9Zilm2JHo5TLiiXzPtDcSSKp3d/9kSwpT+cH8NqCkhQTVKiFnyvuVG+hnIaDSt0KxXGoPA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758274481; 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:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=7xR2kKGqiIkFsy3lqAmDnP/mUiv49WE9ncNAfqCxA8g=; b=VXBoo8MARUZwqoTNDBwPwQvptrDc1rMch48xbMV9fuUHHewuXXsjzxyP3a4+NFRjBestHXPYWQZZGYbldpjxOhDMzGjUVxbSGl41Uq9llsF5cdH7kMSP7/bdHSvH0nr/VleBkxq45kaDk33xKsbtY3SsYJtoYYSktPb3W7mFdfI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758274481482754.7493421014834; Fri, 19 Sep 2025 02:34:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzXTi-0004f2-05; Fri, 19 Sep 2025 05:32:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzXT7-0004G1-Ov; Fri, 19 Sep 2025 05:31:55 -0400 Received: from mail.aspeedtech.com ([211.20.114.72] helo=TWMBX01.aspeed.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzXT4-0001Uy-SY; Fri, 19 Sep 2025 05:31:53 -0400 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.10; Fri, 19 Sep 2025 17:30:21 +0800 Received: from mail.aspeedtech.com (192.168.10.10) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Fri, 19 Sep 2025 17:30:21 +0800 To: Paolo Bonzini , Peter Maydell , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Steven Lee , Troy Lee , Andrew Jeffery , "Joel Stanley" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , "open list:ARM TCG CPUs" , "open list:All patches CC here" CC: , , , , , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Subject: [PATCH v5 10/14] hw/pci-host/aspeed: Add AST2700 PCIe config with dedicated H2X blocks Date: Fri, 19 Sep 2025 17:30:09 +0800 Message-ID: <20250919093017.338309-11-jamin_lin@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250919093017.338309-1-jamin_lin@aspeedtech.com> References: <20250919093017.338309-1-jamin_lin@aspeedtech.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=211.20.114.72; envelope-from=jamin_lin@aspeedtech.com; helo=TWMBX01.aspeed.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_FAIL=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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Jamin Lin From: Jamin Lin via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1758274483664116600 Introduce PCIe config (H2X) support for the AST2700 SoC. Unlike the AST2600, the AST2700 provides three independent Root Complexes, each with its own H2X (AHB to PCIe bridge) register block of size 0x100. All RCs use the same MSI address (0x000000F0). The H2X block includes two different access paths: 1. CFGI (internal bridge): used to access the host bridge itself, always with BDF=3D0. The AST2700 controller simplifies the design by exposing only one register (H2X_CFGI_TLP) with fields for ADDR[15:0], BEN[19:16], and WR[20]. This is not a full TLP descriptor as in the external case. For QEMU readability and code reuse, the model converts H2X_CFGI_TLP into a standard TLP TX descriptor with BDF forced to 0 and then calls the existing helpers aspeed_pcie_cfg_readwrite() and aspeed_pcie_cfg_translate_write(). 2. CFGE (external EP access): used to access external endpoints. The AST2700 design provides H2X_CFGE_TLP1 and a small FIFO at H2X_CFGE_TLPN. For reads, TX DESC0 is stored in TLP1 and DESC1/DESC2 in TLPN FIFO slots. For writes, TX DESC0 is stored in TLP1, DESC1/DESC2 in TLPN FIFO[0..1], and TX write data in TLPN FIFO[2]. The implementation extends AspeedPCIECfgState with a small FIFO and index, wires up new register definitions for AST2700, and adds a specific ops table and class (TYPE_ASPEED_2700_PCIE_CFG). The reset handler clears the FIFO state. Interrupt and MSI status registers are also supported. This provides enough modeling for firmware and drivers to use any of the three PCIe RCs on AST2700 with their own dedicated H2X config window, while reusing existing TLP decode helpers in QEMU. Signed-off-by: Jamin Lin Reviewed-by: C=C3=A9dric Le Goater --- include/hw/pci-host/aspeed_pcie.h | 3 + hw/pci-host/aspeed_pcie.c | 158 ++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/include/hw/pci-host/aspeed_pcie.h b/include/hw/pci-host/aspeed= _pcie.h index 5806505f30..be53ea96b9 100644 --- a/include/hw/pci-host/aspeed_pcie.h +++ b/include/hw/pci-host/aspeed_pcie.h @@ -87,6 +87,7 @@ struct AspeedPCIERcState { =20 /* Bridge between AHB bus and PCIe RC. */ #define TYPE_ASPEED_PCIE_CFG "aspeed.pcie-cfg" +#define TYPE_ASPEED_2700_PCIE_CFG TYPE_ASPEED_PCIE_CFG "-ast2700" OBJECT_DECLARE_TYPE(AspeedPCIECfgState, AspeedPCIECfgClass, ASPEED_PCIE_CF= G); =20 struct AspeedPCIECfgState { @@ -98,6 +99,8 @@ struct AspeedPCIECfgState { =20 const AspeedPCIERcRegs *rc_regs; AspeedPCIERcState rc; + uint32_t tlpn_fifo[3]; + uint32_t tlpn_idx; }; =20 struct AspeedPCIECfgClass { diff --git a/hw/pci-host/aspeed_pcie.c b/hw/pci-host/aspeed_pcie.c index 788160d532..a757fd7ec8 100644 --- a/hw/pci-host/aspeed_pcie.c +++ b/hw/pci-host/aspeed_pcie.c @@ -338,6 +338,11 @@ static const TypeInfo aspeed_pcie_rc_info =3D { * - Registers 0x00 - 0x7F are shared by both PCIe0 (rc_l) and PCIe1 (rc_h= ). * - Registers 0x80 - 0xBF are specific to PCIe0. * - Registers 0xC0 - 0xFF are specific to PCIe1. + * + * On the AST2700: + * - The register range 0x00 - 0xFF is assigned to a single PCIe configura= tion. + * - There are three PCIe Root Complexes (RCs), each with its own dedicate= d H2X + * register set of size 0x100 (covering offsets 0x00 to 0xFF). */ =20 /* AST2600 */ @@ -367,6 +372,31 @@ REG32(H2X_RC_H_MSI_EN1, 0xE4) REG32(H2X_RC_H_MSI_STS0, 0xE8) REG32(H2X_RC_H_MSI_STS1, 0xEC) =20 +/* AST2700 */ +REG32(H2X_CFGE_INT_STS, 0x08) + FIELD(H2X_CFGE_INT_STS, TX_IDEL, 0, 1) + FIELD(H2X_CFGE_INT_STS, RX_BUSY, 1, 1) +REG32(H2X_CFGI_TLP, 0x20) + FIELD(H2X_CFGI_TLP, ADDR, 0, 16) + FIELD(H2X_CFGI_TLP, BEN, 16, 4) + FIELD(H2X_CFGI_TLP, WR, 20, 1) +REG32(H2X_CFGI_WDATA, 0x24) +REG32(H2X_CFGI_CTRL, 0x28) + FIELD(H2X_CFGI_CTRL, FIRE, 0, 1) +REG32(H2X_CFGI_RDATA, 0x2C) +REG32(H2X_CFGE_TLP1, 0x30) +REG32(H2X_CFGE_TLPN, 0x34) +REG32(H2X_CFGE_CTRL, 0x38) + FIELD(H2X_CFGE_CTRL, FIRE, 0, 1) +REG32(H2X_CFGE_RDATA, 0x3C) +REG32(H2X_INT_EN, 0x40) +REG32(H2X_INT_STS, 0x48) + FIELD(H2X_INT_STS, INTX, 0, 4) +REG32(H2X_MSI_EN0, 0x50) +REG32(H2X_MSI_EN1, 0x54) +REG32(H2X_MSI_STS0, 0x58) +REG32(H2X_MSI_STS1, 0x5C) + #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */ @@ -384,6 +414,15 @@ static const AspeedPCIERegMap aspeed_regmap =3D { }, }; =20 +static const AspeedPCIERegMap aspeed_2700_regmap =3D { + .rc =3D { + .int_en_reg =3D R_H2X_INT_EN, + .int_sts_reg =3D R_H2X_INT_STS, + .msi_sts0_reg =3D R_H2X_MSI_STS0, + .msi_sts1_reg =3D R_H2X_MSI_STS1, + }, +}; + static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr, unsigned int size) { @@ -606,6 +645,8 @@ static void aspeed_pcie_cfg_reset(DeviceState *dev) AspeedPCIECfgClass *apc =3D ASPEED_PCIE_CFG_GET_CLASS(s); =20 memset(s->regs, 0, apc->nr_regs << 2); + memset(s->tlpn_fifo, 0, sizeof(s->tlpn_fifo)); + s->tlpn_idx =3D 0; } =20 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp) @@ -680,6 +721,122 @@ static const TypeInfo aspeed_pcie_cfg_info =3D { .class_size =3D sizeof(AspeedPCIECfgClass), }; =20 +static void aspeed_2700_pcie_cfg_write(void *opaque, hwaddr addr, + uint64_t data, unsigned int size) +{ + AspeedPCIECfgState *s =3D ASPEED_PCIE_CFG(opaque); + AspeedPCIECfgTxDesc desc; + uint32_t reg =3D addr >> 2; + + trace_aspeed_pcie_cfg_write(s->id, addr, data); + + switch (reg) { + case R_H2X_CFGE_INT_STS: + if (data & R_H2X_CFGE_INT_STS_TX_IDEL_MASK) { + s->regs[R_H2X_CFGE_INT_STS] &=3D ~R_H2X_CFGE_INT_STS_TX_IDEL_M= ASK; + } + + if (data & R_H2X_CFGE_INT_STS_RX_BUSY_MASK) { + s->regs[R_H2X_CFGE_INT_STS] &=3D ~R_H2X_CFGE_INT_STS_RX_BUSY_M= ASK; + } + break; + case R_H2X_CFGI_CTRL: + if (data & R_H2X_CFGI_CTRL_FIRE_MASK) { + /* + * Internal access to bridge + * Type and BDF are 0 + */ + desc.desc0 =3D 0x04000001 | + (ARRAY_FIELD_EX32(s->regs, H2X_CFGI_TLP, WR) << 30); + desc.desc1 =3D 0x00401000 | + ARRAY_FIELD_EX32(s->regs, H2X_CFGI_TLP, BEN); + desc.desc2 =3D 0x00000000 | + ARRAY_FIELD_EX32(s->regs, H2X_CFGI_TLP, ADDR); + desc.wdata =3D s->regs[R_H2X_CFGI_WDATA]; + desc.rdata_reg =3D R_H2X_CFGI_RDATA; + aspeed_pcie_cfg_readwrite(s, &desc); + } + break; + case R_H2X_CFGE_TLPN: + s->tlpn_fifo[s->tlpn_idx] =3D data; + s->tlpn_idx =3D (s->tlpn_idx + 1) % ARRAY_SIZE(s->tlpn_fifo); + break; + case R_H2X_CFGE_CTRL: + if (data & R_H2X_CFGE_CTRL_FIRE_MASK) { + desc.desc0 =3D s->regs[R_H2X_CFGE_TLP1]; + desc.desc1 =3D s->tlpn_fifo[0]; + desc.desc2 =3D s->tlpn_fifo[1]; + desc.wdata =3D s->tlpn_fifo[2]; + desc.rdata_reg =3D R_H2X_CFGE_RDATA; + aspeed_pcie_cfg_readwrite(s, &desc); + s->regs[R_H2X_CFGE_INT_STS] |=3D R_H2X_CFGE_INT_STS_TX_IDEL_MA= SK; + s->regs[R_H2X_CFGE_INT_STS] |=3D R_H2X_CFGE_INT_STS_RX_BUSY_MA= SK; + s->tlpn_idx =3D 0; + } + break; + + case R_H2X_INT_STS: + s->regs[reg] &=3D ~data | R_H2X_INT_STS_INTX_MASK; + break; + /* + * These status registers are used for notify sources ISR are executed. + * If one source ISR is executed, it will clear one bit. + * If it clear all bits, it means to initialize this register status + * rather than sources ISR are executed. + */ + case R_H2X_MSI_STS0: + case R_H2X_MSI_STS1: + if (data =3D=3D 0) { + return ; + } + + s->regs[reg] &=3D ~data; + if (data =3D=3D 0xffffffff) { + return; + } + + if (!s->regs[R_H2X_MSI_STS0] && + !s->regs[R_H2X_MSI_STS1]) { + trace_aspeed_pcie_rc_msi_clear_irq(s->id, 0); + qemu_set_irq(s->rc.irq, 0); + } + break; + default: + s->regs[reg] =3D data; + break; + } +} + +static const MemoryRegionOps aspeed_2700_pcie_cfg_ops =3D { + .read =3D aspeed_pcie_cfg_read, + .write =3D aspeed_2700_pcie_cfg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static void aspeed_2700_pcie_cfg_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + AspeedPCIECfgClass *apc =3D ASPEED_PCIE_CFG_CLASS(klass); + + dc->desc =3D "ASPEED 2700 PCIe Config"; + apc->reg_ops =3D &aspeed_2700_pcie_cfg_ops; + apc->reg_map =3D &aspeed_2700_regmap; + apc->nr_regs =3D 0x100 >> 2; + apc->rc_msi_addr =3D 0x000000F0; + apc->rc_bus_nr =3D 0; +} + +static const TypeInfo aspeed_2700_pcie_cfg_info =3D { + .name =3D TYPE_ASPEED_2700_PCIE_CFG, + .parent =3D TYPE_ASPEED_PCIE_CFG, + .class_init =3D aspeed_2700_pcie_cfg_class_init, +}; + /* * PCIe PHY * @@ -847,6 +1004,7 @@ static void aspeed_pcie_register_types(void) type_register_static(&aspeed_pcie_root_device_info); type_register_static(&aspeed_pcie_root_port_info); type_register_static(&aspeed_pcie_cfg_info); + type_register_static(&aspeed_2700_pcie_cfg_info); type_register_static(&aspeed_pcie_phy_info); type_register_static(&aspeed_2700_pcie_phy_info); } --=20 2.43.0