diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/opensbi/platform | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/opensbi/platform')
39 files changed, 2951 insertions, 0 deletions
diff --git a/roms/opensbi/platform/andes/ae350/cache.c b/roms/opensbi/platform/andes/ae350/cache.c new file mode 100644 index 000000000..af724c5c7 --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/cache.c @@ -0,0 +1,89 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Andes Technology Corporation + * + * Authors: + * Nylon Chen <nylon7@andestech.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_types.h> +#include "platform.h" + +uintptr_t mcall_set_mcache_ctl(unsigned long input) +{ + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_MASK); + csr_write(CSR_MCACHECTL, input); + return 0; +} + +uintptr_t mcall_set_mmisc_ctl(unsigned long input) +{ + csr_clear(CSR_MMISCCTL, V5_MMISC_CTL_MASK); + csr_write(CSR_MMISCCTL, input); + return 0; +} + +uintptr_t mcall_icache_op(unsigned int enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_IC_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_IC_EN); + asm volatile("fence.i\n\t"); + } + return 0; +} + +uintptr_t mcall_dcache_op(unsigned int enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_DC_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_DC_EN); + csr_write(CSR_MCCTLCOMMAND, V5_UCCTL_L1D_WBINVAL_ALL); + } + return 0; +} + +uintptr_t mcall_l1_cache_i_prefetch_op(unsigned long enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_L1I_PREFETCH_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_L1I_PREFETCH_EN); + } + return 0; +} + +uintptr_t mcall_l1_cache_d_prefetch_op(unsigned long enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_L1D_PREFETCH_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_L1D_PREFETCH_EN); + } + return 0; +} + +uintptr_t mcall_non_blocking_load_store(unsigned long enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MMISC_CTL_NON_BLOCKING_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MMISC_CTL_NON_BLOCKING_EN); + } + return 0; +} + +uintptr_t mcall_write_around(unsigned long enable) +{ + if (enable) { + csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_DC_WAROUND_1_EN); + } else { + csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_DC_WAROUND_1_EN); + } + return 0; +} diff --git a/roms/opensbi/platform/andes/ae350/cache.h b/roms/opensbi/platform/andes/ae350/cache.h new file mode 100644 index 000000000..e1c1826f3 --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/cache.h @@ -0,0 +1,17 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Andes Technology Corporation + * + * Authors: + * Nylon Chen <nylon7@andestech.com> + */ + +uintptr_t mcall_set_mcache_ctl(unsigned long input); +uintptr_t mcall_set_mmisc_ctl(unsigned long input); +uintptr_t mcall_icache_op(unsigned int enable); +uintptr_t mcall_dcache_op(unsigned int enable); +uintptr_t mcall_l1_cache_i_prefetch_op(unsigned long enable); +uintptr_t mcall_l1_cache_d_prefetch_op(unsigned long enable); +uintptr_t mcall_non_blocking_load_store(unsigned long enable); +uintptr_t mcall_write_around(unsigned long enable); diff --git a/roms/opensbi/platform/andes/ae350/config.mk b/roms/opensbi/platform/andes/ae350/config.mk new file mode 100644 index 000000000..f555ef5be --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/config.mk @@ -0,0 +1,36 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Andes Technology Corporation +# +# Authors: +# Zong Li <zong@andestech.com> +# Nylon Chen <nylon7@andestech.com> + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Blobs to build +FW_TEXT_START=0x00000000 + +FW_DYNAMIC=y + +FW_JUMP=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + FW_JUMP_ADDR=0x400000 +else + FW_JUMP_ADDR=0x200000 +endif +FW_JUMP_FDT_ADDR=0x2000000 + +FW_PAYLOAD=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + FW_PAYLOAD_OFFSET=0x400000 +else + FW_PAYLOAD_OFFSET=0x200000 +endif + +FW_PAYLOAD_FDT_ADDR=0x2000000 diff --git a/roms/opensbi/platform/andes/ae350/objects.mk b/roms/opensbi/platform/andes/ae350/objects.mk new file mode 100644 index 000000000..5369677c3 --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/objects.mk @@ -0,0 +1,11 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Andes Technology Corporation +# +# Authors: +# Zong Li <zong@andestech.com> +# Nylon Chen <nylon7@andestech.com> +# + +platform-objs-y += cache.o platform.o plicsw.o plmt.o diff --git a/roms/opensbi/platform/andes/ae350/platform.c b/roms/opensbi/platform/andes/ae350/platform.c new file mode 100644 index 000000000..aec91cdff --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/platform.c @@ -0,0 +1,192 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + * Nylon Chen <nylon7@andestech.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_platform.h> +#include <sbi/sbi_trap.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/uart8250.h> +#include "platform.h" +#include "plicsw.h" +#include "plmt.h" +#include "cache.h" + +static struct plic_data plic = { + .addr = AE350_PLIC_ADDR, + .num_src = AE350_PLIC_NUM_SOURCES, +}; + +/* Platform final initialization. */ +static int ae350_final_init(bool cold_boot) +{ + void *fdt; + + /* enable L1 cache */ + uintptr_t mcache_ctl_val = csr_read(CSR_MCACHECTL); + + if (!(mcache_ctl_val & V5_MCACHE_CTL_IC_EN)) + mcache_ctl_val |= V5_MCACHE_CTL_IC_EN; + if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_EN)) + mcache_ctl_val |= V5_MCACHE_CTL_DC_EN; + if (!(mcache_ctl_val & V5_MCACHE_CTL_CCTL_SUEN)) + mcache_ctl_val |= V5_MCACHE_CTL_CCTL_SUEN; + csr_write(CSR_MCACHECTL, mcache_ctl_val); + + /* enable L2 cache */ + uint32_t *l2c_ctl_base = (void *)AE350_L2C_ADDR + V5_L2C_CTL_OFFSET; + uint32_t l2c_ctl_val = *l2c_ctl_base; + + if (!(l2c_ctl_val & V5_L2C_CTL_ENABLE_MASK)) + l2c_ctl_val |= V5_L2C_CTL_ENABLE_MASK; + *l2c_ctl_base = l2c_ctl_val; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + fdt_fixups(fdt); + + return 0; +} + +/* Initialize the platform console. */ +static int ae350_console_init(void) +{ + return uart8250_init(AE350_UART_ADDR, + AE350_UART_FREQUENCY, + AE350_UART_BAUDRATE, + AE350_UART_REG_SHIFT, + AE350_UART_REG_WIDTH); +} + +/* Initialize the platform interrupt controller for current HART. */ +static int ae350_irqchip_init(bool cold_boot) +{ + u32 hartid = current_hartid(); + int ret; + + if (cold_boot) { + ret = plic_cold_irqchip_init(&plic); + if (ret) + return ret; + } + + return plic_warm_irqchip_init(&plic, 2 * hartid, 2 * hartid + 1); +} + +/* Initialize IPI for current HART. */ +static int ae350_ipi_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = plicsw_cold_ipi_init(AE350_PLICSW_ADDR, + AE350_HART_COUNT); + if (ret) + return ret; + } + + return plicsw_warm_ipi_init(); +} + +/* Initialize platform timer for current HART. */ +static int ae350_timer_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = plmt_cold_timer_init(AE350_PLMT_ADDR, + AE350_HART_COUNT); + if (ret) + return ret; + } + + return plmt_warm_timer_init(); +} + +/* Vendor-Specific SBI handler */ +static int ae350_vendor_ext_provider(long extid, long funcid, + const struct sbi_trap_regs *regs, unsigned long *out_value, + struct sbi_trap_info *out_trap) +{ + int ret = 0; + switch (funcid) { + case SBI_EXT_ANDES_GET_MCACHE_CTL_STATUS: + *out_value = csr_read(CSR_MCACHECTL); + break; + case SBI_EXT_ANDES_GET_MMISC_CTL_STATUS: + *out_value = csr_read(CSR_MMISCCTL); + break; + case SBI_EXT_ANDES_SET_MCACHE_CTL: + ret = mcall_set_mcache_ctl(regs->a0); + break; + case SBI_EXT_ANDES_SET_MMISC_CTL: + ret = mcall_set_mmisc_ctl(regs->a0); + break; + case SBI_EXT_ANDES_ICACHE_OP: + ret = mcall_icache_op(regs->a0); + break; + case SBI_EXT_ANDES_DCACHE_OP: + ret = mcall_dcache_op(regs->a0); + break; + case SBI_EXT_ANDES_L1CACHE_I_PREFETCH: + ret = mcall_l1_cache_i_prefetch_op(regs->a0); + break; + case SBI_EXT_ANDES_L1CACHE_D_PREFETCH: + ret = mcall_l1_cache_d_prefetch_op(regs->a0); + break; + case SBI_EXT_ANDES_NON_BLOCKING_LOAD_STORE: + ret = mcall_non_blocking_load_store(regs->a0); + break; + case SBI_EXT_ANDES_WRITE_AROUND: + ret = mcall_write_around(regs->a0); + break; + default: + sbi_printf("Unsupported vendor sbi call : %ld\n", funcid); + asm volatile("ebreak"); + } + return ret; +} + +/* Platform descriptor. */ +const struct sbi_platform_operations platform_ops = { + .final_init = ae350_final_init, + + .console_init = ae350_console_init, + .console_putc = uart8250_putc, + .console_getc = uart8250_getc, + + .irqchip_init = ae350_irqchip_init, + + .ipi_init = ae350_ipi_init, + .ipi_send = plicsw_ipi_send, + .ipi_clear = plicsw_ipi_clear, + + .timer_init = ae350_timer_init, + .timer_value = plmt_timer_value, + .timer_event_start = plmt_timer_event_start, + .timer_event_stop = plmt_timer_event_stop, + + .vendor_ext_provider = ae350_vendor_ext_provider +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "Andes AE350", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = AE350_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/andes/ae350/platform.h b/roms/opensbi/platform/andes/ae350/platform.h new file mode 100644 index 000000000..f34ca0fcc --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/platform.h @@ -0,0 +1,125 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + * Nylon Chen <nylon7@andestech.com> + */ + +#ifndef _AE350_PLATFORM_H_ +#define _AE350_PLATFORM_H_ + +#define AE350_HART_COUNT 4 + +#define AE350_PLIC_ADDR 0xe4000000 +#define AE350_PLIC_NUM_SOURCES 71 + +#define AE350_PLICSW_ADDR 0xe6400000 + +#define AE350_PLMT_ADDR 0xe6000000 + +#define AE350_L2C_ADDR 0xe0500000 + +#define AE350_UART_ADDR_OFFSET 0x20 +#define AE350_UART_ADDR (0xf0300000 + AE350_UART_ADDR_OFFSET) +#define AE350_UART_FREQUENCY 19660800 +#define AE350_UART_BAUDRATE 38400 +#define AE350_UART_REG_SHIFT 2 +#define AE350_UART_REG_WIDTH 0 + +/*Memory and Miscellaneous Registers*/ +#define CSR_MILMB 0x7c0 +#define CSR_MDLMB 0x7c1 +#define CSR_MECC_CDOE 0x7c2 +#define CSR_MNVEC 0x7c3 +#define CSR_MPFTCTL 0x7c5 +#define CSR_MCACHECTL 0x7ca +#define CSR_MCCTLBEGINADDR 0x7cb +#define CSR_MCCTLCOMMAND 0x7cc +#define CSR_MCCTLDATA 0x7cc +#define CSR_SCCTLDATA 0x9cd +#define CSR_UCCTLBEGINADDR 0x80c +#define CSR_MMISCCTL 0x7d0 + +enum sbi_ext_andes_fid { + SBI_EXT_ANDES_GET_MCACHE_CTL_STATUS = 0, + SBI_EXT_ANDES_GET_MMISC_CTL_STATUS, + SBI_EXT_ANDES_SET_MCACHE_CTL, + SBI_EXT_ANDES_SET_MMISC_CTL, + SBI_EXT_ANDES_ICACHE_OP, + SBI_EXT_ANDES_DCACHE_OP, + SBI_EXT_ANDES_L1CACHE_I_PREFETCH, + SBI_EXT_ANDES_L1CACHE_D_PREFETCH, + SBI_EXT_ANDES_NON_BLOCKING_LOAD_STORE, + SBI_EXT_ANDES_WRITE_AROUND, +}; + +/* nds v5 mmisc_ctl register*/ +#define V5_MMISC_CTL_VEC_PLIC_OFFSET 1 +#define V5_MMISC_CTL_RVCOMPM_OFFSET 2 +#define V5_MMISC_CTL_BRPE_OFFSET 3 +#define V5_MMISC_CTL_MSA_OR_UNA_OFFSET 6 +#define V5_MMISC_CTL_NON_BLOCKING_OFFSET 8 +#define V5_MCACHE_CTL_L1I_PREFETCH_OFFSET 9 +#define V5_MCACHE_CTL_L1D_PREFETCH_OFFSET 10 +#define V5_MCACHE_CTL_DC_WAROUND_OFFSET_1 13 +#define V5_MCACHE_CTL_DC_WAROUND_OFFSET_2 14 + +#define V5_MMISC_CTL_VEC_PLIC_EN (1UL << V5_MMISC_CTL_VEC_PLIC_OFFSET) +#define V5_MMISC_CTL_RVCOMPM_EN (1UL << V5_MMISC_CTL_RVCOMPM_OFFSET) +#define V5_MMISC_CTL_BRPE_EN (1UL << V5_MMISC_CTL_BRPE_OFFSET) +#define V5_MMISC_CTL_MSA_OR_UNA_EN (1UL << V5_MMISC_CTL_MSA_OR_UNA_OFFSET) +#define V5_MMISC_CTL_NON_BLOCKING_EN (1UL << V5_MMISC_CTL_NON_BLOCKING_OFFSET) +#define V5_MCACHE_CTL_L1I_PREFETCH_EN (1UL << V5_MCACHE_CTL_L1I_PREFETCH_OFFSET) +#define V5_MCACHE_CTL_L1D_PREFETCH_EN (1UL << V5_MCACHE_CTL_L1D_PREFETCH_OFFSET) +#define V5_MCACHE_CTL_DC_WAROUND_1_EN (1UL << V5_MCACHE_CTL_DC_WAROUND_OFFSET_1) +#define V5_MCACHE_CTL_DC_WAROUND_2_EN (1UL << V5_MCACHE_CTL_DC_WAROUND_OFFSET_2) + +#define V5_MMISC_CTL_MASK (V5_MMISC_CTL_VEC_PLIC_EN | V5_MMISC_CTL_RVCOMPM_EN \ + | V5_MMISC_CTL_BRPE_EN | V5_MMISC_CTL_MSA_OR_UNA_EN | V5_MMISC_CTL_NON_BLOCKING_EN) + +/* nds mcache_ctl register*/ +#define V5_MCACHE_CTL_IC_EN_OFFSET 0 +#define V5_MCACHE_CTL_DC_EN_OFFSET 1 +#define V5_MCACHE_CTL_IC_ECCEN_OFFSET 2 +#define V5_MCACHE_CTL_DC_ECCEN_OFFSET 4 +#define V5_MCACHE_CTL_IC_RWECC_OFFSET 6 +#define V5_MCACHE_CTL_DC_RWECC_OFFSET 7 +#define V5_MCACHE_CTL_CCTL_SUEN_OFFSET 8 + +/*nds cctl command*/ +#define V5_UCCTL_L1D_WBINVAL_ALL 6 +#define V5_UCCTL_L1D_WB_ALL 7 + +#define V5_MCACHE_CTL_IC_EN (1UL << V5_MCACHE_CTL_IC_EN_OFFSET) +#define V5_MCACHE_CTL_DC_EN (1UL << V5_MCACHE_CTL_DC_EN_OFFSET) +#define V5_MCACHE_CTL_IC_RWECC (1UL << V5_MCACHE_CTL_IC_RWECC_OFFSET) +#define V5_MCACHE_CTL_DC_RWECC (1UL << V5_MCACHE_CTL_DC_RWECC_OFFSET) +#define V5_MCACHE_CTL_CCTL_SUEN (1UL << V5_MCACHE_CTL_CCTL_SUEN_OFFSET) + +#define V5_MCACHE_CTL_MASK (V5_MCACHE_CTL_IC_EN | V5_MCACHE_CTL_DC_EN \ + | V5_MCACHE_CTL_IC_RWECC | V5_MCACHE_CTL_DC_RWECC \ + | V5_MCACHE_CTL_CCTL_SUEN | V5_MCACHE_CTL_L1I_PREFETCH_EN \ + | V5_MCACHE_CTL_L1D_PREFETCH_EN | V5_MCACHE_CTL_DC_WAROUND_1_EN \ + | V5_MCACHE_CTL_DC_WAROUND_2_EN) + +#define V5_L2C_CTL_OFFSET 0x8 +#define V5_L2C_CTL_ENABLE_OFFSET 0 +#define V5_L2C_CTL_IPFDPT_OFFSET 3 +#define V5_L2C_CTL_DPFDPT_OFFSET 5 +#define V5_L2C_CTL_TRAMOCTL_OFFSET 8 +#define V5_L2C_CTL_TRAMICTL_OFFSET 10 +#define V5_L2C_CTL_DRAMOCTL_OFFSET 11 +#define V5_L2C_CTL_DRAMICTL_OFFSET 13 + +#define V5_L2C_CTL_ENABLE_MASK (1UL << V5_L2C_CTL_ENABLE_OFFSET) +#define V5_L2C_CTL_IPFDPT_MASK (3UL << V5_L2C_CTL_IPFDPT_OFFSET) +#define V5_L2C_CTL_DPFDPT_MASK (3UL << V5_L2C_CTL_DPFDPT_OFFSET) +#define V5_L2C_CTL_TRAMOCTL_MASK (3UL << V5_L2C_CTL_TRAMOCTL_OFFSET) +#define V5_L2C_CTL_TRAMICTL_MASK (1UL << V5_L2C_CTL_TRAMICTL_OFFSET) +#define V5_L2C_CTL_DRAMOCTL_MASK (3UL << V5_L2C_CTL_DRAMOCTL_OFFSET) +#define V5_L2C_CTL_DRAMICTL_MASK (1UL << V5_L2C_CTL_DRAMICTL_OFFSET) + +#endif /* _AE350_PLATFORM_H_ */ diff --git a/roms/opensbi/platform/andes/ae350/plicsw.c b/roms/opensbi/platform/andes/ae350/plicsw.c new file mode 100644 index 000000000..d07df28c8 --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/plicsw.c @@ -0,0 +1,145 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + * Nylon Chen <nylon7@andestech.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_types.h> +#include "plicsw.h" +#include "platform.h" + +static u32 plicsw_ipi_hart_count; +static struct plicsw plicsw_dev[AE350_HART_COUNT]; + +static inline void plicsw_claim(void) +{ + u32 source_hart = current_hartid(); + + plicsw_dev[source_hart].source_id = + readl(plicsw_dev[source_hart].plicsw_claim); +} + +static inline void plicsw_complete(void) +{ + u32 source_hart = current_hartid(); + u32 source = plicsw_dev[source_hart].source_id; + + writel(source, plicsw_dev[source_hart].plicsw_claim); +} + +static inline u32 plicsw_get_pending(u32 source_hart, u32 target_hart) +{ + return readl(plicsw_dev[source_hart].plicsw_pending) + & (PLICSW_HART_MASK >> target_hart); +} + +static inline void plic_sw_pending(u32 target_hart) +{ + /* + * The pending array registers are w1s type. + * IPI pending array mapping as following: + * + * Pending array start address: base + 0x1000 + * ------------------------------------- + * | hart 3 | hart 2 | hart 1 | hart 0 | + * ------------------------------------- + * Each hart X can send IPI to another hart by setting the + * corresponding bit in hart X own region(see the below). + * + * In each hart region: + * ----------------------------------------------- + * | bit 7 | bit 6 | bit 5 | bit 4 | ... | bit 0 | + * ----------------------------------------------- + * The bit 7 is used to send IPI to hart 0 + * The bit 6 is used to send IPI to hart 1 + * The bit 5 is used to send IPI to hart 2 + * The bit 4 is used to send IPI to hart 3 + */ + u32 source_hart = current_hartid(); + u32 target_offset = (PLICSW_PENDING_PER_HART - 1) - target_hart; + u32 per_hart_offset = PLICSW_PENDING_PER_HART * source_hart; + u32 val = 1 << target_offset << per_hart_offset; + + writel(val, plicsw_dev[source_hart].plicsw_pending); +} + +void plicsw_ipi_send(u32 target_hart) +{ + if (plicsw_ipi_hart_count <= target_hart) + return; + + /* Set PLICSW IPI */ + plic_sw_pending(target_hart); +} + +void plicsw_ipi_clear(u32 target_hart) +{ + if (plicsw_ipi_hart_count <= target_hart) + return; + + /* Clear CLINT IPI */ + plicsw_claim(); + plicsw_complete(); +} + +int plicsw_warm_ipi_init(void) +{ + u32 hartid = current_hartid(); + + if (!plicsw_dev[hartid].plicsw_pending + && !plicsw_dev[hartid].plicsw_enable + && !plicsw_dev[hartid].plicsw_claim) + return -1; + + /* Clear PLICSW IPI */ + plicsw_ipi_clear(hartid); + + return 0; +} + +int plicsw_cold_ipi_init(unsigned long base, u32 hart_count) +{ + /* Setup source priority */ + uint32_t *priority = (void *)base + PLICSW_PRIORITY_BASE; + + for (int i = 0; i < AE350_HART_COUNT*PLICSW_PENDING_PER_HART; i++) + writel(1, &priority[i]); + + /* Setup target enable.*/ + uint32_t enable_mask = PLICSW_HART_MASK; + + for (int i = 0; i < AE350_HART_COUNT; i++) { + uint32_t *enable = (void *)base + PLICSW_ENABLE_BASE + + PLICSW_ENABLE_PER_HART * i; + writel(enable_mask, &enable[0]); + enable_mask >>= 1; + } + + /* Figure-out PLICSW IPI register address */ + plicsw_ipi_hart_count = hart_count; + + for (u32 hartid = 0; hartid < AE350_HART_COUNT; hartid++) { + plicsw_dev[hartid].source_id = 0; + plicsw_dev[hartid].plicsw_pending = + (void *)base + + PLICSW_PENDING_BASE + + ((hartid / 4) * 4); + plicsw_dev[hartid].plicsw_enable = + (void *)base + + PLICSW_ENABLE_BASE + + PLICSW_ENABLE_PER_HART * hartid; + plicsw_dev[hartid].plicsw_claim = + (void *)base + + PLICSW_CONTEXT_BASE + + PLICSW_CONTEXT_CLAIM + + PLICSW_CONTEXT_PER_HART * hartid; + } + + return 0; +} diff --git a/roms/opensbi/platform/andes/ae350/plicsw.h b/roms/opensbi/platform/andes/ae350/plicsw.h new file mode 100644 index 000000000..8be61945b --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/plicsw.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + * Nylon Chen <nylon7@andestech.com> + */ + +#ifndef _AE350_PLICSW_H_ +#define _AE350_PLICSW_H_ + +#define PLICSW_PRIORITY_BASE 0x4 + +#define PLICSW_PENDING_BASE 0x1000 +#define PLICSW_PENDING_PER_HART 0x8 + +#define PLICSW_ENABLE_BASE 0x2000 +#define PLICSW_ENABLE_PER_HART 0x80 + +#define PLICSW_CONTEXT_BASE 0x200000 +#define PLICSW_CONTEXT_PER_HART 0x1000 +#define PLICSW_CONTEXT_CLAIM 0x4 + +#define PLICSW_HART_MASK 0x80808080 + +struct plicsw { + u32 source_id; + + volatile uint32_t *plicsw_pending; + volatile uint32_t *plicsw_enable; + volatile uint32_t *plicsw_claim; +}; + +void plicsw_ipi_send(u32 target_hart); + +void plicsw_ipi_sync(u32 target_hart); + +void plicsw_ipi_clear(u32 target_hart); + +int plicsw_warm_ipi_init(void); + +int plicsw_cold_ipi_init(unsigned long base, u32 hart_count); + +#endif /* _AE350_PLICSW_H_ */ diff --git a/roms/opensbi/platform/andes/ae350/plmt.c b/roms/opensbi/platform/andes/ae350/plmt.c new file mode 100644 index 000000000..3848e158d --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/plmt.c @@ -0,0 +1,97 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + * Nylon Chen <nylon7@andestech.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> + +static u32 plmt_time_hart_count; +static volatile void *plmt_time_base; +static volatile u64 *plmt_time_val; +static volatile u64 *plmt_time_cmp; + +u64 plmt_timer_value(void) +{ +#if __riscv_xlen == 64 + return readq_relaxed(plmt_time_val); +#else + u32 lo, hi; + + do { + hi = readl_relaxed((void *)plmt_time_val + 0x04); + lo = readl_relaxed(plmt_time_val); + } while (hi != readl_relaxed((void *)plmt_time_val + 0x04)); + + return ((u64)hi << 32) | (u64)lo; +#endif +} + +void plmt_timer_event_stop(void) +{ + u32 target_hart = current_hartid(); + + if (plmt_time_hart_count <= target_hart) + return; + + /* Clear PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); +#endif +} + +void plmt_timer_event_start(u64 next_event) +{ + u32 target_hart = current_hartid(); + + if (plmt_time_hart_count <= target_hart) + return; + + /* Program PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(next_event, &plmt_time_cmp[target_hart]); +#else + u32 mask = -1UL; + + writel_relaxed(next_event & mask, &plmt_time_cmp[target_hart]); + writel_relaxed(next_event >> 32, + (void *)(&plmt_time_cmp[target_hart]) + 0x04); +#endif + +} + +int plmt_warm_timer_init(void) +{ + u32 target_hart = current_hartid(); + + if (plmt_time_hart_count <= target_hart || !plmt_time_base) + return -1; + + /* Clear PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); +#endif + + return 0; +} + +int plmt_cold_timer_init(unsigned long base, u32 hart_count) +{ + plmt_time_hart_count = hart_count; + plmt_time_base = (void *)base; + plmt_time_val = (u64 *)(plmt_time_base); + plmt_time_cmp = (u64 *)(plmt_time_base + 0x8); + + return 0; +} diff --git a/roms/opensbi/platform/andes/ae350/plmt.h b/roms/opensbi/platform/andes/ae350/plmt.h new file mode 100644 index 000000000..129fcf8d1 --- /dev/null +++ b/roms/opensbi/platform/andes/ae350/plmt.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Andes Technology Corporation + * + * Authors: + * Zong Li <zong@andestech.com> + */ + +#ifndef _AE350_PLMT_H_ +#define _AE350_PLMT_H_ + +u64 plmt_timer_value(void); + +void plmt_timer_event_stop(void); + +void plmt_timer_event_start(u64 next_event); + +int plmt_warm_timer_init(void); + +int plmt_cold_timer_init(unsigned long base, u32 hart_count); + +#endif /* _AE350_PLMT_H_ */ diff --git a/roms/opensbi/platform/fpga/ariane/config.mk b/roms/opensbi/platform/fpga/ariane/config.mk new file mode 100644 index 000000000..3556461a1 --- /dev/null +++ b/roms/opensbi/platform/fpga/ariane/config.mk @@ -0,0 +1,36 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2019 FORTH-ICS/CARV +# Panagiotis Peristerakis <perister@ics.forth.gr> +# + +#for more infos, check out /platform/template/config.mk + +PLATFORM_RISCV_XLEN = 64 + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_JUMP=n + +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit support + FW_JUMP_ADDR=0x80400000 + else + # This needs to be 2MB aligned for 64-bit support + FW_JUMP_ADDR=0x80200000 + endif +FW_JUMP_FDT_ADDR=0x82200000 + +# Firmware with payload configuration. +FW_PAYLOAD=y + +ifeq ($(PLATFORM_RISCV_XLEN), 32) +# This needs to be 4MB aligned for 32-bit support + FW_PAYLOAD_OFFSET=0x400000 +else +# This needs to be 2MB aligned for 64-bit support + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=0x82200000 +FW_PAYLOAD_ALIGN=0x1000 diff --git a/roms/opensbi/platform/fpga/ariane/objects.mk b/roms/opensbi/platform/fpga/ariane/objects.mk new file mode 100644 index 000000000..814e6da63 --- /dev/null +++ b/roms/opensbi/platform/fpga/ariane/objects.mk @@ -0,0 +1,8 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2019 FORTH-ICS/CARV +# Panagiotis Peristerakis <perister@ics.forth.gr> +# + +platform-objs-y += platform.o diff --git a/roms/opensbi/platform/fpga/ariane/platform.c b/roms/opensbi/platform/fpga/ariane/platform.c new file mode 100644 index 000000000..ea179e52d --- /dev/null +++ b/roms/opensbi/platform/fpga/ariane/platform.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019 FORTH-ICS/CARV + * Panagiotis Peristerakis <perister@ics.forth.gr> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_hart.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/uart8250.h> +#include <sbi_utils/sys/clint.h> + +#define ARIANE_UART_ADDR 0x10000000 +#define ARIANE_UART_FREQ 50000000 +#define ARIANE_UART_BAUDRATE 115200 +#define ARIANE_UART_REG_SHIFT 2 +#define ARIANE_UART_REG_WIDTH 4 +#define ARIANE_PLIC_ADDR 0xc000000 +#define ARIANE_PLIC_NUM_SOURCES 3 +#define ARIANE_HART_COUNT 1 +#define ARIANE_CLINT_ADDR 0x2000000 + +static struct plic_data plic = { + .addr = ARIANE_PLIC_ADDR, + .num_src = ARIANE_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = ARIANE_CLINT_ADDR, + .first_hartid = 0, + .hart_count = ARIANE_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + +/* + * Ariane platform early initialization. + */ +static int ariane_early_init(bool cold_boot) +{ + /* For now nothing to do. */ + return 0; +} + +/* + * Ariane platform final initialization. + */ +static int ariane_final_init(bool cold_boot) +{ + void *fdt; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + fdt_fixups(fdt); + + return 0; +} + +/* + * Initialize the ariane console. + */ +static int ariane_console_init(void) +{ + return uart8250_init(ARIANE_UART_ADDR, + ARIANE_UART_FREQ, + ARIANE_UART_BAUDRATE, + ARIANE_UART_REG_SHIFT, + ARIANE_UART_REG_WIDTH); +} + +static int plic_ariane_warm_irqchip_init(int m_cntx_id, int s_cntx_id) +{ + size_t i, ie_words = ARIANE_PLIC_NUM_SOURCES / 32 + 1; + + /* By default, enable all IRQs for M-mode of target HART */ + if (m_cntx_id > -1) { + for (i = 0; i < ie_words; i++) + plic_set_ie(&plic, m_cntx_id, i, 1); + } + /* Enable all IRQs for S-mode of target HART */ + if (s_cntx_id > -1) { + for (i = 0; i < ie_words; i++) + plic_set_ie(&plic, s_cntx_id, i, 1); + } + /* By default, enable M-mode threshold */ + if (m_cntx_id > -1) + plic_set_thresh(&plic, m_cntx_id, 1); + /* By default, disable S-mode threshold */ + if (s_cntx_id > -1) + plic_set_thresh(&plic, s_cntx_id, 0); + + return 0; +} + +/* + * Initialize the ariane interrupt controller for current HART. + */ +static int ariane_irqchip_init(bool cold_boot) +{ + u32 hartid = current_hartid(); + int ret; + + if (cold_boot) { + ret = plic_cold_irqchip_init(&plic); + if (ret) + return ret; + } + return plic_ariane_warm_irqchip_init(2 * hartid, 2 * hartid + 1); +} + +/* + * Initialize IPI for current HART. + */ +static int ariane_ipi_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = clint_cold_ipi_init(&clint); + if (ret) + return ret; + } + + return clint_warm_ipi_init(); +} + +/* + * Initialize ariane timer for current HART. + */ +static int ariane_timer_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = clint_cold_timer_init(&clint, NULL); + if (ret) + return ret; + } + + return clint_warm_timer_init(); +} + +/* + * Platform descriptor. + */ +const struct sbi_platform_operations platform_ops = { + .early_init = ariane_early_init, + .final_init = ariane_final_init, + .console_init = ariane_console_init, + .console_putc = uart8250_putc, + .console_getc = uart8250_getc, + .irqchip_init = ariane_irqchip_init, + .ipi_init = ariane_ipi_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + .timer_init = ariane_timer_init, + .timer_value = clint_timer_value, + .timer_event_start = clint_timer_event_start, + .timer_event_stop = clint_timer_event_stop, +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "ARIANE RISC-V", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = ARIANE_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/fpga/openpiton/config.mk b/roms/opensbi/platform/fpga/openpiton/config.mk new file mode 100644 index 000000000..a969b250a --- /dev/null +++ b/roms/opensbi/platform/fpga/openpiton/config.mk @@ -0,0 +1,35 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Western Digital Corporation or its affiliates. +# + +#for more infos, check out /platform/template/config.mk + +PLATFORM_RISCV_XLEN = 64 + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_JUMP=n + +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit support + FW_JUMP_ADDR=0x80400000 + else + # This needs to be 2MB aligned for 64-bit support + FW_JUMP_ADDR=0x80200000 + endif +FW_JUMP_FDT_ADDR=0x82200000 + +# Firmware with payload configuration. +FW_PAYLOAD=y + +ifeq ($(PLATFORM_RISCV_XLEN), 32) +# This needs to be 4MB aligned for 32-bit support + FW_PAYLOAD_OFFSET=0x400000 +else +# This needs to be 2MB aligned for 64-bit support + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=0x82200000 +FW_PAYLOAD_ALIGN=0x1000 diff --git a/roms/opensbi/platform/fpga/openpiton/objects.mk b/roms/opensbi/platform/fpga/openpiton/objects.mk new file mode 100644 index 000000000..30a3c4fb8 --- /dev/null +++ b/roms/opensbi/platform/fpga/openpiton/objects.mk @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Western Digital Corporation or its affiliates. +# + +platform-objs-y += platform.o diff --git a/roms/opensbi/platform/fpga/openpiton/platform.c b/roms/opensbi/platform/fpga/openpiton/platform.c new file mode 100644 index 000000000..5eae47799 --- /dev/null +++ b/roms/opensbi/platform/fpga/openpiton/platform.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_hart.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/uart8250.h> +#include <sbi_utils/sys/clint.h> + +#define OPENPITON_DEFAULT_UART_ADDR 0xfff0c2c000 +#define OPENPITON_DEFAULT_UART_FREQ 60000000 +#define OPENPITON_DEFAULT_UART_BAUDRATE 115200 +#define OPENPITON_DEFAULT_UART_REG_SHIFT 0 +#define OPENPITON_DEFAULT_UART_REG_WIDTH 1 +#define OPENPITON_DEFAULT_PLIC_ADDR 0xfff1100000 +#define OPENPITON_DEFAULT_PLIC_NUM_SOURCES 2 +#define OPENPITON_DEFAULT_HART_COUNT 3 +#define OPENPITON_DEFAULT_CLINT_ADDR 0xfff1020000 + +static struct platform_uart_data uart = { + OPENPITON_DEFAULT_UART_ADDR, + OPENPITON_DEFAULT_UART_FREQ, + OPENPITON_DEFAULT_UART_BAUDRATE, +}; +static struct plic_data plic = { + .addr = OPENPITON_DEFAULT_PLIC_ADDR, + .num_src = OPENPITON_DEFAULT_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = OPENPITON_DEFAULT_CLINT_ADDR, + .first_hartid = 0, + .hart_count = OPENPITON_DEFAULT_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + +/* + * OpenPiton platform early initialization. + */ +static int openpiton_early_init(bool cold_boot) +{ + void *fdt; + struct platform_uart_data uart_data; + struct plic_data plic_data; + unsigned long clint_addr; + int rc; + + if (!cold_boot) + return 0; + fdt = sbi_scratch_thishart_arg1_ptr(); + + rc = fdt_parse_uart8250(fdt, &uart_data, "ns16550"); + if (!rc) + uart = uart_data; + + rc = fdt_parse_plic(fdt, &plic_data, "riscv,plic0"); + if (!rc) + plic = plic_data; + + rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0"); + if (!rc) + clint.addr = clint_addr; + + return 0; +} + +/* + * OpenPiton platform final initialization. + */ +static int openpiton_final_init(bool cold_boot) +{ + void *fdt; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + fdt_fixups(fdt); + + return 0; +} + +/* + * Initialize the openpiton console. + */ +static int openpiton_console_init(void) +{ + return uart8250_init(uart.addr, + uart.freq, + uart.baud, + OPENPITON_DEFAULT_UART_REG_SHIFT, + OPENPITON_DEFAULT_UART_REG_WIDTH); +} + +static int plic_openpiton_warm_irqchip_init(int m_cntx_id, int s_cntx_id) +{ + size_t i, ie_words = plic.num_src / 32 + 1; + + /* By default, enable all IRQs for M-mode of target HART */ + if (m_cntx_id > -1) { + for (i = 0; i < ie_words; i++) + plic_set_ie(&plic, m_cntx_id, i, 1); + } + /* Enable all IRQs for S-mode of target HART */ + if (s_cntx_id > -1) { + for (i = 0; i < ie_words; i++) + plic_set_ie(&plic, s_cntx_id, i, 1); + } + /* By default, enable M-mode threshold */ + if (m_cntx_id > -1) + plic_set_thresh(&plic, m_cntx_id, 1); + /* By default, disable S-mode threshold */ + if (s_cntx_id > -1) + plic_set_thresh(&plic, s_cntx_id, 0); + + return 0; +} + +/* + * Initialize the openpiton interrupt controller for current HART. + */ +static int openpiton_irqchip_init(bool cold_boot) +{ + u32 hartid = current_hartid(); + int ret; + + if (cold_boot) { + ret = plic_cold_irqchip_init(&plic); + if (ret) + return ret; + } + return plic_openpiton_warm_irqchip_init(2 * hartid, 2 * hartid + 1); +} + +/* + * Initialize IPI for current HART. + */ +static int openpiton_ipi_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = clint_cold_ipi_init(&clint); + if (ret) + return ret; + } + + return clint_warm_ipi_init(); +} + +/* + * Initialize openpiton timer for current HART. + */ +static int openpiton_timer_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + ret = clint_cold_timer_init(&clint, NULL); + if (ret) + return ret; + } + + return clint_warm_timer_init(); +} + +/* + * Platform descriptor. + */ +const struct sbi_platform_operations platform_ops = { + .early_init = openpiton_early_init, + .final_init = openpiton_final_init, + .console_init = openpiton_console_init, + .console_putc = uart8250_putc, + .console_getc = uart8250_getc, + .irqchip_init = openpiton_irqchip_init, + .ipi_init = openpiton_ipi_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + .timer_init = openpiton_timer_init, + .timer_value = clint_timer_value, + .timer_event_start = clint_timer_event_start, + .timer_event_stop = clint_timer_event_stop, +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "OPENPITON RISC-V", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = OPENPITON_DEFAULT_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/generic/config.mk b/roms/opensbi/platform/generic/config.mk new file mode 100644 index 000000000..8151974f2 --- /dev/null +++ b/roms/opensbi/platform/generic/config.mk @@ -0,0 +1,40 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Western Digital Corporation or its affiliates. +# +# Authors: +# Anup Patel <anup.patel@wdc.com> +# + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Command for platform specific "make run" +platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M virt -m 256M \ + -nographic -bios $(build_dir)/platform/generic/firmware/fw_payload.elf + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_DYNAMIC=y +FW_JUMP=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000))) +else + # This needs to be 2MB aligned for 64-bit system + FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000))) +endif +FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000))) +FW_PAYLOAD=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_PAYLOAD_OFFSET=0x400000 +else + # This needs to be 2MB aligned for 64-bit system + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR) diff --git a/roms/opensbi/platform/generic/include/platform_override.h b/roms/opensbi/platform/generic/include/platform_override.h new file mode 100644 index 000000000..77a90d645 --- /dev/null +++ b/roms/opensbi/platform/generic/include/platform_override.h @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __PLATFORM_OVERRIDE_H__ +#define __PLATFORM_OVERRIDE_H__ + +#include <sbi/sbi_types.h> + +struct platform_override { + const struct fdt_match *match_table; + u64 (*features)(const struct fdt_match *match); + u64 (*tlbr_flush_limit)(const struct fdt_match *match); + int (*early_init)(bool cold_boot, const struct fdt_match *match); + int (*final_init)(bool cold_boot, const struct fdt_match *match); + void (*early_exit)(const struct fdt_match *match); + void (*final_exit)(const struct fdt_match *match); + int (*system_reset_check)(u32 reset_type, u32 reset_reason, + const struct fdt_match *match); + void (*system_reset)(u32 reset_type, u32 reset_reason, + const struct fdt_match *match); + int (*fdt_fixup)(void *fdt, const struct fdt_match *match); +}; + +#endif diff --git a/roms/opensbi/platform/generic/objects.mk b/roms/opensbi/platform/generic/objects.mk new file mode 100644 index 000000000..d6c8a42d6 --- /dev/null +++ b/roms/opensbi/platform/generic/objects.mk @@ -0,0 +1,11 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Western Digital Corporation or its affiliates. +# +# Authors: +# Anup Patel <anup.patel@wdc.com> +# + +platform-objs-y += platform.o +platform-objs-y += sifive_fu540.o diff --git a/roms/opensbi/platform/generic/platform.c b/roms/opensbi/platform/generic/platform.c new file mode 100644 index 000000000..8c1e06f12 --- /dev/null +++ b/roms/opensbi/platform/generic/platform.c @@ -0,0 +1,241 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <libfdt.h> +#include <platform_override.h> +#include <sbi/riscv_asm.h> +#include <sbi/sbi_hartmask.h> +#include <sbi/sbi_platform.h> +#include <sbi/sbi_string.h> +#include <sbi_utils/fdt/fdt_domain.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/irqchip/fdt_irqchip.h> +#include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/timer/fdt_timer.h> +#include <sbi_utils/ipi/fdt_ipi.h> +#include <sbi_utils/reset/fdt_reset.h> + +extern const struct platform_override sifive_fu540; + +static const struct platform_override *special_platforms[] = { + &sifive_fu540, +}; + +static const struct platform_override *generic_plat = NULL; +static const struct fdt_match *generic_plat_match = NULL; + +static void fw_platform_lookup_special(void *fdt, int root_offset) +{ + int pos, noff; + const struct platform_override *plat; + const struct fdt_match *match; + + for (pos = 0; pos < array_size(special_platforms); pos++) { + plat = special_platforms[pos]; + if (!plat->match_table) + continue; + + noff = fdt_find_match(fdt, -1, plat->match_table, &match); + if (noff < 0) + continue; + + generic_plat = plat; + generic_plat_match = match; + break; + } +} + +extern struct sbi_platform platform; +static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 }; + +/* + * The fw_platform_init() function is called very early on the boot HART + * OpenSBI reference firmwares so that platform specific code get chance + * to update "platform" instance before it is used. + * + * The arguments passed to fw_platform_init() function are boot time state + * of A0 to A4 register. The "arg0" will be boot HART id and "arg1" will + * be address of FDT passed by previous booting stage. + * + * The return value of fw_platform_init() function is the FDT location. If + * FDT is unchanged (or FDT is modified in-place) then fw_platform_init() + * can always return the original FDT location (i.e. 'arg1') unmodified. + */ +unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4) +{ + const char *model; + void *fdt = (void *)arg1; + u32 hartid, hart_count = 0; + int rc, root_offset, cpus_offset, cpu_offset, len; + + root_offset = fdt_path_offset(fdt, "/"); + if (root_offset < 0) + goto fail; + + fw_platform_lookup_special(fdt, root_offset); + + model = fdt_getprop(fdt, root_offset, "model", &len); + if (model) + sbi_strncpy(platform.name, model, sizeof(platform.name)); + + if (generic_plat && generic_plat->features) + platform.features = generic_plat->features(generic_plat_match); + + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + goto fail; + + fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) { + rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid); + if (rc) + continue; + + if (SBI_HARTMASK_MAX_BITS <= hartid) + continue; + + generic_hart_index2id[hart_count++] = hartid; + } + + platform.hart_count = hart_count; + + /* Return original FDT pointer */ + return arg1; + +fail: + while (1) + wfi(); +} + +static int generic_early_init(bool cold_boot) +{ + int rc; + + if (generic_plat && generic_plat->early_init) { + rc = generic_plat->early_init(cold_boot, generic_plat_match); + if (rc) + return rc; + } + + if (!cold_boot) + return 0; + + return fdt_reset_init(); +} + +static int generic_final_init(bool cold_boot) +{ + void *fdt; + int rc; + + if (generic_plat && generic_plat->final_init) { + rc = generic_plat->final_init(cold_boot, generic_plat_match); + if (rc) + return rc; + } + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + + fdt_cpu_fixup(fdt); + fdt_fixups(fdt); + fdt_domain_fixup(fdt); + + if (generic_plat && generic_plat->fdt_fixup) { + rc = generic_plat->fdt_fixup(fdt, generic_plat_match); + if (rc) + return rc; + } + + return 0; +} + +static void generic_early_exit(void) +{ + if (generic_plat && generic_plat->early_exit) + generic_plat->early_exit(generic_plat_match); +} + +static void generic_final_exit(void) +{ + if (generic_plat && generic_plat->final_exit) + generic_plat->final_exit(generic_plat_match); +} + +static int generic_domains_init(void) +{ + return fdt_domains_populate(sbi_scratch_thishart_arg1_ptr()); +} + +static u64 generic_tlbr_flush_limit(void) +{ + if (generic_plat && generic_plat->tlbr_flush_limit) + return generic_plat->tlbr_flush_limit(generic_plat_match); + return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT; +} + +static int generic_system_reset_check(u32 reset_type, u32 reset_reason) +{ + if (generic_plat && generic_plat->system_reset_check) + return generic_plat->system_reset_check(reset_type, + reset_reason, + generic_plat_match); + return fdt_system_reset_check(reset_type, reset_reason); +} + +static void generic_system_reset(u32 reset_type, u32 reset_reason) +{ + if (generic_plat && generic_plat->system_reset) { + generic_plat->system_reset(reset_type, reset_reason, + generic_plat_match); + return; + } + + fdt_system_reset(reset_type, reset_reason); +} + +const struct sbi_platform_operations platform_ops = { + .early_init = generic_early_init, + .final_init = generic_final_init, + .early_exit = generic_early_exit, + .final_exit = generic_final_exit, + .domains_init = generic_domains_init, + .console_putc = fdt_serial_putc, + .console_getc = fdt_serial_getc, + .console_init = fdt_serial_init, + .irqchip_init = fdt_irqchip_init, + .irqchip_exit = fdt_irqchip_exit, + .ipi_send = fdt_ipi_send, + .ipi_clear = fdt_ipi_clear, + .ipi_init = fdt_ipi_init, + .ipi_exit = fdt_ipi_exit, + .get_tlbr_flush_limit = generic_tlbr_flush_limit, + .timer_value = fdt_timer_value, + .timer_event_stop = fdt_timer_event_stop, + .timer_event_start = fdt_timer_event_start, + .timer_init = fdt_timer_init, + .timer_exit = fdt_timer_exit, + .system_reset_check = generic_system_reset_check, + .system_reset = generic_system_reset, +}; + +struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "Generic", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = SBI_HARTMASK_MAX_BITS, + .hart_index2id = generic_hart_index2id, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/generic/sifive_fu540.c b/roms/opensbi/platform/generic/sifive_fu540.c new file mode 100644 index 000000000..08f7bfc40 --- /dev/null +++ b/roms/opensbi/platform/generic/sifive_fu540.c @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <platform_override.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/fdt/fdt_fixup.h> + +static u64 sifive_fu540_tlbr_flush_limit(const struct fdt_match *match) +{ + /* + * The sfence.vma by virtual address does not work on + * SiFive FU540 so we return remote TLB flush limit as zero. + */ + return 0; +} + +static int sifive_fu540_fdt_fixup(void *fdt, const struct fdt_match *match) +{ + /* + * SiFive Freedom U540 has an erratum that prevents S-mode software + * to access a PMP protected region using 1GB page table mapping, so + * always add the no-map attribute on this platform. + */ + fdt_reserved_memory_nomap_fixup(fdt); + + return 0; +} + +static const struct fdt_match sifive_fu540_match[] = { + { .compatible = "sifive,fu540" }, + { .compatible = "sifive,fu540g" }, + { .compatible = "sifive,fu540-c000" }, + { .compatible = "sifive,hifive-unleashed-a00" }, + { }, +}; + +const struct platform_override sifive_fu540 = { + .match_table = sifive_fu540_match, + .tlbr_flush_limit = sifive_fu540_tlbr_flush_limit, + .fdt_fixup = sifive_fu540_fdt_fixup, +}; diff --git a/roms/opensbi/platform/kendryte/k210/config.mk b/roms/opensbi/platform/kendryte/k210/config.mk new file mode 100644 index 000000000..8a9b81418 --- /dev/null +++ b/roms/opensbi/platform/kendryte/k210/config.mk @@ -0,0 +1,19 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# +# Authors: +# Damien Le Moal <damien.lemoal@wdc.com> +# + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_PAYLOAD=y +FW_PAYLOAD_ALIGN=0x1000 diff --git a/roms/opensbi/platform/kendryte/k210/k210.dts b/roms/opensbi/platform/kendryte/k210/k210.dts new file mode 100644 index 000000000..bcd075bf5 --- /dev/null +++ b/roms/opensbi/platform/kendryte/k210/k210.dts @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Damien Le Moal <damien.lemoal@wdc.com> + */ + +/dts-v1/; +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "kendryte,k210"; + + chosen { + bootargs = "console=hvc0 earlycon=sbi"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + device_type = "cpu"; + clock-frequency = <390000000>; + i-cache-size = <32768>; + d-cache-size = <32768>; + mmu-type = "none"; + reg = <0>; + riscv,isa = "rv64imafdc"; + status = "okay"; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + cpu1: cpu@1 { + device_type = "cpu"; + clock-frequency = <390000000>; + d-cache-size = <32768>; + i-cache-size = <32768>; + mmu-type = "none"; + reg = <1>; + riscv,isa = "rv64imafdc"; + status = "okay"; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + + memory@80000000 { + /* Bank 0: 4 MB, Bank 1: 2 MB, AI chip SRAM: 2MB */ + device_type = "memory"; + reg = <0x00000000 0x80000000 0x00000000 0x00800000>; + }; + + plic0: interrupt-controller@C000000 { + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = + <&cpu0_intc 11 &cpu0_intc 9 + &cpu1_intc 11 &cpu1_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + }; +}; diff --git a/roms/opensbi/platform/kendryte/k210/objects.mk b/roms/opensbi/platform/kendryte/k210/objects.mk new file mode 100644 index 000000000..b74da7407 --- /dev/null +++ b/roms/opensbi/platform/kendryte/k210/objects.mk @@ -0,0 +1,14 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# +# Authors: +# Damien Le Moal <damien.lemoal@wdc.com> +# + +platform-objs-y += platform.o + +platform-objs-y += k210.o +platform-varprefix-k210.o = dt_k210 +platform-padding-k210.o = 2048 diff --git a/roms/opensbi/platform/kendryte/k210/platform.c b/roms/opensbi/platform/kendryte/k210/platform.c new file mode 100644 index 000000000..944b38885 --- /dev/null +++ b/roms/opensbi/platform/kendryte/k210/platform.c @@ -0,0 +1,159 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Damien Le Moal <damien.lemoal@wdc.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/sifive-uart.h> +#include <sbi_utils/sys/clint.h> +#include "platform.h" + +extern const char dt_k210_start[]; + +unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4) +{ + return (unsigned long)&dt_k210_start[0]; +} + +static struct plic_data plic = { + .addr = K210_PLIC_BASE_ADDR, + .num_src = K210_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = K210_CLINT_BASE_ADDR, + .first_hartid = 0, + .hart_count = K210_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + +static u32 k210_get_clk_freq(void) +{ + u32 clksel0, pll0; + u64 pll0_freq, clkr0, clkf0, clkod0, div; + + /* + * If the clock selector is not set, use the base frequency. + * Otherwise, use PLL0 frequency with a frequency divisor. + */ + clksel0 = k210_read_sysreg(K210_CLKSEL0); + if (!(clksel0 & 0x1)) + return K210_CLK0_FREQ; + + /* + * Get PLL0 frequency: + * freq = base frequency * clkf0 / (clkr0 * clkod0) + */ + pll0 = k210_read_sysreg(K210_PLL0); + clkr0 = 1 + (pll0 & 0x0000000f); + clkf0 = 1 + ((pll0 & 0x000003f0) >> 4); + clkod0 = 1 + ((pll0 & 0x00003c00) >> 10); + pll0_freq = clkf0 * K210_CLK0_FREQ / (clkr0 * clkod0); + + /* Get the frequency divisor from the clock selector */ + div = 2ULL << ((clksel0 & 0x00000006) >> 1); + + return pll0_freq / div; +} + +static int k210_final_init(bool cold_boot) +{ + void *fdt; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + + fdt_cpu_fixup(fdt); + fdt_fixups(fdt); + + return 0; +} + +static int k210_console_init(void) +{ + return sifive_uart_init(K210_UART_BASE_ADDR, k210_get_clk_freq(), + K210_UART_BAUDRATE); +} + +static int k210_irqchip_init(bool cold_boot) +{ + int rc; + u32 hartid = current_hartid(); + + if (cold_boot) { + rc = plic_cold_irqchip_init(&plic); + if (rc) + return rc; + } + + return plic_warm_irqchip_init(&plic, hartid * 2, hartid * 2 + 1); +} + +static int k210_ipi_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_ipi_init(&clint); + if (rc) + return rc; + } + + return clint_warm_ipi_init(); +} + +static int k210_timer_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_timer_init(&clint, NULL); + if (rc) + return rc; + } + + return clint_warm_timer_init(); +} + +const struct sbi_platform_operations platform_ops = { + .final_init = k210_final_init, + + .console_init = k210_console_init, + .console_putc = sifive_uart_putc, + .console_getc = sifive_uart_getc, + + .irqchip_init = k210_irqchip_init, + + .ipi_init = k210_ipi_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + + .timer_init = k210_timer_init, + .timer_value = clint_timer_value, + .timer_event_stop = clint_timer_event_stop, + .timer_event_start = clint_timer_event_start, +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "Kendryte K210", + .features = SBI_PLATFORM_HAS_TIMER_VALUE, + .hart_count = K210_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/kendryte/k210/platform.h b/roms/opensbi/platform/kendryte/k210/platform.h new file mode 100644 index 000000000..5269bc4fd --- /dev/null +++ b/roms/opensbi/platform/kendryte/k210/platform.h @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Damien Le Moal <damien.lemoal@wdc.com> + */ +#ifndef _K210_PLATFORM_H_ +#define _K210_PLATFORM_H_ + +#include <sbi/riscv_io.h> + +#define K210_HART_COUNT 2 + +#define K210_UART_BAUDRATE 115200 + +#define K210_CLK0_FREQ 26000000UL +#define K210_PLIC_NUM_SOURCES 65 + +/* Registers base address */ +#define K210_SYSCTL_BASE_ADDR 0x50440000ULL +#define K210_UART_BASE_ADDR 0x38000000ULL +#define K210_CLINT_BASE_ADDR 0x02000000ULL +#define K210_PLIC_BASE_ADDR 0x0C000000ULL + +/* Registers */ +#define K210_PLL0 0x08 +#define K210_CLKSEL0 0x20 + +static inline u32 k210_read_sysreg(u32 reg) +{ + return readl((volatile void *)(K210_SYSCTL_BASE_ADDR + reg)); +} + +#endif /* _K210_PLATFORM_H_ */ diff --git a/roms/opensbi/platform/nuclei/ux600/config.mk b/roms/opensbi/platform/nuclei/ux600/config.mk new file mode 100644 index 000000000..dddcc4ea5 --- /dev/null +++ b/roms/opensbi/platform/nuclei/ux600/config.mk @@ -0,0 +1,30 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Nuclei Corporation or its affiliates. +# +# Authors: +# lujun <lujun@nucleisys.com> +# hqfang <578567190@qq.com> +# + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Command for platform specific "make run" +platform-runcmd = xl_spike \ + $(build_dir)/platform/nuclei/ux600/firmware/fw_payload.elf + +# Blobs to build +FW_TEXT_START=0xA0000000 +FW_DYNAMIC=y +FW_JUMP=y + +FW_JUMP_ADDR=0xA0200000 +FW_JUMP_FDT_ADDR=0xA8000000 +FW_PAYLOAD=y +FW_PAYLOAD_OFFSET=0x200000 +FW_PAYLOAD_FDT_ADDR=0xA8000000 diff --git a/roms/opensbi/platform/nuclei/ux600/objects.mk b/roms/opensbi/platform/nuclei/ux600/objects.mk new file mode 100644 index 000000000..8c36c90a7 --- /dev/null +++ b/roms/opensbi/platform/nuclei/ux600/objects.mk @@ -0,0 +1,11 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Nuclei Corporation or its affiliates. +# +# Authors: +# lujun <lujun@nuclesys.com> +# hqfang <578567190@qq.com> +# + +platform-objs-y += platform.o diff --git a/roms/opensbi/platform/nuclei/ux600/platform.c b/roms/opensbi/platform/nuclei/ux600/platform.c new file mode 100644 index 000000000..d0a45a2ef --- /dev/null +++ b/roms/opensbi/platform/nuclei/ux600/platform.c @@ -0,0 +1,228 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) Nuclei Corporation or its affiliates. + * + * Authors: + * lujun <lujun@nucleisys.com> + * hqfang <578567190@qq.com> + */ + +#include <libfdt.h> +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/sifive-uart.h> +#include <sbi_utils/sys/clint.h> + +/* clang-format off */ + +#define UX600_HART_COUNT 1 +#define UX600_TIMER_FREQ 32768 + +/* Nuclei timer base address */ +#define UX600_NUCLEI_TIMER_ADDR 0x2000000 +#define UX600_NUCLEI_TIMER_MSFTRST_OFS 0xFF0 +#define UX600_NUCLEI_TIMER_MSFTRST_KEY 0x80000A5F +/* The clint compatiable timer offset is 0x1000 against nuclei timer */ +#define UX600_CLINT_TIMER_ADDR (UX600_NUCLEI_TIMER_ADDR + 0x1000) + +#define UX600_PLIC_ADDR 0x8000000 +#define UX600_PLIC_NUM_SOURCES 0x35 +#define UX600_PLIC_NUM_PRIORITIES 7 + +#define UX600_UART0_ADDR 0x10013000 +#define UX600_UART1_ADDR 0x10023000 + +#define UX600_DEBUG_UART UX600_UART0_ADDR + +#ifndef UX600_UART_BAUDRATE +#define UX600_UART_BAUDRATE 57600 +#endif + +#define UX600_GPIO_ADDR 0x10012000 +#define UX600_GPIO_IOF_EN_OFS 0x38 +#define UX600_GPIO_IOF_SEL_OFS 0x3C +#define UX600_GPIO_IOF_UART0_MASK 0x00030000 + +#define UX600_TIMER_VALUE() readl((void *)UX600_NUCLEI_TIMER_ADDR) + +/* clang-format on */ +static u32 ux600_clk_freq = 8000000; + +static struct plic_data plic = { + .addr = UX600_PLIC_ADDR, + .num_src = UX600_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = UX600_CLINT_TIMER_ADDR, + .first_hartid = 0, + .hart_count = UX600_HART_COUNT, + .has_64bit_mmio = TRUE, +}; +static u32 measure_cpu_freq(u32 n) +{ + u32 start_mtime, delta_mtime; + u32 mtime_freq = UX600_TIMER_FREQ; + u32 tmp = (u32)UX600_TIMER_VALUE(); + u32 start_mcycle, delta_mcycle, freq; + + /* Don't start measuring until we see an mtime tick */ + do { + start_mtime = (u32)UX600_TIMER_VALUE(); + } while (start_mtime == tmp); + + start_mcycle = csr_read(mcycle); + + do { + delta_mtime = (u32)UX600_TIMER_VALUE() - start_mtime; + } while (delta_mtime < n); + + delta_mcycle = csr_read(mcycle) - start_mcycle; + + freq = (delta_mcycle / delta_mtime) * mtime_freq + + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime; + + return freq; +} + +static u32 ux600_get_clk_freq(void) +{ + u32 cpu_freq; + + /* warm up */ + measure_cpu_freq(1); + /* measure for real */ + cpu_freq = measure_cpu_freq(100); + + return cpu_freq; +} + +static int ux600_early_init(bool cold_boot) +{ + u32 regval; + + /* Measure CPU Frequency using Timer */ + ux600_clk_freq = ux600_get_clk_freq(); + + /* Init GPIO UART pinmux */ + regval = readl((void *)(UX600_GPIO_ADDR + UX600_GPIO_IOF_SEL_OFS)) & + ~UX600_GPIO_IOF_UART0_MASK; + writel(regval, (void *)(UX600_GPIO_ADDR + UX600_GPIO_IOF_SEL_OFS)); + regval = readl((void *)(UX600_GPIO_ADDR + UX600_GPIO_IOF_EN_OFS)) | + UX600_GPIO_IOF_UART0_MASK; + writel(regval, (void *)(UX600_GPIO_ADDR + UX600_GPIO_IOF_EN_OFS)); + return 0; +} + +static void ux600_modify_dt(void *fdt) +{ + fdt_fixups(fdt); +} + +static int ux600_final_init(bool cold_boot) +{ + void *fdt; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + ux600_modify_dt(fdt); + + return 0; +} + +static int ux600_console_init(void) +{ + return sifive_uart_init(UX600_DEBUG_UART, ux600_clk_freq, + UX600_UART_BAUDRATE); +} + +static int ux600_irqchip_init(bool cold_boot) +{ + int rc; + u32 hartid = current_hartid(); + + if (cold_boot) { + rc = plic_cold_irqchip_init(&plic); + if (rc) + return rc; + } + + return plic_warm_irqchip_init(&plic, (hartid) ? (2 * hartid - 1) : 0, + (hartid) ? (2 * hartid) : -1); +} + +static int ux600_ipi_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_ipi_init(&clint); + if (rc) + return rc; + } + + return clint_warm_ipi_init(); +} + +static int ux600_timer_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_timer_init(&clint, NULL); + if (rc) + return rc; + } + + return clint_warm_timer_init(); +} + +static int ux600_system_reset_check(u32 type, u32 reason) +{ + return 1; +} + +static void ux600_system_reset(u32 type, u32 reason) +{ + /* Reset system using MSFTRST register in Nuclei Timer. */ + writel(UX600_NUCLEI_TIMER_MSFTRST_KEY, (void *)(UX600_NUCLEI_TIMER_ADDR + + UX600_NUCLEI_TIMER_MSFTRST_OFS)); + while(1); +} + +const struct sbi_platform_operations platform_ops = { + .early_init = ux600_early_init, + .final_init = ux600_final_init, + .console_putc = sifive_uart_putc, + .console_getc = sifive_uart_getc, + .console_init = ux600_console_init, + .irqchip_init = ux600_irqchip_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + .ipi_init = ux600_ipi_init, + .timer_value = clint_timer_value, + .timer_event_stop = clint_timer_event_stop, + .timer_event_start = clint_timer_event_start, + .timer_init = ux600_timer_init, + .system_reset_check = ux600_system_reset_check, + .system_reset = ux600_system_reset +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0U, 0x01U), + .name = "Nuclei UX600", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = UX600_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/sifive/fu540/config.mk b/roms/opensbi/platform/sifive/fu540/config.mk new file mode 100644 index 000000000..23169b1b9 --- /dev/null +++ b/roms/opensbi/platform/sifive/fu540/config.mk @@ -0,0 +1,40 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# +# Authors: +# Atish Patra <atish.patra@wdc.com> +# + +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Command for platform specific "make run" +platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M sifive_u -m 256M \ + -nographic -bios $(build_dir)/platform/sifive/fu540/firmware/fw_payload.elf + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_DYNAMIC=y +FW_JUMP=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_JUMP_ADDR=0x80400000 +else + # This needs to be 2MB aligned for 64-bit system + FW_JUMP_ADDR=0x80200000 +endif +FW_JUMP_FDT_ADDR=0x88000000 +FW_PAYLOAD=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_PAYLOAD_OFFSET=0x400000 +else + # This needs to be 2MB aligned for 64-bit system + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=0x88000000 diff --git a/roms/opensbi/platform/sifive/fu540/objects.mk b/roms/opensbi/platform/sifive/fu540/objects.mk new file mode 100644 index 000000000..e0d058538 --- /dev/null +++ b/roms/opensbi/platform/sifive/fu540/objects.mk @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# +# Authors: +# Atish Patra <atish.patra@wdc.com> +# + +platform-objs-y += platform.o diff --git a/roms/opensbi/platform/sifive/fu540/platform.c b/roms/opensbi/platform/sifive/fu540/platform.c new file mode 100644 index 000000000..cdd829363 --- /dev/null +++ b/roms/opensbi/platform/sifive/fu540/platform.c @@ -0,0 +1,182 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra <atish.patra@wdc.com> + */ + +#include <libfdt.h> +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/sifive-uart.h> +#include <sbi_utils/sys/clint.h> + +/* clang-format off */ + +#define FU540_HART_COUNT 5 + +#define FU540_SYS_CLK 1000000000 + +#define FU540_CLINT_ADDR 0x2000000 + +#define FU540_PLIC_ADDR 0xc000000 +#define FU540_PLIC_NUM_SOURCES 0x35 +#define FU540_PLIC_NUM_PRIORITIES 7 + +#define FU540_UART0_ADDR 0x10010000 +#define FU540_UART1_ADDR 0x10011000 +#define FU540_UART_BAUDRATE 115200 + +/* PRCI clock related macros */ +//TODO: Do we need a separate driver for this ? +#define FU540_PRCI_BASE_ADDR 0x10000000 +#define FU540_PRCI_CLKMUXSTATUSREG 0x002C +#define FU540_PRCI_CLKMUX_STATUS_TLCLKSEL (0x1 << 1) + +/* Full tlb flush always */ +#define FU540_TLB_RANGE_FLUSH_LIMIT 0 + +/* clang-format on */ + +static struct plic_data plic = { + .addr = FU540_PLIC_ADDR, + .num_src = FU540_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = FU540_CLINT_ADDR, + .first_hartid = 0, + .hart_count = FU540_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + +static void fu540_modify_dt(void *fdt) +{ + fdt_cpu_fixup(fdt); + + fdt_fixups(fdt); + + /* + * SiFive Freedom U540 has an erratum that prevents S-mode software + * to access a PMP protected region using 1GB page table mapping, so + * always add the no-map attribute on this platform. + */ + fdt_reserved_memory_nomap_fixup(fdt); +} + +static int fu540_final_init(bool cold_boot) +{ + void *fdt; + + if (!cold_boot) + return 0; + + fdt = sbi_scratch_thishart_arg1_ptr(); + fu540_modify_dt(fdt); + + return 0; +} + +static int fu540_console_init(void) +{ + unsigned long peri_in_freq; + + if (readl((volatile void *)FU540_PRCI_BASE_ADDR + + FU540_PRCI_CLKMUXSTATUSREG) & + FU540_PRCI_CLKMUX_STATUS_TLCLKSEL) { + peri_in_freq = FU540_SYS_CLK; + } else { + peri_in_freq = FU540_SYS_CLK / 2; + } + + return sifive_uart_init(FU540_UART0_ADDR, peri_in_freq, + FU540_UART_BAUDRATE); +} + +static int fu540_irqchip_init(bool cold_boot) +{ + int rc; + u32 hartid = current_hartid(); + + if (cold_boot) { + rc = plic_cold_irqchip_init(&plic); + if (rc) + return rc; + } + + return plic_warm_irqchip_init(&plic, (hartid) ? (2 * hartid - 1) : 0, + (hartid) ? (2 * hartid) : -1); +} + +static int fu540_ipi_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_ipi_init(&clint); + if (rc) + return rc; + } + + return clint_warm_ipi_init(); +} + +static u64 fu540_get_tlbr_flush_limit(void) +{ + return FU540_TLB_RANGE_FLUSH_LIMIT; +} + +static int fu540_timer_init(bool cold_boot) +{ + int rc; + + if (cold_boot) { + rc = clint_cold_timer_init(&clint, NULL); + if (rc) + return rc; + } + + return clint_warm_timer_init(); +} + +static u32 fu540_hart_index2id[FU540_HART_COUNT - 1] = { + [0] = 1, + [1] = 2, + [2] = 3, + [3] = 4, +}; + +const struct sbi_platform_operations platform_ops = { + .final_init = fu540_final_init, + .console_putc = sifive_uart_putc, + .console_getc = sifive_uart_getc, + .console_init = fu540_console_init, + .irqchip_init = fu540_irqchip_init, + .ipi_send = clint_ipi_send, + .ipi_clear = clint_ipi_clear, + .ipi_init = fu540_ipi_init, + .get_tlbr_flush_limit = fu540_get_tlbr_flush_limit, + .timer_value = clint_timer_value, + .timer_event_stop = clint_timer_event_stop, + .timer_event_start = clint_timer_event_start, + .timer_init = fu540_timer_init, +}; + +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), + .name = "SiFive Freedom U540", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = (FU540_HART_COUNT - 1), + .hart_index2id = fu540_hart_index2id, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/template/config.mk b/roms/opensbi/platform/template/config.mk new file mode 100644 index 000000000..f817342c2 --- /dev/null +++ b/roms/opensbi/platform/template/config.mk @@ -0,0 +1,77 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# + +# Compiler pre-processor flags +platform-cppflags-y = + +# C Compiler and assembler flags. +platform-cflags-y = +platform-asflags-y = + +# Linker flags: additional libraries and object files that the platform +# code needs can be added here +platform-ldflags-y = + +# +# Command for platform specific "make run" +# Useful for development and debugging on plaftform simulator (such as QEMU) +# +# platform-runcmd = your_platform_run.sh + +# +# Platform RISC-V XLEN, ABI, ISA and Code Model configuration. +# These are optional parameters but platforms can optionaly provide it. +# Some of these are guessed based on GCC compiler capabilities +# +# PLATFORM_RISCV_XLEN = 64 +# PLATFORM_RISCV_ABI = lp64 +# PLATFORM_RISCV_ISA = rv64imafdc +# PLATFORM_RISCV_CODE_MODEL = medany + +# Firmware load address configuration. This is mandatory. +FW_TEXT_START=0x80000000 + +# Optional parameter for path to external FDT +# FW_FDT_PATH="path to platform flattened device tree file" + +# +# Dynamic firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_DYNAMIC=<y|n> + +# +# Jump firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_JUMP=<y|n> +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +# ifeq ($(PLATFORM_RISCV_XLEN), 32) +# FW_JUMP_ADDR=0x80400000 +# else +# FW_JUMP_ADDR=0x80200000 +# endif +# FW_JUMP_FDT_ADDR=0x82200000 + +# +# Firmware with payload configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_PAYLOAD=<y|n> +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +ifeq ($(PLATFORM_RISCV_XLEN), 32) +FW_PAYLOAD_OFFSET=0x400000 +else +FW_PAYLOAD_OFFSET=0x200000 +endif +# FW_PAYLOAD_ALIGN=0x1000 +# FW_PAYLOAD_PATH="path to next boot stage binary image file" +# FW_PAYLOAD_FDT_ADDR=0x82200000 diff --git a/roms/opensbi/platform/template/objects.mk b/roms/opensbi/platform/template/objects.mk new file mode 100644 index 000000000..caaec2bee --- /dev/null +++ b/roms/opensbi/platform/template/objects.mk @@ -0,0 +1,15 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# + +# Space separated list of object file names to be compiled for the platform +platform-objs-y += platform.o + +# +# If the platform support requires a builtin device tree file, the name of +# the device tree compiled file should be specified here. The device tree +# source file be in the form <dt file name>.dts +# +# platform-objs-y += <dt file name>.o diff --git a/roms/opensbi/platform/template/platform.c b/roms/opensbi/platform/template/platform.c new file mode 100644 index 000000000..5bdb186c1 --- /dev/null +++ b/roms/opensbi/platform/template/platform.c @@ -0,0 +1,223 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_platform.h> + +/* + * Include these files as needed. + * See config.mk PLATFORM_xxx configuration parameters. + */ +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/uart8250.h> +#include <sbi_utils/sys/clint.h> + +#define PLATFORM_PLIC_ADDR 0xc000000 +#define PLATFORM_PLIC_NUM_SOURCES 128 +#define PLATFORM_HART_COUNT 4 +#define PLATFORM_CLINT_ADDR 0x2000000 +#define PLATFORM_UART_ADDR 0x09000000 +#define PLATFORM_UART_INPUT_FREQ 10000000 +#define PLATFORM_UART_BAUDRATE 115200 + +static struct plic_data plic = { + .addr = PLATFORM_PLIC_ADDR, + .num_src = PLATFORM_PLIC_NUM_SOURCES, +}; + +static struct clint_data clint = { + .addr = PLATFORM_CLINT_ADDR, + .first_hartid = 0, + .hart_count = PLATFORM_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + +/* + * Platform early initialization. + */ +static int platform_early_init(bool cold_boot) +{ + return 0; +} + +/* + * Platform final initialization. + */ +static int platform_final_init(bool cold_boot) +{ + return 0; +} + +/* + * Initialize the platform console. + */ +static int platform_console_init(void) +{ + /* Example if the generic UART8250 driver is used */ + return uart8250_init(PLATFORM_UART_ADDR, PLATFORM_UART_INPUT_FREQ, + PLATFORM_UART_BAUDRATE, 0, 1); +} + +/* + * Write a character to the platform console output. + */ +static void platform_console_putc(char ch) +{ + /* Example if the generic UART8250 driver is used */ + uart8250_putc(ch); +} + +/* + * Read a character from the platform console input. + */ +static int platform_console_getc(void) +{ + return uart8250_getc(); +} + +/* + * Initialize the platform interrupt controller for current HART. + */ +static int platform_irqchip_init(bool cold_boot) +{ + u32 hartid = current_hartid(); + int ret; + + /* Example if the generic PLIC driver is used */ + if (cold_boot) { + ret = plic_cold_irqchip_init(&plic); + if (ret) + return ret; + } + + return plic_warm_irqchip_init(&plic, 2 * hartid, 2 * hartid + 1); +} + +/* + * Initialize IPI for current HART. + */ +static int platform_ipi_init(bool cold_boot) +{ + int ret; + + /* Example if the generic CLINT driver is used */ + if (cold_boot) { + ret = clint_cold_ipi_init(&clint); + if (ret) + return ret; + } + + return clint_warm_ipi_init(); +} + +/* + * Send IPI to a target HART + */ +static void platform_ipi_send(u32 target_hart) +{ + /* Example if the generic CLINT driver is used */ + clint_ipi_send(target_hart); +} + +/* + * Clear IPI for a target HART. + */ +static void platform_ipi_clear(u32 target_hart) +{ + /* Example if the generic CLINT driver is used */ + clint_ipi_clear(target_hart); +} + +/* + * Initialize platform timer for current HART. + */ +static int platform_timer_init(bool cold_boot) +{ + int ret; + + /* Example if the generic CLINT driver is used */ + if (cold_boot) { + ret = clint_cold_timer_init(&clint, NULL); + if (ret) + return ret; + } + + return clint_warm_timer_init(); +} + +/* + * Get platform timer value. + */ +static u64 platform_timer_value(void) +{ + /* Example if the generic CLINT driver is used */ + return clint_timer_value(); +} + +/* + * Start platform timer event for current HART. + */ +static void platform_timer_event_start(u64 next_event) +{ + /* Example if the generic CLINT driver is used */ + clint_timer_event_start(next_event); +} + +/* + * Stop platform timer event for current HART. + */ +static void platform_timer_event_stop(void) +{ + /* Example if the generic CLINT driver is used */ + clint_timer_event_stop(); +} + +/* + * Check reset type and reason supported by the platform. + */ +static int platform_system_reset_check(u32 type, u32 reason) +{ + return 0; +} + +/* + * Reset the platform. + */ +static void platform_system_reset(u32 type, u32 reason) +{ +} + +/* + * Platform descriptor. + */ +const struct sbi_platform_operations platform_ops = { + .early_init = platform_early_init, + .final_init = platform_final_init, + .console_putc = platform_console_putc, + .console_getc = platform_console_getc, + .console_init = platform_console_init, + .irqchip_init = platform_irqchip_init, + .ipi_send = platform_ipi_send, + .ipi_clear = platform_ipi_clear, + .ipi_init = platform_ipi_init, + .timer_value = platform_timer_value, + .timer_event_stop = platform_timer_event_stop, + .timer_event_start = platform_timer_event_start, + .timer_init = platform_timer_init, + .system_reset_check = platform_system_reset_check, + .system_reset = platform_system_reset +}; +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x00), + .name = "platform-name", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = 1, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/thead/c910/config.mk b/roms/opensbi/platform/thead/c910/config.mk new file mode 100644 index 000000000..bd5eab716 --- /dev/null +++ b/roms/opensbi/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/roms/opensbi/platform/thead/c910/objects.mk b/roms/opensbi/platform/thead/c910/objects.mk new file mode 100644 index 000000000..d025a3642 --- /dev/null +++ b/roms/opensbi/platform/thead/c910/objects.mk @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +platform-objs-y += platform.o diff --git a/roms/opensbi/platform/thead/c910/platform.c b/roms/opensbi/platform/thead/c910/platform.c new file mode 100644 index 000000000..dfa484ad2 --- /dev/null +++ b/roms/opensbi/platform/thead/c910/platform.c @@ -0,0 +1,156 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sbi/riscv_encoding.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_const.h> +#include <sbi/sbi_hart.h> +#include <sbi/sbi_platform.h> +#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/serial/uart8250.h> +#include <sbi_utils/sys/clint.h> +#include "platform.h" + +static struct c910_regs_struct c910_regs; + +static struct clint_data clint = { + .addr = 0, /* Updated at cold boot time */ + .first_hartid = 0, + .hart_count = C910_HART_COUNT, + .has_64bit_mmio = FALSE, +}; + +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); + + c910_regs.plic_base_addr = csr_read(CSR_PLIC_BASE); + c910_regs.clint_base_addr = + c910_regs.plic_base_addr + C910_PLIC_CLINT_OFFSET; + } 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_MHINT, c910_regs.mhint); + csr_write(CSR_MXSTATUS, c910_regs.mxstatus); + } + + 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) { + clint.addr = c910_regs.clint_base_addr; + rc = clint_cold_ipi_init(&clint); + if (rc) + return rc; + } + + return clint_warm_ipi_init(); +} + +static int c910_timer_init(bool cold_boot) +{ + int ret; + + if (cold_boot) { + clint.addr = c910_regs.clint_base_addr; + ret = clint_cold_timer_init(&clint, NULL); + if (ret) + return ret; + } + + return clint_warm_timer_init(); +} + +static int c910_system_reset_check(u32 type, u32 reason) +{ + return 1; +} + +static void c910_system_reset(u32 type, u32 reason) +{ + asm volatile ("ebreak"); +} + +int c910_hart_start(u32 hartid, ulong saddr) +{ + csr_write(CSR_MRVBR, saddr); + csr_write(CSR_MRMR, csr_read(CSR_MRMR) | (1 << hartid)); + + 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_reset_check = c910_system_reset_check, + .system_reset = c910_system_reset, + + .hart_start = c910_hart_start, +}; + +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 = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .platform_ops_addr = (unsigned long)&platform_ops +}; diff --git a/roms/opensbi/platform/thead/c910/platform.h b/roms/opensbi/platform/thead/c910/platform.h new file mode 100644 index 000000000..354404ef7 --- /dev/null +++ b/roms/opensbi/platform/thead/c910/platform.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _C910_PLATFORM_H_ +#define _C910_PLATFORM_H_ + +#define C910_HART_COUNT 16 + +#define SBI_THEAD_FEATURES \ + (SBI_PLATFORM_HAS_MFAULTS_DELEGATION | \ + SBI_PLATFORM_HAS_HART_SECONDARY_BOOT) + +#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 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_ */ |