Hi Alistair,
On Thu, Aug 27, 2026 at 9:01 PM Alistair Francis
<[email protected]> wrote:
>
> On Mon, 2026-08-17 at 09:42 -0500, Anirudh Srinivasan wrote:
> > Atlantis has 4 PRCMs that are visible from S mode by the Ascalon Core
> > (RCPU, HSIO, PCIe and MM). This commit adds these 4 PRCM blocks to
> > the
> > tt-atlantis model, along with necessary device tree nodes for them.
> >
> > Reviewed-by: Chao Liu <[email protected]>
> > Signed-off-by: Anirudh Srinivasan <[email protected]>
> > ---
> > docs/system/riscv/tt_atlantis.rst | 1 +
> > hw/riscv/tt_atlantis.c | 94
> > +++++++++++++++++++++++++++++++++++++++
> > include/hw/riscv/tt_atlantis.h | 19 ++++++++
> > 3 files changed, 114 insertions(+)
> >
> > diff --git a/docs/system/riscv/tt_atlantis.rst
> > b/docs/system/riscv/tt_atlantis.rst
> > index 1f2880d617..539c22354f 100644
> > --- a/docs/system/riscv/tt_atlantis.rst
> > +++ b/docs/system/riscv/tt_atlantis.rst
> > @@ -14,6 +14,7 @@ tt-atlantis QEMU model features
> > * 8-core Ascalon-X CPU Cluster
> > * RISC-V compliant Advanced Interrupt Architecture
> > * 16550A compatible UART
> > +* 4 PRCMs (Clock and Reset Controllers)
> >
> > Known limitations
> > -----------------
> > diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
> > index d808bcc11c..9ebba07703 100644
> > --- a/hw/riscv/tt_atlantis.c
> > +++ b/hw/riscv/tt_atlantis.c
> > @@ -26,6 +26,7 @@
> > #include "hw/char/serial-mm.h"
> > #include "hw/intc/riscv_aclint.h"
> > #include "hw/misc/unimp.h"
> > +#include "hw/misc/tt_atlantis_prcm.h"
> >
> > #include "system/system.h"
> > #include "system/device_tree.h"
> > @@ -59,6 +60,10 @@ static const MemMapEntry tt_atlantis_memmap[] = {
> > [TT_ATL_I2C3] = { 0xd4070000, 0x10000 },
> > [TT_ATL_I2C4] = { 0xd4080000, 0x10000 },
> > [TT_ATL_UART1] = { 0xd4110000, 0x10000 },
> > + [TT_ATL_PRCM_RCPU] = { 0xd0000000, 0x10000 },
> > + [TT_ATL_PRCM_PCIE] = { 0xd8000000, 0x100 },
> > + [TT_ATL_PRCM_MM] = { 0xdc000000, 0x1000 },
> > + [TT_ATL_PRCM_HSIO] = { 0xe00c0000, 0x510 },
> > [TT_ATL_SAPLIC] = { 0xe8000000, 0x4000000 },
> > [TT_ATL_DDR_HI] = { 0x100000000, 0x1000000000 },
> > };
> > @@ -328,11 +333,35 @@ static void
> > create_fdt_i2c_device(TTAtlantisState *s, int bus,
> > qemu_fdt_setprop_cell(fdt, name, "reg", addr);
> > }
> >
> > +static char *create_fdt_prcm(void *fdt, const MemMapEntry *mem,
> > + const char *prcm_name)
> > +{
> > + hwaddr base = mem->base;
> > + hwaddr size = mem->size;
> > + char *name = g_strdup_printf("/soc/prcm_%s@%" PRIx64,
> > + prcm_name, mem->base);
> > + g_autofree char *compatible =
> > + g_strdup_printf("tenstorrent,atlantis-prcm-%s", prcm_name);
> > +
> > + qemu_fdt_add_subnode(fdt, name);
> > + qemu_fdt_setprop_string(fdt, name, "compatible", compatible);
> > + qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, base, 2,
> > size);
> > + qemu_fdt_setprop_cell(fdt, name, "#address-cells", 1);
> > + qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0);
> > + qemu_fdt_setprop_cell(fdt, name, "#clock-cells", 1);
> > + qemu_fdt_setprop_cell(fdt, name, "#reset-cells", 1);
> > + qemu_fdt_setprop_cell(fdt, name, "phandle", next_phandle());
> > +
> > + return name;
> > +}
> > +
> > static void finalize_fdt(TTAtlantisState *s)
> > {
> > uint32_t aplic_s_phandle = next_phandle();
> > uint32_t imsic_s_phandle = next_phandle();
> > uint32_t periph_clk_phandle = next_phandle();
> > + uint32_t osc_24m_phandle = next_phandle();
> > + uint32_t prcm_rcpu_phandle;
> > void *fdt = MACHINE(s)->fdt;
> >
> > create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle);
> > @@ -348,6 +377,34 @@ static void finalize_fdt(TTAtlantisState *s)
> > aplic_s_phandle);
> >
> > create_fdt_clk(fdt, "periph-clk", 100000000,
> > periph_clk_phandle);
> > + create_fdt_clk(fdt, "osc_24m", 24000000, osc_24m_phandle);
> > +
> > + g_autofree char *rcpu_name = create_fdt_prcm(fdt,
> > + &s->memmap[TT_ATL_PRCM_RCPU], "rcpu");
>
> Please don't mix code and declarations
Yes, will fix. Checkpatch didn't seem to complain about these.
>
> > + prcm_rcpu_phandle = qemu_fdt_get_phandle(fdt, rcpu_name);
> > + qemu_fdt_setprop_cells(fdt, rcpu_name, "clocks",
> > osc_24m_phandle);
> > + qemu_fdt_setprop_cells(fdt, rcpu_name, "assigned-clocks",
> > + prcm_rcpu_phandle, TT_ATL_CLK_RCPU_ROOT,
> > + prcm_rcpu_phandle, TT_ATL_CLK_NOCC_CLK);
> > + qemu_fdt_setprop_cells(fdt, rcpu_name, "assigned-clock-parents",
> > + prcm_rcpu_phandle, TT_ATL_CLK_RCPU_PLL,
> > + prcm_rcpu_phandle, TT_ATL_CLK_NOC_PLL);
> > +
> > + g_autofree char *hsio_name = create_fdt_prcm(fdt,
> > + &s->memmap[TT_ATL_PRCM_HSIO], "hsio");
> > + qemu_fdt_setprop_cells(fdt, hsio_name, "clocks",
> > osc_24m_phandle,
> > + prcm_rcpu_phandle, TT_ATL_CLK_HSIO_PLL);
> > +
> > + g_autofree char *pcie_name = create_fdt_prcm(fdt,
> > + &s->memmap[TT_ATL_PRCM_PCIE], "pcie");
> > + qemu_fdt_setprop_cells(fdt, pcie_name, "clocks",
> > osc_24m_phandle,
> > + prcm_rcpu_phandle, TT_ATL_CLK_PCIE_PLL);
> > +
> > + g_autofree char *mm_name = create_fdt_prcm(fdt,
> > + &s->memmap[TT_ATL_PRCM_MM], "mm");
> > + qemu_fdt_setprop_cells(fdt, mm_name, "clocks", osc_24m_phandle,
> > + prcm_rcpu_phandle, TT_ATL_CLK_MM_PLL0,
> > + prcm_rcpu_phandle, TT_ATL_CLK_MM_PLL1);
> >
> > for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
> > create_fdt_i2c(fdt,
> > @@ -545,6 +602,43 @@ static void
> > tt_atlantis_machine_init(MachineState *machine)
> > serial_mm_init(system_memory, s->memmap[TT_ATL_UART1].base, 2,
> > qdev_get_gpio_in(s->irqchip, TT_ATL_UART1_IRQ),
> > 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
> > +
> > + /* Add rcpu prcm block */
> > + object_initialize_child(OBJECT(s), "prcm-rcpu", &s->prcm[0],
> > + TYPE_TT_ATLANTIS_PRCM_RCPU);
> > + sysbus_realize(SYS_BUS_DEVICE(&s->prcm[0]), &error_fatal);
> > + memory_region_add_subregion(system_memory,
> > + s->memmap[TT_ATL_PRCM_RCPU].base,
> > + sysbus_mmio_get_region(
> > + SYS_BUS_DEVICE(&s->prcm[0]),
> > 0));
> > +
> > + /* Add hsio prcm block */
> > + object_initialize_child(OBJECT(s), "prcm-hsio", &s->prcm[1],
> > + TYPE_TT_ATLANTIS_PRCM_HSIO);
> > + sysbus_realize(SYS_BUS_DEVICE(&s->prcm[1]), &error_fatal);
> > + memory_region_add_subregion(system_memory,
> > + s->memmap[TT_ATL_PRCM_HSIO].base,
> > + sysbus_mmio_get_region(
> > + SYS_BUS_DEVICE(&s->prcm[1]),
> > 0));
> > +
> > + /* Add pcie prcm block */
> > + object_initialize_child(OBJECT(s), "prcm-pcie", &s->prcm[2],
> > + TYPE_TT_ATLANTIS_PRCM_PCIE);
> > + sysbus_realize(SYS_BUS_DEVICE(&s->prcm[2]), &error_fatal);
> > + memory_region_add_subregion(system_memory,
> > + s->memmap[TT_ATL_PRCM_PCIE].base,
> > + sysbus_mmio_get_region(
> > + SYS_BUS_DEVICE(&s->prcm[2]),
> > 0));
> > +
> > + /* Add mm prcm block */
> > + object_initialize_child(OBJECT(s), "prcm-mm", &s->prcm[3],
> > + TYPE_TT_ATLANTIS_PRCM_MM);
> > + sysbus_realize(SYS_BUS_DEVICE(&s->prcm[3]), &error_fatal);
> > + memory_region_add_subregion(system_memory,
> > + s->memmap[TT_ATL_PRCM_MM].base,
> > + sysbus_mmio_get_region(
> > + SYS_BUS_DEVICE(&s->prcm[3]),
>
> You should be able to use your `PRCM_DOMAIN_*` enums here
Ack.
>
> > 0));
> > +
> > /*
> > * Atlantis contains a DesignWare uart while the QEMU machine
> > * uses the serial_mm model with the base ns16550 register set.
> > diff --git a/include/hw/riscv/tt_atlantis.h
> > b/include/hw/riscv/tt_atlantis.h
> > index 7f7d4a5a59..20bcdfeb52 100644
> > --- a/include/hw/riscv/tt_atlantis.h
> > +++ b/include/hw/riscv/tt_atlantis.h
> > @@ -13,12 +13,14 @@
> > #include "hw/core/sysbus.h"
> > #include "hw/i2c/designware_i2c.h"
> > #include "hw/intc/riscv_imsic.h"
> > +#include "hw/misc/tt_atlantis_prcm.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)
> >
> > #define TT_ATL_NUM_I2C 5
> > +#define TT_ATL_NUM_PRCM 4
>
> What about the other 2?
The other 2 aren't accessible from the Ascalon cores in Atlantis
(which is what we have modelled currently in the qemu machine), so I
haven't mapped them in. They're accessible from another rv32 core in
the soc which is part of the boot flow, and will be mapped in when
that is added to the qemu machine.
>
> Alistair
>
> >
> > struct TTAtlantisState {
> > /*< private >*/
> > @@ -31,6 +33,7 @@ struct TTAtlantisState {
> > RISCVHartArrayState soc;
> > DeviceState *irqchip;
> > DesignWareI2CState i2c[TT_ATL_NUM_I2C];
> > + TTAtlantisPRCMState prcm[TT_ATL_NUM_PRCM];
> >
> > int fdt_size;
> > };
> > @@ -59,6 +62,22 @@ enum {
> > TT_ATL_SAPLIC,
> > TT_ATL_SIMSIC,
> > TT_ATL_UART1,
> > + TT_ATL_PRCM_RCPU,
> > + TT_ATL_PRCM_HSIO,
> > + TT_ATL_PRCM_PCIE,
> > + TT_ATL_PRCM_MM,
> > +};
> > +
> > +/* RCPU PRCM Clock IDs */
> > +enum {
> > + TT_ATL_CLK_RCPU_PLL = 0,
> > + TT_ATL_CLK_RCPU_ROOT = 1,
> > + TT_ATL_CLK_NOC_PLL = 25,
> > + TT_ATL_CLK_NOCC_CLK = 26,
> > + TT_ATL_CLK_HSIO_PLL = 54,
> > + TT_ATL_CLK_PCIE_PLL = 55,
> > + TT_ATL_CLK_MM_PLL0 = 56,
> > + TT_ATL_CLK_MM_PLL1 = 57,
> > };
> >
> > #endif