Re: [PATCH 1/2] hw/misc: Add Tenstorrent Atlantis PRCM model
Anirudh Srinivasan <[email protected]> Mon, 3 Aug 2026 10:36:27 -0500
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CAEev2e_Aj+8PJqH14gxYcn0Ni9qhvprW2Q04_ynu6FL0sPj9tw@mail.gmail.com> |
Hi Chao, On Sun, Aug 2, 2026 at 9:25=E2=80=AFPM Chao Liu <[email protected]= m> wrote: > > On Wed, Jul 29, 2026 at 10:21:34AM +0800, Anirudh Srinivasan wrote: > > This device present in Tenstorrent Atlantis has registers that control > > clocks, reset and other misc functionality in the SoC. This commit adds > > models for the RCPU, HSIO, PCIE, MM and 2 DDR PRCMs. > > > > Co-developed-by: Portia Stephens <[email protected]> > > Signed-off-by: Portia Stephens <[email protected]> > > Signed-off-by: Anirudh Srinivasan <[email protected]> > > --- > > MAINTAINERS | 2 + > > hw/misc/meson.build | 1 + > > hw/misc/trace-events | 4 + > > hw/misc/tt_atlantis_prcm.c | 436 +++++++++++++++++++++++++++++= ++++++++ > > include/hw/misc/tt_atlantis_prcm.h | 51 +++++ > > 5 files changed, 494 insertions(+) > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index e25df9493c..49c1a5ad76 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -1802,7 +1802,9 @@ R: Portia Stephens <[email protected]> > > L: [email protected] > > S: Supported > > F: docs/system/riscv/tt_*.rst > > +F: hw/misc/tt_*.c > > F: hw/riscv/tt_*.c > > +F: include/hw/misc/tt_*.h > > F: include/hw/riscv/tt_*.h > > F: tests/functional/riscv64/test_tt_*.py > > > > diff --git a/hw/misc/meson.build b/hw/misc/meson.build > > index 23265f6035..26627013f3 100644 > > --- a/hw/misc/meson.build > > +++ b/hw/misc/meson.build > > @@ -36,6 +36,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: = files('sifive_e_prci.c')) > > system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_ao= n.c')) > > system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_ot= p.c')) > > system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_p= rci.c')) > > +system_ss.add(when: 'CONFIG_TENSTORRENT', if_true: files('tt_atlantis_= prcm.c')) > > > > subdir('macio') > > > > diff --git a/hw/misc/trace-events b/hw/misc/trace-events > > index c9a868b3ef..9359a4e66d 100644 > > --- a/hw/misc/trace-events > > +++ b/hw/misc/trace-events > > @@ -442,3 +442,7 @@ iommu_testdev_dma_read(uint64_t gva, uint32_t len) = "gva=3D0x%" PRIx64 " len=3D%u" > > iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected= =3D0x%x actual=3D0x%x" > > iommu_testdev_dma_result(uint32_t result) "DMA completed result=3D0x%x= " > > iommu_testdev_dma_armed(bool armed) "armed=3D%d" > > + > > +# tt_atlantis_prcm.c > > +tt_atlantis_prcm_read(uint32_t domain, uint64_t offset, uint64_t data)= "domain 0x%02x offset 0x%" PRIx64 " data 0x%" PRIx64 > > +tt_atlantis_prcm_write(uint32_t domain, uint64_t offset, uint64_t data= ) "domain 0x%02x offset 0x%" PRIx64 " data 0x%" PRIx64 > > diff --git a/hw/misc/tt_atlantis_prcm.c b/hw/misc/tt_atlantis_prcm.c > > new file mode 100644 > > index 0000000000..d341e1a8c3 > > --- /dev/null > > +++ b/hw/misc/tt_atlantis_prcm.c > > @@ -0,0 +1,436 @@ > > +/* > > + * PRCM (Clock and Reset Controller) in Tenstorrent Atlantis SoC > > + * > > + * SPDX-License-Identifier: GPL-2.0-or-later > > + * > > + * Copyright 2026 Tenstorrent > > + */ > > + > > +#include "qemu/osdep.h" > > +#include "qemu/bitops.h" > > +#include "qapi/error.h" > > +#include "qemu/log.h" > > +#include "hw/misc/tt_atlantis_prcm.h" > > +#include "hw/core/qdev-properties.h" > > +#include "hw/core/registerfields.h" > > +#include "hw/core/irq.h" > > +#include "trace.h" > > + > > +#define TO_REG(offset) ((offset) >> 2) > > + > > +#define PLL_LOCK_BIT 31 > > +#define PLL_FBDIV_LSB 14 > > +#define PLL_POSTDIV2_LSB 11 > > +#define PLL_POSTDIV1_LSB 8 > > +#define PLL_REFDIV_LSB 2 > > +#define PLL_BYPASS_BIT 1 > > + > > +#define PLL_RESET_VAL(BYPASS, REFDIV, POSTDIV1, POSTDIV2, FBDIV, LOCK)= \ > > + ((LOCK << PLL_LOCK_BIT) | (FBDIV << PLL_FBDIV_LSB) | = \ > > + (POSTDIV2 << PLL_POSTDIV2_LSB) | (POSTDIV1 << PLL_POSTDIV1_LSB) | = \ > > + (REFDIV << PLL_REFDIV_LSB) | (BYPASS << PLL_BYPASS_BIT)) > > + > > +#define RCPU_PLL_RCPU_CFG TO_REG(0) > > +#define RCPU_PLL_NOCC_CFG TO_REG(0x4) > > +#define RCPU_NOCC_CLK_CFG TO_REG(0x8) > > +#define RCPU_RCPU_DIV_CFG TO_REG(0xc) > > +#define RCPU_RCPU_BLK_CG TO_REG(0x14) > > +#define RCPU_LSIO_BLK_CG TO_REG(0x18) > > +#define RCPU_RCPU_BLK_RST TO_REG(0x1c) > > +#define RCPU_LSIO_BLK_RST TO_REG(0x20) > > +#define RCPU_PLL_RCPU_EN TO_REG(0x11c) > > +#define RCPU_PLL_NOCC_EN TO_REG(0x120) > > +#define RCPU_PLL_MM_EN TO_REG(0x0124) > > +#define RCPU_PLL1_MM_EN TO_REG(0x0128) > > +#define RCPU_PLL_HSIO_EN TO_REG(0x12c) > > +#define RCPU_PLL_PCIE_EN TO_REG(0x138) > > +#define RCPU_PLL_I2S_EN TO_REG(0x13C) > > +#define RCPU_PLL_MM_CFG TO_REG(0x19c) > > +#define RCPU_PLL_HSIO_CFG TO_REG(0x1a0) > > +#define RCPU_PLL_PCIE_CFG TO_REG(0x1ac) > > +#define RCPU_BOOT_MODE_CFG TO_REG(0x1b0) > > +#define RCPU_PLL_I2S_CFG TO_REG(0x1f4) > > +#define RCPU_I2S_DIV_CFG TO_REG(0x1f8) > > +#define RCPU_BUS_CFG TO_REG(0x1fc) > > +#define RCPU_PLL1_MM_CFG TO_REG(0x2a4) > > + > > +#define HSIO_HSIO_DIV_CFG TO_REG(0x0) > > +#define HSIO_HSIO_DIV_CFG1 TO_REG(0x4) > > +#define HSIO_HSIO_BLK_CG TO_REG(0x8) > > +#define HSIO_HSIO_BLK_RST TO_REG(0xc) > > +#define HSIO_HSIO_GMAC_DIV_CFG TO_REG(0x10) > > + > > +#define PCIE_SUBS_RST_CTL TO_REG(0x0) > > +#define PCIE_SUBS_CG_CTL TO_REG(0x4) > > +#define PCIE_SUBS_CK_CTL TO_REG(0x8) > > + > > +#define MM_MM_CLK_GATE_CFG TO_REG(0x8) > > +#define MM_MM_CLK_DIV_CFG TO_REG(0xC) > > +#define MM_MM_CLK_SEL_CFG TO_REG(0x10) > > +#define MM_MM_RSTN TO_REG(0x14) > > +#define MM_MM_CLK_DIV_CFG1 TO_REG(0x130) > > + > > +#define DDRC_STAT TO_REG(0x10014) > > +#define DDRC_DFISTAT TO_REG(0x10514) > > +#define DDRC_SWSTAT TO_REG(0x10c84) > > + > > +#define PLL_EN BIT(0) > > +#define RCPU_PLL_BUS_CG_EN BIT(7) > > +#define HSIO_PLL_BUS_CG_EN BIT(3) > > +#define PCIE_PLL_BUS_CG_EN BIT(1) > > +#define NOCC_PLL_BUS_CG_EN BIT(0) > > + > > +#define RCPU_BOOT_MODE_UART (0x0 << 4) > > +#define RCPU_BOOT_MODE_NOR (0x1 << 4) > > +#define RCPU_BOOT_MODE_SD (0x2 << 4) > > + > > +#define RCPU_DOMAIN_SIZE 0x10000 > > +#define HSIO_DOMAIN_SIZE 0x510 > > +#define PCIE_DOMAIN_SIZE 0x100 > > +#define MM_DOMAIN_SIZE 0x1000 > > +#define DDRC0_DOMAIN_SIZE 0x101000 > > +#define DDRC1_DOMAIN_SIZE 0x101000 > > + > > +static uint64_t tt_atlantis_prcm_read(void *opaque, hwaddr offset, > > + unsigned size) { > > + TTAtlantisPRCMState *s =3D TT_ATLANTIS_PRCM(opaque); > > + TTAtlantisPRCMClass *c =3D TT_ATLANTIS_PRCM_GET_CLASS(s); > > + uint32_t data; > > + > > + if (offset >=3D c->regs_size) { > > + qemu_log_mask(LOG_GUEST_ERROR, > > + "%s: Out-of-bounds read at offset 0x%" HWADDR_PR= Ix "\n", > > + __func__, offset); > > + return 0; > > + } > > + data =3D s->regs[TO_REG(offset)]; > > + > > + trace_tt_atlantis_prcm_read(c->domain, offset, data); > > + return data; > > +} > > + > > +static void tt_atlantis_prcm_write(void *opaque, hwaddr offset, > > + uint64_t data, unsigned si= ze) { > Consider aligning the wrapped lines with the first parameter. > > > + TTAtlantisPRCMState *s =3D TT_ATLANTIS_PRCM(opaque); > > + TTAtlantisPRCMClass *c =3D TT_ATLANTIS_PRCM_GET_CLASS(s); > > + > > + trace_tt_atlantis_prcm_write(c->domain, offset, data); > > + > > + if (offset >=3D c->regs_size) { > > + qemu_log_mask(LOG_GUEST_ERROR, > > + "%s: Out-of-bounds write at offset 0x%" HWADDR_P= RIx "\n", > > + __func__, offset); > > + return; > > + } > > + > > + switch (TO_REG(offset)) { > > + default: > > + s->regs[TO_REG(offset)] =3D data; > > + break; > > + } > > +} > > + > > +static void tt_atlantis_prcm_rcpu_write(void *opaque, hwaddr offset, > > + uint64_t data, unsigned si= ze) { > > + TTAtlantisPRCMState *s =3D TT_ATLANTIS_PRCM(opaque); > > + > > + tt_atlantis_prcm_write(opaque, offset, data, size); > > + > > + bool pll_en_written =3D false; > > + uint32_t pll_reg_offset; > > + switch TO_REG(offset) > > + { > > + case RCPU_PLL_RCPU_EN: > > + pll_en_written =3D true; > > + pll_reg_offset =3D RCPU_PLL_RCPU_CFG; > > + break; > This should follow the QEMU coding style: > > switch (TO_REG(offset)) { > case RCPU_PLL_RCPU_EN: > pll_en_written =3D true; > pll_reg_offset =3D RCPU_PLL_RCPU_CFG; > break; > ... > case RCPU_PLL_I2S_EN: > pll_en_written =3D true; > pll_reg_offset =3D RCPU_PLL_I2S_CFG; > break; > default: > g_assert_not_reached(); > } Thanks, checkpatch didn't seem to point these out. Will fix them up in V2. Regards Anirudh Srinivasan > Thanks, > Chao