summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Piggin <[email protected]>2026-04-24 16:25:19 +1000
committerAnup Patel <[email protected]>2026-05-09 20:57:50 +0530
commit6767861c484d07f180f3dd710b5dc59f0c525374 (patch)
tree28afe2faf8b0286bcba5c0800fb2e33ed1940f27
parent1932ee3f0ae2f200431c20018e2d75dbceb65695 (diff)
platform: generic: Tenstorrent Atlantis support
Add the Tenstorrent Atlantis as a generic-platform. This initial support enables the single_fw_region option, and verifies and prints HART PMA CSR configuration. Signed-off-by: Nicholas Piggin <[email protected]> Reviewed-by: Anup Patel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
-rw-r--r--docs/platform/generic.md2
-rw-r--r--docs/platform/tt-atlantis.md35
-rw-r--r--platform/generic/Kconfig6
-rw-r--r--platform/generic/configs/defconfig1
-rw-r--r--platform/generic/include/tenstorrent/ascalon.h12
-rw-r--r--platform/generic/include/tenstorrent/pma.h17
-rw-r--r--platform/generic/tenstorrent/Kconfig5
-rw-r--r--platform/generic/tenstorrent/ascalon.c53
-rw-r--r--platform/generic/tenstorrent/atlantis.c50
-rw-r--r--platform/generic/tenstorrent/objects.mk12
-rw-r--r--platform/generic/tenstorrent/pma.c138
11 files changed, 331 insertions, 0 deletions
diff --git a/docs/platform/generic.md b/docs/platform/generic.md
index c48d6a9a..0b896ede 100644
--- a/docs/platform/generic.md
+++ b/docs/platform/generic.md
@@ -47,6 +47,7 @@ RISC-V Platforms Using Generic Platform
* **SiFive HiFive Unleashed** (*[sifive_fu540.md]*)
* **Spike** (*[spike.md]*)
* **T-HEAD C9xx series Processors** (*[thead-c9xx.md]*)
+* **Tenstorrent Atlantis Platform** (*[tt-atlantis.md]*)
* **OpenPiton FPGA SoC** (*[fpga-openpiton.md]*)
* **Ariane FPGA SoC** (*[fpga-ariane.md]*)
@@ -57,5 +58,6 @@ RISC-V Platforms Using Generic Platform
[sifive_fu540.md]: sifive_fu540.md
[spike.md]: spike.md
[thead-c9xx.md]: thead-c9xx.md
+[tt-atlantis.md]: tt-atlantis.md
[fpga-openpiton.md]: fpga-openpiton.md
[fpga-ariane.md]: fpga-ariane.md
diff --git a/docs/platform/tt-atlantis.md b/docs/platform/tt-atlantis.md
new file mode 100644
index 00000000..b9bdd238
--- /dev/null
+++ b/docs/platform/tt-atlantis.md
@@ -0,0 +1,35 @@
+Tenstorrent Atlantis Platform
+=============================
+
+The Tenstorrent Atlantis is an SoC and development board from
+Tenstorrent in partnership with CoreLab Technology. It contains 8 RISC-V
+RVA23 compliant Tenstorrent Ascalon cores with RISC-V AIA, RISC-V IOMMU,
+and a range of devices and IO connectivity.
+
+To build the platform-specific library and firmware images, provide the
+*PLATFORM=generic* parameter to the top level `make` command.
+
+Platform Options
+----------------
+
+The *Tenstorrent Atlantis* platform does not have any platform-specific
+options.
+
+Building Tenstorrent Atlantis Platform
+--------------------------------------
+
+The Atlantis Platform is still under development. This section will be
+expanded as firmware and support become available.
+
+QEMU support is currently being developed and initial support has been
+proposed for upstream. To run QEMU that is patched with 'tt-atlantis'
+machine support, run:
+
+```
+qemu-system-riscv64 -M tt-atlantis -nographic \
+ -bios build/platform/generic/firmware/fw_payload.bin \
+ -kernel <linux_build_dir>/Image
+```
+
+Recent (6.18) Linux/riscv 64-bit defconfig kernels should run the QEMU
+tt-atlantis machine.
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 600273d1..d594b140 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -89,6 +89,11 @@ config PLATFORM_STARFIVE_JH7110
bool "StarFive JH7110 support"
default n
+config PLATFORM_TENSTORRENT_ATLANTIS
+ bool "Tenstorrent Atlantis support"
+ select CPU_TENSTORRENT_ASCALON
+ default n
+
config PLATFORM_THEAD
bool "THEAD C9xx support"
select THEAD_C9XX_ERRATA
@@ -114,6 +119,7 @@ config PLATFORM_MIPS_P8700_BOSTON
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/eswin/Kconfig"
+source "$(OPENSBI_SRC_DIR)/platform/generic/tenstorrent/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
endif
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 1d3431e7..800f3f14 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -10,6 +10,7 @@ CONFIG_PLATFORM_SIFIVE_FU540=y
CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
+CONFIG_PLATFORM_TENSTORRENT_ATLANTIS=y
CONFIG_PLATFORM_THEAD=y
CONFIG_PLATFORM_MIPS_P8700_EYEQ7H=y
CONFIG_PLATFORM_MIPS_P8700_BOSTON=y
diff --git a/platform/generic/include/tenstorrent/ascalon.h b/platform/generic/include/tenstorrent/ascalon.h
new file mode 100644
index 00000000..5d7b7635
--- /dev/null
+++ b/platform/generic/include/tenstorrent/ascalon.h
@@ -0,0 +1,12 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __TENSTORRENT_ASCALON_H__
+#define __TENSTORRENT_ASCALON_H__
+
+void tt_ascalon_discover_pmas_from_boot_hart(void);
+void tt_ascalon_verify_pmas_nonboot_hart(void);
+
+#endif
diff --git a/platform/generic/include/tenstorrent/pma.h b/platform/generic/include/tenstorrent/pma.h
new file mode 100644
index 00000000..db8310e6
--- /dev/null
+++ b/platform/generic/include/tenstorrent/pma.h
@@ -0,0 +1,17 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __TENSTORRENT_PMA_H__
+#define __TENSTORRENT_PMA_H__
+
+/* Max number of PMAs for devices (CPU, IOMMU) for Tenstorrent platforms. */
+#define TT_MAX_PMAS 32
+
+u64 tt_pma_get(unsigned int n);
+void tt_pma_set(unsigned int n, u64 pma);
+bool tt_pma_validate(unsigned int i, u64 pma);
+void tt_pma_print(unsigned int i, u64 pma);
+
+#endif
diff --git a/platform/generic/tenstorrent/Kconfig b/platform/generic/tenstorrent/Kconfig
new file mode 100644
index 00000000..76c7fb32
--- /dev/null
+++ b/platform/generic/tenstorrent/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+# SPDX-License-Identifier: BSD-2-Clause
+
+config CPU_TENSTORRENT_ASCALON
+ bool
diff --git a/platform/generic/tenstorrent/ascalon.c b/platform/generic/tenstorrent/ascalon.c
new file mode 100644
index 00000000..485144cd
--- /dev/null
+++ b/platform/generic/tenstorrent/ascalon.c
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_csr_detect.h>
+
+#include <tenstorrent/ascalon.h>
+#include <tenstorrent/pma.h>
+
+#define CSR_PMACFG0 0x7e0
+
+void tt_ascalon_discover_pmas_from_boot_hart(void)
+{
+ struct sbi_trap_info trap = {0};
+
+ /* Whisper virtual platform does not implement PMA */
+ csr_read_allowed(CSR_PMACFG0, &trap);
+ if (trap.cause)
+ return;
+
+ for (unsigned int i = 0; i < TT_MAX_PMAS; i++) {
+ u64 pma = csr_read_num(CSR_PMACFG0 + i);
+ if (!tt_pma_validate(i, pma)) {
+ sbi_printf("HART%d: Bad boot PMA%02d 0x%016lx\n",
+ current_hartid(), i, pma);
+ }
+ tt_pma_set(i, pma);
+
+ if (pma)
+ tt_pma_print(i, pma);
+ }
+}
+
+void tt_ascalon_verify_pmas_nonboot_hart(void)
+{
+ struct sbi_trap_info trap = {0};
+
+ /* Whisper virtual platform does not implement PMA */
+ csr_read_allowed(CSR_PMACFG0, &trap);
+ if (trap.cause)
+ return;
+
+ for (unsigned int i = 0; i < TT_MAX_PMAS; i++) {
+ u64 pma = csr_read_num(CSR_PMACFG0 + i);
+ if (pma != tt_pma_get(i)) {
+ sbi_printf("HART%d: Bad boot PMA%02d 0x%016lx does not match boot HART\n",
+ current_hartid(), i, pma);
+ }
+ }
+}
diff --git a/platform/generic/tenstorrent/atlantis.c b/platform/generic/tenstorrent/atlantis.c
new file mode 100644
index 00000000..4c312f7e
--- /dev/null
+++ b/platform/generic/tenstorrent/atlantis.c
@@ -0,0 +1,50 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <platform_override.h>
+#include <libfdt.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_console.h>
+
+#include <tenstorrent/ascalon.h>
+#include <tenstorrent/pma.h>
+
+static int tt_atlantis_final_init(bool cold_boot)
+{
+ if (cold_boot) {
+ /* Boot firmware sets HART PMAs. Read and verify them. */
+ tt_ascalon_discover_pmas_from_boot_hart();
+ } else {
+ /* Verify nonboot HARTs have PMAs matching boot HART */
+ tt_ascalon_verify_pmas_nonboot_hart();
+ }
+
+ return generic_final_init(cold_boot);
+}
+
+static bool tt_atlantis_single_fw_region(void)
+{
+ return true;
+}
+
+static int tt_atlantis_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+ generic_platform_ops.final_init = tt_atlantis_final_init;
+ generic_platform_ops.single_fw_region = tt_atlantis_single_fw_region;
+
+ return 0;
+}
+
+static const struct fdt_match tt_atlantis_match[] = {
+ { .compatible = "tenstorrent,atlantis" },
+ { },
+};
+
+const struct fdt_driver tenstorrent_atlantis = {
+ .match_table = tt_atlantis_match,
+ .init = tt_atlantis_platform_init,
+};
diff --git a/platform/generic/tenstorrent/objects.mk b/platform/generic/tenstorrent/objects.mk
new file mode 100644
index 00000000..17da2c5e
--- /dev/null
+++ b/platform/generic/tenstorrent/objects.mk
@@ -0,0 +1,12 @@
+#
+# SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN), 64)
+platform-objs-y += tenstorrent/pma.o
+platform-objs-$(CONFIG_CPU_TENSTORRENT_ASCALON) += tenstorrent/ascalon.o
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_TENSTORRENT_ATLANTIS) += tenstorrent_atlantis
+platform-objs-$(CONFIG_PLATFORM_TENSTORRENT_ATLANTIS) += tenstorrent/atlantis.o
+endif
diff --git a/platform/generic/tenstorrent/pma.c b/platform/generic/tenstorrent/pma.c
new file mode 100644
index 00000000..daf60192
--- /dev/null
+++ b/platform/generic/tenstorrent/pma.c
@@ -0,0 +1,138 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_math.h>
+#include <libfdt.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+
+#include <tenstorrent/pma.h>
+
+/*
+ * All PMAs in the system should be the same (after boot). The init code
+ * must have set PMAs for all HARTs.
+ */
+
+/*
+ * Ascalon CPU and IOMMU PMA layout:
+ * Field
+ * [2:0] Permission [0] Read, [1] Write, [2] Execute
+ * [4:3] Memory type 00: Main memory, 01: IO memory relaxed,
+ * 10: IO memory channel 0, 11: IO memory channel 1
+ * [6:5] AMO type 00: AMONone, 01: AMOSwap,
+ * 10: AMOLogical, 11: AMOArithmetic
+ * [7] Cacheability (main memory type)
+ * 1: Cacheable, 0: Non-cacheable
+ * Combining Capability (IO memory type)
+ * 1: Combining allowed, 0: Combining disallowed
+ * [8] Routing (coherency)
+ * 1: Coherent network, 0: Non-coherent network
+ * [11:9] Reserved
+ * [51:12] Physical address [51:12] base
+ * [63:58] Size log 2 (number of address LSB to ignore when matching)
+ * 0 = invalid entry (no match)
+ */
+
+#define PMA_PERMISSION_R 0x1
+#define PMA_PERMISSION_W 0x2
+#define PMA_PERMISSION_X 0x4
+#define PMA_PERMISSION_MASK 0x7
+
+#define PMA_TYPE_MAIN_MEMORY 0x0
+#define PMA_TYPE_IO_RELAXED 0x8
+#define PMA_TYPE_IO_ORDERED_0 0x10
+#define PMA_TYPE_IO_ORDERED_1 0x18
+#define PMA_TYPE_MASK 0x18
+
+#define PMA_AMO_NONE 0x0
+#define PMA_AMO_SWAP 0x20
+#define PMA_AMO_LOGICAL 0x40
+#define PMA_AMO_ARITHMETIC 0x60
+#define PMA_AMO_MASK 0x60
+
+#define PMA_MEMORY_CACHEABLE 0x80
+#define PMA_IO_COMBINING 0x80
+#define PMA_ROUTING_COHERENT 0x100
+
+#define PMA_FLAGS_MASK 0x00000000000001ffULL
+#define PMA_ADDRESS_MASK 0x000ffffffffff000ULL
+#define PMA_SIZE_MASK 0xfc00000000000000ULL
+#define PMA_RESERVED_MASK 0x0300000000000e00ULL
+
+#define PMA_SIZE_SHIFT 58
+
+static u64 tt_pma_size(u64 pma)
+{
+ if ((pma & PMA_SIZE_MASK) == 0)
+ return 0;
+
+ return 1ULL << ((pma & PMA_SIZE_MASK) >> PMA_SIZE_SHIFT);
+}
+
+static u64 tt_pma_address(u64 pma)
+{
+ return (pma & PMA_ADDRESS_MASK) & ~((tt_pma_size(pma) - 1));
+}
+
+bool tt_pma_validate(unsigned int i, u64 pma)
+{
+ if (!pma)
+ return true;
+
+ if (pma & PMA_RESERVED_MASK) {
+ sbi_printf("PMA%02u 0x%016lx contains reserved bits\n", i, pma);
+ return false;
+ }
+
+ if (tt_pma_size(pma) < 4096) {
+ sbi_printf("PMA%02u 0x%016lx size < 4KB\n", i, pma);
+ return false;
+ }
+
+ if (tt_pma_address(pma) != (pma & PMA_ADDRESS_MASK)) {
+ sbi_printf("PMA%02u 0x%016lx address is not aligned to size\n", i, pma);
+ return false;
+ }
+
+ return true;
+}
+
+void tt_pma_print(unsigned int i, u64 pma)
+{
+ sbi_printf("PMA%02d : 0x%016lx-0x%016lx perm:%s%s%s type:%s %s %s amo:%s\n", i,
+ tt_pma_address(pma), tt_pma_address(pma) + tt_pma_size(pma) - 1,
+ pma & PMA_PERMISSION_R ? "R" : " ",
+ pma & PMA_PERMISSION_W ? "W" : " ",
+ pma & PMA_PERMISSION_X ? "X" : " ",
+ (pma & PMA_TYPE_MASK) == PMA_TYPE_MAIN_MEMORY ? "main-memory" :
+ ((pma & PMA_TYPE_MASK) == PMA_TYPE_IO_RELAXED ? "io-relaxed" :
+ ((pma & PMA_TYPE_MASK) == PMA_TYPE_IO_ORDERED_0 ? "io-ordered-0" : "io-ordered-1")),
+ (pma & PMA_TYPE_MASK) == PMA_TYPE_MAIN_MEMORY ?
+ (pma & PMA_MEMORY_CACHEABLE ? "cacheable" : "non-cacheable") :
+ (pma & PMA_IO_COMBINING ? "combining" : "non-combining"),
+ pma & PMA_ROUTING_COHERENT ? "coherent" : "non-coherent",
+ (pma & PMA_AMO_MASK) == PMA_AMO_NONE ? "none" :
+ ((pma & PMA_AMO_MASK) == PMA_AMO_SWAP ? "swap" :
+ ((pma & PMA_AMO_MASK) == PMA_AMO_LOGICAL ? "logical" : "arithmetic")));
+}
+
+static u64 pmas[TT_MAX_PMAS];
+
+void tt_pma_set(unsigned int n, u64 pma)
+{
+ if (n >= TT_MAX_PMAS)
+ sbi_panic("PMA exceeded TT_MAX_PMAS");
+
+ pmas[n] = pma;
+}
+
+u64 tt_pma_get(unsigned int n)
+{
+ if (n >= TT_MAX_PMAS)
+ sbi_panic("PMA exceeded TT_MAX_PMAS");
+
+ return pmas[n];
+}