[PATCH v3 01/12] riscv: Add initial support for P8700 SoC

Uros Stajic uros.stajic at htecgroup.com
Tue Jul 29 18:22:03 CEST 2025


From: Chao-ying Fu <cfu at 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 <cfu at mips.com>
Signed-off-by: Uros Stajic <uros.stajic at htecgroup.com>
---
 arch/riscv/Kconfig                          |   1 +
 arch/riscv/cpu/p8700/Kconfig                |  15 ++
 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, 447 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 8c6feae5735..eb721edca2c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -127,6 +127,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..0e5e4c9eda6
--- /dev/null
+++ b/arch/riscv/cpu/p8700/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2021, Chao-ying Fu <cfu at mips.com>
+
+config P8700_RISCV
+	bool
+	select ARCH_EARLY_INIT_R
+	imply CPU
+	imply CPU_RISCV
+	imply RISCV_TIMER
+	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 <cfu at 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 <cfu at 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 <cfu at 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.cn at 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 <cfu at 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 <cfu at 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


More information about the U-Boot mailing list