Re: [PATCH 1/2] hw/misc: Add Tenstorrent Atlantis PRCM model

Anirudh Srinivasan <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <CAEev2e_Aj+8PJqH14gxYcn0Ni9qhvprW2Q04_ynu6FL0sPj9tw@mail.gmail.com>
Hi Chao,

On Sun, Aug 2, 2026 at 9:25 PM Chao Liu <[email protected]> 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_aon.c'))
> >  system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
> >  system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.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=0x%" PRIx64 " len=%u"
> >  iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected=0x%x actual=0x%x"
> >  iommu_testdev_dma_result(uint32_t result) "DMA completed result=0x%x"
> >  iommu_testdev_dma_armed(bool armed) "armed=%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 = TT_ATLANTIS_PRCM(opaque);
> > +    TTAtlantisPRCMClass *c = TT_ATLANTIS_PRCM_GET_CLASS(s);
> > +    uint32_t data;
> > +
> > +    if (offset >= c->regs_size) {
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +        return 0;
> > +    }
> > +    data = 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 size) {
> Consider aligning the wrapped lines with the first parameter.
>
> > +    TTAtlantisPRCMState *s = TT_ATLANTIS_PRCM(opaque);
> > +    TTAtlantisPRCMClass *c = TT_ATLANTIS_PRCM_GET_CLASS(s);
> > +
> > +    trace_tt_atlantis_prcm_write(c->domain, offset, data);
> > +
> > +    if (offset >= c->regs_size) {
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +        return;
> > +    }
> > +
> > +    switch (TO_REG(offset)) {
> > +    default:
> > +        s->regs[TO_REG(offset)] = data;
> > +        break;
> > +    }
> > +}
> > +
> > +static void tt_atlantis_prcm_rcpu_write(void *opaque, hwaddr offset,
> > +                                            uint64_t data, unsigned size) {
> > +    TTAtlantisPRCMState *s = TT_ATLANTIS_PRCM(opaque);
> > +
> > +    tt_atlantis_prcm_write(opaque, offset, data, size);
> > +
> > +    bool pll_en_written = false;
> > +    uint32_t pll_reg_offset;
> > +    switch TO_REG(offset)
> > +    {
> > +        case RCPU_PLL_RCPU_EN:
> > +            pll_en_written = true;
> > +            pll_reg_offset = RCPU_PLL_RCPU_CFG;
> > +            break;
> This should follow the QEMU coding style:
>
>     switch (TO_REG(offset)) {
>     case RCPU_PLL_RCPU_EN:
>         pll_en_written = true;
>         pll_reg_offset = RCPU_PLL_RCPU_CFG;
>         break;
>     ...
>     case RCPU_PLL_I2S_EN:
>         pll_en_written = true;
>         pll_reg_offset = 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.