From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177712322098351.93371355056365; Sat, 25 Apr 2026 06:20:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGctf-00070E-AY; Sat, 25 Apr 2026 09:18:11 -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 1wGcta-0006zL-Sq for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:07 -0400 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGctX-0008Iq-1L for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:06 -0400 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-824c9da9928so4347414b3a.3 for ; Sat, 25 Apr 2026 06:18:02 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.17.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123082; x=1777727882; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=O2PNOHXnFoOUWyr+T/iDnnwkXlcIiAXHW2HFpCYvfWg=; b=FysKx4gYYgNp97gPvP3ibHr/Kg6D+ji2fb330PvuFqRrigD/wdwAzEUDvSex3SMU5D nTwHfnJcnz52RuP8j1cOIB/pNFnHftGzk41UGPcylIA3LEvhTi9gNo7vGHpvxKmonrjz nzzCwRYYPkO3xk1F3WmV8bWIC6ZVvtXDtQXrVIa+6RntKNub+RYjGGnRFHKOtB4S/RSi gdYM9O4mv3VM1Sg2A4UwOQ7BVntg3nC211DDmfdt6qc5yUwfLv+qA3qtW6Wa28H3KZo3 JWpdPQ3NqPNARi1VxMmct1a1Mh0oay0CTD6QVOqsHLuOXIPOo/mBO9RmMu/4nNpbQniA RkJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123082; x=1777727882; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=O2PNOHXnFoOUWyr+T/iDnnwkXlcIiAXHW2HFpCYvfWg=; b=Ep77vmbQOVbyGbJxc3/H8l+XV0dMra+1kntpEB/+XJuenwOvYDmNequzLKNUCLg78s i5VjDkwqpZ+ewlCi0koQPbljknxsGZsMXqR9dH9sTLnMMjfnYqiYsiRuwLHhE68SmfM3 faqGur8aDHkl/hCIHDJImhMZSpUjdRuXLKMWZnlgHnnB6wOuInylk2szPf1I05wUOhT/ uGPAzDylQ6ku1pFm8+wqVDZl043cmdw5AfQ3gx4yIf2ZvCEd82i0fiq2E8z3P2zdB4HY 5Gr+jVw+gN9EGd+45IoZ7HlAEGs8L/O0VLyziQaSSl658ct0PqGc/sEhDl47Yw4PqrxV 2lgg== X-Forwarded-Encrypted: i=1; AFNElJ9VNM9LlQYY7m4ebzAd9kO3l4eV2GmntBJ/15OmVjUy4afyOC9JZwrDssS7WnztWZazgiPpfdvjT1Fz@nongnu.org X-Gm-Message-State: AOJu0YxelpGaNxWVwFtQ/919K8h7HIyqsrFcRwmb3xsSKrKRA76mDD0Q esRRNuMP4P3lEuxh6eMppfml1YjQ1JV5u6sATdY/auqKzuRwcUL442uw X-Gm-Gg: AeBDietT7lkkAvlRZpvXNQf4ZyXGL632JE1Rp3OvM8fVvjVmaX7/gTNEBqC5qMih0/w F0DStt5aTBIHJTrPmAKaVfRnGc/AG+UlCrHMtlFIzkghrkXF6MKyk4W1x0j13YIm7vT7cvod2Ub hduNyICtdxXNfRY98V+8hiiej930NgvqnB3kEPXwt25MRlzdEXJdPg3F9voDeqjx84amegxcq9v 2fs1I2CH2QDIW1aMi2FvZyiApodDadyjNNwAgiv2o8E4xzbn0qOLo51g7comAe0VURPczoElpQr LhQvufZzhZgp7BL4JLZrduZkrsz0aZpqvrvXp3+1+6vgjHj7PQJuqEj05AT0DsrA7FCRZPlUZcO d/0XTcJdpAeOoIM01HSafz1Myve+C4I5KAC5qPe2eZIEKHotkbP1Oul+CvHE2gXxIUhJxxl363W DuXmMmF8LAHD/+kiIr67YJiI/k8MQh651eBy1rfFlZc6+Bcvz+j8YK0I9mYCs8pAR4/nExMn5ZD bXJUZQLZIZvsqXUt4RfCmIZvpPosDfPPXdBYnNmcoc= X-Received: by 2002:aa7:8892:0:b0:82a:60ad:874 with SMTP id d2e1a72fcca58-82f8c8b56c0mr39116428b3a.19.1777123081387; Sat, 25 Apr 2026 06:18:01 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Chris Rauer , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Hao Wu Subject: [PATCH v4 01/13] hw/i2c: Add designware i2c controller Date: Sat, 25 Apr 2026 23:17:07 +1000 Message-ID: <20260425131721.932250-2-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::430; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x430.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123221749158500 Content-Type: text/plain; charset="utf-8" From: Chris Rauer In the past this model has been submitted for use with the arm virt machine, however in this case it will be used by the upcoming Tenstorrent Atlantis RISC-V machine. This is a re-submission of the model with Chris' permission, with a light touch of updates to make it build with qemu master. Reviewed-by: Hao Wu Signed-off-by: Chris Rauer Link: https://lore.kernel.org/qemu-devel/20220110214755.810343-2-venture@go= ogle.com [jms: rebase and minor build fixes for class_init and reset callback] Signed-off-by: Joel Stanley Acked-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- v4: Remove unused random header v2: Add trace event for read and write, document Alano and myself as reviewers. --- MAINTAINERS | 8 + include/hw/i2c/designware_i2c.h | 101 ++++ hw/i2c/designware_i2c.c | 817 ++++++++++++++++++++++++++++++++ hw/i2c/Kconfig | 4 + hw/i2c/meson.build | 1 + hw/i2c/trace-events | 4 + 6 files changed, 935 insertions(+) create mode 100644 include/hw/i2c/designware_i2c.h create mode 100644 hw/i2c/designware_i2c.c diff --git a/MAINTAINERS b/MAINTAINERS index aa4267b15806..e1942a86eba5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2716,6 +2716,14 @@ S: Orphan F: hw/gpio/pcf8574.c F: include/gpio/pcf8574.h =20 +DesignWare I2C +M: Chris Rauer +R: Alano Song +R: Joel Stanley +S: Maintained +F: hw/i2c/designware_i2c.c +F: include/hw/i2c/designware_i2c.h + Generic Loader M: Alistair Francis S: Maintained diff --git a/include/hw/i2c/designware_i2c.h b/include/hw/i2c/designware_i2= c.h new file mode 100644 index 000000000000..0d8f904f51b7 --- /dev/null +++ b/include/hw/i2c/designware_i2c.h @@ -0,0 +1,101 @@ +/* + * DesignWare I2C Module. + * + * Copyright 2021 Google LLC + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef DESIGNWARE_I2C_H +#define DESIGNWARE_I2C_H + +#include "hw/i2c/i2c.h" +#include "hw/core/irq.h" +#include "hw/core/sysbus.h" + +/* Size of the FIFO buffers. */ +#define DESIGNWARE_I2C_RX_FIFO_SIZE 16 +#define DESIGNWARE_I2C_TX_FIFO_SIZE 16 + +typedef enum DesignWareI2CStatus { + DW_I2C_STATUS_IDLE, + DW_I2C_STATUS_SENDING_ADDRESS, + DW_I2C_STATUS_SENDING, + DW_I2C_STATUS_RECEIVING, +} DesignWareI2CStatus; + +/* + * struct DesignWareI2CState - DesignWare I2C device state. + * @bus: The underlying I2C Bus + * @irq: GIC interrupt line to fire on events + * @ic_con: : I2C control register + * @ic_tar: I2C target address register + * @ic_sar: I2C slave address register + * @ic_ss_scl_hcnt: Standard speed i2c clock scl high count register + * @ic_ss_scl_lcnt: Standard speed i2c clock scl low count register + * @ic_fs_scl_hcnt: Fast mode or fast mode plus i2c clock scl high count + * register + * @ic_fs_scl_lcnt:Fast mode or fast mode plus i2c clock scl low count + * register + * @ic_intr_mask: I2C Interrupt Mask Register + * @ic_raw_intr_stat: I2C raw interrupt status register + * @ic_rx_tl: I2C receive FIFO threshold register + * @ic_tx_tl: I2C transmit FIFO threshold register + * @ic_enable: I2C enable register + * @ic_status: I2C status register + * @ic_txflr: I2C transmit fifo level register + * @ic_rxflr: I2C receive fifo level register + * @ic_sda_hold: I2C SDA hold time length register + * @ic_tx_abrt_source: The I2C transmit abort source register + * @ic_sda_setup: I2C SDA setup register + * @ic_enable_status: I2C enable status register + * @ic_fs_spklen: I2C SS, FS or FM+ spike suppression limit + * @ic_comp_param_1: Component parameter register + * @ic_comp_version: I2C component version register + * @ic_comp_type: I2C component type register + * @rx_fifo: The FIFO buffer for receiving in FIFO mode. + * @rx_cur: The current position of rx_fifo. + * @status: The current status of the SMBus. + */ +typedef struct DesignWareI2CState { + SysBusDevice parent; + + MemoryRegion iomem; + + I2CBus *bus; + qemu_irq irq; + + uint32_t ic_con; + uint32_t ic_tar; + uint32_t ic_sar; + uint32_t ic_ss_scl_hcnt; + uint32_t ic_ss_scl_lcnt; + uint32_t ic_fs_scl_hcnt; + uint32_t ic_fs_scl_lcnt; + uint32_t ic_intr_mask; + uint32_t ic_raw_intr_stat; + uint32_t ic_rx_tl; + uint32_t ic_tx_tl; + uint32_t ic_enable; + uint32_t ic_status; + uint32_t ic_txflr; + uint32_t ic_rxflr; + uint32_t ic_sda_hold; + uint32_t ic_tx_abrt_source; + uint32_t ic_sda_setup; + uint32_t ic_enable_status; + uint32_t ic_fs_spklen; + uint32_t ic_comp_param_1; + uint32_t ic_comp_version; + uint32_t ic_comp_type; + + uint8_t rx_fifo[DESIGNWARE_I2C_RX_FIFO_SIZE]; + uint8_t rx_cur; + + DesignWareI2CStatus status; +} DesignWareI2CState; + +#define TYPE_DESIGNWARE_I2C "designware-i2c" +#define DESIGNWARE_I2C(obj) OBJECT_CHECK(DesignWareI2CState, (obj), \ + TYPE_DESIGNWARE_I2C) + +#endif /* DESIGNWARE_I2C_H */ diff --git a/hw/i2c/designware_i2c.c b/hw/i2c/designware_i2c.c new file mode 100644 index 000000000000..7d8b1c13533e --- /dev/null +++ b/hw/i2c/designware_i2c.c @@ -0,0 +1,817 @@ +/* + * DesignWare I2C Module. + * + * Copyright 2021 Google LLC + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "hw/i2c/designware_i2c.h" +#include "migration/vmstate.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "trace.h" + +enum DesignWareI2CRegister { + DW_IC_CON =3D 0x00, + DW_IC_TAR =3D 0x04, + DW_IC_SAR =3D 0x08, + DW_IC_DATA_CMD =3D 0x10, + DW_IC_SS_SCL_HCNT =3D 0x14, + DW_IC_SS_SCL_LCNT =3D 0x18, + DW_IC_FS_SCL_HCNT =3D 0x1c, + DW_IC_FS_SCL_LCNT =3D 0x20, + DW_IC_INTR_STAT =3D 0x2c, + DW_IC_INTR_MASK =3D 0x30, + DW_IC_RAW_INTR_STAT =3D 0x34, + DW_IC_RX_TL =3D 0x38, + DW_IC_TX_TL =3D 0x3c, + DW_IC_CLR_INTR =3D 0x40, + DW_IC_CLR_RX_UNDER =3D 0x44, + DW_IC_CLR_RX_OVER =3D 0x48, + DW_IC_CLR_TX_OVER =3D 0x4c, + DW_IC_CLR_RD_REQ =3D 0x50, + DW_IC_CLR_TX_ABRT =3D 0x54, + DW_IC_CLR_RX_DONE =3D 0x58, + DW_IC_CLR_ACTIVITY =3D 0x5c, + DW_IC_CLR_STOP_DET =3D 0x60, + DW_IC_CLR_START_DET =3D 0x64, + DW_IC_CLR_GEN_CALL =3D 0x68, + DW_IC_ENABLE =3D 0x6c, + DW_IC_STATUS =3D 0x70, + DW_IC_TXFLR =3D 0x74, + DW_IC_RXFLR =3D 0x78, + DW_IC_SDA_HOLD =3D 0x7c, + DW_IC_TX_ABRT_SOURCE =3D 0x80, + DW_IC_SLV_DATA_NACK_ONLY =3D 0x84, + DW_IC_DMA_CR =3D 0x88, + DW_IC_DMA_TDLR =3D 0x8c, + DW_IC_DMA_RDLR =3D 0x90, + DW_IC_SDA_SETUP =3D 0x94, + DW_IC_ACK_GENERAL_CALL =3D 0x98, + DW_IC_ENABLE_STATUS =3D 0x9c, + DW_IC_FS_SPKLEN =3D 0xa0, + DW_IC_CLR_RESTART_DET =3D 0xa8, + DW_IC_COMP_PARAM_1 =3D 0xf4, + DW_IC_COMP_VERSION =3D 0xf8, + DW_IC_COMP_TYPE =3D 0xfc, +}; + +/* DW_IC_CON fields */ +#define DW_IC_CON_STOP_DET_IF_MASTER_ACTIV BIT(10) +#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9) +#define DW_IC_CON_TX_EMPTY_CTRL BIT(8) +#define DW_IC_CON_STOP_IF_ADDRESSED BIT(7) +#define DW_IC_CON_SLAVE_DISABLE BIT(6) +#define DW_IC_CON_IC_RESTART_EN BIT(5) +#define DW_IC_CON_10BITADDR_MASTER BIT(4) +#define DW_IC_CON_10BITADDR_SLAVE BIT(3) +#define DW_IC_CON_SPEED(rv) extract32((rv), 1, 2) +#define DW_IC_CON_MASTER_MODE BIT(0) + +/* DW_IC_TAR fields */ +#define DW_IC_TAR_IC_10BITADDR_MASTER BIT(12) +#define DW_IC_TAR_SPECIAL BIT(11) +#define DW_IC_TAR_GC_OR_START BIT(10) +#define DW_IC_TAR_ADDRESS(rv) extract32((rv), 0, 10) + +/* DW_IC_DATA_CMD fields */ +#define DW_IC_DATA_CMD_RESTART BIT(10) +#define DW_IC_DATA_CMD_STOP BIT(9) +#define DW_IC_DATA_CMD_CMD BIT(8) +#define DW_IC_DATA_CMD_DAT(rv) extract32((rv), 0, 8) + +/* DW_IC_INTR_STAT/INTR_MASK/RAW_INTR_STAT fields */ +#define DW_IC_INTR_RESTART_DET BIT(12) +#define DW_IC_INTR_GEN_CALL BIT(11) +#define DW_IC_INTR_START_DET BIT(10) +#define DW_IC_INTR_STOP_DET BIT(9) +#define DW_IC_INTR_ACTIVITY BIT(8) +#define DW_IC_INTR_RX_DONE BIT(7) +#define DW_IC_INTR_TX_ABRT BIT(6) +#define DW_IC_INTR_RD_REQ BIT(5) +#define DW_IC_INTR_TX_EMPTY BIT(4) /* Hardware clear only. */ +#define DW_IC_INTR_TX_OVER BIT(3) +#define DW_IC_INTR_RX_FULL BIT(2) /* Hardware clear only. */ +#define DW_IC_INTR_RX_OVER BIT(1) +#define DW_IC_INTR_RX_UNDER BIT(0) + +/* DW_IC_ENABLE fields */ +#define DW_IC_ENABLE_TX_CMD_BLOCK BIT(2) +#define DW_IC_ENABLE_ABORT BIT(1) +#define DW_IC_ENABLE_ENABLE BIT(0) + +/* DW_IC_STATUS fields */ +#define DW_IC_STATUS_SLV_ACTIVITY BIT(6) +#define DW_IC_STATUS_MST_ACTIVITY BIT(5) +#define DW_IC_STATUS_RFF BIT(4) +#define DW_IC_STATUS_RFNE BIT(3) +#define DW_IC_STATUS_TFE BIT(2) +#define DW_IC_STATUS_TFNF BIT(1) +#define DW_IC_STATUS_ACTIVITY BIT(0) + +/* DW_IC_TX_ABRT_SOURCE fields */ +#define DW_IC_TX_TX_FLUSH_CNT extract32((rv), 23, 9) +#define DW_IC_TX_ABRT_USER_ABRT BIT(16) +#define DW_IC_TX_ABRT_SLVRD_INTX BIT(15) +#define DW_IC_TX_ABRT_SLV_ARBLOST BIT(14) +#define DW_IC_TX_ABRT_SLVFLUSH_TXFIFO BIT(13) +#define DW_IC_TX_ARB_LOST BIT(12) +#define DW_IC_TX_ABRT_MASTER_DIS BIT(11) +#define DW_IC_TX_ABRT_10B_RD_NORSTRT BIT(10) +#define DW_IC_TX_ABRT_SBYTE_NORSTRT BIT(9) +#define DW_IC_TX_ABRT_HS_NORSTRT BIT(8) +#define DW_IC_TX_ABRT_SBYTE_ACKDET BIT(7) +#define DW_IC_TX_ABRT_HS_ACKDET BIT(6) +#define DW_IC_TX_ABRT_GCALL_READ BIT(5) +#define DW_IC_TX_ABRT_GCALL_NOACK BIT(4) +#define DW_IC_TX_ABRT_TXDATA_NOACK BIT(3) +#define DW_IC_TX_ABRT_10ADDR2_NOACK BIT(2) +#define DW_IC_TX_ABRT_10ADDR1_NOACK BIT(1) +#define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT(0) + + +/* IC_ENABLE_STATUS fields */ +#define DW_IC_ENABLE_STATUS_SLV_RX_DATA_LOST BIT(2) +#define DW_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY BIT(1) +#define DW_IC_ENABLE_STATUS_IC_EN BIT(0) + +/* Masks for writable registers. */ +#define DW_IC_CON_MASK 0x000003ff +#define DW_IC_TAR_MASK 0x00000fff +#define DW_IC_SAR_MASK 0x000003ff +#define DW_IC_SS_SCL_HCNT_MASK 0x0000ffff +#define DW_IC_SS_SCL_LCNT_MASK 0x0000ffff +#define DW_IC_FS_SCL_HCNT_MASK 0x0000ffff +#define DW_IC_FS_SCL_LCNT_MASK 0x0000ffff +#define DW_IC_INTR_MASK_MASK 0x00001fff +#define DW_IC_ENABLE_MASK 0x00000007 +#define DW_IC_SDA_HOLD_MASK 0x00ffffff +#define DW_IC_SDA_SETUP_MASK 0x000000ff +#define DW_IC_FS_SPKLEN_MASK 0x000000ff + +/* Reset values */ +#define DW_IC_CON_INIT_VAL 0x7d +#define DW_IC_TAR_INIT_VAL 0x1055 +#define DW_IC_SAR_INIT_VAL 0x55 +#define DW_IC_SS_SCL_HCNT_INIT_VAL 0x190 +#define DW_IC_SS_SCL_LCNT_INIT_VAL 0x1d6 +#define DW_IC_FS_SCL_HCNT_INIT_VAL 0x3c +#define DW_IC_FS_SCL_LCNT_INIT_VAL 0x82 +#define DW_IC_INTR_MASK_INIT_VAL 0x8ff +#define DW_IC_STATUS_INIT_VAL 0x6 +#define DW_IC_SDA_HOLD_INIT_VAL 0x1 +#define DW_IC_SDA_SETUP_INIT_VAL 0x64 +#define DW_IC_FS_SPKLEN_INIT_VAL 0x2 + +#define DW_IC_COMP_PARAM_1_HAS_ENCODED_PARAMS BIT(7) +#define DW_IC_COMP_PARAM_1_HAS_DMA 0 /* bit 6 - DMA disabled.= */ +#define DW_IC_COMP_PARAM_1_INTR_IO BIT(5) +#define DW_IC_COMP_PARAM_1_HC_COUNT_VAL 0 /* bit 4 - disabled */ +#define DW_IC_COMP_PARAM_1_HIGH_SPEED_MODE (BIT(2) | BIT(3)) +#define DW_IC_COMP_PARAM_1_APB_DATA_WIDTH_32 BIT(1) /* bits 0, 1 */ +#define DW_IC_COMP_PARAM_1_INIT_VAL \ + (DW_IC_COMP_PARAM_1_APB_DATA_WIDTH_32 | \ + DW_IC_COMP_PARAM_1_HIGH_SPEED_MODE | \ + DW_IC_COMP_PARAM_1_HC_COUNT_VAL | \ + DW_IC_COMP_PARAM_1_INTR_IO | \ + DW_IC_COMP_PARAM_1_HAS_DMA | \ + DW_IC_COMP_PARAM_1_HAS_ENCODED_PARAMS | \ + ((DESIGNWARE_I2C_RX_FIFO_SIZE - 1) << 8) | \ + ((DESIGNWARE_I2C_TX_FIFO_SIZE - 1) << 16)) +#define DW_IC_COMP_VERSION_INIT_VAL 0x3132302a +#define DW_IC_COMP_TYPE_INIT_VAL 0x44570140 + +static void dw_i2c_update_irq(DesignWareI2CState *s) +{ + int level; + uint32_t intr =3D s->ic_raw_intr_stat & s->ic_intr_mask; + + level =3D !!((intr & DW_IC_INTR_RX_UNDER) | + (intr & DW_IC_INTR_RX_OVER) | + (intr & DW_IC_INTR_RX_FULL) | + (intr & DW_IC_INTR_TX_OVER) | + (intr & DW_IC_INTR_TX_EMPTY) | + (intr & DW_IC_INTR_RD_REQ) | + (intr & DW_IC_INTR_TX_ABRT) | + (intr & DW_IC_INTR_RX_DONE) | + (intr & DW_IC_INTR_ACTIVITY) | + (intr & DW_IC_INTR_STOP_DET) | + (intr & DW_IC_INTR_START_DET) | + (intr & DW_IC_INTR_GEN_CALL) | + (intr & DW_IC_INTR_RESTART_DET) + ); + qemu_set_irq(s->irq, level); +} + +static uint32_t dw_i2c_read_ic_data_cmd(DesignWareI2CState *s) +{ + uint32_t value =3D s->rx_fifo[s->rx_cur]; + + if (s->status !=3D DW_I2C_STATUS_RECEIVING) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Attempted to read from RX fifo when not in rece= ive " + "state.\n", DEVICE(s)->canonical_path); + if (s->status !=3D DW_I2C_STATUS_IDLE) { + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_UNDER; + dw_i2c_update_irq(s); + } + return 0; + } + + s->rx_cur =3D (s->rx_cur + 1) % DESIGNWARE_I2C_RX_FIFO_SIZE; + + if (s->ic_rxflr > 0) { + s->ic_rxflr--; + } else { + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_UNDER; + dw_i2c_update_irq(s); + return 0; + } + + if (s->ic_rxflr <=3D s->ic_rx_tl) { + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_FULL; + dw_i2c_update_irq(s); + } + + return value; +} + +static uint64_t dw_i2c_read(void *opaque, hwaddr offset, unsigned size) +{ + uint64_t value =3D 0; + + DesignWareI2CState *s =3D opaque; + + switch (offset) { + case DW_IC_CON: + value =3D s->ic_con; + break; + case DW_IC_TAR: + value =3D s->ic_tar; + break; + case DW_IC_SAR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported read - ic_sar\n", + DEVICE(s)->canonical_path); + value =3D s->ic_sar; + break; + case DW_IC_DATA_CMD: + value =3D dw_i2c_read_ic_data_cmd(s); + break; + case DW_IC_SS_SCL_HCNT: + value =3D s->ic_ss_scl_hcnt; + break; + case DW_IC_SS_SCL_LCNT: + value =3D s->ic_ss_scl_lcnt; + break; + case DW_IC_FS_SCL_HCNT: + value =3D s->ic_fs_scl_hcnt; + break; + case DW_IC_FS_SCL_LCNT: + value =3D s->ic_fs_scl_lcnt; + break; + case DW_IC_INTR_STAT: + value =3D s->ic_raw_intr_stat & s->ic_intr_mask; + break; + case DW_IC_INTR_MASK: + value =3D s->ic_intr_mask; + break; + case DW_IC_RAW_INTR_STAT: + value =3D s->ic_raw_intr_stat; + break; + case DW_IC_RX_TL: + value =3D s->ic_rx_tl; + break; + case DW_IC_TX_TL: + value =3D s->ic_tx_tl; + break; + case DW_IC_CLR_INTR: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_GEN_CALL | + DW_IC_INTR_RESTART_DET | + DW_IC_INTR_START_DET | + DW_IC_INTR_STOP_DET | + DW_IC_INTR_ACTIVITY | + DW_IC_INTR_RX_DONE | + DW_IC_INTR_TX_ABRT | + DW_IC_INTR_RD_REQ | + DW_IC_INTR_TX_OVER | + DW_IC_INTR_RX_OVER | + DW_IC_INTR_RX_UNDER); + s->ic_tx_abrt_source =3D 0; + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_RX_UNDER: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_RX_UNDER); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_RX_OVER: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_RX_OVER); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_TX_OVER: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_TX_OVER); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_RD_REQ: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_RD_REQ); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_TX_ABRT: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_TX_ABRT); + s->ic_tx_abrt_source =3D 0; + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_RX_DONE: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_RX_DONE); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_ACTIVITY: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_ACTIVITY); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_STOP_DET: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_STOP_DET); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_START_DET: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_START_DET); + dw_i2c_update_irq(s); + break; + case DW_IC_CLR_GEN_CALL: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_GEN_CALL); + dw_i2c_update_irq(s); + break; + case DW_IC_ENABLE: + value =3D s->ic_enable; + break; + case DW_IC_STATUS: + value =3D s->ic_status; + break; + case DW_IC_TXFLR: + value =3D s->ic_txflr; + break; + case DW_IC_RXFLR: + value =3D s->ic_rxflr; + break; + case DW_IC_SDA_HOLD: + value =3D s->ic_sda_hold; + break; + case DW_IC_TX_ABRT_SOURCE: + value =3D s->ic_tx_abrt_source; + break; + case DW_IC_SLV_DATA_NACK_ONLY: + qemu_log_mask(LOG_UNIMP, + "%s: unsupported read - ic_slv_data_nack_only\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_CR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported read - ic_dma_cr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_TDLR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported read - ic_dma_tdlr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_RDLR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported read - ic_dma_rdlr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_SDA_SETUP: + value =3D s->ic_sda_setup; + break; + case DW_IC_ACK_GENERAL_CALL: + qemu_log_mask(LOG_UNIMP, "%s: unsupported read - ic_ack_general_ca= ll\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_ENABLE_STATUS: + value =3D s->ic_enable_status; + break; + case DW_IC_FS_SPKLEN: + value =3D s->ic_fs_spklen; + break; + case DW_IC_CLR_RESTART_DET: + s->ic_raw_intr_stat &=3D ~(DW_IC_INTR_RESTART_DET); + break; + case DW_IC_COMP_PARAM_1: + value =3D s->ic_comp_param_1; + break; + case DW_IC_COMP_VERSION: + value =3D s->ic_comp_version; + break; + case DW_IC_COMP_TYPE: + value =3D s->ic_comp_type; + break; + + /* This register is invalid at this point. */ + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } + + trace_dw_i2c_read(DEVICE(s)->canonical_path, offset, value); + + return value; +} + +static void dw_i2c_write_ic_con(DesignWareI2CState *s, uint32_t value) +{ + if (value & DW_IC_CON_RX_FIFO_FULL_HLD_CTRL) { + qemu_log_mask(LOG_UNIMP, + "%s: unsupported ic_con flag - RX_FIFO_FULL_HLD_CTRL= \n", + DEVICE(s)->canonical_path); + } + + if (!(s->ic_enable & DW_IC_ENABLE_ENABLE)) { + s->ic_con =3D value & DW_IC_CON_MASK; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid setting to ic_con %d when ic_enable[0]= =3D=3D1\n", + DEVICE(s)->canonical_path, value); + } +} + +static void dw_i2c_reset_to_idle(DesignWareI2CState *s) +{ + s->ic_enable_status &=3D ~DW_IC_ENABLE_STATUS_IC_EN; + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_TX_EMPTY; + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_FULL; + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_UNDER; + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_OVER; + s->ic_rxflr =3D 0; + s->ic_status &=3D ~DW_IC_STATUS_ACTIVITY; + s->status =3D DW_I2C_STATUS_IDLE; + dw_i2c_update_irq(s); +} + +static void dw_ic_tx_abort(DesignWareI2CState *s, uint32_t src) +{ + s->ic_tx_abrt_source |=3D src; + s->ic_raw_intr_stat |=3D DW_IC_INTR_TX_ABRT; + dw_i2c_reset_to_idle(s); + dw_i2c_update_irq(s); +} + +static void dw_i2c_write_ic_data_cmd(DesignWareI2CState *s, uint32_t value) +{ + int recv =3D !!(value & DW_IC_DATA_CMD_CMD); + + if (s->status =3D=3D DW_I2C_STATUS_IDLE || + s->ic_raw_intr_stat & DW_IC_INTR_TX_ABRT) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Attempted to write to TX fifo when it is held i= n " + "reset.\n", DEVICE(s)->canonical_path); + return; + } + + /* Send the address if it hasn't been sent yet. */ + if (s->status =3D=3D DW_I2C_STATUS_SENDING_ADDRESS) { + int rv =3D i2c_start_transfer(s->bus, DW_IC_TAR_ADDRESS(s->ic_tar)= , recv); + if (rv) { + dw_ic_tx_abort(s, DW_IC_TX_ABRT_7B_ADDR_NOACK); + return; + } + s->status =3D recv ? DW_I2C_STATUS_RECEIVING : DW_I2C_STATUS_SENDI= NG; + } + + /* Send data */ + if (!recv) { + int rv =3D i2c_send(s->bus, DW_IC_DATA_CMD_DAT(value)); + if (rv) { + i2c_end_transfer(s->bus); + dw_ic_tx_abort(s, DW_IC_TX_ABRT_TXDATA_NOACK); + return; + } + dw_i2c_update_irq(s); + } + + /* Restart command */ + if (value & DW_IC_DATA_CMD_RESTART && s->ic_con & DW_IC_CON_IC_RESTART= _EN) { + s->ic_raw_intr_stat |=3D DW_IC_INTR_RESTART_DET | + DW_IC_INTR_START_DET | + DW_IC_INTR_ACTIVITY; + s->ic_status |=3D DW_IC_STATUS_ACTIVITY; + dw_i2c_update_irq(s); + + if (i2c_start_transfer(s->bus, DW_IC_TAR_ADDRESS(s->ic_tar), recv)= ) { + dw_ic_tx_abort(s, DW_IC_TX_ABRT_7B_ADDR_NOACK); + return; + } + + s->status =3D recv ? DW_I2C_STATUS_RECEIVING : DW_I2C_STATUS_SENDI= NG; + } + + /* Receive data */ + if (recv) { + uint8_t pos =3D (s->rx_cur + s->ic_rxflr) % DESIGNWARE_I2C_RX_FIFO= _SIZE; + + if (s->ic_rxflr < DESIGNWARE_I2C_RX_FIFO_SIZE) { + s->rx_fifo[pos] =3D i2c_recv(s->bus); + s->ic_rxflr++; + } else { + s->ic_raw_intr_stat |=3D DW_IC_INTR_RX_OVER; + dw_i2c_update_irq(s); + } + + if (s->ic_rxflr > s->ic_rx_tl) { + s->ic_raw_intr_stat |=3D DW_IC_INTR_RX_FULL; + dw_i2c_update_irq(s); + } + if (value & DW_IC_DATA_CMD_STOP) { + i2c_nack(s->bus); + } + } + + /* Stop command */ + if (value & DW_IC_DATA_CMD_STOP) { + s->ic_raw_intr_stat |=3D DW_IC_INTR_STOP_DET; + s->ic_status &=3D ~DW_IC_STATUS_ACTIVITY; + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_TX_EMPTY; + i2c_end_transfer(s->bus); + dw_i2c_update_irq(s); + } +} + +static void dw_i2c_write_ic_enable(DesignWareI2CState *s, uint32_t value) +{ + if (value & DW_IC_ENABLE_ENABLE && !(s->ic_con & DW_IC_CON_SLAVE_DISAB= LE)) { + qemu_log_mask(LOG_UNIMP, + "%s: Designware I2C slave mode is not supported.\n", + DEVICE(s)->canonical_path); + return; + } + + s->ic_enable =3D value & DW_IC_ENABLE_MASK; + + if (value & DW_IC_ENABLE_ABORT || value & DW_IC_ENABLE_TX_CMD_BLOCK) { + dw_ic_tx_abort(s, DW_IC_TX_ABRT_USER_ABRT); + return; + } + + if (value & DW_IC_ENABLE_ENABLE) { + s->ic_enable_status |=3D DW_IC_ENABLE_STATUS_IC_EN; + s->ic_status |=3D DW_IC_STATUS_ACTIVITY; + s->ic_raw_intr_stat |=3D DW_IC_INTR_ACTIVITY | + DW_IC_INTR_START_DET | + DW_IC_INTR_TX_EMPTY; + s->status =3D DW_I2C_STATUS_SENDING_ADDRESS; + dw_i2c_update_irq(s); + } else if ((value & DW_IC_ENABLE_ENABLE) =3D=3D 0) { + dw_i2c_reset_to_idle(s); + } + +} + +static void dw_i2c_write_ic_rx_tl(DesignWareI2CState *s, uint32_t value) +{ + /* Note that a value of 0 for ic_rx_tl indicates a threashold of 1. */ + if (value > DESIGNWARE_I2C_RX_FIFO_SIZE - 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid setting to ic_rx_tl %d\n", + DEVICE(s)->canonical_path, value); + s->ic_rx_tl =3D DESIGNWARE_I2C_RX_FIFO_SIZE - 1; + } else { + s->ic_rx_tl =3D value; + } + + if (s->ic_rxflr > s->ic_rx_tl && s->ic_enable & DW_IC_ENABLE_ENABLE) { + s->ic_raw_intr_stat |=3D DW_IC_INTR_RX_FULL; + } else { + s->ic_raw_intr_stat &=3D ~DW_IC_INTR_RX_FULL; + } + dw_i2c_update_irq(s); +} + +static void dw_i2c_write_ic_tx_tl(DesignWareI2CState *s, uint32_t value) +{ + /* + * Note that a value of 0 for ic_tx_tl indicates a threashold of 1. + * However, the tx threshold is not used in the model because commands= are + * always sent out as soon as they are written. + */ + if (value > DESIGNWARE_I2C_TX_FIFO_SIZE - 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid setting to ic_tx_tl %d\n", + DEVICE(s)->canonical_path, value); + s->ic_tx_tl =3D DESIGNWARE_I2C_TX_FIFO_SIZE - 1; + } else { + s->ic_tx_tl =3D value; + } +} + +static void dw_i2c_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + DesignWareI2CState *s =3D opaque; + + trace_dw_i2c_write(DEVICE(s)->canonical_path, offset, value); + + /* The order of the registers are their order in memory. */ + switch (offset) { + case DW_IC_CON: + dw_i2c_write_ic_con(s, value); + break; + case DW_IC_TAR: + s->ic_tar =3D value & DW_IC_TAR_MASK; + break; + case DW_IC_SAR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported write - ic_sar\n", + DEVICE(s)->canonical_path); + s->ic_sar =3D value & DW_IC_SAR_MASK; + break; + case DW_IC_DATA_CMD: + dw_i2c_write_ic_data_cmd(s, value); + break; + case DW_IC_SS_SCL_HCNT: + s->ic_ss_scl_hcnt =3D value & DW_IC_SS_SCL_HCNT_MASK; + break; + case DW_IC_SS_SCL_LCNT: + s->ic_ss_scl_lcnt =3D value & DW_IC_SS_SCL_LCNT_MASK; + break; + case DW_IC_FS_SCL_HCNT: + s->ic_fs_scl_hcnt =3D value & DW_IC_FS_SCL_HCNT_MASK; + break; + case DW_IC_FS_SCL_LCNT: + s->ic_fs_scl_lcnt =3D value & DW_IC_FS_SCL_LCNT_MASK; + break; + case DW_IC_INTR_MASK: + s->ic_intr_mask =3D value & DW_IC_INTR_MASK_MASK; + dw_i2c_update_irq(s); + break; + case DW_IC_RX_TL: + dw_i2c_write_ic_rx_tl(s, value); + break; + case DW_IC_TX_TL: + dw_i2c_write_ic_tx_tl(s, value); + break; + case DW_IC_ENABLE: + dw_i2c_write_ic_enable(s, value); + break; + case DW_IC_SDA_HOLD: + s->ic_sda_hold =3D value & DW_IC_SDA_HOLD_MASK; + break; + case DW_IC_SLV_DATA_NACK_ONLY: + qemu_log_mask(LOG_UNIMP, + "%s: unsupported write - ic_slv_data_nack_only\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_CR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported write - ic_dma_cr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_TDLR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported write - ic_dma_tdlr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_DMA_RDLR: + qemu_log_mask(LOG_UNIMP, "%s: unsupported write - ic_dma_rdlr\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_SDA_SETUP: + s->ic_sda_setup =3D value & DW_IC_SDA_SETUP_MASK; + break; + case DW_IC_ACK_GENERAL_CALL: + qemu_log_mask(LOG_UNIMP, + "%s: unsupported write - ic_ack_general_call\n", + DEVICE(s)->canonical_path); + break; + case DW_IC_FS_SPKLEN: + s->ic_fs_spklen =3D value & DW_IC_FS_SPKLEN_MASK; + break; + + /* This register is invalid at this point. */ + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset or readonly register 0x= %" + HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } +} + +static const MemoryRegionOps designware_i2c_ops =3D { + .read =3D dw_i2c_read, + .write =3D dw_i2c_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static void designware_i2c_enter_reset(Object *obj, ResetType type) +{ + DesignWareI2CState *s =3D DESIGNWARE_I2C(obj); + + s->ic_con =3D DW_IC_CON_INIT_VAL; + s->ic_tar =3D DW_IC_TAR_INIT_VAL; + s->ic_sar =3D DW_IC_SAR_INIT_VAL; + s->ic_ss_scl_hcnt =3D DW_IC_SS_SCL_HCNT_INIT_VAL; + s->ic_ss_scl_lcnt =3D DW_IC_SS_SCL_LCNT_INIT_VAL; + s->ic_fs_scl_hcnt =3D DW_IC_FS_SCL_HCNT_INIT_VAL; + s->ic_fs_scl_lcnt =3D DW_IC_FS_SCL_LCNT_INIT_VAL; + s->ic_intr_mask =3D DW_IC_INTR_MASK_INIT_VAL; + s->ic_raw_intr_stat =3D 0; + s->ic_rx_tl =3D 0; + s->ic_tx_tl =3D 0; + s->ic_enable =3D 0; + s->ic_status =3D DW_IC_STATUS_INIT_VAL; + s->ic_txflr =3D 0; + s->ic_rxflr =3D 0; + s->ic_sda_hold =3D DW_IC_SDA_HOLD_INIT_VAL; + s->ic_tx_abrt_source =3D 0; + s->ic_sda_setup =3D DW_IC_SDA_SETUP_INIT_VAL; + s->ic_enable_status =3D 0; + s->ic_fs_spklen =3D DW_IC_FS_SPKLEN_INIT_VAL; + s->ic_comp_param_1 =3D DW_IC_COMP_PARAM_1_INIT_VAL; + s->ic_comp_version =3D DW_IC_COMP_VERSION_INIT_VAL; + s->ic_comp_type =3D DW_IC_COMP_TYPE_INIT_VAL; + + s->rx_cur =3D 0; + s->status =3D DW_I2C_STATUS_IDLE; +} + +static void designware_i2c_hold_reset(Object *obj, ResetType type) +{ + DesignWareI2CState *s =3D DESIGNWARE_I2C(obj); + + qemu_irq_lower(s->irq); +} + +static const VMStateDescription vmstate_designware_i2c =3D { + .name =3D TYPE_DESIGNWARE_I2C, + .version_id =3D 0, + .minimum_version_id =3D 0, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(ic_con, DesignWareI2CState), + VMSTATE_UINT32(ic_tar, DesignWareI2CState), + VMSTATE_UINT32(ic_sar, DesignWareI2CState), + VMSTATE_UINT32(ic_ss_scl_hcnt, DesignWareI2CState), + VMSTATE_UINT32(ic_ss_scl_lcnt, DesignWareI2CState), + VMSTATE_UINT32(ic_fs_scl_hcnt, DesignWareI2CState), + VMSTATE_UINT32(ic_fs_scl_lcnt, DesignWareI2CState), + VMSTATE_UINT32(ic_intr_mask, DesignWareI2CState), + VMSTATE_UINT32(ic_raw_intr_stat, DesignWareI2CState), + VMSTATE_UINT32(ic_rx_tl, DesignWareI2CState), + VMSTATE_UINT32(ic_tx_tl, DesignWareI2CState), + VMSTATE_UINT32(ic_enable, DesignWareI2CState), + VMSTATE_UINT32(ic_status, DesignWareI2CState), + VMSTATE_UINT32(ic_txflr, DesignWareI2CState), + VMSTATE_UINT32(ic_rxflr, DesignWareI2CState), + VMSTATE_UINT32(ic_sda_hold, DesignWareI2CState), + VMSTATE_UINT32(ic_tx_abrt_source, DesignWareI2CState), + VMSTATE_UINT32(ic_sda_setup, DesignWareI2CState), + VMSTATE_UINT32(ic_enable_status, DesignWareI2CState), + VMSTATE_UINT32(ic_fs_spklen, DesignWareI2CState), + VMSTATE_UINT32(ic_comp_param_1, DesignWareI2CState), + VMSTATE_UINT32(ic_comp_version, DesignWareI2CState), + VMSTATE_UINT32(ic_comp_type, DesignWareI2CState), + VMSTATE_UINT32(status, DesignWareI2CState), + VMSTATE_UINT8_ARRAY(rx_fifo, DesignWareI2CState, + DESIGNWARE_I2C_RX_FIFO_SIZE), + VMSTATE_UINT8(rx_cur, DesignWareI2CState), + VMSTATE_END_OF_LIST(), + }, +}; + +static void designware_i2c_smbus_init(Object *obj) +{ + DesignWareI2CState *s =3D DESIGNWARE_I2C(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->iomem, obj, &designware_i2c_ops, s, + "regs", 4 * KiB); + sysbus_init_mmio(sbd, &s->iomem); + + s->bus =3D i2c_init_bus(DEVICE(s), "i2c-bus"); +} + +static void designware_i2c_class_init(ObjectClass *klass, const void *data) +{ + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->desc =3D "Designware I2C"; + dc->vmsd =3D &vmstate_designware_i2c; + rc->phases.enter =3D designware_i2c_enter_reset; + rc->phases.hold =3D designware_i2c_hold_reset; +} + +static const TypeInfo designware_i2c_types[] =3D { + { + .name =3D TYPE_DESIGNWARE_I2C, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(DesignWareI2CState), + .class_init =3D designware_i2c_class_init, + .instance_init =3D designware_i2c_smbus_init, + }, +}; +DEFINE_TYPES(designware_i2c_types); diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig index 596a7a3165ad..d3f394edeb9c 100644 --- a/hw/i2c/Kconfig +++ b/hw/i2c/Kconfig @@ -18,6 +18,10 @@ config ARM_SBCON_I2C bool select BITBANG_I2C =20 +config DESIGNWARE_I2C + bool + select I2C + config ACPI_SMBUS bool select SMBUS diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index c459adcb596c..88aea35662dd 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -11,6 +11,7 @@ i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2= c.c')) i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c')) i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c')) i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c')) +i2c_ss.add(when: 'CONFIG_DESIGNWARE_I2C', if_true: files('designware_i2c.c= ')) i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c')) i2c_ss.add(when: 'CONFIG_ARM_SBCON_I2C', if_true: files('arm_sbcon_i2c.c')) i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events index 1ad0e95c0e60..8a78d2d3c8de 100644 --- a/hw/i2c/trace-events +++ b/hw/i2c/trace-events @@ -61,3 +61,7 @@ pca954x_read_data(uint8_t value) "PCA954X read data: 0x%0= 2x" =20 imx_i2c_read(const char *id, const char *reg, uint64_t ofs, uint64_t value= ) "%s:[%s (0x%" PRIx64 ")] -> 0x%02" PRIx64 imx_i2c_write(const char *id, const char *reg, uint64_t ofs, uint64_t valu= e) "%s:[%s (0x%" PRIx64 ")] <- 0x%02" PRIx64 + +# designware_i2c.c +dw_i2c_read(const char *id, uint64_t ofs, uint64_t value) "%s: offset 0x%0= 2" PRIx64 " -> value: 0x%02" PRIx64 +dw_i2c_write(const char *id, uint64_t ofs, uint64_t value) "%s: offset: 0x= %02" PRIx64 " <- value: 0x%02" PRIx64 --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123129680151.84417644741904; Sat, 25 Apr 2026 06:18:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGctj-00070z-1s; Sat, 25 Apr 2026 09:18:15 -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 1wGcte-00070G-UD for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:11 -0400 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGctd-0008K6-Cv for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:10 -0400 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-82735a41920so3560117b3a.2 for ; Sat, 25 Apr 2026 06:18:09 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123088; x=1777727888; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=SvuG1jTaGZrGaRxOJASSzc8k9CIquBkG8wiP7fGUjWo=; b=HNjll7B6QbHuctDcQ8sB2T4xqYWEBMpzQ5Vw+n2jYuncWa9lXrxrVST1xzR+R7Ca88 8tTP+WN70jFZmzENT0uAdgAHd6m8KVoW+hAiFeP5EOceV1saF6+CThKixUZqf8pJsl1x IL7E1XovV8KcLhIsbVHYXfBtaGDplua4aIXFM8joyzt9Z3AJ3UbmxQAYHuRbNHegerTD MkN4PsaYOCp+otBZGz5wSLfg5OkAwsO/DV4TK+9Lk9v/lXB2n93BrIq1egvYhnRu/l3R 6mZXTkjkVgJNFdmj3r4BvB4SnWjzSYgiI16W8LFdJ5tiqT8xOXscc8nXxt+eTbXxXQQs IcZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123088; x=1777727888; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SvuG1jTaGZrGaRxOJASSzc8k9CIquBkG8wiP7fGUjWo=; b=M1Xlarf5JhLwVWjKK7ynyEAwvljilmhYUAW2F4kWW4Lb3AF5ZbQ7Yb8N7LKf6mxGd+ eziwdS4eVNAmnRHs3PYKgEMXKr2WLDAaxXFe9PLFcIu2KmfLBlZ4GoZJS5ewpPtlrbNB WiEcUBE43osEYUYMlMD8V/BYW3i4gbPQzQIR8Ithcf+Ze1qr+K4/Vw0hKPb0pQnsM3sD FH0qROxLs71YP5dgXWZiqKS3KPLMD3uyu3uU8n307ySKsyDTt7yrCMqhwHR/je2BSjAB qtV9A0CqgaLg/7Gnr81hDAXBpGxpFAS9LY5/2MW/XK/gxKtImE+3gRvLcU17MSCe8kVw cwjA== X-Forwarded-Encrypted: i=1; AFNElJ8/YDJI2YeNeedoh6rZSi1iRc6mESb97ZNr4oaCmv/Q+nUTSZHNTHYSIihA7iBuZzMNBXI6YtKjypFO@nongnu.org X-Gm-Message-State: AOJu0YxFFj4qi+JCM5HzfYPnDDU35nLnuUmg2+9JZvE4os3xCnWi9E4O Dn6DR0rBDTvnr3SDAKzBZqY3PwNiox0mnL1Z/B7dD+tfcg+fc3VP+B6r X-Gm-Gg: AeBDievWXWiPdGitTtmnB4pNWAashC3h2082VXNGp4SgQynqm3jNN8RqdvKnEcooXjC 2I4vm5syJ3kuk+VLY/X1n1KfsCzijOfP55oo9ulXmwD5/aEzufCQLtBBbfcDDcwGdKIaJBVy8VI M64c2dyqlAdZv5ZPE8F2Sd1Nk5dYNFQey71G/Fi/XAfDRRAqnwCuVwwiC1r+nuXIwoEvCNqEjA7 ToIyJ/MW8m7xN009kn4YC12kpZ8Y/V9x7VVrGFTQ35K2fhaFS6t4OD5liftHbm27o6kpfpgh4G5 A6G7cylAcrl2Yv8RVqNwSFH0bQpmpZvf+1/EJHNVb6fm7M/Jkq5cf44ykcEWr1xJ3kdTBT2dvHw CrD7VvalKZp3j72Pz0bfovOuT3Qk8+7arpUXtWwtw5W0tdiDzLEJsREPaP7JXBBd/GqJgk3IFq+ 6bwHjJOamlW18RC8LbWOlRUVBmsQnE8Rh8Q8jjdHetBtBBHtbuiBmQxgRLZzFYLEyb42Evvukuc TGl3p5nvmfwxCHCEWAbVJ9q+yaYryeQ X-Received: by 2002:a05:6a00:ad86:b0:82c:daa4:ce29 with SMTP id d2e1a72fcca58-82f8c91b723mr37352440b3a.47.1777123088033; Sat, 25 Apr 2026 06:18:08 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 02/13] hw/riscv/boot: Describe discontiguous memory in boot_info Date: Sat, 25 Apr 2026 23:17:08 +1000 Message-ID: <20260425131721.932250-3-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::429; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x429.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123133488154100 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin Machines that have discontiguous memory may need to adjust where firmware and images are loaded at boot. Provide an interface for machines to describe a discontiguous low/high RAM scheme for this purpose. Signed-off-by: Nicholas Piggin Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Signed-off-by: Joel Stanley --- include/hw/riscv/boot.h | 7 +++++++ hw/riscv/boot.c | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index f00b3ca12245..115e3222174f 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -28,6 +28,10 @@ #define RISCV64_BIOS_BIN "opensbi-riscv64-generic-fw_dynamic.bin" =20 typedef struct RISCVBootInfo { + /* First contiguous RAM region. If size is zero then assume entire RAM= */ + hwaddr ram_low_start; + hwaddr ram_low_size; + ssize_t kernel_size; hwaddr image_low_addr; hwaddr image_high_addr; @@ -43,6 +47,9 @@ bool riscv_is_32bit(RISCVHartArrayState *harts); char *riscv_plic_hart_config_string(int hart_count); =20 void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts); +void riscv_boot_info_init_discontig_mem(RISCVBootInfo *info, + RISCVHartArrayState *harts, + hwaddr start, hwaddr size); vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info, hwaddr firmware_end_addr); hwaddr riscv_find_and_load_firmware(MachineState *machine, diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 9086793b7a7b..5c9547429a36 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -69,11 +69,22 @@ char *riscv_plic_hart_config_string(int hart_count) =20 void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts) { + info->ram_low_start =3D 0; + info->ram_low_size =3D 0; info->kernel_size =3D 0; info->initrd_size =3D 0; info->is_32bit =3D riscv_is_32bit(harts); } =20 +void riscv_boot_info_init_discontig_mem(RISCVBootInfo *info, + RISCVHartArrayState *harts, + hwaddr start, hwaddr size) +{ + riscv_boot_info_init(info, harts); + info->ram_low_start =3D start; + info->ram_low_size =3D size; +} + vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info, hwaddr firmware_end_addr) { if (info->is_32bit) { --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123129796327.971794030209; Sat, 25 Apr 2026 06:18:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcto-000743-NB; Sat, 25 Apr 2026 09:18:22 -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 1wGctk-00071l-Jx for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:16 -0400 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcti-0008Sd-FI for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:16 -0400 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-82f33d28c1dso4764892b3a.3 for ; Sat, 25 Apr 2026 06:18:14 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123093; x=1777727893; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Vt5sRZArkhJCu53zKZmmSu/3/eUzzNisCbL+VsSeRpU=; b=aOA3ncywwTBLeAp2X68LQ33jDdR837TtfBtb3R8beRSkcCHuxjKKi1veURx+bf+0Pj Rr0bd0Xy7sszU0WhAn2fcNdiUVQ6oUbppbWGqFRxkdGBEp2hKnWONItgweYmzvc/Tb5B 3vNYLC8DH6hwp6/Orrbt41R8/joGbX71Ozc6RnKwsI693RA/pqan6Du9dWg6cP1JQ7jM 6m6eb79nGMbG0yVCEXICLY5G65upn7+nZXgrjexXoNnlogziMiG8ZEgI1u+ZfeNEuUvL yd3K2Pqt2fR5sVvjrQdv1FmOOuQe2I+5oXjyI2ifS3baj2/Mih9iPMVnQ4cRwkhxLtxw XUqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123093; x=1777727893; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Vt5sRZArkhJCu53zKZmmSu/3/eUzzNisCbL+VsSeRpU=; b=dXWJkyZzu/OCdnhj0NZ/LEf2bN77uLNWQ7VAakN1PznrLFLVbfjy5wdY/VxTLkayNh bJK5j3++pkzFG1nex5EKeFjzBbw3e0YWst+ci+9h7aiGeyqBx2N+lH1jzL82zGwUE18B mbwR+1taz3fsICqRPPOgxFBAJvXrlnDLGcg0P0WzvwOFPIYjVmFcrLybBESKz70E/zdU 4orvUHMk6r/tlDr0sf81RnhzbocCjZ2UoAAhg+bHO/3fsi7S66aHHKrgVtWSrW9hyNci N2Vob3TvGP7Db1rxi+t7K01yuqhqhalyXLwQmSB1BOiPx53tZK7zqIEJMkqdRmoR+i8p HPFQ== X-Forwarded-Encrypted: i=1; AFNElJ8HKlGg8xxj9OA4CiFdDvfUFRRcK4yRgUQSuibshuBWB7iJJjJ5dln0jMKf7bi2hf1uw1GY5ZZQ0yGv@nongnu.org X-Gm-Message-State: AOJu0Ywm5ciBFdPqnRyhmG3CTjUwKciS6X/jY52XDpUpntZ7g6xaiw6X NHUx56WcOLo316VzpdlTA8t80RxLcHxL2I03OZBodCIQNzxkwt3iKW08 X-Gm-Gg: AeBDiet0/rd6C9EGF4VKPu2K3Jr1ZZqcc4M+aK9ogJGBQKL9PI4o8qYvo3A6a45mgXT TL3xz7/pNp0PoAI99nD9mV2BmBk9aFEKhc4TU/0OLVTmfbFV8Zg62z0TNTdwMDB25yLyOiFZckV Jhr9YqFVvwKXplLdXnocvZfjrnO1zXd95sVlAjJXOIBo3G0z/Ilx9o6CHf5UD2HBp03zd+OnJX7 vnXqNxjYxF12JLcXYukjFh/tFZZfT5Ec6nnXhCiMQZm+bgKtC86Cx1e6/4doFQxJfcTmnAXFoh7 u9eMOGjdIZK3vfmlNme76X3ViFG9kmsZeKqJF059yPsIsh0031yzJFy8vXD4F+LRdHx+1XA+TL5 kq8bHY48njHHsUOvO+WZxQmsspCVbxpeX+fueN92hjbli/XunbRyflMaZf9CRoVEedvUvGRDpTp HgsR2vfmyhKJha55ruyGTfFp/JMuQfLvtXGLYLPL2JyqkGkLjIBcWu5FAYcbmzEcT1i5NB7dgsV R8nrABH14isTfC3PgeJwS56aakqjXix X-Received: by 2002:a05:6a00:6de7:b0:82f:776f:a78d with SMTP id d2e1a72fcca58-82f8c888e09mr36076980b3a.19.1777123093077; Sat, 25 Apr 2026 06:18:13 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 03/13] hw/riscv/boot: Account for discontiguous memory when loading firmware Date: Sat, 25 Apr 2026 23:17:09 +1000 Message-ID: <20260425131721.932250-4-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::433; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x433.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123133539154100 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin This loads firmware into the first (low) memory range, accounting for machines having discontiguous memory regions. Signed-off-by: Nicholas Piggin Reviewed-by: Daniel Henrique Barboza Signed-off-by: Joel Stanley --- v4: Make RISCVBootInfo *info const in riscv_load_firmware v3: Call riscv_boot_info_init before riscv_find_and_load_firmware in sifive_u --- include/hw/riscv/boot.h | 5 ++++- hw/riscv/boot.c | 18 ++++++++++++------ hw/riscv/microchip_pfsoc.c | 6 ++++-- hw/riscv/opentitan.c | 6 ++++-- hw/riscv/shakti_c.c | 6 +++++- hw/riscv/sifive_u.c | 6 ++++-- hw/riscv/spike.c | 6 ++++-- hw/riscv/virt.c | 7 ++++--- hw/riscv/xiangshan_kmh.c | 6 +++++- 9 files changed, 46 insertions(+), 20 deletions(-) diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 115e3222174f..b2ef64fb1d14 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -53,13 +53,16 @@ void riscv_boot_info_init_discontig_mem(RISCVBootInfo *= info, vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info, hwaddr firmware_end_addr); hwaddr riscv_find_and_load_firmware(MachineState *machine, + RISCVBootInfo *info, const char *default_machine_firmware, hwaddr *firmware_load_addr, symbol_fn_t sym_cb); const char *riscv_default_firmware_name(RISCVHartArrayState *harts); char *riscv_find_firmware(const char *firmware_filename, const char *default_machine_firmware); -hwaddr riscv_load_firmware(const char *firmware_filename, +hwaddr riscv_load_firmware(MachineState *machine, + const RISCVBootInfo *info, + const char *firmware_filename, hwaddr *firmware_load_addr, symbol_fn_t sym_cb); void riscv_load_kernel(MachineState *machine, diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 5c9547429a36..4fbc778263cf 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -145,6 +145,7 @@ char *riscv_find_firmware(const char *firmware_filename, } =20 hwaddr riscv_find_and_load_firmware(MachineState *machine, + RISCVBootInfo *info, const char *default_machine_firmware, hwaddr *firmware_load_addr, symbol_fn_t sym_cb) @@ -157,7 +158,8 @@ hwaddr riscv_find_and_load_firmware(MachineState *machi= ne, =20 if (firmware_filename) { /* If not "none" load the firmware */ - firmware_end_addr =3D riscv_load_firmware(firmware_filename, + firmware_end_addr =3D riscv_load_firmware(machine, info, + firmware_filename, firmware_load_addr, sym_cb= ); g_free(firmware_filename); } @@ -165,10 +167,13 @@ hwaddr riscv_find_and_load_firmware(MachineState *mac= hine, return firmware_end_addr; } =20 -hwaddr riscv_load_firmware(const char *firmware_filename, +hwaddr riscv_load_firmware(MachineState *machine, + const RISCVBootInfo *info, + const char *firmware_filename, hwaddr *firmware_load_addr, symbol_fn_t sym_cb) { + uint64_t mem_size =3D info->ram_low_size ?: machine->ram_size; uint64_t firmware_entry, firmware_end; ssize_t firmware_size; =20 @@ -197,7 +202,7 @@ hwaddr riscv_load_firmware(const char *firmware_filenam= e, =20 firmware_size =3D load_image_targphys_as(firmware_filename, *firmware_load_addr, - current_machine->ram_size, NULL, + mem_size, NULL, NULL); =20 if (firmware_size > 0) { @@ -212,7 +217,7 @@ hwaddr riscv_load_firmware(const char *firmware_filenam= e, static void riscv_load_initrd(MachineState *machine, RISCVBootInfo *info) { const char *filename =3D machine->initrd_filename; - uint64_t mem_size =3D machine->ram_size; + uint64_t mem_size =3D info->ram_low_size ?: machine->ram_size; void *fdt =3D machine->fdt; hwaddr start, end; ssize_t size; @@ -258,6 +263,7 @@ void riscv_load_kernel(MachineState *machine, bool load_initrd, symbol_fn_t sym_cb) { + uint64_t mem_size =3D info->ram_low_size ?: machine->ram_size; const char *kernel_filename =3D machine->kernel_filename; ssize_t kernel_size; void *fdt =3D machine->fdt; @@ -289,7 +295,7 @@ void riscv_load_kernel(MachineState *machine, } =20 kernel_size =3D load_image_targphys_as(kernel_filename, kernel_start_a= ddr, - current_machine->ram_size, NULL, = NULL); + mem_size, NULL, NULL); if (kernel_size > 0) { info->kernel_size =3D kernel_size; info->image_low_addr =3D kernel_start_addr; @@ -385,7 +391,7 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwadd= r dram_size, dtb_start =3D QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB); =20 if (dtb_start_limit && (dtb_start < dtb_start_limit)) { - error_report("No enough memory to place DTB after kernel/initrd"); + error_report("Not enough memory to place DTB after kernel/initrd"); exit(1); } =20 diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 743f31f00578..1d1ddb05a882 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -618,18 +618,20 @@ static void microchip_icicle_kit_machine_init(Machine= State *machine) firmware_load_addr =3D RESET_VECTOR; } =20 + riscv_boot_info_init(&boot_info, &s->soc.u_cpus); + /* Load the firmware if necessary */ firmware_end_addr =3D firmware_load_addr; if (firmware_name) { char *filename =3D riscv_find_firmware(firmware_name, NULL); if (filename) { - firmware_end_addr =3D riscv_load_firmware(filename, + firmware_end_addr =3D riscv_load_firmware(machine, &boot_info, + filename, &firmware_load_addr, N= ULL); g_free(filename); } } =20 - riscv_boot_info_init(&boot_info, &s->soc.u_cpus); if (machine->kernel_filename) { kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, firmware_end_addr= ); diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 309125e854bc..8cd660dd4154 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -99,12 +99,14 @@ static void opentitan_machine_init(MachineState *machin= e) memory_region_add_subregion(sys_mem, memmap[IBEX_DEV_RAM].base, machine->ram); =20 + riscv_boot_info_init(&boot_info, &s->soc.cpus); + if (machine->firmware) { hwaddr firmware_load_addr =3D memmap[IBEX_DEV_RAM].base; - riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); + riscv_load_firmware(machine, &boot_info, machine->firmware, + &firmware_load_addr, NULL); } =20 - riscv_boot_info_init(&boot_info, &s->soc.cpus); if (machine->kernel_filename) { riscv_load_kernel(machine, &boot_info, memmap[IBEX_DEV_RAM].base, diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index 49a39b30212d..eb720d9cdf5d 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -45,6 +45,7 @@ static void shakti_c_machine_state_init(MachineState *mst= ate) { ShaktiCMachineState *sms =3D RISCV_SHAKTI_MACHINE(mstate); MemoryRegion *system_memory =3D get_system_memory(); + RISCVBootInfo boot_info; hwaddr firmware_load_addr =3D shakti_c_memmap[SHAKTI_C_RAM].base; =20 /* Initialize SoC */ @@ -57,8 +58,11 @@ static void shakti_c_machine_state_init(MachineState *ms= tate) shakti_c_memmap[SHAKTI_C_RAM].base, mstate->ram); =20 + riscv_boot_info_init(&boot_info, &sms->soc.cpus); + if (mstate->firmware) { - riscv_load_firmware(mstate->firmware, &firmware_load_addr, NULL); + riscv_load_firmware(mstate, &boot_info, mstate->firmware, + &firmware_load_addr, NULL); } =20 /* ROM reset vector */ diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 7ec67b256514..dda8687bfdd8 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -589,11 +589,13 @@ static void sifive_u_machine_init(MachineState *machi= ne) break; } =20 + riscv_boot_info_init(&boot_info, &s->soc.u_cpus); + firmware_name =3D riscv_default_firmware_name(&s->soc.u_cpus); - firmware_end_addr =3D riscv_find_and_load_firmware(machine, firmware_n= ame, + firmware_end_addr =3D riscv_find_and_load_firmware(machine, &boot_info, + firmware_name, &start_addr, NULL); =20 - riscv_boot_info_init(&boot_info, &s->soc.u_cpus); if (machine->kernel_filename) { kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, firmware_end_addr= ); diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 35c696f891d8..6ee915a8ba4e 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -281,9 +281,12 @@ static void spike_board_init(MachineState *machine) } } =20 + riscv_boot_info_init(&boot_info, &s->soc[0]); + /* Load firmware */ if (firmware_name) { - firmware_end_addr =3D riscv_load_firmware(firmware_name, + firmware_end_addr =3D riscv_load_firmware(machine, &boot_info, + firmware_name, &firmware_load_addr, htif_symbol_callback); g_free(firmware_name); @@ -293,7 +296,6 @@ static void spike_board_init(MachineState *machine) create_fdt(s, memmap, riscv_is_32bit(&s->soc[0]), htif_custom_base); =20 /* Load kernel */ - riscv_boot_info_init(&boot_info, &s->soc[0]); if (machine->kernel_filename) { kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, firmware_end_addr= ); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index a1c323e66dfd..4501d5581b62 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1457,7 +1457,10 @@ static void virt_machine_done(Notifier *notifier, vo= id *data) } } =20 - firmware_end_addr =3D riscv_find_and_load_firmware(machine, firmware_n= ame, + riscv_boot_info_init(&boot_info, &s->soc[0]); + + firmware_end_addr =3D riscv_find_and_load_firmware(machine, &boot_info, + firmware_name, &start_addr, NULL); =20 pflash_blk0 =3D pflash_cfi01_get_blk(s->flash[0]); @@ -1480,8 +1483,6 @@ static void virt_machine_done(Notifier *notifier, voi= d *data) } } =20 - riscv_boot_info_init(&boot_info, &s->soc[0]); - if (machine->kernel_filename && !kernel_entry) { kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, firmware_end_addr= ); diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c index 436e51c1c593..247a0b5d1f21 100644 --- a/hw/riscv/xiangshan_kmh.c +++ b/hw/riscv/xiangshan_kmh.c @@ -166,6 +166,7 @@ static void xiangshan_kmh_machine_init(MachineState *ma= chine) const MemMapEntry *memmap =3D xiangshan_kmh_memmap; MemoryRegion *system_memory =3D get_system_memory(); hwaddr start_addr =3D memmap[XIANGSHAN_KMH_DRAM].base; + RISCVBootInfo boot_info; =20 /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, @@ -177,13 +178,16 @@ static void xiangshan_kmh_machine_init(MachineState *= machine) memmap[XIANGSHAN_KMH_DRAM].base, machine->ram); =20 + riscv_boot_info_init(&boot_info, &s->soc.cpus); + /* ROM reset vector */ riscv_setup_rom_reset_vec(machine, &s->soc.cpus, start_addr, memmap[XIANGSHAN_KMH_ROM].base, memmap[XIANGSHAN_KMH_ROM].size, 0, 0); if (machine->firmware) { - riscv_load_firmware(machine->firmware, &start_addr, NULL); + riscv_load_firmware(machine, &boot_info, machine->firmware, + &start_addr, NULL); } =20 /* Note: dtb has been integrated into firmware(OpenSBI) when compiling= */ --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123230881721.6870775746577; Sat, 25 Apr 2026 06:20:30 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcts-00075H-NW; Sat, 25 Apr 2026 09:18:24 -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 1wGctp-00074f-Dn for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:22 -0400 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGctn-0008TV-VP for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:21 -0400 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-83177129e28so1195312b3a.1 for ; Sat, 25 Apr 2026 06:18:18 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123098; x=1777727898; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=sW0fdPqCEH1I1Gmqkpz2eOq8cT+yEGpRcyXw/JwbtO4=; b=IKjnjme/h7RX0D0ujU6/lH/j78aFVlxaAp4ky2jkkEwXP1EM4f1CBDfBc11yr08sJo on1VZYA5kZTPH4Fj93nkpQrPaiu5rykKlmySi1bEkhnQLNE9wx1LI0unHQnhA1/U8SV7 n4laM9ajK4eYZ0W2lW7q94N4CgyZQByBFlL+eSRGzMoB28oCeDPStuaDqP8hp+Rndx0+ UWCOiqqePtRSmKTfL++QbnlVCsZo5h+o8+4be8W9QvWM3ZbBE3BFyqsOV3sWTviuchJy I7vUeexXZND22QzFbMrrKN3f+g4L8hHfnkXianLY0P/iUW1KlyVfEuCrQOFreRHG5klz O4lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123098; x=1777727898; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=sW0fdPqCEH1I1Gmqkpz2eOq8cT+yEGpRcyXw/JwbtO4=; b=U8P8PyJQtpYlY48c1SmBz/oUUjqmZtBQZVRIg6zswYrERwW+2EJiGLq0ZEbvRZGGdr /7jF+2JubBzol0yo6cCV8qka5gUft4SmQY8JIiui9eMYxthQGCKdKQuMmuFWtFV5H2E3 BDqkOk/o4AhCAFSIAnhvIr9qCvF/s621AbMrgbz8iodYkpYjiJT3cnABh3691nYc1sL9 Dibhi+XjQ6gQ39gHlWdmeDTdBcn2BiMHn4vynxvToIPJDvwyLnGY3t0ccBHvMK/7Ihb8 bK78aHyt9UoqDtpyhBf19BtIrOCUx9I46SbxHpr4NUOncEPB3PkIUblS0iHZtmAVsbG6 2QAA== X-Forwarded-Encrypted: i=1; AFNElJ83uU+kBeRyNZz7SyvHrIhYSdCEfL3ytwIUJmrw0unYu9P/OCup/J52EaK7kvPjF8rPmIx9M2TCYU0W@nongnu.org X-Gm-Message-State: AOJu0Yw5l20S5p3qgsXRjw8K/0jUdv77sthYX6tD4bVOl+ZkNQFVvJof w4ZvAcHtwkbc8KWzePUl4fR8zx4g9RQsqGAAtDKa3WGTwXAVkmzTYOc+ X-Gm-Gg: AeBDiesrprv7oWSwRGHmbysiMxmRfPV9AEhYMCuhziBHHnEbwYyuXYRpjc7t0n3lNpU w36J3c2n29QpG0F+CVVTQyq/s8T0mfeU7HBzh9//E1WdBCf9iX/MAV5iFu5veZajooRzaPlHCZL eBt/NfDo7riqoRfpE3stfGSl21UmyOZ0Y5ZEFeMGqNuMq/VPUVhgeWsJ11djvJ4PVHVIgaPCGBB 0jjPsXvTcukB9EB4rrdCWoma5JPWUohWjV13Fp23mV9w0PcTAxvog7AY+rz5wep+jfnr2fSB/mX gTWYKbuBPBmpjY3Re1BTm9HYOk5FAemVuafvPtymlVTOsp/9zHSq7wdDqbT4M9C79lARpsZ9Zjz vsEqfxSbkUVSxSlvskN1mmzJ8WVT9sYYcD7Gu5JboR9aBykgdhu2QLn9MSYFMgHGKbaJ37MOPKr 22my70lKPSbWSlvUUpvrqn4RrT7caHA8npB9MOkg2li8QosOs+FrFBeniScMyR7KBfrfWICONgc 8Laoe+clBJLhzjJVwW7IWoZqHmm+vL6 X-Received: by 2002:a05:6a00:2d03:b0:82d:6310:2efc with SMTP id d2e1a72fcca58-82f8c82d824mr36173369b3a.17.1777123097874; Sat, 25 Apr 2026 06:18:17 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 04/13] hw/riscv/boot: Provide a simple halting payload Date: Sat, 25 Apr 2026 23:17:10 +1000 Message-ID: <20260425131721.932250-5-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::433; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x433.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123231569158500 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin OpenSBI hangs before any console output if the domain init code sees the next stage is not in an executable region. If no kernel payload is provided to QEMU, the next stage address is NULL, and the riscv virt machine memory map ends up covering the 0 address with the catch all S-mode RWX region and so OpenSBI prints console messages and does not hang until the next stage boot. The soon to be added Tenstorrent Atlantis board address map has RAM starting at 0 and it loads OpenSBI there, so it is M-mode and not accessible by S-mode, tripping the early check and hang. Add a helper to set up a simple payload that gets OpenSBI messages to console. Signed-off-by: Nicholas Piggin Reviewed-by: Daniel Henrique Barboza Signed-off-by: Joel Stanley --- v4: Make vec instructions const v3: MachineState argument was unused --- include/hw/riscv/boot.h | 1 + hw/riscv/boot.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index b2ef64fb1d14..3dfb0e98db4c 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -78,6 +78,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RIS= CVHartArrayState *harts hwaddr rom_base, hwaddr rom_size, uint64_t kernel_entry, uint64_t fdt_load_addr); +void riscv_setup_halting_payload(RISCVBootInfo *info, hwaddr addr); void riscv_rom_copy_firmware_info(MachineState *machine, RISCVHartArrayState *harts, hwaddr rom_base, diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 4fbc778263cf..3c2501b3c721 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -518,6 +518,22 @@ void riscv_setup_rom_reset_vec(MachineState *machine, = RISCVHartArrayState *harts kernel_entry); } =20 +/* Simple payload so OpenSBI does not hang early with no output */ +void riscv_setup_halting_payload(RISCVBootInfo *info, hwaddr addr) +{ + /* Store the payload vector in little_endian byte order */ + static const uint32_t payload_vec[] =3D { + const_le32(0x10500073), /* 1: wfi */ + const_le32(0xffdff06f), /* j 1b */ + }; + rom_add_blob_fixed_as("mrom.payload", payload_vec, sizeof(payload_vec), + addr, &address_space_memory); + + info->kernel_size =3D sizeof(payload_vec); + info->image_low_addr =3D addr; + info->image_high_addr =3D info->image_low_addr + info->kernel_size; +} + void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr) { CPUState *cs; --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123138717434.39215128993897; Sat, 25 Apr 2026 06:18:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcu8-00078p-UV; Sat, 25 Apr 2026 09:18:41 -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 1wGctx-000773-GC for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:30 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGctt-00006v-Gb for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:29 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-82735a41920so3560200b3a.2 for ; Sat, 25 Apr 2026 06:18:24 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123104; x=1777727904; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=FPFZawW7CBjQCqRdR52jBPq2AM2fVcdKfMBVBqWA1qE=; b=K/IV4zepdUGgVQ47Xxn4wDPLlvvVHOm+89wCX7iq3w/WIveXaHFFXXO+LeBP5TCzWs 8xTOonW+hjUJG38KDTnZpg6k7SIy8BNe1dRE/sVaanBZGaQaEZ6MiQL2PT52Za29c1LW BIROfCsp5XBOr26zZcwXKsGHxWEpoZBe77MxEAlBXuP+1rHerVVV8e8jFZ47Dsne8oox 38WNa5pZ2a7bT/3XMUBAsdpPHfTKcn6pCNjCaFy5cqb9uThtgbhsEKka8LmzBuUQtAyL yVkGFWknsd0WfvpUeGzOiOrcUXCxd1fWmOX5cXL6mUUWNA7qLaYl3fv8mM6VVIB5CO2Z 3OSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123104; x=1777727904; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=FPFZawW7CBjQCqRdR52jBPq2AM2fVcdKfMBVBqWA1qE=; b=ac6+pWPd5ppcA8w1ffcaB4i/QKvQ6fv1w0jUcMRfjSeBUKu3JXAkqYA0TUwBcW4JM1 ilLr5TrGuBsPYybKjfehBXBimukE5nmRUltHw7bULz08R7AfQ9Ry2tgQ4qRv1o1RSU+y HCPio5rQWWpaW35viS+Sj/deMU0YzNRxpME4S/vHXgnkL9bkc3ufZlnbA9OKBGIp/yvR ilNRj34Ad3vQiIvoZZjHtg895l/FYfarQpScAh1BmUlzYaTr8n5PqTqAAlPxAveRabqR k+0hyNVx9MsjFc1LaDZDzFbULWH22KsamXuKJTych8624ft+C8yFef5FeiizJ9nIK2Xg F0wQ== X-Forwarded-Encrypted: i=1; AFNElJ8Z2xpuViP75SqY6hN7CAV2E1Axd3t3B2r6JxfGHXEhfJ6lAqCle8/ClWXX1+PnL+c1GBMVVMjUi24J@nongnu.org X-Gm-Message-State: AOJu0YyH8bqR9WGo3oUcX6fhYD3o8ItTV3pBcf06SSaTVPus/kGcZJxY J4lgUSAiDBW8BNhx1rne7PQOwplyQzp+LU6eqEhGozU/x7wDyVOmDLdg X-Gm-Gg: AeBDieuqleE7KFwMZ56fOfI3SrJU8b93ZU+DBTKuSzfR0xjDMh5aWujhV2iTGIMjbD2 oPrJLbwAYqSfLywW6yW5j9xpgRurVpBvga/x4G5v105f6fF8NtDCwuf2+INt2DZKG+ILio8K+ug 3Cg9xVuz/INaHyaZm4EqHgqt/QmJNxGKz8/KyRW/YE2ZyqOCzfjvqmmiJj2Gem/gMk+Ii0e5T86 +pL442yyh6sJgIPG4QBw2XoBJLzc8NgZeN3dYRasZZGWtTsjluqzMDUAtBvF9av+c8rIqybglGh zG2nMI3G62bxnk5zBW+jgkI01/9uQEbXY9bLfnbZFzIEtIc2dkPQgvRaw5ZRTUsczMHnQFOENHe e8HMJe8ozpKC1i0ent0ldDnNj9RNSaOuuNwgF9M1bIvzS8mxBzzr6d8Lp53jQXcdy5S9XPgsJtw ff6gdmQn/MGdSknfn2f9fgYD+/O3YdOo4oMqv49b7kcdvjPeKfIsuMY6EVhwEJQ4y1MBKz8Zbyy oJYCBb3rcvqNJppHfEMzLSW4mu4Kc9b7WChJHxFIFw= X-Received: by 2002:a05:6a00:bb84:b0:81f:be3c:9c9e with SMTP id d2e1a72fcca58-82f8c8d67d0mr37148389b3a.33.1777123103653; Sat, 25 Apr 2026 06:18:23 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Nutty Liu , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 05/13] hw/riscv/virt: Move AIA initialisation to helper file Date: Sat, 25 Apr 2026 23:17:11 +1000 Message-ID: <20260425131721.932250-6-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42c.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123142812158500 The AIA init will be used by any server class riscv machine. Separate it out in order to share code with such systems. The virt machine keeps machine specific #defines such as VIRT_IRQCHIP_NUM_MSIS, VIRT_IRQCHIP_NUM_PRIO_BITS. Reviewed-by: Daniel Henrique Barboza Reviewed-by: Nutty Liu Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Joel Stanley --- v3: - Add r-b - Move fewer things out of virt machine into aia common code, as they are virt machine specific and not part of aia. Done as part of this movement patch to avoid moving them out only put them back in the next patch. --- hw/riscv/aia.h | 26 +++++++++++ include/hw/riscv/virt.h | 1 - hw/riscv/aia.c | 89 ++++++++++++++++++++++++++++++++++++++ hw/riscv/virt-acpi-build.c | 2 + hw/riscv/virt.c | 87 +++++-------------------------------- hw/riscv/meson.build | 2 +- 6 files changed, 129 insertions(+), 78 deletions(-) create mode 100644 hw/riscv/aia.h create mode 100644 hw/riscv/aia.c diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h new file mode 100644 index 000000000000..dbb833340276 --- /dev/null +++ b/hw/riscv/aia.h @@ -0,0 +1,26 @@ +/* + * QEMU RISC-V Advanced Interrupt Architecture (AIA) + * + * Copyright (C) 2019 Western Digital Corporation or its affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_RISCV_AIA_H +#define HW_RISCV_AIA_H + +#include "exec/hwaddr.h" + +#define VIRT_IRQCHIP_NUM_SOURCES 96 + +uint32_t imsic_num_bits(uint32_t count); + +DeviceState *riscv_create_aia(bool msimode, int aia_guests, + const MemMapEntry *aplic_m, + const MemMapEntry *aplic_s, + const MemMapEntry *imsic_m, + const MemMapEntry *imsic_s, + int socket, int base_hartid, int hart_count, + uint32_t num_msis, uint32_t num_prio_bits); + +#endif diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 18a2a323a344..ad858deb76ad 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -135,7 +135,6 @@ enum { bool virt_is_acpi_enabled(RISCVVirtState *s); bool virt_is_iommu_sys_enabled(RISCVVirtState *s); void virt_acpi_setup(RISCVVirtState *vms); -uint32_t imsic_num_bits(uint32_t count); =20 /* * The virt machine physical address space used by some of the devices diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c new file mode 100644 index 000000000000..c724612a50a5 --- /dev/null +++ b/hw/riscv/aia.c @@ -0,0 +1,89 @@ +/* + * QEMU RISC-V Advanced Interrupt Architecture (AIA) + * + * Copyright (C) 2019 Western Digital Corporation or its affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "system/kvm.h" +#include "hw/intc/riscv_aplic.h" +#include "hw/intc/riscv_imsic.h" + +#include "aia.h" + +uint32_t imsic_num_bits(uint32_t count) +{ + uint32_t ret =3D 0; + + while (BIT(ret) < count) { + ret++; + } + + return ret; +} + +DeviceState *riscv_create_aia(bool msimode, int aia_guests, + const MemMapEntry *aplic_m, + const MemMapEntry *aplic_s, + const MemMapEntry *imsic_m, + const MemMapEntry *imsic_s, + int socket, int base_hartid, int hart_count, + uint32_t num_msis, uint32_t num_prio_bits) +{ + int i; + hwaddr addr =3D 0; + uint32_t guest_bits; + DeviceState *aplic_s_dev =3D NULL; + DeviceState *aplic_m_dev =3D NULL; + + if (msimode) { + if (!kvm_enabled()) { + /* Per-socket M-level IMSICs */ + addr =3D imsic_m->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_= SHIFT); + for (i =3D 0; i < hart_count; i++) { + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0), + base_hartid + i, true, 1, + num_msis); + } + } + + /* Per-socket S-level IMSICs */ + guest_bits =3D imsic_num_bits(aia_guests + 1); + addr =3D imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIF= T); + for (i =3D 0; i < hart_count; i++) { + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits), + base_hartid + i, false, 1 + aia_guests, + num_msis); + } + } + + if (!kvm_enabled()) { + /* Per-socket M-level APLIC */ + aplic_m_dev =3D riscv_aplic_create(aplic_m->base + + socket * aplic_m->size, + aplic_m->size, + (msimode) ? 0 : base_hartid, + (msimode) ? 0 : hart_count, + VIRT_IRQCHIP_NUM_SOURCES, + num_prio_bits, + msimode, true, NULL); + } + + /* Per-socket S-level APLIC */ + aplic_s_dev =3D riscv_aplic_create(aplic_s->base + + socket * aplic_s->size, + aplic_s->size, + (msimode) ? 0 : base_hartid, + (msimode) ? 0 : hart_count, + VIRT_IRQCHIP_NUM_SOURCES, + num_prio_bits, + msimode, false, aplic_m_dev); + + if (kvm_enabled() && msimode) { + riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s_dev), addr); + } + + return kvm_enabled() ? aplic_s_dev : aplic_m_dev; +} diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index fd6ca5dbc4ff..145f8d92ad69 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -42,6 +42,8 @@ #include "system/kvm.h" #include "system/reset.h" =20 +#include "aia.h" + #define ACPI_BUILD_TABLE_SIZE 0x20000 #define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) =20 diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 4501d5581b62..ce0fd6f50c4a 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -59,6 +59,8 @@ #include "hw/virtio/virtio-iommu.h" #include "hw/uefi/var-service-api.h" =20 +#include "aia.h" + /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU= . */ static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type) { @@ -509,17 +511,6 @@ static void create_fdt_socket_plic(RISCVVirtState *s, } } =20 -uint32_t imsic_num_bits(uint32_t count) -{ - uint32_t ret =3D 0; - - while (BIT(ret) < count) { - ret++; - } - - return ret; -} - static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr, uint32_t *intc_phandles, uint32_t msi_pha= ndle, bool m_mode, uint32_t imsic_guest_bits) @@ -1293,68 +1284,6 @@ static DeviceState *virt_create_plic(const MemMapEnt= ry *memmap, int socket, memmap[VIRT_PLIC].size); } =20 -static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_gue= sts, - const MemMapEntry *memmap, int socket, - int base_hartid, int hart_count) -{ - int i; - hwaddr addr =3D 0; - uint32_t guest_bits; - DeviceState *aplic_s =3D NULL; - DeviceState *aplic_m =3D NULL; - bool msimode =3D aia_type =3D=3D VIRT_AIA_TYPE_APLIC_IMSIC; - - if (msimode) { - if (!kvm_enabled()) { - /* Per-socket M-level IMSICs */ - addr =3D memmap[VIRT_IMSIC_M].base + - socket * VIRT_IMSIC_GROUP_MAX_SIZE; - for (i =3D 0; i < hart_count; i++) { - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0), - base_hartid + i, true, 1, - VIRT_IRQCHIP_NUM_MSIS); - } - } - - /* Per-socket S-level IMSICs */ - guest_bits =3D imsic_num_bits(aia_guests + 1); - addr =3D memmap[VIRT_IMSIC_S].base + socket * VIRT_IMSIC_GROUP_MAX= _SIZE; - for (i =3D 0; i < hart_count; i++) { - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits), - base_hartid + i, false, 1 + aia_guests, - VIRT_IRQCHIP_NUM_MSIS); - } - } - - if (!kvm_enabled()) { - /* Per-socket M-level APLIC */ - aplic_m =3D riscv_aplic_create(memmap[VIRT_APLIC_M].base + - socket * memmap[VIRT_APLIC_M].size, - memmap[VIRT_APLIC_M].size, - (msimode) ? 0 : base_hartid, - (msimode) ? 0 : hart_count, - VIRT_IRQCHIP_NUM_SOURCES, - VIRT_IRQCHIP_NUM_PRIO_BITS, - msimode, true, NULL); - } - - /* Per-socket S-level APLIC */ - aplic_s =3D riscv_aplic_create(memmap[VIRT_APLIC_S].base + - socket * memmap[VIRT_APLIC_S].size, - memmap[VIRT_APLIC_S].size, - (msimode) ? 0 : base_hartid, - (msimode) ? 0 : hart_count, - VIRT_IRQCHIP_NUM_SOURCES, - VIRT_IRQCHIP_NUM_PRIO_BITS, - msimode, false, aplic_m); - - if (kvm_enabled() && msimode) { - riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s), addr); - } - - return kvm_enabled() ? aplic_s : aplic_m; -} - static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip) { DeviceState *dev; @@ -1617,9 +1546,15 @@ static void virt_machine_init(MachineState *machine) s->irqchip[i] =3D virt_create_plic(s->memmap, i, base_hartid, hart_count); } else { - s->irqchip[i] =3D virt_create_aia(s->aia_type, s->aia_guests, - s->memmap, i, base_hartid, - hart_count); + s->irqchip[i] =3D riscv_create_aia(s->aia_type =3D=3D VIRT_AIA= _TYPE_APLIC_IMSIC, + s->aia_guests, + &s->memmap[VIRT_APLIC_M], + &s->memmap[VIRT_APLIC_S], + &s->memmap[VIRT_IMSIC_M], + &s->memmap[VIRT_IMSIC_S], + i, base_hartid, hart_count, + VIRT_IRQCHIP_NUM_MSIS, + VIRT_IRQCHIP_NUM_PRIO_BITS); } =20 /* Try to use different IRQCHIP instance based device type */ diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 533472e22aef..e53c180d0d10 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -1,5 +1,5 @@ riscv_ss =3D ss.source_set() -riscv_ss.add(files('boot.c')) +riscv_ss.add(files('boot.c', 'aia.c')) riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177712339017293.44170478497063; Sat, 25 Apr 2026 06:23:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuP-0007JM-17; Sat, 25 Apr 2026 09:18:57 -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 1wGcu5-00078W-3a for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:38 -0400 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGctz-00008H-8c for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:34 -0400 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-82f8b60e485so3690026b3a.0 for ; Sat, 25 Apr 2026 06:18:30 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123110; x=1777727910; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=nW9ZH4U2QO4sH1DbhH2/N7/zNF6OnlzomtW8a7+btRo=; b=lcP7A2jSptj4nPJipTuMma198tOF5CCHGgS3Mb124dpt+Nr6TYcrqRGsXywHmib9h/ c0lmxdpb2xydTHI6JsVSMCevvRNSA6DCLEYC3539VezmMBceGhHJqV+9oFDgS3Q9WudL S/YuL81zUsr4bnCZPSlLiJyCYD6rl0FmjPpLu1Cc7fm62rsgrLEFs0Rx51yFOWBU7utk DaFuYVqdhu5nQdwzlbiRXkwq5BnpM/Hnpr7KQFt1wN+dtGdew5AWWwYpSVpXOC6E77ci xzWA+MZn991bgZRE2vOeGvmJZ34Vsyx/89AJiXD9kAznzdgm0hUc6OctrpQG7cY79JdY 1ANA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123110; x=1777727910; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nW9ZH4U2QO4sH1DbhH2/N7/zNF6OnlzomtW8a7+btRo=; b=DwNFccTfJDO+aVol68IFa1MZCMzwG96Fu5IIiECYejTGcdqIyj8OZC4FKMNf27DvO7 egi0Ai4Ed7HXJCids/BoCetng6NmGfcZwFCHaJrQnlkdsY36Fbwfwc8dBpR+4afooSAK BTtAK2uyi92zOMwvFxb5oZZuObthTdQzU9ERu9jwMRrlZckv61HkDYKYqf2BTR3Qab6T lghrFMBpeao4J3OM0k56EHuE7kjQsGtMORwI5cyQ44QphmucH1pF0yK5DKOfQkhzqMl3 fuzaltBx1l1kHlQEVnd+Y5G4Pic+WdNjwNLxctPyJ6aoflGotwL5hpl4SuiQiFn2H07n Ll3g== X-Forwarded-Encrypted: i=1; AFNElJ9YNRcAmk5IcWo4ZlCW0dW+6kgvRo9j4Cqb+6Ark9UFW71aJbpKxwWYXkinnDd+KQE3f+yYOTFOAe8K@nongnu.org X-Gm-Message-State: AOJu0Yy8DI5YLpFEOsZHfRUWo9UaBlXVd5PKvCR3K1nfgzaQwOb7fQkJ RVx0N27BRgNW2tuPxiQlIn4BXo9/ftSOKJQaE4T7HUp7eYPbUm1wuB+M X-Gm-Gg: AeBDieuf+61IZrlIWgUsP2uEpG9VM21/ZoxOdVYvzqdeaq6Kn+SYzOnpjN7c7rLAwG9 qyIXyJ6Bt0HYV+q2EJJPeoZrYXdCyZVUiab9WYaJPvtvWbC2xuFbIofjyMIERQATZiI4ftBulSr 9t86mTttOrogFIY1RaVvGIjMcVPXnLCFjOLNa+RgVzPUyRBJhRs9n/hhaRnW4KVhTjNR9hwMXk8 LSgn+sp/CsxjaNiFOogPUt/wa2aaHPA3VzfhOOwSTxMd6FKRIs4dAxMjqF1xNcM64Dgju0KzsNI fDQAJKNnL8QejoDEShHvY1yBaY8IYyD/YHdFRhe2n7tWzs03Ob4NuQsMPlO0M+TQNhW279SnyRD sURqPZqPbF9cRqw16mYZw6YdsEn1AldKEJgzw6OM0T2wgVYPScpxiWJ0esA4xDQcJKA5rp7wTSZ JiDN4lpI+0cCZxgHwuEuHqfMX7XgqmPwqINpxiDbx2ewU9Uy1vzkDGjkonW1pxKn97Wpo2sXOsF 2nSRXwNpF/KSsaaWMz0wgUT0Rlr0ea+ X-Received: by 2002:a05:6a00:6c8d:b0:82c:7f08:8826 with SMTP id d2e1a72fcca58-82f8c8b3dbemr32397957b3a.17.1777123109845; Sat, 25 Apr 2026 06:18:29 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Nutty Liu , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 06/13] hw/riscv/aia: Provide number of irq sources Date: Sat, 25 Apr 2026 23:17:12 +1000 Message-ID: <20260425131721.932250-7-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42d; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42d.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123392257158500 Instead of hard coding the number of IRQ sources used by the APLIC pass it in as a parameter. This allows other machines to configure this as required. The maximum number of sources is 1023. Reviewed-by: Nutty Liu Reviewed-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Joel Stanley --- v3: Add r-b --- hw/riscv/aia.h | 3 +-- include/hw/riscv/virt.h | 1 + hw/riscv/aia.c | 8 ++++++-- hw/riscv/virt-acpi-build.c | 25 ++++++++++++++++--------- hw/riscv/virt.c | 2 ++ 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h index dbb833340276..5ad0a902be0d 100644 --- a/hw/riscv/aia.h +++ b/hw/riscv/aia.h @@ -11,11 +11,10 @@ =20 #include "exec/hwaddr.h" =20 -#define VIRT_IRQCHIP_NUM_SOURCES 96 - uint32_t imsic_num_bits(uint32_t count); =20 DeviceState *riscv_create_aia(bool msimode, int aia_guests, + uint16_t num_sources, const MemMapEntry *aplic_m, const MemMapEntry *aplic_s, const MemMapEntry *imsic_m, diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index ad858deb76ad..36a2def41096 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -64,6 +64,7 @@ struct RISCVVirtState { struct GPEXHost *gpex_host; OnOffAuto iommu_sys; uint16_t pci_iommu_bdf; + uint16_t num_sources; }; =20 enum { diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c index c724612a50a5..82ea9d48ea75 100644 --- a/hw/riscv/aia.c +++ b/hw/riscv/aia.c @@ -25,6 +25,7 @@ uint32_t imsic_num_bits(uint32_t count) } =20 DeviceState *riscv_create_aia(bool msimode, int aia_guests, + uint16_t num_sources, const MemMapEntry *aplic_m, const MemMapEntry *aplic_s, const MemMapEntry *imsic_m, @@ -38,6 +39,9 @@ DeviceState *riscv_create_aia(bool msimode, int aia_guest= s, DeviceState *aplic_s_dev =3D NULL; DeviceState *aplic_m_dev =3D NULL; =20 + /* The RISC-V Advanced Interrupt Architecture, Chapter 1.2. Limits */ + g_assert(num_sources <=3D 1023); + if (msimode) { if (!kvm_enabled()) { /* Per-socket M-level IMSICs */ @@ -66,7 +70,7 @@ DeviceState *riscv_create_aia(bool msimode, int aia_guest= s, aplic_m->size, (msimode) ? 0 : base_hartid, (msimode) ? 0 : hart_count, - VIRT_IRQCHIP_NUM_SOURCES, + num_sources, num_prio_bits, msimode, true, NULL); } @@ -77,7 +81,7 @@ DeviceState *riscv_create_aia(bool msimode, int aia_guest= s, aplic_s->size, (msimode) ? 0 : base_hartid, (msimode) ? 0 : hart_count, - VIRT_IRQCHIP_NUM_SOURCES, + num_sources, num_prio_bits, msimode, false, aplic_m_dev); =20 diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 145f8d92ad69..9ef3ef842a28 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -146,6 +146,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtSta= te *s) } =20 static void acpi_dsdt_add_plic_aplic(Aml *scope, uint8_t socket_count, + uint16_t num_sources, uint64_t mmio_base, uint64_t mmio_siz= e, const char *hid) { @@ -153,9 +154,12 @@ static void acpi_dsdt_add_plic_aplic(Aml *scope, uint8= _t socket_count, uint32_t gsi_base; uint8_t socket; =20 + /* The RISC-V Advanced Interrupt Architecture, Chapter 1.2. Limits */ + g_assert(num_sources <=3D 1023); + for (socket =3D 0; socket < socket_count; socket++) { plic_aplic_addr =3D mmio_base + mmio_size * socket; - gsi_base =3D VIRT_IRQCHIP_NUM_SOURCES * socket; + gsi_base =3D num_sources * socket; Aml *dev =3D aml_device("IC%.02X", socket); aml_append(dev, aml_name_decl("_HID", aml_string("%s", hid))); aml_append(dev, aml_name_decl("_UID", aml_int(socket))); @@ -474,10 +478,13 @@ static void build_dsdt(GArray *table_data, socket_count =3D riscv_socket_count(ms); =20 if (s->aia_type =3D=3D VIRT_AIA_TYPE_NONE) { - acpi_dsdt_add_plic_aplic(scope, socket_count, memmap[VIRT_PLIC].ba= se, - memmap[VIRT_PLIC].size, "RSCV0001"); + acpi_dsdt_add_plic_aplic(scope, socket_count, s->num_sources, + memmap[VIRT_PLIC].base, + memmap[VIRT_PLIC].size, + "RSCV0001"); } else { - acpi_dsdt_add_plic_aplic(scope, socket_count, memmap[VIRT_APLIC_S]= .base, + acpi_dsdt_add_plic_aplic(scope, socket_count, s->num_sources, + memmap[VIRT_APLIC_S].base, memmap[VIRT_APLIC_S].size, "RSCV0002"); } =20 @@ -494,15 +501,15 @@ static void build_dsdt(GArray *table_data, } else if (socket_count =3D=3D 2) { virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base, memmap[VIRT_VIRTIO].size, - VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0, + VIRTIO_IRQ + s->num_sources, 0, VIRTIO_COUNT); - acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES= ); + acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + s->num_sources); } else { virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base, memmap[VIRT_VIRTIO].size, - VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0, + VIRTIO_IRQ + s->num_sources, 0, VIRTIO_COUNT); - acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES= * 2); + acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + s->num_sources * 2); } =20 aml_append(dsdt, scope); @@ -581,7 +588,7 @@ static void build_madt(GArray *table_data, for (socket =3D 0; socket < riscv_socket_count(ms); socket++) { aplic_addr =3D s->memmap[VIRT_APLIC_S].base + s->memmap[VIRT_APLIC_S].size * socket; - gsi_base =3D VIRT_IRQCHIP_NUM_SOURCES * socket; + gsi_base =3D s->num_sources * socket; build_append_int_noprefix(table_data, 0x1A, 1); /* Type */ build_append_int_noprefix(table_data, 36, 1); /* Length */ build_append_int_noprefix(table_data, 1, 1); /* Version = */ diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index ce0fd6f50c4a..6c5bcd43dc54 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1548,6 +1548,7 @@ static void virt_machine_init(MachineState *machine) } else { s->irqchip[i] =3D riscv_create_aia(s->aia_type =3D=3D VIRT_AIA= _TYPE_APLIC_IMSIC, s->aia_guests, + s->num_sources, &s->memmap[VIRT_APLIC_M], &s->memmap[VIRT_APLIC_S], &s->memmap[VIRT_IMSIC_M], @@ -1691,6 +1692,7 @@ static void virt_machine_instance_init(Object *obj) s->oem_table_id =3D g_strndup(ACPI_BUILD_APPNAME8, 8); s->acpi =3D ON_OFF_AUTO_AUTO; s->iommu_sys =3D ON_OFF_AUTO_AUTO; + s->num_sources =3D VIRT_IRQCHIP_NUM_SOURCES; } =20 static char *virt_get_aia_guests(Object *obj, Error **errp) --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123370620757.1021257297098; Sat, 25 Apr 2026 06:22:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuP-0007Jv-64; Sat, 25 Apr 2026 09:18:57 -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 1wGcu7-000791-HC for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:40 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcu4-000092-Si for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:39 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-827270d50d4so7915814b3a.3 for ; Sat, 25 Apr 2026 06:18:36 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123115; x=1777727915; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=ds3iAenO+UXvZzQuaJ+VaWdAeqbbsN56XKEzFwIJ67o=; b=sOTieoT7iGDU5z/X2eGho6cXeW2q8rRF/oEPknmCsvYZ8ixoJSqsNySyZou4uSrTJY gNduhhsit9F2QndHq1/OM69kL7239F2GIwv08p9JfAPfkYEhXWzhdIefaMUz+pLS06TT TW4+3oXwsuwPRisoKMlON2WxnXfEBHberlCjHZlWTLmkKfEJKSgK5Ci377GXTAC5tvgb rlF8T1wJzaFM7pbO1y0VQV6kfIUb80owfdJ5JKXsrlG2RauKhE/4n5T0r8R6uJt6p0yT +gtMhzjL0y/OvuIA5lzzVwbnpes9IjmIbTn7wSFSyj78OPeFGRf5QYExZ9e/yGM7TvED qx4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123115; x=1777727915; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ds3iAenO+UXvZzQuaJ+VaWdAeqbbsN56XKEzFwIJ67o=; b=UgO+cfeQS/1l9Qcse5zER0BI3417hJb9Am+qodcBT+4RnFwLXXxhnnXx2aZwgVFfWr UnAmcjLkFtSo/MRknUMcZ52vT5sKa6klwUwMuh+oi/YwxmqT9nh+bantM5JH0lPgJoKb yepj+x5lf15Wz0a2dPvCdvucDGJPkFFyPd2zCutNINlGfOwq/mUmC7dBUVFvleKmlb2g OQgWHzfJEv6sX2dLXT+ze93naqwP1I0ls0ixG/KwRoDalynWFKYEmoPrtAJOU6MWwmAO /ZcqVbCN7s3WT/Owb6N7/wAgsyo5OnlNI4ByurEkkd6kexocbMV6fYEv7mP817jbPqe6 Dyzg== X-Forwarded-Encrypted: i=1; AFNElJ/xvr8oQd4N86K6OKobP5vdXGeACDi6RfYpVA0JUpre+fxEJ4SDDnBVO+f9MNG7aIekGZJhelZK8L+D@nongnu.org X-Gm-Message-State: AOJu0YzX7+hFOhRkFvBREYFXlfMBQt1+njs04KPsxjMqVPrsCnGx3w4g RqPfEnh0JS6PpB2HNg2xX6k8ac2NMTn4L2OxjcQkJnTY55qHXXvNp09o X-Gm-Gg: AeBDietmfPvEnFDcEfXnmKjkTkIIcVlSEQ/5dhEBcgkKTfRNt5HyoxqknAne2mOIk2m Z6A/UijE33AFYIUNV3HBgT1HNY5BKt50XxDArvzvh2qQde2YXDzSAIIz4hhzB5L26BFC05jBJ/S pZKLEB5SLaGxcY3wD2nNKEVepZhFtvK73FegsZ/lBJtjUzpA5470yttebrkhZPQRUhwN9ZVDdXA ZF/Kf+UZIn1undF1JG97YGATUZ0Fd328geC7ICN3ke3ZQK0QjD7JVlx/danvG5HCmaTwSZ7JMl/ yy+T2L3t2BTPXsMRT9yNURWb2x3vHPeYVMwL+WiFQN3IdjRWjrtJVFWNmTS81k3m5ftubSGY0Rs XbYgi2J75gAjYEbCE4vWiQ65uahrPk+kpw9XwMWdD/XEQspTLxs1ddZdYB7VosJxCIC/NRltrGZ OFpnEMf5MwdmHHu1gn7Ax1fCEnyHl5gnPnj8te7ldcGtq6PnJnjUarwauvUv6EsqUXYhScDHYZt Di0zu7lSezD+XIlA/6zfMJi7SNfSPp7f1x5SOLd0gY= X-Received: by 2002:a05:6a00:418b:b0:82c:7383:3745 with SMTP id d2e1a72fcca58-82f8c834458mr38844433b3a.19.1777123115541; Sat, 25 Apr 2026 06:18:35 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 07/13] target/riscv: tt-ascalon: Enable Zkr extension Date: Sat, 25 Apr 2026 23:17:13 +1000 Message-ID: <20260425131721.932250-8-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42c.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123372104158500 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin Ascalon supports Zkr and the SEED CSR. Signed-off-by: Nicholas Piggin Reviewed-by: Chao Liu Signed-off-by: Joel Stanley Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ce15a17c37de..69649462dd89 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3190,6 +3190,7 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .cfg.ext_zba =3D true, .cfg.ext_zbb =3D true, .cfg.ext_zbs =3D true, + .cfg.ext_zkr =3D true, .cfg.ext_zkt =3D true, .cfg.ext_zvbb =3D true, .cfg.ext_zvbc =3D true, --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123448064136.36095790321338; Sat, 25 Apr 2026 06:24:08 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuQ-0007OY-1r; Sat, 25 Apr 2026 09:18:58 -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 1wGcuC-00079p-QL for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:45 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcuB-0000EL-BP for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:44 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-82f8892d4d6so3835835b3a.0 for ; Sat, 25 Apr 2026 06:18:41 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123120; x=1777727920; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=3ojdWe8DEiJvFMFhtT9VbXuuzewxCBF2+DB34sWnmVg=; b=cRuOi+NS3nAzEd0zFrCYoRkvgb8med0693MCPR0E9UEv2r406axRZv/pD28mt4D2Ci ECsKBQGoNLyHbhSK+yVNBmf2+aifBp9l+ZUaUxdWm/rZNmppYYhYS2Zk+KjioMaeIFde xWeG28YWdIKEK7SJAw9ABrzFxGLwZ8pUu3ffmJdP110L1YxUg/8ZviX/n6JpuO2iLFLQ DDs0mqS9WVh4OFxVvHBoZQwqLDDg6FyTOFTo7W8jkbVME2jaselv8gHazHPSdnOL2ikz Zy6eYyyxieJ5VyxLLp3QoBxesd6jDoIUeyzurTp3cCC9utePfmBeJ2bwtJXS2u+Scp5/ M9Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123120; x=1777727920; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3ojdWe8DEiJvFMFhtT9VbXuuzewxCBF2+DB34sWnmVg=; b=SqZH7YUpgFx1/6lcIERWeBezrJJ0GgcTalg5i71IHabrUZ/eICrFd4nQPGd1f7eI5Q WiA/Jm6zoahZC4Q6dS3PChHur8cILdvPAswSnv7p/FcaS9T75UaheaVU5V6M979JI0rB Z6ooM7bL6Hq419v0bWRKVbdwkg2Bfx85Oh82cenAbxgs1LUXSWuNI06v5YGtftJD/Mgr awduC9a/us300rmXala8h4PBo7O/aQd1q6Hp3HxCO9w4vLKevW3O9B3M/414p5ewEiZJ aKyUVLL3Gcj4MOAzb9DxrM2DLcWhWKiuVNCsmY7wylgLZvWTnUzVijWU79kvIiE2acdx uOYw== X-Forwarded-Encrypted: i=1; AFNElJ/2/cmKNFSOzLNMkEMuqQabtuOiOZu80C4tNIKdGh7Ynitc01Za2Xmr0dMbkHH7n86heuK+h2taYd7G@nongnu.org X-Gm-Message-State: AOJu0Yy2oeu4U2gOO0+KPEck1EkLBVKEOKuE3GlNQgJo5bPNvdgLBNze wJHPl+5aUwazlcIjxZZmzDJHDW1bY4DBfUZfT3oO22VH0ouxkktUEZJA X-Gm-Gg: AeBDieuTKOb4BcUiO8K0qkJ88VfTEgaNDLFeD8Cytvk1yR2W+ed5cW79zHr+tVgMEvZ 6f6m69VZr3UwKaAopf/sUHotRc45U40fOs5KPA0os3TrUsGuBftWFcK/kxixSZ8vU6z2UkJd5ev yvwr2cCvLXS+OmnyhOjyMvi6b55npwy/dC+Sprt5WixPElnYddKbNGGCOzIfNW5w3ZppNaJB8/g gqcJ/YE6weEMFBukhKxhij6zY/7/D+BGQxQdTzeXMAP85eMyEUJ7nDzreNgajHHEwpUGMlSRhPo AHwv43Tew1b4SYRJxRMeUcSVP5VOlJHH1aBDeHSiqnHLD8eopYOA6BTByr5XtotZIMmnlsPf0AI LnsbmJvV6xiqEHw//gY3tqHz+Jnkgedv5nxv3JqyaUVMFVTb37Vws3hOqrqhjaWhnDYwvTJkG19 iUlWa0YT0FZmZ/5m+YpA1QLFOKTBMjeXSui5fDE5dCfdCQnK2QnDWU5pubSjE79NtZLg7pL2n7/ 2I02vlUpW2oOM+PSvwPQhLluydNhvyv X-Received: by 2002:a05:6a00:bb84:b0:82f:1d38:f693 with SMTP id d2e1a72fcca58-82f8c8e0f98mr36573368b3a.35.1777123120371; Sat, 25 Apr 2026 06:18:40 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 08/13] target/riscv: tt-ascalon: Enable Svadu by removing Svade Date: Sat, 25 Apr 2026 23:17:14 +1000 Message-ID: <20260425131721.932250-9-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42c.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123448574158500 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin Ascalon supports Svadu (hardware A/D bit updates). QEMU makes Svadu and Svade mutually exclusive, remove Svade so Ascalon comes up with Svadu working. Signed-off-by: Nicholas Piggin Signed-off-by: Joel Stanley Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 69649462dd89..97e35672649e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3204,7 +3204,6 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .cfg.ext_ssaia =3D true, .cfg.ext_sscofpmf =3D true, .cfg.ext_sstc =3D true, - .cfg.ext_svade =3D true, .cfg.ext_svinval =3D true, .cfg.ext_svnapot =3D true, .cfg.ext_svpbmt =3D true, --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123170071932.0365846082286; Sat, 25 Apr 2026 06:19:30 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuR-0007R4-7M; Sat, 25 Apr 2026 09:18:59 -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 1wGcuM-0007Hi-WE for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:56 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcuI-0000Gz-RE for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:54 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-82f1bfc9b8fso3999423b3a.1 for ; Sat, 25 Apr 2026 06:18:50 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123129; x=1777727929; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=C5hVR0szfLa1Sd9HchfmovkD60pPov32aK2HjckAgro=; b=k57YKe5HwPiJp8pgXowrW0lbE2MSpif9AG6iEC3/+yH/MY2o+tApdMOhEEUG9vtEvT eMbXEwTMcjLFunT/X7DQoa+30OsHo/dU/4Tir1EY9X2fBfEKqQ17qDRhM38vsOBsd6nI xV99IuKJBy7KRM+zqzBGZs+ZcLfjefJsRYXLEIuiDrVQhM96BoLF+zN2vrEw7OC7ruAu CcQGJVMF3Y/gJIrYFYC6lhbTF2hd884jLJSsRv0Blf8KLvsE+SdxdIuwVBgSf1qEoA78 PthJ2dW+87zdRO05zAiGUlfAP+XovMpfZsMUUu1qVFhvFsyR/KvxeJ9Gx+hFNCXEEQ0I 92iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123129; x=1777727929; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=C5hVR0szfLa1Sd9HchfmovkD60pPov32aK2HjckAgro=; b=enyiAyzDaElUpIRhLShVuG66TTLgCRL92HyQnGXWXmZBSasgJUcas+hihiHuxp3BC2 iRyb78N5cHPL7YiH2zynCVtKEo5wRZDYPbStH0+VmFPrCgJUVg3eIoE8v4pyuhf5V5vD F2qV/B0IYxejWW24q4nAyUArGgBlJlCUBJ/bIheimeRyk3yLxUBf1NFesVQmDqAd05cn 44+ZCy7tF105NTlJcWu3OwOqhqJ08Zjfc3nZkegYrMr+ZEnfmfHgKEDBUNbdnxaF7FrX bSOQEpPkATc4DwsC42kdbpZvFiTpyfQRckMDJaOkZRqR+U+bl1/o/OWc0inBDKP4j237 3AKA== X-Forwarded-Encrypted: i=1; AFNElJ9/9oQFOOQTLPwh9NvGLnSOVUI6DU090Xx/WxhfHoH95CFVw0GlAMmdyxcTb09cU4+YbnVXTMDkrIKg@nongnu.org X-Gm-Message-State: AOJu0YwmY1g9K5z1K9jj7J0fRqWHdnudXMzBYoQkPXxmXkNMDwKQZe9v 4J1e27NAwHKALJA3tzkObcnYQGh3H7eC0DmFZLkzHFMIx7FyJqtBL0hn X-Gm-Gg: AeBDiesb5WYmvkqXh1NvJC916wV2Y4uk6dttS/xZ2LuazOl9rRVQND1/sQrKjmymjje 9znTcE/1RDjwFhSbDdZG9N4QMzgusqe0VffSdFtY0h5MoPnmP9qC2P+XSSmz7GfaNxh78Qht84A Q0SVpH7s6xzgG/w7026MpGfdhT/8dXjwY31ho/K5/ktE54+Xgv84glVZhZ9Ots88cItp5e8iwhC uLKdktbRaR82pnxWjtqm/Q+3/8x1v2jaIXSBNNZ+gCPtvum/lBdVkrfwqwMSL2HmcEM45ZgIz5d +Z53glwsOndcsumCliDAg9sGVwFwdMofYA3X8W4GCMlYbc4paKj9iaABlj7UoQyVdeVIKTPF0xm m0L3xs04M0PmYhY4NUb77d6wEQELvxxbnLl03DTo00qYZCxXjNErpD4Lu+Ab0TWzgubl3yiXowS EAMNqIPsi8GOP91turRh0TMWiNE8lTdHjr9DVQ6gUrWndiQ/WvdQLDGOP4Acqav936IGFxE8fNi BmCzhHczQfRtUdxPto5veNsRBJFWRWi X-Received: by 2002:a05:6a00:14c2:b0:82f:8332:4933 with SMTP id d2e1a72fcca58-82f8c7dd158mr35501433b3a.3.1777123129353; Sat, 25 Apr 2026 06:18:49 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 09/13] hw/riscv: Add Tenstorrent Atlantis machine Date: Sat, 25 Apr 2026 23:17:15 +1000 Message-ID: <20260425131721.932250-10-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42b; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42b.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123171423158500 The Tenstorrent Atlantis platform is a collaboration between Tenstorrent and CoreLab Technology. It is based on the Atlantis SoC, which includes the Ascalon-X CPU and other IP from Tenstorrent and CoreLab Technology. The Tenstorrent Ascalon-X is a high performance 64-bit RVA23 compliant RISC-V CPU. This adds the machine containing serial console, interrupt controllers and device tree support. qemu-system-riscv64 -M tt-atlantis -m 512M \ -kernel Image -initrd rootfs.cpio -nographic If there is no kernel provided the simple payload is loaded to avoid OpenSBI hanging with no messages. Co-Developed-by: Nicholas Piggin Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Chao Liu Signed-off-by: Joel Stanley --- v4: - Clean up unused PCIe defines v3: - Merge simple payload change into this patch - Fix fw_cfg_init_mem_dma API change - Clean up irqchip #defines - Add Michael and Nick as reviewers - create_fdt_pmu was copying RISCVCPU by value - Remove unused platform_bus remove unused defines Signed-off-by: Joel Stanley --- MAINTAINERS | 11 + docs/system/riscv/tt_atlantis.rst | 38 ++ docs/system/target-riscv.rst | 1 + include/hw/riscv/tt_atlantis.h | 61 +++ hw/riscv/tt_atlantis.c | 632 ++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 15 + hw/riscv/meson.build | 1 + 7 files changed, 759 insertions(+) create mode 100644 docs/system/riscv/tt_atlantis.rst create mode 100644 include/hw/riscv/tt_atlantis.h create mode 100644 hw/riscv/tt_atlantis.c diff --git a/MAINTAINERS b/MAINTAINERS index e1942a86eba5..635a380945fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1760,6 +1760,17 @@ F: hw/*/*sifive*.c F: include/hw/*/*sifive*.h F: tests/functional/test_riscv64_sifive_u.py =20 +Tenstorrent Machines +M: Joel Stanley +R: Nicholas Piggin +R: Michael Ellerman +L: qemu-riscv@nongnu.org +S: Supported +F: docs/system/riscv/tt_*.rst +F: hw/riscv/tt_*.c +F: hw/riscv/aia.[ch] +F: include/hw/riscv/tt_*.h + AMD Microblaze-V Generic Board M: Sai Pavan Boddu S: Maintained diff --git a/docs/system/riscv/tt_atlantis.rst b/docs/system/riscv/tt_atlan= tis.rst new file mode 100644 index 000000000000..640cabf7b046 --- /dev/null +++ b/docs/system/riscv/tt_atlantis.rst @@ -0,0 +1,38 @@ +Tenstorrent Atlantis (``tt-atlantis``) +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The Tenstorrent Atlantis platform is a collaboration between Tenstorrent +and CoreLab Technology. It is based on the Atlantis SoC, which includes +the Ascalon-X CPU and other IP from Tenstorrent and CoreLab Technology. + +The Tenstorrent Ascalon-X is a high performance 64-bit RVA23 compliant +RISC-V CPU. + +Features +-------- + +* 8-core Ascalon-X CPU Cluster +* Dual x32 LPDDR5 @ 6400 MT/s +* RISC-V compliant Advanced Interrupt Architecture +* PCIe Gen4 +* RISC-V compliant IOMMU +* GPU and Video subsystem +* 2x USB3.1 & 2x USB2.0 +* 2x 1GbE Ethernet +* 2x eMMC5.1/SDIO3.0 storage +* Extensive connectivity (SPI, I2C, UART, GPIO, CANFD) + +Note: the QEMU tt-atlantis machine does not model the platform +exactly or all devices, but it is undergoing improvement. + +Supported software +------------------ + +The Tenstorrent Ascalon CPUs avoid proprietary or non-standard +extensions, so compatibility with existing software is generally +good. The QEMU tt-atlantis machine works with upstream OpenSBI +and Linux with default configurations. + +The development board hardware will require some implementation +specific setup in firmware which is being developed and may +become a requirement or option for the tt-atlantis machine. diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 3ad5d1ddafbb..a8e6b3342186 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -71,6 +71,7 @@ undocumented; you can get a complete list by running riscv/mips riscv/shakti-c riscv/sifive_u + riscv/tt_atlantis riscv/virt riscv/xiangshan-kunminghu =20 diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h new file mode 100644 index 000000000000..9fe50d9c9040 --- /dev/null +++ b/include/hw/riscv/tt_atlantis.h @@ -0,0 +1,61 @@ +/* + * Tenstorrent Atlantis RISC-V System on Chip + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright 2025 Tenstorrent, Joel Stanley + */ + +#ifndef HW_RISCV_TT_ATLANTIS_H +#define HW_RISCV_TT_ATLANTIS_H + +#include "hw/core/boards.h" +#include "hw/core/sysbus.h" +#include "hw/intc/riscv_imsic.h" +#include "hw/riscv/riscv_hart.h" + +#define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis") +OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE) + +struct TTAtlantisState { + /*< private >*/ + MachineState parent; + + /*< public >*/ + Notifier machine_done; + FWCfgState *fw_cfg; + const MemMapEntry *memmap; + + RISCVHartArrayState soc; + DeviceState *irqchip; + + int fdt_size; +}; + +enum { + TT_ATL_SYSCON_IRQ =3D 10, + TT_ATL_UART0_IRQ =3D 38, + TT_ATL_UART1_IRQ =3D 39, + TT_ATL_UART2_IRQ =3D 40, + TT_ATL_UART3_IRQ =3D 41, + TT_ATL_UART4_IRQ =3D 42, +}; + +enum { + TT_ATL_ACLINT, + TT_ATL_BOOTROM, + TT_ATL_DDR_LO, + TT_ATL_DDR_HI, + TT_ATL_FW_CFG, + TT_ATL_I2C0, + TT_ATL_MAPLIC, + TT_ATL_MIMSIC, + TT_ATL_SAPLIC, + TT_ATL_SIMSIC, + TT_ATL_SYSCON, + TT_ATL_TIMER, + TT_ATL_UART0, + TT_ATL_WDT0, +}; + +#endif diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c new file mode 100644 index 000000000000..5b66d7e95bb9 --- /dev/null +++ b/hw/riscv/tt_atlantis.c @@ -0,0 +1,632 @@ +/* + * Tenstorrent Atlantis RISC-V System on Chip + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright 2025 Tenstorrent, Joel Stanley + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qemu/units.h" + +#include "hw/core/boards.h" +#include "hw/core/loader.h" +#include "hw/core/sysbus.h" + +#include "target/riscv/cpu.h" +#include "target/riscv/pmu.h" + +#include "hw/riscv/boot.h" +#include "hw/riscv/numa.h" +#include "hw/riscv/riscv_hart.h" + +#include "hw/char/serial-mm.h" +#include "hw/intc/riscv_aclint.h" +#include "hw/intc/riscv_aplic.h" +#include "hw/misc/pvpanic.h" + +#include "system/system.h" +#include "system/device_tree.h" + +#include "hw/riscv/tt_atlantis.h" + +#include "aia.h" + +#define TT_IRQCHIP_NUM_MSIS 255 +#define TT_IRQCHIP_NUM_SOURCES 128 +#define TT_IRQCHIP_NUM_PRIO_BITS 3 +#define TT_IRQCHIP_GUESTS 7 /* aia_guests */ + +#define FDT_PCI_ADDR_CELLS 3 +#define FDT_PCI_INT_CELLS 1 +#define FDT_MAX_INT_CELLS 2 +#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \ + 1 + FDT_MAX_INT_CELLS) + +#define TT_ACLINT_MTIME_SIZE 0x8050 +#define TT_ACLINT_MTIME 0x0 +#define TT_ACLINT_MTIMECMP 0x8000 +#define TT_ACLINT_TIMEBASE_FREQ 1000000000 + +static const MemMapEntry tt_atlantis_memmap[] =3D { + /* Keep sorted with :'<,'>!sort -g -k 4 */ + [TT_ATL_DDR_LO] =3D { 0x00000000, 0x80000000 }, + [TT_ATL_BOOTROM] =3D { 0x80000000, 0x2000 }, + [TT_ATL_FW_CFG] =3D { 0x80002000, 0xff }, /* qemu o= nly */ + [TT_ATL_SYSCON] =3D { 0x80004000, 0x1000 }, /* qemu o= nly */ + [TT_ATL_MIMSIC] =3D { 0xa0000000, 0x200000 }, + [TT_ATL_ACLINT] =3D { 0xa2180000, 0x10000 }, + [TT_ATL_SIMSIC] =3D { 0xa4000000, 0x200000 }, + [TT_ATL_TIMER] =3D { 0xa8020000, 0x10000 }, + [TT_ATL_WDT0] =3D { 0xa8030000, 0x10000 }, + [TT_ATL_UART0] =3D { 0xb0100000, 0x10000 }, + [TT_ATL_MAPLIC] =3D { 0xcc000000, 0x4000000 }, + [TT_ATL_SAPLIC] =3D { 0xe8000000, 0x4000000 }, + [TT_ATL_DDR_HI] =3D { 0x100000000, 0x1000000000 }, +}; + +static uint32_t next_phandle(void) +{ + static uint32_t phandle =3D 1; + return phandle++; +} + +static void create_fdt_cpus(TTAtlantisState *s, uint32_t *intc_phandles) +{ + uint32_t cpu_phandle; + void *fdt =3D MACHINE(s)->fdt; + + for (int cpu =3D s->soc.num_harts - 1; cpu >=3D 0; cpu--) { + RISCVCPU *cpu_ptr =3D &s->soc.harts[cpu]; + g_autofree char *cpu_name =3D NULL; + g_autofree char *intc_name =3D NULL; + + cpu_phandle =3D next_phandle(); + + cpu_name =3D g_strdup_printf("/cpus/cpu@%d", s->soc.hartid_base + = cpu); + qemu_fdt_add_subnode(fdt, cpu_name); + + qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv57"); + + riscv_isa_write_fdt(cpu_ptr, fdt, cpu_name); + + qemu_fdt_setprop_cell(fdt, cpu_name, "riscv,cbom-block-size", + cpu_ptr->cfg.cbom_blocksize); + + qemu_fdt_setprop_cell(fdt, cpu_name, "riscv,cboz-block-size", + cpu_ptr->cfg.cboz_blocksize); + + qemu_fdt_setprop_cell(fdt, cpu_name, "riscv,cbop-block-size", + cpu_ptr->cfg.cbop_blocksize); + + qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv"); + qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); + qemu_fdt_setprop_cell(fdt, cpu_name, "reg", s->soc.hartid_base + c= pu); + qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); + qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle); + + intc_phandles[cpu] =3D next_phandle(); + + intc_name =3D g_strdup_printf("%s/interrupt-controller", cpu_name); + qemu_fdt_add_subnode(fdt, intc_name); + qemu_fdt_setprop_cell(fdt, intc_name, "phandle", + intc_phandles[cpu]); + qemu_fdt_setprop_string(fdt, intc_name, "compatible", + "riscv,cpu-intc"); + qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1); + } +} + +static void create_fdt_memory_node(TTAtlantisState *s, + hwaddr addr, hwaddr size) +{ + void *fdt =3D MACHINE(s)->fdt; + g_autofree char *name =3D g_strdup_printf("/memory@%"HWADDR_PRIX, addr= ); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, addr, 2, size); + qemu_fdt_setprop_string(fdt, name, "device_type", "memory"); +} + +static void create_fdt_memory(TTAtlantisState *s) +{ + hwaddr size_lo =3D MACHINE(s)->ram_size; + hwaddr size_hi =3D 0; + + if (size_lo > s->memmap[TT_ATL_DDR_LO].size) { + size_lo =3D s->memmap[TT_ATL_DDR_LO].size; + size_hi =3D MACHINE(s)->ram_size - size_lo; + } + + create_fdt_memory_node(s, s->memmap[TT_ATL_DDR_LO].base, size_lo); + if (size_hi) { + /* + * The first part of the HI address is aliased at the LO address + * so do not include that as usable memory. Is there any way + * (or good reason) to describe that aliasing 2GB with DT? + */ + create_fdt_memory_node(s, s->memmap[TT_ATL_DDR_HI].base + size_lo, + size_hi); + } +} + +static void create_fdt_aclint(TTAtlantisState *s, uint32_t *intc_phandles) +{ + void *fdt =3D MACHINE(s)->fdt; + g_autofree char *name =3D NULL; + g_autofree uint32_t *aclint_mtimer_cells =3D NULL; + uint32_t aclint_cells_size; + hwaddr addr; + + aclint_mtimer_cells =3D g_new0(uint32_t, s->soc.num_harts * 2); + + for (int cpu =3D 0; cpu < s->soc.num_harts; cpu++) { + aclint_mtimer_cells[cpu * 2 + 0] =3D cpu_to_be32(intc_phandles[cpu= ]); + aclint_mtimer_cells[cpu * 2 + 1] =3D cpu_to_be32(IRQ_M_TIMER); + } + aclint_cells_size =3D s->soc.num_harts * sizeof(uint32_t) * 2; + + addr =3D s->memmap[TT_ATL_ACLINT].base; + + name =3D g_strdup_printf("/soc/mtimer@%"HWADDR_PRIX, addr); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,aclint-mtimer"= ); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, addr + TT_ACLINT_MTIME, + 2, 0x1000, + 2, addr + TT_ACLINT_MTIMECMP, + 2, 0x1000); + qemu_fdt_setprop(fdt, name, "interrupts-extended", + aclint_mtimer_cells, aclint_cells_size); +} + +static void create_fdt_one_imsic(void *fdt, const MemMapEntry *mem, int cp= us, + uint32_t *intc_phandles, uint32_t msi_pha= ndle, + int irq_line, uint32_t imsic_guest_bits) +{ + g_autofree char *name =3D NULL; + g_autofree uint32_t *imsic_cells =3D g_new0(uint32_t, cpus * 2); + + for (int cpu =3D 0; cpu < cpus; cpu++) { + imsic_cells[cpu * 2 + 0] =3D cpu_to_be32(intc_phandles[cpu]); + imsic_cells[cpu * 2 + 1] =3D cpu_to_be32(irq_line); + } + + name =3D g_strdup_printf("/soc/interrupt-controller@%"HWADDR_PRIX, mem= ->base); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,imsics"); + + qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0); + qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0); + qemu_fdt_setprop(fdt, name, "msi-controller", NULL, 0); + qemu_fdt_setprop(fdt, name, "interrupts-extended", + imsic_cells, sizeof(uint32_t) * cpus * 2); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop_cell(fdt, name, "riscv,num-ids", TT_IRQCHIP_NUM_MSIS); + + if (imsic_guest_bits) { + qemu_fdt_setprop_cell(fdt, name, "riscv,guest-index-bits", + imsic_guest_bits); + } + qemu_fdt_setprop_cell(fdt, name, "phandle", msi_phandle); +} + +static void create_fdt_one_aplic(void *fdt, + const MemMapEntry *mem, + uint32_t msi_phandle, + uint32_t *intc_phandles, + uint32_t aplic_phandle, + uint32_t aplic_child_phandle, + int irq_line, int num_harts) +{ + g_autofree char *name =3D + g_strdup_printf("/soc/interrupt-controller@%"HWADDR_PRIX, mem->bas= e); + g_autofree uint32_t *aplic_cells =3D g_new0(uint32_t, num_harts * 2); + + for (int cpu =3D 0; cpu < num_harts; cpu++) { + aplic_cells[cpu * 2 + 0] =3D cpu_to_be32(intc_phandles[cpu]); + aplic_cells[cpu * 2 + 1] =3D cpu_to_be32(irq_line); + } + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,aplic"); + qemu_fdt_setprop_cell(fdt, name, "#address-cells", 0); + qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 2); + qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0); + + qemu_fdt_setprop(fdt, name, "interrupts-extended", + aplic_cells, num_harts * sizeof(uint32_t) * 2); + qemu_fdt_setprop_cell(fdt, name, "msi-parent", msi_phandle); + + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop_cell(fdt, name, "riscv,num-sources", + TT_IRQCHIP_NUM_SOURCES); + + if (aplic_child_phandle) { + qemu_fdt_setprop_cell(fdt, name, "riscv,children", + aplic_child_phandle); + qemu_fdt_setprop_cells(fdt, name, "riscv,delegation", + aplic_child_phandle, 1, TT_IRQCHIP_NUM_SOUR= CES); + } + + qemu_fdt_setprop_cell(fdt, name, "phandle", aplic_phandle); +} + +static void create_fdt_pmu(TTAtlantisState *s) +{ + g_autofree char *pmu_name =3D g_strdup_printf("/pmu"); + void *fdt =3D MACHINE(s)->fdt; + RISCVCPU *hart =3D &s->soc.harts[0]; + + qemu_fdt_add_subnode(fdt, pmu_name); + qemu_fdt_setprop_string(fdt, pmu_name, "compatible", "riscv,pmu"); + riscv_pmu_generate_fdt_node(fdt, hart->pmu_avail_ctrs, pmu_name); +} + +static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap, + uint32_t aplic_s_phandle, + uint32_t imsic_s_phandle) +{ + MachineState *ms =3D MACHINE(s); + void *fdt =3D MACHINE(s)->fdt; + g_autofree uint32_t *intc_phandles =3D NULL; + + qemu_fdt_add_subnode(fdt, "/cpus"); + qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", + TT_ACLINT_TIMEBASE_FREQ); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); + + intc_phandles =3D g_new0(uint32_t, ms->smp.cpus); + + create_fdt_cpus(s, intc_phandles); + + create_fdt_memory(s); + + create_fdt_aclint(s, intc_phandles); + + /* M-level IMSIC node */ + uint32_t msi_m_phandle =3D next_phandle(); + create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_MIMSIC], ms->smp.cpus, + intc_phandles, msi_m_phandle, + IRQ_M_EXT, 0); + + /* S-level IMSIC node */ + create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_SIMSIC], ms->smp.cpus, + intc_phandles, imsic_s_phandle, + IRQ_S_EXT, imsic_num_bits(TT_IRQCHIP_GUESTS + 1)); + + uint32_t aplic_m_phandle =3D next_phandle(); + + /* M-level APLIC node */ + create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_MAPLIC], + msi_m_phandle, intc_phandles, + aplic_m_phandle, aplic_s_phandle, + IRQ_M_EXT, s->soc.num_harts); + + /* S-level APLIC node */ + create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_SAPLIC], + imsic_s_phandle, intc_phandles, + aplic_s_phandle, 0, + IRQ_S_EXT, s->soc.num_harts); +} + +static void create_fdt_reset(void *fdt, const MemMapEntry *mem) +{ + uint32_t syscon_phandle =3D next_phandle(); + char *name; + + name =3D g_strdup_printf("/soc/syscon@%"HWADDR_PRIX, mem->base); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "syscon"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop_cell(fdt, name, "phandle", syscon_phandle); + g_free(name); + + name =3D g_strdup_printf("/poweroff"); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-poweroff"); + qemu_fdt_setprop_cell(fdt, name, "regmap", syscon_phandle); + qemu_fdt_setprop_cell(fdt, name, "offset", 0x0); + qemu_fdt_setprop_cell(fdt, name, "value", PVPANIC_SHUTDOWN); + g_free(name); +} + +static void create_fdt_uart(void *fdt, const MemMapEntry *mem, int irq, + int irqchip_phandle) +{ + g_autofree char *name =3D g_strdup_printf("/soc/serial@%"HWADDR_PRIX, + mem->base); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop_cell(fdt, name, "reg-shift", 2); + qemu_fdt_setprop_cell(fdt, name, "reg-io-width", 4); + qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 3686400); + qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irqchip_phandle); + qemu_fdt_setprop_cells(fdt, name, "interrupts", irq, 0x4); + + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name); + qemu_fdt_setprop_string(fdt, "/aliases", "serial0", name); +} + +static void create_fdt_fw_cfg(void *fdt, const MemMapEntry *mem) +{ + g_autofree char *name =3D g_strdup_printf("/fw-cfg@%"HWADDR_PRIX, mem-= >base); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "qemu,fw-cfg-mmio"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0); +} + +static void finalize_fdt(TTAtlantisState *s) +{ + uint32_t aplic_s_phandle =3D next_phandle(); + uint32_t imsic_s_phandle =3D next_phandle(); + void *fdt =3D MACHINE(s)->fdt; + + create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle); + + /* + * We want to do this, but the Linux aplic driver was broken before v6= .16 + * + * qemu_fdt_setprop_cell(MACHINE(s)->fdt, "/soc", "interrupt-parent", + * aplic_s_phandle); + */ + + create_fdt_reset(fdt, &s->memmap[TT_ATL_SYSCON]); + + create_fdt_uart(fdt, &s->memmap[TT_ATL_UART0], TT_ATL_UART0_IRQ, + aplic_s_phandle); +} + +static void create_fdt(TTAtlantisState *s) +{ + MachineState *ms =3D MACHINE(s); + uint8_t rng_seed[32]; + g_autofree char *name =3D NULL; + void *fdt; + + fdt =3D create_device_tree(&s->fdt_size); + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + ms->fdt =3D fdt; + + qemu_fdt_setprop_string(fdt, "/", "model", + "Tenstorrent Atlantis RISC-V Machine"); + qemu_fdt_setprop_string(fdt, "/", "compatible", "tenstorrent,atlantis"= ); + qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); + + qemu_fdt_add_subnode(fdt, "/soc"); + qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); + qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus"); + qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); + + qemu_fdt_add_subnode(fdt, "/chosen"); + + /* Pass seed to RNG */ + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); + qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed= )); + + qemu_fdt_add_subnode(fdt, "/aliases"); + + create_fdt_fw_cfg(fdt, &s->memmap[TT_ATL_FW_CFG]); + create_fdt_pmu(s); +} + +static DeviceState *create_reboot_device(const MemMapEntry *mem) +{ + DeviceState *dev =3D qdev_new(TYPE_PVPANIC_MMIO_DEVICE); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + qdev_prop_set_uint32(dev, "events", PVPANIC_SHUTDOWN | PVPANIC_PANICKE= D); + + sysbus_realize_and_unref(sbd, &error_fatal); + sysbus_mmio_map(sbd, 0, mem->base); + + return dev; +} + +static FWCfgState *create_fw_cfg(const MemMapEntry *mem, int num_cpus) +{ + FWCfgState *fw_cfg; + hwaddr base =3D mem->base; + + fw_cfg =3D fw_cfg_init_mem_dma(base + 8, base, 8, base + 16, + &address_space_memory); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, num_cpus); + + return fw_cfg; +} + +static void tt_atlantis_machine_done(Notifier *notifier, void *data) +{ + TTAtlantisState *s =3D container_of(notifier, TTAtlantisState, machine= _done); + MachineState *machine =3D MACHINE(s); + hwaddr start_addr =3D s->memmap[TT_ATL_DDR_LO].base; + hwaddr mem_size; + target_ulong firmware_end_addr, kernel_start_addr; + const char *firmware_name =3D riscv_default_firmware_name(&s->soc); + uint64_t fdt_load_addr; + uint64_t kernel_entry; + RISCVBootInfo boot_info; + + /* + * A user provided dtb must include everything, including + * dynamic sysbus devices. Our FDT needs to be finalized. + */ + if (machine->dtb =3D=3D NULL) { + finalize_fdt(s); + } + + mem_size =3D machine->ram_size; + if (mem_size > s->memmap[TT_ATL_DDR_LO].size) { + mem_size =3D s->memmap[TT_ATL_DDR_LO].size; + } + riscv_boot_info_init_discontig_mem(&boot_info, &s->soc, + s->memmap[TT_ATL_DDR_LO].base, + mem_size); + + firmware_end_addr =3D riscv_find_and_load_firmware(machine, &boot_info, + firmware_name, + &start_addr, NULL); + + kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, + firmware_end_addr); + if (machine->kernel_filename) { + riscv_load_kernel(machine, &boot_info, kernel_start_addr, + true, NULL); + } else { + riscv_setup_halting_payload(&boot_info, kernel_start_addr); + } + kernel_entry =3D boot_info.image_low_addr; + + fdt_load_addr =3D riscv_compute_fdt_addr(s->memmap[TT_ATL_DDR_LO].base, + s->memmap[TT_ATL_DDR_LO].size, + machine, &boot_info); + riscv_load_fdt(fdt_load_addr, machine->fdt); + + /* load the reset vector */ + riscv_setup_rom_reset_vec(machine, &s->soc, start_addr, + s->memmap[TT_ATL_BOOTROM].base, + s->memmap[TT_ATL_BOOTROM].size, + kernel_entry, + fdt_load_addr); + +} + +static void tt_atlantis_machine_init(MachineState *machine) +{ + TTAtlantisState *s =3D TT_ATLANTIS_MACHINE(machine); + + MemoryRegion *system_memory =3D get_system_memory(); + MemoryRegion *ram_hi =3D g_new(MemoryRegion, 1); + MemoryRegion *ram_lo =3D g_new(MemoryRegion, 1); + MemoryRegion *bootrom =3D g_new(MemoryRegion, 1); + ram_addr_t lo_ram_size, hi_ram_size; + int hart_count =3D machine->smp.cpus; + int base_hartid =3D 0; + + s->memmap =3D tt_atlantis_memmap; + + object_initialize_child(OBJECT(machine), "soc", &s->soc, + TYPE_RISCV_HART_ARRAY); + object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type, + &error_abort); + object_property_set_int(OBJECT(&s->soc), "hartid-base", base_hartid, + &error_abort); + object_property_set_int(OBJECT(&s->soc), "num-harts", hart_count, + &error_abort); + object_property_set_int(OBJECT(&s->soc), "resetvec", + s->memmap[TT_ATL_BOOTROM].base, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); + + s->irqchip =3D riscv_create_aia(true, TT_IRQCHIP_GUESTS, + TT_IRQCHIP_NUM_SOURCES, + &s->memmap[TT_ATL_MAPLIC], + &s->memmap[TT_ATL_SAPLIC], + &s->memmap[TT_ATL_MIMSIC], + &s->memmap[TT_ATL_SIMSIC], + 0, base_hartid, hart_count, + TT_IRQCHIP_NUM_MSIS, + TT_IRQCHIP_NUM_PRIO_BITS); + + riscv_aclint_mtimer_create(s->memmap[TT_ATL_ACLINT].base, + TT_ACLINT_MTIME_SIZE, + base_hartid, hart_count, + TT_ACLINT_MTIMECMP, + TT_ACLINT_MTIME, + TT_ACLINT_TIMEBASE_FREQ, true); + + /* DDR */ + + /* The high address covers all of RAM, the low address just the first = 2GB */ + lo_ram_size =3D s->memmap[TT_ATL_DDR_LO].size; + hi_ram_size =3D s->memmap[TT_ATL_DDR_HI].size; + if (machine->ram_size > hi_ram_size) { + char *sz =3D size_to_str(hi_ram_size); + error_report("RAM size is too large, maximum is %s", sz); + g_free(sz); + exit(EXIT_FAILURE); + } + + memory_region_init_alias(ram_lo, OBJECT(machine), "ram.low", machine->= ram, + 0, lo_ram_size); + memory_region_init_alias(ram_hi, OBJECT(machine), "ram.high", machine-= >ram, + 0, hi_ram_size); + memory_region_add_subregion(system_memory, + s->memmap[TT_ATL_DDR_LO].base, ram_lo); + memory_region_add_subregion(system_memory, + s->memmap[TT_ATL_DDR_HI].base, ram_hi); + + /* Boot ROM */ + memory_region_init_rom(bootrom, NULL, "tt-atlantis.bootrom", + s->memmap[TT_ATL_BOOTROM].size, &error_fatal); + memory_region_add_subregion(system_memory, s->memmap[TT_ATL_BOOTROM].b= ase, + bootrom); + + /* + * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the + * device tree cannot be altered and we get FDT_ERR_NOSPACE. + */ + s->fw_cfg =3D create_fw_cfg(&s->memmap[TT_ATL_FW_CFG], machine->smp.cp= us); + rom_set_fw(s->fw_cfg); + + /* Reboot and exit */ + create_reboot_device(&s->memmap[TT_ATL_SYSCON]); + + /* UART */ + serial_mm_init(system_memory, s->memmap[TT_ATL_UART0].base, 2, + qdev_get_gpio_in(s->irqchip, TT_ATL_UART0_IRQ), + 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); + + /* Load or create device tree */ + if (machine->dtb) { + machine->fdt =3D load_device_tree(machine->dtb, &s->fdt_size); + if (!machine->fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + } else { + create_fdt(s); + } + + s->machine_done.notify =3D tt_atlantis_machine_done; + qemu_add_machine_init_done_notifier(&s->machine_done); +} + +static void tt_atlantis_machine_class_init(ObjectClass *oc, const void *da= ta) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "Tenstorrent Atlantis RISC-V SoC"; + mc->init =3D tt_atlantis_machine_init; + mc->max_cpus =3D 8; + mc->default_cpus =3D 8; + mc->default_ram_size =3D 2 * GiB; + mc->default_cpu_type =3D TYPE_RISCV_CPU_TT_ASCALON; + mc->block_default_type =3D IF_VIRTIO; + mc->no_cdrom =3D 1; + mc->default_ram_id =3D "tt_atlantis.ram"; +} + +static const TypeInfo tt_atlantis_types[] =3D { + { + .name =3D MACHINE_TYPE_NAME("tt-atlantis"), + .parent =3D TYPE_MACHINE, + .class_init =3D tt_atlantis_machine_class_init, + .instance_size =3D sizeof(TTAtlantisState), + }, +}; + +DEFINE_TYPES(tt_atlantis_types) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0222c93f878b..0601ae1a7494 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -120,6 +120,21 @@ config SPIKE select RISCV_ACLINT select SIFIVE_PLIC =20 +config TENSTORRENT + bool + default y + depends on RISCV64 + imply PCI_DEVICES + imply TEST_DEVICES + select DEVICE_TREE + select RISCV_NUMA + select PVPANIC_MMIO + select SERIAL_MM + select RISCV_ACLINT + select RISCV_APLIC + select RISCV_IMSIC + select FW_CFG_DMA + config XIANGSHAN_KUNMINGHU bool default y diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index e53c180d0d10..026e79591f4b 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -9,6 +9,7 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifiv= e_e.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfs= oc.c')) +riscv_ss.add(when: 'CONFIG_TENSTORRENT', if_true: files('tt_atlantis.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files( 'riscv-iommu.c', 'riscv-iommu-pci.c', 'riscv-iommu-sys.c', 'riscv-iommu-h= pm.c')) --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123246962697.4242480765582; Sat, 25 Apr 2026 06:20:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuU-0007To-WD; Sat, 25 Apr 2026 09:19:03 -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 1wGcuT-0007Sd-3g for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:01 -0400 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcuQ-0000Hv-Hp for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:00 -0400 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-82f8cebc935so3831500b3a.0 for ; Sat, 25 Apr 2026 06:18:58 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:18:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123137; x=1777727937; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=vALn2gzhdl8xVZ/Nk4kuywsAYoGFx0DePWWWeklTFI0=; b=q9znpy1DEx46ckjpZMZEcxZQDxkRSz7OHhSmmQK8YRINzhQQpsgIQLbBXkrhvdedeE RZE7Pi+SqEpZSpRKoYGazqHwTW7YWLB/KF1Bzpz7nRNOFJsR9Kmj+L2fP/3X/rDXQEky wCQDGxzURtnQ4wLlBwe1uPQfDqAszrv/ac/VsJKFJMzOCdf+HaULMoMBGxlT/GsAEWGZ eoFNCuL/p7IIxSnaAptMufoh1mnINS/ggfg3Nf8bHNGqyvPXKBXFnTISF9coqW5h3pJy fvUCUWeD1iOub7VeL7VKwFHlL5WcdZqZfbDAkn3570BqberE3DdHjYIvo3RQ21yFhNLj hZug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123137; x=1777727937; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vALn2gzhdl8xVZ/Nk4kuywsAYoGFx0DePWWWeklTFI0=; b=AyV68MobOwcK8Brd+/1BrRBfslQ+cPcfeVLmb+RbLJiNfsZKRcjVwfUUv8zQSt4Sg8 H4EswNmlg4Jmqa1TNc+daZ3oHRBej75dyOpMPd/D4MoEjDOywAkK4FAltpXSGYVE1qff bSQw+aNfyTy7he/TnrLBF8/Nii+vpDNyRwTpQa73NOBDeRbyj8qX//QkX5aYU8oMzDTA BCu0cs51KVmJP2DGKJZ0UOMmxQlvGqyNXNh8twWH9vqwGn80esoBP80WTCT/G4rlURDO JG9BoNBHKkv9jlkcqXIpvW65gMH1w50o85H49QnlPIhF7V9X5V9M+J5B8oYUrcaN3YR0 mb8A== X-Forwarded-Encrypted: i=1; AFNElJ/puuqP8ICrc+OfPI/2ts3e+lpiKoMFfQQbyeToTOEvmaaYYiytEacF+y/ReGiLQbl/cEsqG906ZvZV@nongnu.org X-Gm-Message-State: AOJu0YwVCWIfdRqSvt0zHMlK1BjLdFJ56WVNs6QmjhtuQyX5qNpBLdX/ OMLM8lc+PmpfRPlmDp1M9AHhtKa43WE9Fdq/phK5egmazsxI7k/S3RSo X-Gm-Gg: AeBDiev0N87PKM6JV38D7hD8sZak14hzh+/r7J85sxsnTzW6DXLR714WRXMbPhVhfFT a2OP/ZQnHbbuaniLQbijGJiKzZsDv1h8W2K7nAe/yop00T3LXPjzWwRXiMknf/5phMf6FNTifaq ELaDaBHBq1Hxn90B2j+t2zyqLQ9LMqxAuB41Q4uBoPWEBHKu8BMzOgW+vV6ZAF8eenGIHKpKsG8 dPclm7+F8U2FouMlZ8srbwBOlZVgTCWrW9dwmKk9TYLlZNAKbgjXHFKoLD+v5D0neeEn/5bGDMe A7mtb8TPkNqbVJFlsotp18pq85x7EST+OFgErHos3z1IkEc7tvuYeHmqqxWmjpQbrf/o/Ux7RTY fxCoxw77PRrUIo2KTsF8nxplYxkyLlpTBhs20t9OElIH//Hq7tTI/rjnAXufTMw6mo6dW2mqomH +gXtVPEX2pZpqlpALKSSLuUh0PLmzP89jA5Vij0NHFODxXDCyxMI4fVhon9yeFld0ozKQS3s7vh 4xCt1Mc9Hn0DzCugn1kp+iiWG4wbEN7 X-Received: by 2002:a05:6a00:e08:b0:82f:776f:a79a with SMTP id d2e1a72fcca58-82f8c8bc107mr37755426b3a.29.1777123136742; Sat, 25 Apr 2026 06:18:56 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 10/13] hw/riscv/atlantis: Add PCIe controller Date: Sat, 25 Apr 2026 23:17:16 +1000 Message-ID: <20260425131721.932250-11-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::430; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x430.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123249699154100 Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin Atlantis has 3 DesignWare PCIe host controllers, however the boot firmware has not been tested with the QEMU DesignWare model so a generic ECAM controller is used for the interim. The system bus aperture and PCIe IO mappings match the hardware configuration. Only a single PCIe controller is implemented, because the gpex model does not support multiple controllers. Booting Linux v6.19: pci-host-generic 1110000000.pci: host bridge /soc/pci@1110000000 ranges: pci-host-generic 1110000000.pci: IO 0x30011000000..0x300110fffff -> = 0x0000000000 pci-host-generic 1110000000.pci: MEM 0x30080000000..0x300ffffffff -> = 0x0080000000 pci-host-generic 1110000000.pci: MEM 0x30100000000..0x3ff7fffffff -> = 0x30100000000 pci-host-generic 1110000000.pci: ECAM at [mem 0x1110000000-0x111fffffff] f= or [bus 00-ff] pci-host-generic 1110000000.pci: PCI host bridge to bus 0000:00 pci_bus 0000:00: root bus resource [bus 00-ff] pci_bus 0000:00: root bus resource [io 0x0000-0xfffff] pci_bus 0000:00: root bus resource [mem 0x30080000000-0x300ffffffff] (bus = address [0x80000000-0xffffffff]) pci_bus 0000:00: root bus resource [mem 0x30100000000-0x3ff7fffffff pref] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000 conventional PCI endp= oint pci 0000:00:01.0: [1af4:1001] type 00 class 0x010000 conventional PCI endp= oint pci 0000:00:01.0: BAR 0 [io 0x0000-0x007f] pci 0000:00:01.0: BAR 1 [mem 0x00000000-0x00000fff] pci 0000:00:01.0: BAR 4 [mem 0x00000000-0x00003fff 64bit pref] pci 0000:00:01.0: BAR 4 [mem 0x30100000000-0x30100003fff 64bit pref]: assi= gned pci 0000:00:01.0: BAR 1 [mem 0x30080000000-0x30080000fff]: assigned pci 0000:00:01.0: BAR 0 [io 0x0080-0x00ff]: assigned pci_bus 0000:00: resource 4 [io 0x0000-0xfffff] pci_bus 0000:00: resource 5 [mem 0x30080000000-0x300ffffffff] pci_bus 0000:00: resource 6 [mem 0x30100000000-0x3ff7fffffff pref] Signed-off-by: Nicholas Piggin Signed-off-by: Joel Stanley --- v4: - Remove select PCI - Rework addressing, use a table for describing the map - Remove traces of controller 2 and 3; they will be implemented in future patches v3: Avoid leaks in the dt string allocation --- include/hw/riscv/tt_atlantis.h | 12 ++ hw/riscv/tt_atlantis.c | 234 ++++++++++++++++++++++++++++++++- hw/riscv/Kconfig | 1 + 3 files changed, 246 insertions(+), 1 deletion(-) diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h index 9fe50d9c9040..070f53eeb450 100644 --- a/include/hw/riscv/tt_atlantis.h +++ b/include/hw/riscv/tt_atlantis.h @@ -17,6 +17,13 @@ #define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis") OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE) =20 +typedef struct { + hwaddr pcie_addr; /* Device side address */ + hwaddr window_offset; /* Host side offset */ + hwaddr size; + uint32_t flags; +} PciMapEntry; + struct TTAtlantisState { /*< private >*/ MachineState parent; @@ -25,9 +32,11 @@ struct TTAtlantisState { Notifier machine_done; FWCfgState *fw_cfg; const MemMapEntry *memmap; + const PciMapEntry *pcimap; =20 RISCVHartArrayState soc; DeviceState *irqchip; + GPEXHost gpex_host; =20 int fdt_size; }; @@ -39,6 +48,7 @@ enum { TT_ATL_UART2_IRQ =3D 40, TT_ATL_UART3_IRQ =3D 41, TT_ATL_UART4_IRQ =3D 42, + TT_ATL_PCIE0_INTA_IRQ =3D 96, }; =20 enum { @@ -50,6 +60,8 @@ enum { TT_ATL_I2C0, TT_ATL_MAPLIC, TT_ATL_MIMSIC, + TT_ATL_PCIE_ECAM0, + TT_ATL_PCIE_MMIO0, TT_ATL_SAPLIC, TT_ATL_SIMSIC, TT_ATL_SYSCON, diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c index 5b66d7e95bb9..1eb473907ad7 100644 --- a/hw/riscv/tt_atlantis.c +++ b/hw/riscv/tt_atlantis.c @@ -27,6 +27,7 @@ #include "hw/intc/riscv_aclint.h" #include "hw/intc/riscv_aplic.h" #include "hw/misc/pvpanic.h" +#include "hw/pci-host/gpex.h" =20 #include "system/system.h" #include "system/device_tree.h" @@ -51,6 +52,13 @@ #define TT_ACLINT_MTIMECMP 0x8000 #define TT_ACLINT_TIMEBASE_FREQ 1000000000 =20 + +enum { + PCIE0_PIO, + PCIE0_MMIO_32, + PCIE0_MMIO_64, +}; + static const MemMapEntry tt_atlantis_memmap[] =3D { /* Keep sorted with :'<,'>!sort -g -k 4 */ [TT_ATL_DDR_LO] =3D { 0x00000000, 0x80000000 }, @@ -66,6 +74,19 @@ static const MemMapEntry tt_atlantis_memmap[] =3D { [TT_ATL_MAPLIC] =3D { 0xcc000000, 0x4000000 }, [TT_ATL_SAPLIC] =3D { 0xe8000000, 0x4000000 }, [TT_ATL_DDR_HI] =3D { 0x100000000, 0x1000000000 }, + [TT_ATL_PCIE_ECAM0] =3D { 0x01110000000, 0x10000000 }, + [TT_ATL_PCIE_MMIO0] =3D { 0x30000000000, 0x10000000000 }, +}; + +static const PciMapEntry tt_atlantis_pci_map[] =3D { + /* pcie_addr window_offset size flags */ + { 0x0, 0x11000000, 1 * MiB, FDT_PCI_RANGE_IOPORT | + FDT_PCI_RANGE_RELOCATABL= E }, + { 0x80000000, 0x80000000, 2 * GiB, FDT_PCI_RANGE_MMIO | + FDT_PCI_RANGE_RELOCATABL= E }, + { 0x30100000000, 0x100000000, 1018 * GiB, FDT_PCI_RANGE_MMIO_64BIT | + FDT_PCI_RANGE_RELOCATABL= E | + FDT_PCI_RANGE_PREFETCHAB= LE }, }; =20 static uint32_t next_phandle(void) @@ -74,6 +95,59 @@ static uint32_t next_phandle(void) return phandle++; } =20 +static void create_pcie_irq_map(void *fdt, char *nodename, int legacy_irq, + uint32_t irqchip_phandle) +{ + int pin, dev; + uint32_t irq_map_stride =3D 0; + uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * + FDT_MAX_INT_MAP_WIDTH] =3D {}; + uint32_t *irq_map =3D full_irq_map; + + /* + * This code creates a standard swizzle of interrupts such that + * each device's first interrupt is based on it's PCI_SLOT number. + * (See pci_swizzle_map_irq_fn()) + * + * We only need one entry per interrupt in the table (not one per + * possible slot) seeing the interrupt-map-mask will allow the table + * to wrap to any number of devices. + */ + for (dev =3D 0; dev < PCI_NUM_PINS; dev++) { + int devfn =3D dev * 0x8; + + for (pin =3D 0; pin < PCI_NUM_PINS; pin++) { + int irq_nr =3D legacy_irq + ((pin + PCI_SLOT(devfn)) % PCI_NUM= _PINS); + int i =3D 0; + + /* Fill PCI address cells */ + irq_map[i] =3D cpu_to_be32(devfn << 8); + i +=3D FDT_PCI_ADDR_CELLS; + + /* Fill PCI Interrupt cells */ + irq_map[i] =3D cpu_to_be32(pin + 1); + i +=3D FDT_PCI_INT_CELLS; + + /* Fill interrupt controller phandle and cells */ + irq_map[i++] =3D cpu_to_be32(irqchip_phandle); + irq_map[i++] =3D cpu_to_be32(irq_nr); + irq_map[i++] =3D cpu_to_be32(0x4); + + if (!irq_map_stride) { + irq_map_stride =3D i; + } + irq_map +=3D irq_map_stride; + } + } + + qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map, + PCI_NUM_PINS * PCI_NUM_PINS * + irq_map_stride * sizeof(uint32_t)); + + qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", + 0x1800, 0, 0, 0x7); +} + static void create_fdt_cpus(TTAtlantisState *s, uint32_t *intc_phandles) { uint32_t cpu_phandle; @@ -314,6 +388,52 @@ static void create_fdt_cpu(TTAtlantisState *s, const M= emMapEntry *memmap, IRQ_S_EXT, s->soc.num_harts); } =20 +static void create_fdt_pcie(void *fdt, + const MemMapEntry *ecam_mem, + const MemMapEntry *pcie_mem, + const PciMapEntry *pio, + const PciMapEntry *mmio32, + const PciMapEntry *mmio64, + int legacy_irq, + uint32_t aplic_s_phandle, + uint32_t imsic_s_phandle) +{ + g_autofree char *name =3D g_strdup_printf("/soc/pci@%"HWADDR_PRIX, + ecam_mem->base); + + qemu_fdt_setprop_cell(fdt, name, "#address-cells", FDT_PCI_ADDR_CELLS); + qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", FDT_PCI_INT_CELLS= ); + qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0x2); + qemu_fdt_setprop_string(fdt, name, "compatible", "pci-host-ecam-generi= c"); + qemu_fdt_setprop_string(fdt, name, "device_type", "pci"); + qemu_fdt_setprop_cells(fdt, name, "bus-range", 0, + ecam_mem->size / PCIE_MMCFG_SIZE_MIN - 1); + qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0); + qemu_fdt_setprop_cell(fdt, name, "msi-parent", imsic_s_phandle); + + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, ecam_mem->base, + 2, ecam_mem->size); + + qemu_fdt_setprop_sized_cells(fdt, name, "ranges", + 1, pio->flags, + 2, pio->pcie_addr, + 2, pio->window_offset + pcie_mem->base, + 2, pio->size, + + 1, mmio32->flags, + 2, mmio32->pcie_addr, + 2, mmio32->window_offset + pcie_mem->base, + 2, mmio32->size, + + 1, mmio64->flags, + 2, mmio64->pcie_addr, + 2, mmio64->window_offset + pcie_mem->base, + 2, mmio64->size); + + create_pcie_irq_map(fdt, name, legacy_irq, aplic_s_phandle); +} + static void create_fdt_reset(void *fdt, const MemMapEntry *mem) { uint32_t syscon_phandle =3D next_phandle(); @@ -379,6 +499,15 @@ static void finalize_fdt(TTAtlantisState *s) * aplic_s_phandle); */ =20 + create_fdt_pcie(fdt, + &s->memmap[TT_ATL_PCIE_ECAM0], + &s->memmap[TT_ATL_PCIE_MMIO0], + &s->pcimap[PCIE0_PIO], + &s->pcimap[PCIE0_MMIO_32], + &s->pcimap[PCIE0_MMIO_64], + TT_ATL_PCIE0_INTA_IRQ, + aplic_s_phandle, imsic_s_phandle); + create_fdt_reset(fdt, &s->memmap[TT_ATL_SYSCON]); =20 create_fdt_uart(fdt, &s->memmap[TT_ATL_UART0], TT_ATL_UART0_IRQ, @@ -389,7 +518,7 @@ static void create_fdt(TTAtlantisState *s) { MachineState *ms =3D MACHINE(s); uint8_t rng_seed[32]; - g_autofree char *name =3D NULL; + char *name; void *fdt; =20 fdt =3D create_device_tree(&s->fdt_size); @@ -411,6 +540,15 @@ static void create_fdt(TTAtlantisState *s) qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); =20 + /* + * The "/soc/pci@..." node is needed for PCIE hotplugs + * that might happen before finalize_fdt(). + */ + name =3D g_strdup_printf("/soc/pci@%"HWADDR_PRIX, + s->memmap[TT_ATL_PCIE_ECAM0].base); + qemu_fdt_add_subnode(fdt, name); + g_free(name); + qemu_fdt_add_subnode(fdt, "/chosen"); =20 /* Pass seed to RNG */ @@ -423,6 +561,95 @@ static void create_fdt(TTAtlantisState *s) create_fdt_pmu(s); } =20 +static void gpex_pcie_init_one(TTAtlantisState *s, GPEXHost *gpex_host, + MemoryRegion *mr, + const MemMapEntry *ecam_mem, + const MemMapEntry *pcie_mem, + const PciMapEntry *mem_pio, + const PciMapEntry *mem_mmio32, + const PciMapEntry *mem_mmio64, + int legacy_irq) +{ + DeviceState *dev; + Object *obj; + MemoryRegion *ecam_alias, *ecam_reg; + MemoryRegion *mmio32_alias, *mmio64_alias, *mmio_reg; + hwaddr ecam_base =3D ecam_mem->base; + hwaddr ecam_size =3D ecam_mem->size; + hwaddr pio_base =3D mem_pio->window_offset + pcie_mem->base; + hwaddr pio_size =3D mem_pio->size; + hwaddr mmio32_base =3D mem_mmio32->window_offset + pcie_mem->base; + hwaddr mmio32_size =3D mem_mmio32->size; + hwaddr mmio64_base =3D mem_mmio64->window_offset + pcie_mem->base; + hwaddr mmio64_size =3D mem_mmio64->size; + qemu_irq irq; + char name[16]; + int i; + + snprintf(name, sizeof(name), "pcie"); + object_initialize_child(OBJECT(s), name, gpex_host, TYPE_GPEX_HOST); + dev =3D DEVICE(gpex_host); + obj =3D OBJECT(dev); + + object_property_set_uint(obj, PCI_HOST_ECAM_BASE, ecam_base, &error_ab= ort); + object_property_set_int(obj, PCI_HOST_ECAM_SIZE, ecam_size, &error_abo= rt); + object_property_set_uint(obj, PCI_HOST_BELOW_4G_MMIO_BASE, mmio32_base, + &error_abort); + object_property_set_int(obj, PCI_HOST_BELOW_4G_MMIO_SIZE, mmio32_size, + &error_abort); + object_property_set_uint(obj, PCI_HOST_ABOVE_4G_MMIO_BASE, mmio64_base, + &error_abort); + object_property_set_int(obj, PCI_HOST_ABOVE_4G_MMIO_SIZE, mmio64_size, + &error_abort); + object_property_set_uint(obj, PCI_HOST_PIO_BASE, pio_base, &error_abor= t); + object_property_set_int(obj, PCI_HOST_PIO_SIZE, pio_size, &error_abort= ); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + ecam_alias =3D g_new0(MemoryRegion, 1); + ecam_reg =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + snprintf(name, sizeof(name), "pcie.ecam"); + memory_region_init_alias(ecam_alias, obj, name, + ecam_reg, 0, ecam_size); + memory_region_add_subregion(mr, ecam_base, ecam_alias); + + mmio_reg =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + + mmio32_alias =3D g_new0(MemoryRegion, 1); + snprintf(name, sizeof(name), "pcie.mmio32"); + memory_region_init_alias(mmio32_alias, obj, name, + mmio_reg, mmio32_base & 0xffffffffUL, mmio32_= size); + memory_region_add_subregion(mr, mmio32_base, mmio32_alias); + + mmio64_alias =3D g_new0(MemoryRegion, 1); + snprintf(name, sizeof(name), "pcie.mmio64"); + memory_region_init_alias(mmio64_alias, obj, name, + mmio_reg, mmio64_base, mmio64_size); + memory_region_add_subregion(mr, mmio64_base, mmio64_alias); + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base); + + for (i =3D 0; i < PCI_NUM_PINS; i++) { + irq =3D qdev_get_gpio_in(s->irqchip, legacy_irq + i); + + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); + gpex_set_irq_num(GPEX_HOST(dev), i, legacy_irq + i); + } + + gpex_host->gpex_cfg.bus =3D PCI_HOST_BRIDGE(dev)->bus; +} + +static void gpex_pcie_init(TTAtlantisState *s, MemoryRegion *mr) +{ + gpex_pcie_init_one(s, &s->gpex_host, mr, + &s->memmap[TT_ATL_PCIE_ECAM0], + &s->memmap[TT_ATL_PCIE_MMIO0], + &s->pcimap[PCIE0_PIO], + &s->pcimap[PCIE0_MMIO_32], + &s->pcimap[PCIE0_MMIO_64], + TT_ATL_PCIE0_INTA_IRQ); +} + static DeviceState *create_reboot_device(const MemMapEntry *mem) { DeviceState *dev =3D qdev_new(TYPE_PVPANIC_MMIO_DEVICE); @@ -517,6 +744,7 @@ static void tt_atlantis_machine_init(MachineState *mach= ine) int base_hartid =3D 0; =20 s->memmap =3D tt_atlantis_memmap; + s->pcimap =3D tt_atlantis_pci_map; =20 object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_HART_ARRAY); @@ -582,6 +810,9 @@ static void tt_atlantis_machine_init(MachineState *mach= ine) s->fw_cfg =3D create_fw_cfg(&s->memmap[TT_ATL_FW_CFG], machine->smp.cp= us); rom_set_fw(s->fw_cfg); =20 + /* PCIe */ + gpex_pcie_init(s, system_memory); + /* Reboot and exit */ create_reboot_device(&s->memmap[TT_ATL_SYSCON]); =20 @@ -617,6 +848,7 @@ static void tt_atlantis_machine_class_init(ObjectClass = *oc, const void *data) mc->default_cpu_type =3D TYPE_RISCV_CPU_TT_ASCALON; mc->block_default_type =3D IF_VIRTIO; mc->no_cdrom =3D 1; + mc->pci_allow_0_address =3D true; mc->default_ram_id =3D "tt_atlantis.ram"; } =20 diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0601ae1a7494..f13a05c7b1d1 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -129,6 +129,7 @@ config TENSTORRENT select DEVICE_TREE select RISCV_NUMA select PVPANIC_MMIO + select PCI_EXPRESS_GENERIC_BRIDGE select SERIAL_MM select RISCV_ACLINT select RISCV_APLIC --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123233879795.5866264997777; Sat, 25 Apr 2026 06:20:33 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuZ-0007VT-MT; Sat, 25 Apr 2026 09:19:07 -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 1wGcuY-0007Uo-8S for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:06 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcuW-0000Iy-F3 for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:06 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-82f69a286dbso6647625b3a.2 for ; Sat, 25 Apr 2026 06:19:04 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:19:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123143; x=1777727943; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=L96ytGhBLABpw2IZylcy/zQEaxsFjn/Yuu5E+/yR5VY=; b=hDL5E6IGS6ZE4gsiaQ9Hc7+BZxaJEEJ6sU2E8tG/SIllpaSp6+H2W25VklzXvd7FTy J7fuweRGSMAWraqP2ZxHbtRX6ycFVijzKaQE8AAgDvO048kvtmFmP5VtFHFJ4v8H7jO1 LyuvH1ADxPfqPbzf83cm7c5+zSAqTnlZng7bXGLKST81wEcLBnqh/8qH4qxT86B/Lkhy WkcTyxYirtkzt6TPtJZo90cZA24Im045emc+pi8Z/RRehRuABP4Eeeuh9BdLwIQLBfdR gc0eQB5AeM8f2KeeSl7dz3p98jGtOS6WLTDbN+aZG7jfTsEJs2k2hWUrNVXENPiiPvZI VsgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123143; x=1777727943; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=L96ytGhBLABpw2IZylcy/zQEaxsFjn/Yuu5E+/yR5VY=; b=AQGmPZOD9ljhdRe+Is/UluISEdUJk8xciekTCsBPvTTMreeVClq9Vzqa6huxo2LeQd zwkB+kaket0zUxEgFgQEm4F91IFMMa+rOFYXpg+kt0hWd+IE+4vv6tIcjjsY8UpwT8Sa VWNbEQHMok+rpihHLXa1AAbjx4KPYCNLnpxdP8Jpkxs6CwBPHlpXS+N6Y290DRv/xzIJ 3yNVRN5wtR2rnSBebqGTd17dIjtP27vjaKxDIkxfJafG4zkS1Zsdd67Meqg5xv8+KhLM uyxepu9whi6DPOLs7OPLysIUgV4qxnuyrKYXYlsJERQQ6pO4VyDeRfjNAQEmKKoaIxUC achg== X-Forwarded-Encrypted: i=1; AFNElJ/EhP1O8gIJb/1tBTWXLUOQXqoghCJx8iGrMoFORFtvArnuoGG+l96LdpHPQm1UbcTCRBGwnsvJrzs2@nongnu.org X-Gm-Message-State: AOJu0YwfhvHXGNSVmi35dGy74R9lVhEwOSyNOrOiadqtlsgPzHhYu34h 3YpJ3Gvvs8SNc6jQMcduOeALx6qMnC8InIwP7XFgeMbjvXf2nEyAzSPa X-Gm-Gg: AeBDieuXX/TJsESUBoPgx4CRcKZYxDQglwpy0yl0JysgrOn89T7EYnJsMtftH/nkgiM UDsjYSzfv5gAhz6r2Z1FJorl0Z5BLtYERkgLTBbrZtpysd3cxr3e8s7abwBOEBLvJ3U7oCI821E WsL/MOXE3nrYiJ5npc14+fnBivRJ0AEoGJmjHiVKGod1kHsZMalq7hrhbvR7gJfEsNdWW/YUv1T mRIjdYA/R6Ffst1HW2d0gfjXiWaJyCCHauFXJ5Li5n0AOnQigNK9yDmlB90iTo+pymnxeDFHPZD uzSU/Gh8e4CrYN7AYLB5ZVvsqdUpYl072aJLL2spYzLyRBR9PqK+0IK/hvryof4vmHoiZTRHIrS bC5cKpIIvXX0IlP37rorLTswLk9tKhT2bqaJa3Z8lsZpTvBQUQsF9gfVaoT1w+IqN0slUiGDVct +i0wt3ItVFfeKi0MrVuFXmM3omQ0cJ6EvekCbrAN/SrN7lqI1jk2S2f/4rLT/bIXdbhuVaM3Sq1 GogTTIffwtv/tlfoTBAvck04J1Dfaeo X-Received: by 2002:a05:6a00:1995:b0:82a:6ef8:cb43 with SMTP id d2e1a72fcca58-82f8c84b34emr37955098b3a.19.1777123143028; Sat, 25 Apr 2026 06:19:03 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Nicholas Piggin , Michael Ellerman , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 11/13] tests/functional/riscv64: Add tt-atlantis tests Date: Sat, 25 Apr 2026 23:17:17 +1000 Message-ID: <20260425131721.932250-12-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42c.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123235600158501 From: Nicholas Piggin Add OpenSBI and Linux boot tests for the tt-atlantis machine. Based on tests/functional/riscv64/test_sifive_u.py. Signed-off-by: Nicholas Piggin Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Joel Stanley --- v4: Remove unnecessary os.remove(rootfs_path) v3: - Fix path to test files - Dedupe command line root argument - Remove unused import --- MAINTAINERS | 1 + tests/functional/riscv64/meson.build | 1 + tests/functional/riscv64/test_opensbi.py | 4 ++ tests/functional/riscv64/test_tt_atlantis.py | 59 ++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100755 tests/functional/riscv64/test_tt_atlantis.py diff --git a/MAINTAINERS b/MAINTAINERS index 635a380945fd..9622ffc9edb2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1770,6 +1770,7 @@ F: docs/system/riscv/tt_*.rst F: hw/riscv/tt_*.c F: hw/riscv/aia.[ch] F: include/hw/riscv/tt_*.h +F: tests/functional/riscv64/test_tt_*.py =20 AMD Microblaze-V Generic Board M: Sai Pavan Boddu diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv6= 4/meson.build index b996c89d7df9..c4456fabd757 100644 --- a/tests/functional/riscv64/meson.build +++ b/tests/functional/riscv64/meson.build @@ -13,5 +13,6 @@ tests_riscv64_system_quick =3D [ tests_riscv64_system_thorough =3D [ 'boston', 'sifive_u', + 'tt_atlantis', 'tuxrun', ] diff --git a/tests/functional/riscv64/test_opensbi.py b/tests/functional/ri= scv64/test_opensbi.py index d077e40f4278..0f8beb7e7a8c 100755 --- a/tests/functional/riscv64/test_opensbi.py +++ b/tests/functional/riscv64/test_opensbi.py @@ -28,6 +28,10 @@ def test_riscv_sifive_u(self): self.set_machine('sifive_u') self.boot_opensbi() =20 + def test_riscv_tt_atlantis(self): + self.set_machine('tt-atlantis') + self.boot_opensbi() + def test_riscv_virt(self): self.set_machine('virt') self.boot_opensbi() diff --git a/tests/functional/riscv64/test_tt_atlantis.py b/tests/functiona= l/riscv64/test_tt_atlantis.py new file mode 100755 index 000000000000..ce6e7fc63e34 --- /dev/null +++ b/tests/functional/riscv64/test_tt_atlantis.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Tenstorrent Atlantis mach= ine +# and checks the console +# +# Copyright (c) Linaro Ltd. +# Copyright 2026 Tenstorrent +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, LinuxKernelTest + + +class TTAtlantis(LinuxKernelTest): + + ASSET_KERNEL =3D Asset( + 'https://storage.tuxboot.com/kernels/6.11.9/riscv64/Image', + '174f8bb87f08961e54fa3fcd954a8e31f4645f6d6af4dd43983d5e9841490fb0') + ASSET_ROOTFS =3D Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '9819da19e6eef291686fdd7b029ea00e764dc62f/rootfs/riscv64/' + 'rootfs.ext2.gz'), + 'b6ed95610310b7956f9bf20c4c9c0c05fea647900df441da9dfe767d24e8b28b') + + def do_test_riscv64_tt_atlantis(self, connect_disk): + self.set_machine('tt-atlantis') + kernel_path =3D self.ASSET_KERNEL.fetch() + rootfs_path =3D self.uncompress(self.ASSET_ROOTFS) + + self.vm.set_console() + kernel_command_line =3D self.KERNEL_COMMON_COMMAND_LINE + 'earlyco= n=3Dsbi ' + + if connect_disk: + kernel_command_line +=3D 'root=3D/dev/vda panic=3D-1 noreboot = rootwait ' + self.vm.add_args('-device', + 'virtio-blk,drive=3Ddrive0,serial=3D0x1234,bu= s=3Dpcie.0') + self.vm.add_args('-drive', + f'file=3D{rootfs_path},if=3Dnone,id=3Ddrive0,= format=3Draw') + pattern =3D 'Boot successful.' + else: + kernel_command_line +=3D 'panic=3D0 noreboot ' + pattern =3D 'Cannot open root device' + + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-no-reboot') + + self.vm.launch() + self.wait_for_console_pattern(pattern) + + def test_riscv64_tt_atlantis(self): + self.do_test_riscv64_tt_atlantis(False) + + def test_riscv64_tt_atlantis_disk(self): + self.do_test_riscv64_tt_atlantis(True) + + +if __name__ =3D=3D '__main__': + LinuxKernelTest.main() --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123203563556.0252466878541; Sat, 25 Apr 2026 06:20:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcuy-0007v4-6t; Sat, 25 Apr 2026 09:19:34 -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 1wGcue-0007bt-S8 for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:16 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcud-0000MO-3w for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:12 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-82735a41920so3560381b3a.2 for ; Sat, 25 Apr 2026 06:19:10 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.19.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:19:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123150; x=1777727950; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=yoGuy7Y7mcp7aomRMsnsXeq4e2FJ2nZOLuRGsrIDzxY=; b=nzX0mzp/Ar2rwwhnA/ZlqIL3q/sjD46N/rZg6T/ZyUI8QkRSsuoaTHXQKbx6GUsso7 TOduHPohC3byo9beY6Lt7G+DUqT4URjev1QYdu41Yb/8XnAOwvhlqMPMeolRPShcKhlA MjHeuOvR8Z4/Qpj5j37qwPWpSepqaTVi9wGycs5ZiX+LdrLFUOcZggHKYRRGi7rmCSMT byjaJ54gJnTASObF+hHu/EYKwWCT+lXdGiQ4ontthvyEojrcdnk2G26OK8ghA+CiGX3J tUYdg3mkEJIifxib06zS19OBnMKynhuBuADr+ICmZzCu9l1byBR+QUBSJROFwoMctpdD +Grg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123150; x=1777727950; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=yoGuy7Y7mcp7aomRMsnsXeq4e2FJ2nZOLuRGsrIDzxY=; b=igzO+BJRu3gQXzIv226gyq03gqYkYq5n/vaqZA7lLz7VA6FGizfAuJufHuOcPOJcFk 1cORh2CELKx2uBn9V2Y8kYqiYIB9v8WOjhBwzTsO2o+CZ21pQY1EbKqEXcSO82VEycM6 8kq0sDNND2VlJLYP/tafsnVtfVYOQAP8bvNrqNiGqZuG/84Klm1VHkq5651xITtNhkzG m7uaa16Fq94s2HSh4WsLaAbydBXs2vu9I1zgw+o90nP9q0tCa+/ArToeKprSu5Q8yoK8 yEJ961zxLYFOub+/s4VqVJJnKryNkRlM9ZP2BGdg0iS+m8n55UkRD4INUyki4bj5JSp/ zEdg== X-Forwarded-Encrypted: i=1; AFNElJ+IRbBN5LgVh+o42xIXHafjmsA/8aaGAN9bLJcN+XuNcn82TLwrRn2DjLAcudOqw9rR2UNJqvOLOKpz@nongnu.org X-Gm-Message-State: AOJu0YxK3OoHTcKrZyYy64Yy+ihDIbxWR1bojA7TPNbs6PXUm0G+hB73 kL+viY4In1suZeRsSH98a1+6hivKAWvgalWQKMZE+yiqYJ3/fhgE9y3H X-Gm-Gg: AeBDietG4tBCFXRyhmkPKNtjMDE2hzcqBmrp5M2/bzesupWouhaPZLQvvtvSIpRNOvJ wT2IkZ93fd300geAr6Gqx1kM702Ib+gp+V+gSPck38ZuDsWEvlgv2sF6uPjjCMM/mi0ebwlAeFd yYFeRzEdoDFQGcHmep76yDqo5e44QQNQ1NWybSxNUo3Qhz0LqfCZhiRL3h+ASERIDDkgd0I65Gg zvg3j+xTimgjvwnRZatiVb3rtjqCAp8wCeIBWhQFf2/9Cqx+sl16ROvaCyJ9+wpvAc0EEvAgzJz PhUWZCrZHJQArXB4lCMFrecd65MflZBvZvNcr9RSrClNLlMhB+qBezBwT7CEfy2k5w+OtxZL3ME 06SpjajdOl30cQLbODLDsEAGSVY7gMhye0iDdF4vsLhHqMiprIgL/JsOPdOX1xDTCGi2nHwxwZx 5d4FoaM2lVzCzc43uDBm1CR7M3fjnHsDzj6P/sJPdxT4p2GilPDUejuw7UkWKBkjKJ+C2ZPLj55 mdf5vQ4pFjlG5Vy2emCpDI+xBXQpGbR X-Received: by 2002:a05:6a00:4b01:b0:82f:390a:69df with SMTP id d2e1a72fcca58-82f8c8d616emr38415084b3a.35.1777123149725; Sat, 25 Apr 2026 06:19:09 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 12/13] hw/riscv/atlantis: Integrate i2c buses Date: Sat, 25 Apr 2026 23:17:18 +1000 Message-ID: <20260425131721.932250-13-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::432; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x432.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123205124154100 Now that we have the DesignWare model we can add buses to the tt-atlantis machine. Provide a fixed clock in the device tree so that the Linux driver probes without WARNing. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Joel Stanley --- v3: - Add device tree clock v2: - Correct count from 4 to 5 - Fix headers location - Use HWADDR_PRIX to be consistent --- include/hw/riscv/tt_atlantis.h | 13 +++++++++ hw/riscv/tt_atlantis.c | 53 ++++++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 1 + 3 files changed, 67 insertions(+) diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h index 070f53eeb450..a19a8cc0773f 100644 --- a/include/hw/riscv/tt_atlantis.h +++ b/include/hw/riscv/tt_atlantis.h @@ -11,12 +11,15 @@ =20 #include "hw/core/boards.h" #include "hw/core/sysbus.h" +#include "hw/i2c/designware_i2c.h" #include "hw/intc/riscv_imsic.h" #include "hw/riscv/riscv_hart.h" =20 #define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis") OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE) =20 +#define TT_ATL_NUM_I2C 5 + typedef struct { hwaddr pcie_addr; /* Device side address */ hwaddr window_offset; /* Host side offset */ @@ -37,12 +40,18 @@ struct TTAtlantisState { RISCVHartArrayState soc; DeviceState *irqchip; GPEXHost gpex_host; + DesignWareI2CState i2c[TT_ATL_NUM_I2C]; =20 int fdt_size; }; =20 enum { TT_ATL_SYSCON_IRQ =3D 10, + TT_ATL_I2C0_IRQ =3D 33, + TT_ATL_I2C1_IRQ =3D 34, + TT_ATL_I2C2_IRQ =3D 35, + TT_ATL_I2C3_IRQ =3D 36, + TT_ATL_I2C4_IRQ =3D 37, TT_ATL_UART0_IRQ =3D 38, TT_ATL_UART1_IRQ =3D 39, TT_ATL_UART2_IRQ =3D 40, @@ -58,6 +67,10 @@ enum { TT_ATL_DDR_HI, TT_ATL_FW_CFG, TT_ATL_I2C0, + TT_ATL_I2C1, + TT_ATL_I2C2, + TT_ATL_I2C3, + TT_ATL_I2C4, TT_ATL_MAPLIC, TT_ATL_MIMSIC, TT_ATL_PCIE_ECAM0, diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c index 1eb473907ad7..d517d0aee2d1 100644 --- a/hw/riscv/tt_atlantis.c +++ b/hw/riscv/tt_atlantis.c @@ -71,6 +71,11 @@ static const MemMapEntry tt_atlantis_memmap[] =3D { [TT_ATL_TIMER] =3D { 0xa8020000, 0x10000 }, [TT_ATL_WDT0] =3D { 0xa8030000, 0x10000 }, [TT_ATL_UART0] =3D { 0xb0100000, 0x10000 }, + [TT_ATL_I2C0] =3D { 0xb0400000, 0x10000 }, + [TT_ATL_I2C1] =3D { 0xb0500000, 0x10000 }, + [TT_ATL_I2C2] =3D { 0xb0600000, 0x10000 }, + [TT_ATL_I2C3] =3D { 0xb0700000, 0x10000 }, + [TT_ATL_I2C4] =3D { 0xb0800000, 0x10000 }, [TT_ATL_MAPLIC] =3D { 0xcc000000, 0x4000000 }, [TT_ATL_SAPLIC] =3D { 0xe8000000, 0x4000000 }, [TT_ATL_DDR_HI] =3D { 0x100000000, 0x1000000000 }, @@ -484,10 +489,36 @@ static void create_fdt_fw_cfg(void *fdt, const MemMap= Entry *mem) qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0); } =20 +static void create_fdt_clk(void *fdt, const char *name, uint32_t clk_phand= le) +{ + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "fixed-clock"); + qemu_fdt_setprop_cell(fdt, name, "#clock-cells", 0); + qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 100000000); + qemu_fdt_setprop_cell(fdt, name, "phandle", clk_phandle); +} + +static void create_fdt_i2c(void *fdt, const MemMapEntry *mem, uint32_t irq, + uint32_t irqchip_phandle, uint32_t clk_phandle) +{ + g_autofree char *name =3D g_strdup_printf("/soc/i2c@%"HWADDR_PRIX, mem= ->base); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "snps,designware-i2c"= ); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, mem->s= ize); + qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irqchip_phandle); + qemu_fdt_setprop_cells(fdt, name, "interrupts", irq, 0x4); + qemu_fdt_setprop_cell(fdt, name, "clocks", clk_phandle); + qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 100000); + qemu_fdt_setprop_cell(fdt, name, "#address-cells", 1); + qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0); +} + static void finalize_fdt(TTAtlantisState *s) { uint32_t aplic_s_phandle =3D next_phandle(); uint32_t imsic_s_phandle =3D next_phandle(); + uint32_t periph_clk_phandle =3D next_phandle(); void *fdt =3D MACHINE(s)->fdt; =20 create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle); @@ -512,6 +543,15 @@ static void finalize_fdt(TTAtlantisState *s) =20 create_fdt_uart(fdt, &s->memmap[TT_ATL_UART0], TT_ATL_UART0_IRQ, aplic_s_phandle); + + create_fdt_clk(fdt, "/periph-clk", periph_clk_phandle); + + for (int i =3D 0; i < TT_ATL_NUM_I2C; i++) { + create_fdt_i2c(fdt, + &s->memmap[TT_ATL_I2C0 + i], + TT_ATL_I2C0_IRQ + i, + aplic_s_phandle, periph_clk_phandle); + } } =20 static void create_fdt(TTAtlantisState *s) @@ -821,6 +861,19 @@ static void tt_atlantis_machine_init(MachineState *mac= hine) qdev_get_gpio_in(s->irqchip, TT_ATL_UART0_IRQ), 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); =20 + /* I2C */ + for (int i =3D 0; i < TT_ATL_NUM_I2C; i++) { + object_initialize_child(OBJECT(s), "i2c[*]", &s->i2c[i], + TYPE_DESIGNWARE_I2C); + sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), &error_fatal); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(&s->i2c[i]); + memory_region_add_subregion(system_memory, + s->memmap[TT_ATL_I2C0 + i].base, + sysbus_mmio_get_region(sbd, 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, + qdev_get_gpio_in(s->irqchip, TT_ATL_I2C0_IRQ + = i)); + } + /* Load or create device tree */ if (machine->dtb) { machine->fdt =3D load_device_tree(machine->dtb, &s->fdt_size); diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index f13a05c7b1d1..2db8f409b926 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -135,6 +135,7 @@ config TENSTORRENT select RISCV_APLIC select RISCV_IMSIC select FW_CFG_DMA + select DESIGNWARE_I2C =20 config XIANGSHAN_KUNMINGHU bool --=20 2.47.3 From nobody Mon May 25 13:49:01 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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 Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777123214796449.8918810230782; Sat, 25 Apr 2026 06:20:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wGcvF-0008Fx-Sx; Sat, 25 Apr 2026 09:19:50 -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 1wGcul-0007i2-TK for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:22 -0400 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wGcui-0000NT-Eo for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:19:18 -0400 Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-83178c0f29cso1816563b3a.0 for ; Sat, 25 Apr 2026 06:19:15 -0700 (PDT) Received: from donnager-debian.. ([45.124.203.19]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.19.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 06:19:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777123155; x=1777727955; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=xFdee4nHaejEKDKlQFwGR+4gsOxo5tQfJ+kbcTE/iEU=; b=Itbrf03ijXOhhC85VUiRXVQ6+UR+nJEXCK8AtAxE6+WL/oBPaDXsXI2Qckfo7gOIOL ZsOBQqQVsGLHDuubAaNf1LUWe6RIILuoL/bqWylZ9En1NhsBv70TZGsAfW9I0ifWjA+5 qNd+aoLCEAAdc9IGyuAR+TyjRAUy9qHQkpkEP6aAWIkhhIH/LdevuCEokSS7JmdkwukE TbA8RFCAv+ZgRkxAv2Y0LgxhJf2X6J0FBGUSvyfXDxCPxFX6Ny1d8m6H40n8qS9rZEk7 +6KEIIBRNkQ2DX4nd2O2eIyTR2a1mZiXWpMuF749Ni+lJISbBGRR1VNjDnoXAvE7cK+Q kqKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777123155; x=1777727955; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=xFdee4nHaejEKDKlQFwGR+4gsOxo5tQfJ+kbcTE/iEU=; b=FFWwpgoOfxbGlu4EeGjPpp+13aPdolVqAIKJUVjNCJsn7LyveFPyMCVmdNHUD8kyD7 2Dsi+P43rJNn2GJO9XWNku/GAJNop2wO6nJEO1D73PdAveRJpNnXoZPFZAkhG0WYpDaY JFWSwifUWn1AEBVlTzfPrOpZPZTTKgxLbGiet0hzqOoX3JsgMnzfNN61QNv1Ou+A/B/w 8ZkxliLux2YqTGor5HFlatadNBBMfPsUD1M8Taf8vDYj0jbLUrrtY3KhXEEX9egTpEhy eYXUTTDuoq6yBp75pwa004Hdp36FWYzm+JaPX/qsO9f6KA9ZjiTdfd7XwQzy8dzoFBNT ax8w== X-Forwarded-Encrypted: i=1; AFNElJ860aUwXZfsJP/q0PU6nZmCbY+5B/OuFaxe+dpPwyOdVL/KLaBjkPrtJcacH4wGJCeP9txnj7oKX8B3@nongnu.org X-Gm-Message-State: AOJu0YyCED6aA1tWA/8W6LCXIrqrO+PRl36h95pFF3KETGjsXgSXShMt TQKokTJtiFPeVkvKOGsgCPiWtomJylXL+Y2lPkIzDZc+8wHlsKwGGbyj X-Gm-Gg: AeBDiet/WVGZ83j+T2gfB6Q9N+Ug1+xeA7eLWRrK5RQitmjp8WgYOpG/XZH2jXbAdUU OvT3hXB9jUgnDLPv7bYtoxsEWGDX+44wgXMgcyQ7ZhJxjPMLluCgJOxRRqSxT0T/ZZUKAVrn8UW wXUA0bPdkaP0ZhZu4XXD7r+hlw5F3sb/b4pm2Xrcnpj5dt6nT/fNTjpdLwn3//hnf4zp0adO/HR 3iRNN5R50ukRi3xS+HygsfE6KWltsqWaNta7HNjID9U7FmTCiHkos+29kEnbYIUkMGCU/iIGTLE WWFO+j2aJtwlXVJ2YwdHXJB/5kOXfhBc4+3EGKqigHFVBbMYXcxeR+wFBH/Epo/JPnZs4ymQwJc OzagsO/Ics7TAwvshjIpvq3TpdhpCaXskkTkbVIZPf1TLxvxJH/hYQgrIML1s7xjVOr5fI7O4qz 9moQ9gfrJT/z8WANK7PIo8QkLnvbljrS+/q7gXDhU84jZYw6uVYafrAJu8m9lATirmXZKRukuz4 NR0BAAsg+XCuTIn/fcpfIZvqg7qKnCJ X-Received: by 2002:a05:6a00:1953:b0:82c:d861:3caf with SMTP id d2e1a72fcca58-82f8c907fbfmr39138122b3a.36.1777123154850; Sat, 25 Apr 2026 06:19:14 -0700 (PDT) From: Joel Stanley To: Alistair Francis , Daniel Henrique Barboza Cc: Chao Liu , Michael Ellerman , Nicholas Piggin , Joel Stanley , Anirudh Srinivasan , Portia Stephens , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v4 13/13] hw/riscv/atlantis: Add some i2c peripherals Date: Sat, 25 Apr 2026 23:17:19 +1000 Message-ID: <20260425131721.932250-14-joel@jms.id.au> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260425131721.932250-1-joel@jms.id.au> References: <20260425131721.932250-1-joel@jms.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42a; envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42a.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: fail (Header signature does not verify) X-ZM-MESSAGEID: 1777123215781158500 Add an I2C RTC device and a temperature sensor. These are not present on the board but help for testing. The tmp105 is a lm75 compatible temperature sensor used by the SENSORS_LM75 Linux kernel driver. The ds1338 is a RTC device that is used by the RTC_DRV_DS1307 Linux kernel driver. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Joel Stanley --- v4: - Place i2c on bus 0 and 4 - lm75 compatible to tmp105, which is same qemu model and linux driver - Mention the kernel drivers in the commit message v3: Use HWADDR_PRIX in i2c device string consistent --- hw/riscv/tt_atlantis.c | 27 +++++++++++++++++++++++++++ hw/riscv/Kconfig | 2 ++ 2 files changed, 29 insertions(+) diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c index d517d0aee2d1..521748af1b99 100644 --- a/hw/riscv/tt_atlantis.c +++ b/hw/riscv/tt_atlantis.c @@ -94,6 +94,13 @@ static const PciMapEntry tt_atlantis_pci_map[] =3D { FDT_PCI_RANGE_PREFETCHAB= LE }, }; =20 +static I2CBus *i2c_get_bus(TTAtlantisState *s, unsigned busnr) +{ + assert(busnr < TT_ATL_NUM_I2C); + + return s->i2c[busnr].bus; +} + static uint32_t next_phandle(void) { static uint32_t phandle =3D 1; @@ -514,6 +521,19 @@ static void create_fdt_i2c(void *fdt, const MemMapEntr= y *mem, uint32_t irq, qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0); } =20 +static void create_fdt_i2c_device(TTAtlantisState *s, int bus, + const char *compat, int addr) +{ + void *fdt =3D MACHINE(s)->fdt; + hwaddr base =3D s->memmap[TT_ATL_I2C0 + bus].base; + g_autofree char *name =3D g_strdup_printf("/soc/i2c@%"HWADDR_PRIX"/sen= sor@%x", + base, addr); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", compat); + qemu_fdt_setprop_cell(fdt, name, "reg", addr); +} + static void finalize_fdt(TTAtlantisState *s) { uint32_t aplic_s_phandle =3D next_phandle(); @@ -552,6 +572,9 @@ static void finalize_fdt(TTAtlantisState *s) TT_ATL_I2C0_IRQ + i, aplic_s_phandle, periph_clk_phandle); } + + create_fdt_i2c_device(s, 0, "dallas,ds1338", 0x6f); + create_fdt_i2c_device(s, 4, "ti,tmp105", 0x48); } =20 static void create_fdt(TTAtlantisState *s) @@ -874,6 +897,10 @@ static void tt_atlantis_machine_init(MachineState *mac= hine) qdev_get_gpio_in(s->irqchip, TT_ATL_I2C0_IRQ + = i)); } =20 + /* I2C peripherals: qemu specific */ + i2c_slave_create_simple(i2c_get_bus(s, 0), "ds1338", 0x6f); + i2c_slave_create_simple(i2c_get_bus(s, 4), "tmp105", 0x48); + /* Load or create device tree */ if (machine->dtb) { machine->fdt =3D load_device_tree(machine->dtb, &s->fdt_size); diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 2db8f409b926..6ad7b3e07e9e 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -136,6 +136,8 @@ config TENSTORRENT select RISCV_IMSIC select FW_CFG_DMA select DESIGNWARE_I2C + select DS1338 + select TMP105 =20 config XIANGSHAN_KUNMINGHU bool --=20 2.47.3