diff options
-rw-r--r-- | docs/platform/platform.md | 3 | ||||
-rw-r--r-- | docs/platform/thead-c910.md | 34 | ||||
-rw-r--r-- | platform/thead/c910/config.mk | 14 | ||||
-rw-r--r-- | platform/thead/c910/objects.mk | 5 | ||||
-rw-r--r-- | platform/thead/c910/platform.c | 159 | ||||
-rw-r--r-- | platform/thead/c910/platform.h | 51 |
6 files changed, 266 insertions, 0 deletions
diff --git a/docs/platform/platform.md b/docs/platform/platform.md index 424efe9..17cbfb8 100644 --- a/docs/platform/platform.md +++ b/docs/platform/platform.md @@ -26,6 +26,8 @@ OpenSBI currently supports the following virtual and hardware platforms: * **Andes AE350 SoC**: Platform support for the Andes's SoC (AE350). +* **T-HEAD C910**: Platform support for the T-HEAD C910 Processor. + The code for these supported platforms can be used as example to implement support for other platforms. The *platform/template* directory also provides template files for implementing support for a new platform. The *object.mk*, @@ -37,3 +39,4 @@ facilitate the implementation. [sifive_fu540.md]: sifive_fu540.md [ariane-fpga.md]: ariane-fpga.md [andes_ae350.md]: andes-ae350.md +[thead-c910.md]: thead-c910.md diff --git a/docs/platform/thead-c910.md b/docs/platform/thead-c910.md new file mode 100644 index 0000000..3ba0b96 --- /dev/null +++ b/docs/platform/thead-c910.md @@ -0,0 +1,34 @@ +T-HEAD C910 Processor +===================== +C910 is a 12-stage, 3 issues, 8 executions, out-of-order 64-bit RISC-V CPU which +supports 16 cores, runs with 2.5GHz, and is capable of running Linux. + +To build platform specific library and firmwares, provide the *PLATFORM=thead/c910* +parameter to the top level make command. + +Platform Options +---------------- + +The *T-HEAD C910* platform does not have any platform-specific options. + +Building T-HEAD C910 Platform +----------------------------- + +``` +make PLATFORM=thead/c910 +``` + +Booting T-HEAD C910 Platform +----------------------------- + +**No Payload** + +As there's no payload, you may download vmlinux or u-boot to FW_JUMP_ADDR which +specified in config.mk or compile commands with GDB. And the execution flow will +turn to vmlinux or u-boot when opensbi ends. + +**Linux Kernel Payload** + +You can also choose to use Linux kernel as payload by enabling FW_PAYLOAD=y +along with specifying FW_PAYLOAD_OFFSET. The kernel image will be embedded in +the OPENSBI firmware binary, T-head will directly boot into Linux after OpenSBI. diff --git a/platform/thead/c910/config.mk b/platform/thead/c910/config.mk new file mode 100644 index 0000000..bd5eab7 --- /dev/null +++ b/platform/thead/c910/config.mk @@ -0,0 +1,14 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Blobs to build +FW_TEXT_START?=0x0 +FW_JUMP=y +FW_JUMP_ADDR?=0x00200000 diff --git a/platform/thead/c910/objects.mk b/platform/thead/c910/objects.mk new file mode 100644 index 0000000..d025a36 --- /dev/null +++ b/platform/thead/c910/objects.mk @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +platform-objs-y += platform.o diff --git a/platform/thead/c910/platform.c b/platform/thead/c910/platform.c new file mode 100644 index 0000000..1ad3e49 --- /dev/null +++ b/platform/thead/c910/platform.c @@ -0,0 +1,159 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sbi/riscv_encoding.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_hart.h> +#include <sbi/sbi_platform.h> +#include <sbi/sbi_console.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/sys/clint.h> +#include <sbi_utils/serial/uart8250.h> +#include "platform.h" + +static struct c910_regs_struct c910_regs; + +static int c910_early_init(bool cold_boot) +{ + if (cold_boot) { + /* Load from boot core */ + c910_regs.pmpaddr0 = csr_read(CSR_PMPADDR0); + c910_regs.pmpaddr1 = csr_read(CSR_PMPADDR1); + c910_regs.pmpaddr2 = csr_read(CSR_PMPADDR2); + c910_regs.pmpaddr3 = csr_read(CSR_PMPADDR3); + c910_regs.pmpaddr4 = csr_read(CSR_PMPADDR4); + c910_regs.pmpaddr5 = csr_read(CSR_PMPADDR5); + c910_regs.pmpaddr6 = csr_read(CSR_PMPADDR6); + c910_regs.pmpaddr7 = csr_read(CSR_PMPADDR7); + c910_regs.pmpcfg0 = csr_read(CSR_PMPCFG0); + + c910_regs.mcor = csr_read(CSR_MCOR); + c910_regs.mhcr = csr_read(CSR_MHCR); + c910_regs.mccr2 = csr_read(CSR_MCCR2); + c910_regs.mhint = csr_read(CSR_MHINT); + c910_regs.mxstatus = csr_read(CSR_MXSTATUS); + } else { + /* Store to other core */ + csr_write(CSR_PMPADDR0, c910_regs.pmpaddr0); + csr_write(CSR_PMPADDR1, c910_regs.pmpaddr1); + csr_write(CSR_PMPADDR2, c910_regs.pmpaddr2); + csr_write(CSR_PMPADDR3, c910_regs.pmpaddr3); + csr_write(CSR_PMPADDR4, c910_regs.pmpaddr4); + csr_write(CSR_PMPADDR5, c910_regs.pmpaddr5); + csr_write(CSR_PMPADDR6, c910_regs.pmpaddr6); + csr_write(CSR_PMPADDR7, c910_regs.pmpaddr7); + csr_write(CSR_PMPCFG0, c910_regs.pmpcfg0); + + csr_write(CSR_MCOR, c910_regs.mcor); + csr_write(CSR_MHCR, c910_regs.mhcr); + csr_write(CSR_MCCR2, c910_regs.mccr2); + csr_write(CSR_MHINT, c910_regs.mhint); + csr_write(CSR_MXSTATUS, c910_regs.mxstatus); + } + + c910_regs.plic_base_addr = csr_read(CSR_PLIC_BASE); + c910_regs.clint_base_addr = + c910_regs.plic_base_addr + C910_PLIC_CLINT_OFFSET; + + return 0; +} + +static int c910_final_init(bool cold_boot) +{ + return 0; +} + +static int c910_irqchip_init(bool cold_boot) +{ + /* Delegate plic enable into S-mode */ + writel(C910_PLIC_DELEG_ENABLE, + (void *)c910_regs.plic_base_addr + C910_PLIC_DELEG_OFFSET); + + return 0; +} + +static int c910_ipi_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_ipi_init(c910_regs.clint_base_addr, C910_HART_COUNT); + if (rc) + return rc; + } + + return clint_warm_ipi_init(); +} + +static int c910_timer_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = clint_cold_timer_init(c910_regs.clint_base_addr, + C910_HART_COUNT, FALSE); + if (ret) + return ret; + } + + return clint_warm_timer_init(); +} + +static int c910_system_shutdown(u32 type) +{ + asm volatile ("ebreak"); + return 0; +} + +void sbi_boot_other_core(int hartid) +{ + csr_write(CSR_MRVBR, FW_TEXT_START); + csr_write(CSR_MRMR, csr_read(CSR_MRMR) | (1 << hartid)); +} + +static int c910_vendor_ext_provider(long extid, long funcid, + unsigned long *args, + unsigned long *out_value, + struct sbi_trap_info *out_trap) +{ + switch (extid) { + case SBI_EXT_VENDOR_C910_BOOT_OTHER_CORE: + sbi_boot_other_core((int)args[0]); + break; + default: + sbi_printf("Unsupported private sbi call: %ld\n", extid); + asm volatile ("ebreak"); + } + return 0; +} + +const struct sbi_platform_operations platform_ops = { + .early_init = c910_early_init, + .final_init = c910_final_init, + + .irqchip_init = c910_irqchip_init, + + .ipi_init = c910_ipi_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + + .timer_init = c910_timer_init, + .timer_event_start = clint_timer_event_start, + + .system_shutdown = c910_system_shutdown, + + .vendor_ext_provider = c910_vendor_ext_provider, +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "T-HEAD Xuantie c910", + .features = SBI_THEAD_FEATURES, + .hart_count = C910_HART_COUNT, + .hart_stack_size = C910_HART_STACK_SIZE, + .disabled_hart_mask = 0, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/platform/thead/c910/platform.h b/platform/thead/c910/platform.h new file mode 100644 index 0000000..bc176e5 --- /dev/null +++ b/platform/thead/c910/platform.h @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _C910_PLATFORM_H_ +#define _C910_PLATFORM_H_ + +#define C910_HART_COUNT 16 +#define C910_HART_STACK_SIZE 8192 + +#define SBI_THEAD_FEATURES \ + (SBI_PLATFORM_HAS_PMP | \ + SBI_PLATFORM_HAS_SCOUNTEREN | \ + SBI_PLATFORM_HAS_MCOUNTEREN | \ + SBI_PLATFORM_HAS_MFAULTS_DELEGATION) + +#define CSR_MCOR 0x7c2 +#define CSR_MHCR 0x7c1 +#define CSR_MCCR2 0x7c3 +#define CSR_MHINT 0x7c5 +#define CSR_MXSTATUS 0x7c0 +#define CSR_PLIC_BASE 0xfc1 +#define CSR_MRMR 0x7c6 +#define CSR_MRVBR 0x7c7 + +#define SBI_EXT_VENDOR_C910_BOOT_OTHER_CORE 0x09000003 + +#define C910_PLIC_CLINT_OFFSET 0x04000000 /* 64M */ +#define C910_PLIC_DELEG_OFFSET 0x001ffffc +#define C910_PLIC_DELEG_ENABLE 0x1 + +struct c910_regs_struct { + u64 pmpaddr0; + u64 pmpaddr1; + u64 pmpaddr2; + u64 pmpaddr3; + u64 pmpaddr4; + u64 pmpaddr5; + u64 pmpaddr6; + u64 pmpaddr7; + u64 pmpcfg0; + u64 mcor; + u64 mhcr; + u64 mccr2; + u64 mhint; + u64 mxstatus; + u64 plic_base_addr; + u64 clint_base_addr; +}; + +#endif /* _C910_PLATFORM_H_ */ |