From: Chao-ying Fu <c...@mips.com> Add initial platform support for the P8700-F, a high-performance multi-core RV64GC SoC with optional multi-cluster configuration and hardware multithreading.
This patch introduces the initial platform code necessary to support the P8700 CPU in U-Boot. Signed-off-by: Chao-ying Fu <c...@mips.com> Signed-off-by: Uros Stajic <uros.sta...@htecgroup.com> --- arch/riscv/Kconfig | 1 + arch/riscv/cpu/p8700/Kconfig | 14 ++ arch/riscv/cpu/p8700/Makefile | 9 ++ arch/riscv/cpu/p8700/cache.c | 93 +++++++++++ arch/riscv/cpu/p8700/cpu.c | 13 ++ arch/riscv/cpu/p8700/dram.c | 37 +++++ arch/riscv/cpu/p8700/p8700_platform_setup.S | 169 ++++++++++++++++++++ arch/riscv/include/asm/arch-p8700/p8700.h | 110 +++++++++++++ 8 files changed, 446 insertions(+) create mode 100644 arch/riscv/cpu/p8700/Kconfig create mode 100644 arch/riscv/cpu/p8700/Makefile create mode 100644 arch/riscv/cpu/p8700/cache.c create mode 100644 arch/riscv/cpu/p8700/cpu.c create mode 100644 arch/riscv/cpu/p8700/dram.c create mode 100644 arch/riscv/cpu/p8700/p8700_platform_setup.S create mode 100644 arch/riscv/include/asm/arch-p8700/p8700.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 04eb0e6f23c..4eaf0e3db71 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -131,6 +131,7 @@ source "arch/riscv/cpu/jh7110/Kconfig" source "arch/riscv/cpu/k1/Kconfig" source "arch/riscv/cpu/k230/Kconfig" source "arch/riscv/cpu/th1520/Kconfig" +source "arch/riscv/cpu/p8700/Kconfig" # architecture-specific options below diff --git a/arch/riscv/cpu/p8700/Kconfig b/arch/riscv/cpu/p8700/Kconfig new file mode 100644 index 00000000000..7023575a6be --- /dev/null +++ b/arch/riscv/cpu/p8700/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + +config P8700_RISCV + bool + select ARCH_EARLY_INIT_R + imply CPU + imply CPU_RISCV + imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE) + imply CMD_CPU + imply SPL_CPU_SUPPORT + imply SPL_OPENSBI + imply SPL_LOAD_FIT diff --git a/arch/riscv/cpu/p8700/Makefile b/arch/riscv/cpu/p8700/Makefile new file mode 100644 index 00000000000..4dfbddc5cba --- /dev/null +++ b/arch/riscv/cpu/p8700/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + +obj-y += cache.o +obj-y += cpu.o +obj-y += dram.o + +obj-$(CONFIG_P8700_RISCV) += p8700_platform_setup.o diff --git a/arch/riscv/cpu/p8700/cache.c b/arch/riscv/cpu/p8700/cache.c new file mode 100644 index 00000000000..7559c688321 --- /dev/null +++ b/arch/riscv/cpu/p8700/cache.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + */ + +#include <cpu_func.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch-p8700/p8700.h> + +#define MCACHE_BASE_INST 0xec0500f3 + +/* NOTE: We force to use a0 in mcache to encode via .word. + * 0xec0500f3 is a manually encoded custom RISC-V MCACHE instruction. + * The bits [19:15] are set to 01010, selecting register x10 (a0) + * as the source operand. + * The bits [24:20] represent the 'op' field, which is currently set to 0. + * Different cache operations are applied by OR-ing (op << 20) dynamically + * to this base value. + * Because of this encoding, the variable 'addr' is forced into register a0, + * so that the MCACHE instruction uses the address in a0 as its operand. + */ +#define cache_loop(start, end, lsize, op) do { \ + const __typeof__(lsize) __lsize = (lsize); \ + const register void *addr asm("a0") = (const void *)((start) & ~(__lsize - 1)); \ + const void *aend = (const void *)(((end) - 1) & ~(__lsize - 1)); \ + for (; addr <= aend; addr += __lsize) \ + asm volatile (".word %0 | %1 # force to use %2" \ + ::"i"(MCACHE_BASE_INST), "i"((op) << 20), "r"(addr)); \ +} while (0) + +static unsigned long lsize; +static unsigned long l1d_total_size; +static unsigned long slsize; + +static void probe_cache_config(void) +{ + lsize = 64; + l1d_total_size = 64 * 1024; + + int l2_config = 0; + + l2_config = readl((void __iomem *)GCR_L2_CONFIG); + int l2_line_size_info = (l2_config >> L2_LINE_SIZE_SHIFT) + & L2_LINE_SIZE_MASK; + slsize = (l2_line_size_info == 0) ? 0 : 1 << (l2_line_size_info + 1); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + if (lsize == 0) + probe_cache_config(); + + /* aend will be miscalculated when size is zero, so we return here */ + if (start >= end) + return; + + cache_loop(start, end, lsize, HIT_WRITEBACK_INV_D); + + /* flush L2 cache */ + if (slsize) + cache_loop(start, end, slsize, HIT_WRITEBACK_INV_SD); + + /* Instruction Hazard Barrier (IHB) — a hint-encoded SLLI (rd=0, rs1=0, imm=1). + * Ensures that all subsequent instruction fetches, including speculative ones, + * observe state changes from prior instructions. + * Required after MCACHE instructions when instruction fetch depends on cache ops. + */ + asm volatile ("slli x0,x0,1 # ihb"); +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + if (lsize == 0) + probe_cache_config(); + + /* aend will be miscalculated when size is zero, so we return here */ + if (start >= end) + return; + + /* invalidate L2 cache */ + if (slsize) + cache_loop(start, end, slsize, HIT_INVALIDATE_SD); + + cache_loop(start, end, lsize, HIT_INVALIDATE_D); + + /* Instruction Hazard Barrier (IHB) — a hint-encoded SLLI (rd=0, rs1=0, imm=1). + * Ensures that all subsequent instruction fetches, including speculative ones, + * observe state changes from prior instructions. + * Required after MCACHE instructions when instruction fetch depends on cache ops. + */ + asm volatile ("slli x0,x0,1 # ihb"); +} diff --git a/arch/riscv/cpu/p8700/cpu.c b/arch/riscv/cpu/p8700/cpu.c new file mode 100644 index 00000000000..ee0d8f377ac --- /dev/null +++ b/arch/riscv/cpu/p8700/cpu.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + */ + +extern void p8700_platform_setup(void); +extern void set_flash_uncached(void); + +void harts_early_init(void) +{ + p8700_platform_setup(); + set_flash_uncached(); +} diff --git a/arch/riscv/cpu/p8700/dram.c b/arch/riscv/cpu/p8700/dram.c new file mode 100644 index 00000000000..2b54326be39 --- /dev/null +++ b/arch/riscv/cpu/p8700/dram.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng...@gmail.com> + */ + +#include <fdtdec.h> +#include <init.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} + +phys_size_t board_get_usable_ram_top(phys_size_t total_size) +{ + if (IS_ENABLED(CONFIG_64BIT)) { + /* + * Ensure that we run from first 4GB so that all + * addresses used by U-Boot are 32bit addresses. + * + * This in-turn ensures that 32bit DMA capable + * devices work fine because DMA mapping APIs will + * provide 32bit DMA addresses only. + */ + if (gd->ram_top > SZ_4G) + return SZ_4G; + } + return gd->ram_top; +} diff --git a/arch/riscv/cpu/p8700/p8700_platform_setup.S b/arch/riscv/cpu/p8700/p8700_platform_setup.S new file mode 100644 index 00000000000..7c4475a03dd --- /dev/null +++ b/arch/riscv/cpu/p8700/p8700_platform_setup.S @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <elf.h> +#include <system-constants.h> +#include <asm/encoding.h> +#include <generated/asm-offsets.h> +#include <asm/arch-p8700/p8700.h> + +.global p8700_platform_setup +.global set_flash_uncached + +p8700_platform_setup: + addi sp, sp, -48 + sd s6, 0(sp) + sd s7, 8(sp) + sd s8, 16(sp) + sd s9, 24(sp) + sd s10, 32(sp) + sd s11, 40(sp) + + move s6, ra + move s7, x10 + move s8, x5 + move s9, x6 + move s10, x7 + move s11, x8 + + li x1, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x10, 0 + + /* a0 has mhartid */ + csrr a0, CSR_MHARTID + + li t0, BOSTON_PLAT_DDR3STAT +1: lw t1, 0(t0) + andi t1, t1, BOSTON_PLAT_DDR3STAT_CALIB + beqz t1, 1b + + /* Test mhartid lowest 4 bits */ + andi t0, a0, 0xf + bne t0, zero, setup_pmp + + li s0, CM_BASE + li t0, 0x1fb80000 + /* Get cluster number to update CM_BASE */ + srl t1, a0, MHARTID_CLUSTER_SHIFT + andi t1, t1, MHARTID_CLUSTER_MASK + sll t1, t1, CM_BASE_CLUSTER_SHIFT + add s0, s0, t1 + move t1, s0 + + /* Test mhartid lowest 16 bits */ + li t2, 0xffff + and t2, a0, t2 + bne t2, zero, cm_relocate_done + sd t1, GCR_BASE_OFFSET(t0) +cm_relocate_done: + + li t0, GCR_CL_COH_EN_EN + + /* Get core number to update CM_BASE */ + srl t1, a0, MHARTID_CORE_SHIFT + andi t1, t1, MHARTID_CORE_MASK + sll t1, t1, CM_BASE_CORE_SHIFT + add s0, s0, t1 + INDEXED(sd, t0, t1, P8700_GCR_C0_COH_EN, s0) +3: + + /* Test mhartid */ + bne a0, zero, setup_pmp + + /* Map all PCIe DMA access to its default, non-IOCU, target */ + li t0, BOSTON_PLAT_NOCPCIE0ADDR + sw zero, 0(t0) + li t0, BOSTON_PLAT_NOCPCIE1ADDR + sw zero, 0(t0) + li t0, BOSTON_PLAT_NOCPCIE2ADDR + sw zero, 0(t0) + +setup_pmp: + /* Setup PMP */ + li t0, 0x2fffffff # 2G from 0x80000000 + csrw pmpaddr1, t0 + li t0, 0x07ff7fff # 0x40000 from 0x1ffc0000 + csrw pmpaddr2, t0 + li t0, 0x07f3ffff # 2M from 0x1fc00000 + csrw pmpaddr3, t0 + li t0, 0x1fffffffffffffff # All from 0x0 + csrw pmpaddr4, t0 + li t0, ((PMP_NAPOT | PMP_R | PMP_W | PMP_X) << 32) | \ + ((PMP_NAPOT | PMP_R | PMP_X) << 24) | \ + ((PMP_NAPOT | PMP_R | PMP_W | PMP_X) << 16) | \ + ((PMP_NAPOT | PMP_R | PMP_W | PMP_X) << 8) + csrw pmpcfg0, t0 + + /* Test mhartid */ + bne a0, zero, 2f + /* HART 0: Set cacheable for pmp0, pmp1, pmp3, uncacheable for pmp2, pmp4 */ + li t0, (CCA_CACHE_DISABLE << 32) | (CCA_CACHE_ENABLE << 24) | \ + (CCA_CACHE_DISABLE << 16) | (CCA_CACHE_ENABLE << 8) | CCA_CACHE_ENABLE + j 3f +2: /* HART 1 or above: Set cacheable for pmp0, pmp1, uncacheable for pmp2, pmp3, pmp4 */ + li t0, (CCA_CACHE_DISABLE << 32) | (CCA_CACHE_DISABLE << 24) | \ + (CCA_CACHE_DISABLE << 16) | (CCA_CACHE_ENABLE << 8) | CCA_CACHE_ENABLE +3: + csrw CSR_PMACFG0, t0 + fence + + /* Test mhartid */ + beq a0, zero, 1f + /* Jump to 0x80000000 */ + li t0, CONFIG_SYS_LOAD_ADDR + jr t0 +1: + move ra, s6 + move x10, s7 + move x5, s8 + move x6, s9 + move x7, s10 + move x8, s11 + + ld s6, 0(sp) + ld s7, 8(sp) + ld s8, 16(sp) + ld s9, 24(sp) + ld s10, 32(sp) + ld s11, 40(sp) + addi sp, sp, 48 + + ret + +set_flash_uncached: + addi sp, sp, -32 + sd s6, 0(sp) + sd s7, 8(sp) + sd s8, 16(sp) + + move s6, ra + move s7, x5 + move s8, x6 + + /* Set flash uncached at pmp3 */ + csrr t0, CSR_PMACFG0 + li t1, 0xffffffffffffffff - (0xff << 24) + and t0, t0, t1 + li t1, (CCA_CACHE_DISABLE << 24) + or t0, t0, t1 + csrw CSR_PMACFG0, t0 + fence + + move ra, s6 + move x5, s7 + move x6, s8 + + ld s8, 16(sp) + ld s7, 8(sp) + ld s6, 0(sp) + addi sp, sp, 32 + + ret diff --git a/arch/riscv/include/asm/arch-p8700/p8700.h b/arch/riscv/include/asm/arch-p8700/p8700.h new file mode 100644 index 00000000000..5ca9b4b9497 --- /dev/null +++ b/arch/riscv/include/asm/arch-p8700/p8700.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021, Chao-ying Fu <c...@mips.com> + */ + +#ifndef __P8700_H__ +#define __P8700_H__ + +#define CSR_MIPSCONFIG7 0x7d7 +#define CSR_PMACFG0 0x7e0 + +#define MHARTID_HART_SHIFT 0 +#define MHARTID_HART_MASK 0xf +#define MHARTID_CORE_SHIFT 4 +#define MHARTID_CORE_MASK 0xff +#define MHARTID_CLUSTER_SHIFT 16 +#define MHARTID_CLUSTER_MASK 0xf + +#define MARCHID_UARCH_SHIFT 0 +#define MARCHID_UARCH_MASK 0xff +#define MARCHID_CLASS_SHIFT 8 +#define MARCHID_CLASS_MASK 0xff +#define MARCHID_CLASS_M 0 +#define MARCHID_CLASS_I 1 +#define MARCHID_CLASS_P 2 + +#define CM_BASE_CORE_SHIFT 8 +#define CM_BASE_CLUSTER_SHIFT 19 + +#define P8700_TIMER_ADDR 0x16108050 + +#define CCA_CACHE_ENABLE 0 +#define CCA_BUFFER_CACHE 1 +#define CCA_CACHE_DISABLE 2 +#define CCA_UNCACHE_ACC 3 +#define PMA_SPECULATION (0x1 << 3) + +#define L1_I_CACHE 0 +#define L1_D_CACHE 1 +#define L3_CACHE 2 +#define L2_CACHE 3 + +#define HIT_INVALIDATE 4 +#define HIT_WRITEBACK_INV 5 + +#define HIT_INVALIDATE_D ((HIT_INVALIDATE << 2) | L1_D_CACHE) +#define HIT_INVALIDATE_SD ((HIT_INVALIDATE << 2) | L2_CACHE) +#define HIT_WRITEBACK_INV_D ((HIT_WRITEBACK_INV << 2) | L1_D_CACHE) +#define HIT_WRITEBACK_INV_SD ((HIT_WRITEBACK_INV << 2) | L2_CACHE) + +#define L1D_LINE_SIZE_SHIFT 10 +#define L1D_LINE_SIZE_MASK 0x7 + +#define GCR_L2_CONFIG 0x16100130 +#define L2_LINE_SIZE_SHIFT 8 +#define L2_LINE_SIZE_MASK 0xf + +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_TOR 0x8 +#define PMP_NA4 0x10 +#define PMP_NAPOT 0x18 + +#define CM_BASE 0x16100000 +#define CPC_BASE (CM_BASE + 0x8000) + +/* CPC Block offsets */ +#define CPC_OFF_LOCAL 0x2000 + +#define CPC_PWRUP_CTL 0x0030 + +#define CPC_SYS_CONFIG 0x0140 + +#define CPC_Cx_CMD 0x0000 +#define CPC_Cx_CMD_RESET 0x4 + +#define P8700_GCR_C0_COH_EN 0x20f8 +#define P8700_GCR_C1_COH_EN 0x21f8 +#define P8700_GCR_C2_COH_EN 0x22f8 +#define P8700_GCR_C3_COH_EN 0x23f8 +#define P8700_GCR_C4_COH_EN 0x24f8 +#define P8700_GCR_C5_COH_EN 0x25f8 + +#define GCR_CL_COH_EN 0x2008 +#define GCR_CL_COH_EN_EN (0x1 << 0) +#define GCR_BASE_OFFSET 0x0008 +#define GIC_BASE_OFFSET 0x0080 +#define CPC_BASE_OFFSET 0x0088 +#define ENABLE 0x1 +#define COUNT_STOP (0x1 << 28) +#define GIC_LOCAL_SECTION_OFS 0x8000 +#define GIC_VL_MASK 0x08 +#define GIC_VL_RMASK 0x0c +#define GIC_VL_SMASK 0x10 +#define GIC_VL_COMPARE_MAP 0x44 + +#define INDEXED(op, reg, idx, offset, base) \ + li idx, offset ;\ + add idx, idx, base ;\ + op reg, (idx) + +#define BOSTON_PLAT_BASE 0x17ffd000 +#define BOSTON_PLAT_DDR3STAT (BOSTON_PLAT_BASE + 0x14) +#define BOSTON_PLAT_DDR3STAT_CALIB (0x1 << 2) +#define BOSTON_PLAT_NOCPCIE0ADDR (BOSTON_PLAT_BASE + 0x3c) +#define BOSTON_PLAT_NOCPCIE1ADDR (BOSTON_PLAT_BASE + 0x40) +#define BOSTON_PLAT_NOCPCIE2ADDR (BOSTON_PLAT_BASE + 0x44) + +#endif /* __P8700_H__ */ -- 2.34.1