diff options
Diffstat (limited to 'roms/opensbi/platform/andes')
-rw-r--r-- | roms/opensbi/platform/andes/ae350/cache.c | 89 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/cache.h | 17 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/config.mk | 36 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/objects.mk | 11 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/platform.c | 192 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/platform.h | 125 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/plicsw.c | 145 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/plicsw.h | 46 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/plmt.c | 97 | ||||
-rw-r--r-- | roms/opensbi/platform/andes/ae350/plmt.h | 23 |
10 files changed, 781 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_ */ |