[PATCH v5 1/8] riscv: Add initial support for P8700 SoC

Uros Stajic
2026-03-27T16:27:22Z

Hi Leo,

On 3/17/26 09:36, Leo Liang wrote:
> Hi Uros,
>
> On Wed, Dec 24, 2025 at 03:45:22PM +0000, Uros Stajic wrote:
>> From: Chao-ying Fu <cfu@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@mips.com>
>> Signed-off-by: Uros Stajic <uros.stajic@htecgroup.com>
>> Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>
>> ---
>> arch/riscv/Kconfig | 1 +
>> arch/riscv/cpu/p8700/Kconfig | 14 +++
>> arch/riscv/cpu/p8700/Makefile | 7 ++
>> arch/riscv/cpu/p8700/cache.c | 93 ++++++++++++++++++
>> arch/riscv/cpu/p8700/cpu.c | 111 ++++++++++++++++++++++
>> arch/riscv/cpu/p8700/dram.c | 37 ++++++++
>> arch/riscv/include/asm/arch-p8700/p8700.h | 110 +++++++++++++++++++++
>> 7 files changed, 373 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/include/asm/arch-p8700/p8700.h
> ...
>> diff --git a/arch/riscv/cpu/p8700/cpu.c b/arch/riscv/cpu/p8700/cpu.c
>> new file mode 100644
>> index 00000000000..d63f7073d75
>> --- /dev/null
>> +++ b/arch/riscv/cpu/p8700/cpu.c
>> @@ -0,0 +1,111 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2021, Chao-ying Fu <cfu@mips.com>
>> + */
>> +
>> +#include <asm/encoding.h>
>> +#include <asm/io.h>
>> +#include <linux/types.h>
>> +#include <asm/arch-p8700/p8700.h>
>> +
>> +static __noreturn void jump_to_addr(ulong addr)
>> +{
>> + asm volatile ("jr %0" :: "r"(addr) : "memory");
>> + __builtin_unreachable();
>> +}
>> +
>> +void harts_early_init(void)
>> +{
>> + if (!IS_ENABLED(CONFIG_RISCV_MMODE))
>> + return;
>> +
>> + ulong hartid = csr_read(CSR_MHARTID);
>> +
>> + /* Wait for DDR3 calibration */
>> + while (!(readl((void __iomem *)BOSTON_PLAT_DDR3STAT) &
>> + BOSTON_PLAT_DDR3STAT_CALIB)) {
>> + /* busy-wait */
>> + }
>> +
>> + /*
>> + * Only mhartid[3:0] == 0 performs CM/GCR programming.
>> + * Other harts skip CM/GCR setup and go straight to PMP/PMA setup.
>> + */
>> + if ((hartid & 0xFULL) == 0) {
>> + ulong cm_base = CM_BASE;
>> + void __iomem *gcr_win = (void __iomem *)0x1fb80000;
>> + ulong cluster = (hartid >> MHARTID_CLUSTER_SHIFT) &
>> + MHARTID_CLUSTER_MASK;
>> +
>> + cm_base += cluster << CM_BASE_CLUSTER_SHIFT;
>> +
>> + if ((hartid & 0xFFFFUL) == 0)
>> + writeq(cm_base, gcr_win + GCR_BASE_OFFSET);
>> +
>> + ulong core = (hartid >> MHARTID_CORE_SHIFT) & MHARTID_CORE_MASK;
>> +
>> + /* Enable coherency for the current core */
>> + cm_base += core << CM_BASE_CORE_SHIFT;
>> + writeq((u64)GCR_CL_COH_EN_EN,
>> + (void __iomem *)(cm_base + P8700_GCR_C0_COH_EN));
>> +
>> + /*
>> + * On hart 0, default PCIe DMA mapping should be the non-IOCU
>> + * target.
>> + */
>> + if (hartid == 0) {
>> + writel(0x00, (void __iomem *)BOSTON_PLAT_NOCPCIE0ADDR);
>> + writel(0x00, (void __iomem *)BOSTON_PLAT_NOCPCIE1ADDR);
>> + writel(0x00, (void __iomem *)BOSTON_PLAT_NOCPCIE2ADDR);
>> + }
>> + }
>> +
>> + /* PMP setup */
>> + csr_write(pmpaddr1, 0x2fffffffUL);
>> + csr_write(pmpaddr2, 0x07ff7fffUL);
>> + csr_write(pmpaddr3, 0x07f3ffffUL);
>> + csr_write(pmpaddr4, 0x1fffffffffffffffUL);
>> +
>> + unsigned long pmpcfg = ((unsigned long)(PMP_NAPOT | PMP_R | PMP_W |
>> + PMP_X) << 32) |
>> + ((unsigned long)(PMP_NAPOT | PMP_R |
>> + PMP_X) << 24) |
>> + ((unsigned long)(PMP_NAPOT | PMP_R | PMP_W |
>> + PMP_X) << 16) |
>> + ((unsigned long)(PMP_NAPOT | PMP_R | PMP_W |
>> + PMP_X) << 8);
>> +
>> + csr_write(pmpcfg0, pmpcfg);
>> +
>> + /* PMA/cache attributes */
>> + ulong pmacfg0;
>> +
>> + if (hartid == 0) {
>> + /*
>> + * Hart 0: cacheable for pmp0, pmp1, pmp3; uncacheable for
>> + * pmp2, pmp4.
>> + */
>
> Are these typos? Are they meant to be pma0, pma1, pma3, ...etc?
> If yes, I can modify them on my side.
>

Yes, they are typos. They should be pma0, pma1, pma2, etc. I’ll fix that
in v6. Thanks for catching this.

>> + pmacfg0 = ((unsigned long)CCA_CACHE_DISABLE << 32) |
>> + ((unsigned long)CCA_CACHE_ENABLE << 24) |
>> + ((unsigned long)CCA_CACHE_DISABLE << 16) |
>> + ((unsigned long)CCA_CACHE_ENABLE << 8) |
>> + ((unsigned long)CCA_CACHE_ENABLE);
>> + } else {
>> + /*
>> + * Hart 1 or above: cacheable for pmp0, pmp1; uncacheable for
>> + * pmp2, pmp3, pmp4.
>> + */
>
> Ditto.
>
>> + pmacfg0 = ((unsigned long)CCA_CACHE_DISABLE << 32) |
>> + ((unsigned long)CCA_CACHE_DISABLE << 24) |
>> + ((unsigned long)CCA_CACHE_DISABLE << 16) |
>> + ((unsigned long)CCA_CACHE_ENABLE << 8) |
>> + ((unsigned long)CCA_CACHE_ENABLE);
>> + }
>> +
>> + asm volatile ("csrw %0, %1" :: "i"(CSR_PMACFG0), "r"(pmacfg0));
>> + asm volatile ("fence" ::: "memory");
>> +
>> + /* Secondary harts: after early setup, jump to the common entry point */
>> + if (hartid != 0)
>> + jump_to_addr(CONFIG_SYS_LOAD_ADDR);
>> +}
> ...
>> 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@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
>
> Just checking. Are these indices correct?
>

Yes, these indices are correct. According to the documentation for the
P8700 MCACHE instruction, the target cache values are defined as
L1 I-cache = 0, L1 D-cache = 1, L3 cache = 2, and 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
>
> "BOSTON_PLAT_BASE" seems to cause redefinition error when build with -Werror.
> The redefinition is introduced in the second patch.
>

You're right. The BOSTON_PLAT_BASE redefinition comes from the second
patch. I will fix it in v6.

>> +#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__ */

Best regards,
Uros