mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-05-23 14:21:32 +01:00
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 <npiggin@gmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260424062520.238403-1-npiggin@gmail.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
committed by
Anup Patel
parent
1932ee3f0a
commit
6767861c48
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
# SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
config CPU_TENSTORRENT_ASCALON
|
||||
bool
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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
|
||||
@@ -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];
|
||||
}
|
||||
Reference in New Issue
Block a user