On Tue, Jun 24, 2025 at 10:25:30AM +0000, Uros Stajic wrote:
> 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 implements initial support required for U-Boot to run on
> the P8700-based Boston board.
> 
> Signed-off-by: Chao-ying Fu <c...@mips.com>
> Signed-off-by: Uros Stajic <uros.sta...@htecgroup.com>
> ---
>  arch/riscv/Kconfig                          |  11 +
>  arch/riscv/cpu/Makefile                     |   2 +
>  arch/riscv/cpu/p8700/Kconfig                |  15 ++
>  arch/riscv/cpu/p8700/Makefile               |   7 +
>  arch/riscv/cpu/p8700/cache.c                |  74 ++++++
>  arch/riscv/cpu/p8700/cpu.c                  |  22 ++
>  arch/riscv/cpu/p8700/dram.c                 |  37 +++
>  arch/riscv/cpu/p8700/p8700_platform_setup.S | 155 ++++++++++++
>  arch/riscv/cpu/start.S                      |   8 +
>  arch/riscv/dts/Makefile                     |   1 +
>  arch/riscv/dts/boston-p8700.dts             | 253 ++++++++++++++++++++
>  arch/riscv/include/asm/arch-p8700/p8700.h   | 110 +++++++++
>  board/mips/boston-riscv/Kconfig             |  43 ++++
>  board/mips/boston-riscv/MAINTAINERS         |   9 +
>  board/mips/boston-riscv/Makefile            |   8 +
>  board/mips/boston-riscv/boston-lcd.h        |  20 ++
>  board/mips/boston-riscv/boston-regs.h       |  38 +++
>  board/mips/boston-riscv/boston-riscv.c      |   9 +
>  board/mips/boston-riscv/checkboard.c        |  43 ++++
>  board/mips/boston-riscv/config.mk           |  15 ++
>  board/mips/boston-riscv/lowlevel_init.S     |  18 ++
>  board/mips/boston-riscv/reset.c             |  15 ++
>  configs/boston-p8700_defconfig              |  94 ++++++++
>  drivers/clk/Kconfig                         |   2 +-
>  include/asm-generic/global_data.h           |   5 +
>  include/configs/boston-riscv.h              |  11 +
>  26 files changed, 1024 insertions(+), 1 deletion(-)

It's a relatively large patch, and it'll be nice if you could split it
into several smaller ones, for exampe, one for CPU stuff and one for
board stuff.

>  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/dts/boston-p8700.dts
>  create mode 100644 arch/riscv/include/asm/arch-p8700/p8700.h
>  create mode 100644 board/mips/boston-riscv/Kconfig
>  create mode 100644 board/mips/boston-riscv/MAINTAINERS
>  create mode 100644 board/mips/boston-riscv/Makefile
>  create mode 100644 board/mips/boston-riscv/boston-lcd.h
>  create mode 100644 board/mips/boston-riscv/boston-regs.h
>  create mode 100644 board/mips/boston-riscv/boston-riscv.c
>  create mode 100644 board/mips/boston-riscv/checkboard.c
>  create mode 100644 board/mips/boston-riscv/config.mk
>  create mode 100644 board/mips/boston-riscv/lowlevel_init.S
>  create mode 100644 board/mips/boston-riscv/reset.c
>  create mode 100644 configs/boston-p8700_defconfig
>  create mode 100644 include/configs/boston-riscv.h

...

> diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile
> index 6bf6f911c67..38894861694 100644
> --- a/arch/riscv/cpu/Makefile
> +++ b/arch/riscv/cpu/Makefile
> @@ -5,3 +5,5 @@
>  extra-y = start.o
>  
>  obj-y += cpu.o mtrap.o
> +
> +obj-$(CONFIG_P8700_RISCV) += p8700/p8700_platform_setup.o

This could be moved to arch/riscv/cpu/p8700/Makefile. It seems more
natural to me since arch/riscv/cpu/p8700 contains p8700_platform_setup.S

...

> diff --git a/arch/riscv/cpu/p8700/Makefile b/arch/riscv/cpu/p8700/Makefile
> new file mode 100644
> index 00000000000..ecdd232da6f
> --- /dev/null
> +++ b/arch/riscv/cpu/p8700/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright (C) 2021, Chao-ying Fu <c...@mips.com>
> +
> +obj-y += dram.o
> +obj-y += cpu.o
> +obj-y += cache.o

It'll be nice to sort the files in alphabetical order. Same for headers
included in files below.

> diff --git a/arch/riscv/cpu/p8700/cache.c b/arch/riscv/cpu/p8700/cache.c
> new file mode 100644
> index 00000000000..27641035d80
> --- /dev/null
> +++ b/arch/riscv/cpu/p8700/cache.c
> @@ -0,0 +1,74 @@
> +// 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/arch-p8700/p8700.h>
> +
> +/* NOTE: We force to use a0 in mcache to encode via .word. */
> +#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 0xec0500f3|%0 # force to use %1" \
> +                                                             ::"i"((op) << 
> 20), "r"(addr));  \

It's unclear what the magical instruction does, could you please add a
comment and use a meaningful macro to make it easier to understand?

> +} 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;
> +     long address = GCR_L2_CONFIG;
> +
> +     asm volatile ("lw %0,0(%1)" : "=r"(l2_config) : "r"(address) : 
> "memory");

Is it really necessary to use inline assembly? If GCR_L2_CONFIG is an
MMIO register, readl() should work here.

> +     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);
> +
> +     /* ensure cache ops complete before any further memory access */
> +     asm volatile ("slli x0,x0,1 # ihb");

This instruction also looks confusing: slli usually means left-shift
with an immediate in the context of RISC-V, which obviously doesn't
match the corresponding comment. Could you please provide a macro for
the instruction, and explain it further if possible? This applies also
for the asm statement in invalidate_dcache_range().

> +}
> +
> +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);
> +
> +     /* ensure cache ops complete before any further memory access */
> +     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..f13c18942f3
> --- /dev/null
> +++ b/arch/riscv/cpu/p8700/cpu.c
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018, Bin Meng <bmeng...@gmail.com>
> + */
> +
> +#include <irq_func.h>
> +#include <asm/cache.h>
> +
> +/*
> + * cleanup_before_linux() is called just before we call linux
> + * it prepares the processor for linux
> + *
> + * we disable interrupt and caches.
> + */
> +int cleanup_before_linux(void)
> +{
> +     disable_interrupts();
> +
> +     cache_flush();
> +
> +     return 0;
> +}

We have a weak, general implementation in arch/riscv/cpu.c, thus the
whole file could be dropped.

...

> 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..c2999045175
> --- /dev/null
> +++ b/arch/riscv/cpu/p8700/p8700_platform_setup.S
> @@ -0,0 +1,155 @@
> +/* 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:
> +     move s6, ra
> +     li      x1,0
> +     li      x2,0
> +     li      x3,0
> +     li      x4,0
> +     li      x5,0
> +     li      x6,0
> +     li      x7,0
> +     li      x8,0
> +     li      x9,0
> +     li      x10,0
> +     li      x11,0
> +     li      x12,0
> +     li      x13,0
> +     li      x14,0
> +     li      x15,0
> +     li      x16,0
> +     li      x17,0
> +     li      x18,0
> +     li      x19,0
> +     li      x20,0
> +     li      x21,0
> +     li      x23,0
> +     li      x24,0
> +     li      x25,0
> +     li      x26,0
> +     li      x27,0
> +     li      x28,0
> +     li      x29,0
> +     li      x30,0
> +     li      x31,0

These instructions miss some space between the two operands.

...

> +     /* 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)

Here miss some space between the two operands of the li instructions.

> +     /* Test mhartid */
> +     beq     a0, zero, 1f
> +     /* Jump to 0x80000000 */
> +     li      t0, 0x80000000

Why choose this specific address? If possible please use a macro instead
(I noticed it's actually CONFIG_SYS_LOAD_ADDR).

> +     jr      t0

...

> diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
> index 7bafdfd390a..e36abb5957b 100644
> --- a/arch/riscv/cpu/start.S
> +++ b/arch/riscv/cpu/start.S
> @@ -39,6 +39,10 @@ secondary_harts_relocation_error:
>  .section .text
>  .globl _start
>  _start:
> +#ifdef CONFIG_P8700_RISCV
> +     call p8700_platform_setup
> +#endif
> +
>  #if CONFIG_IS_ENABLED(RISCV_MMODE)
>       csrr    a0, CSR_MHARTID
>  #endif
> @@ -416,6 +420,10 @@ call_board_init_r:
>       mv      a1, s4                  /* dest_addr */
>       mv      s0, zero                /* fp == NULL */
>  
> +#ifdef CONFIG_P8700_RISCV
> +     call set_flash_uncached
> +#endif

Is it necessary to call these initialization rountines so early that
even harts_early_init() doesn't work? It really doesn't look clean
especially IIRC there's no platform-specific code in
arch/riscv/cpu/start.S.

>  /*
>   * jump to it ...
>   */

...

> diff --git a/arch/riscv/dts/boston-p8700.dts b/arch/riscv/dts/boston-p8700.dts
> new file mode 100644
> index 00000000000..6d700a5675c
> --- /dev/null
> +++ b/arch/riscv/dts/boston-p8700.dts
> @@ -0,0 +1,253 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2021, Chao-ying Fu <c...@mips.com>
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/clock/boston-clock.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/interrupt-controller/mips-gic.h>
> +
> +/ {
> +     #address-cells = <1>;
> +     #size-cells = <1>;
> +     model = "p8700";
> +     compatible = "img,boston";
> +
> +     chosen {
> +             stdout-path = &uart0;
> +             bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
> +     };
> +
> +     cpus {
> +             #address-cells = <1>;
> +             #size-cells = <0>;
> +             timebase-frequency = <20000000>;
> +
> +             cpu@0 {
> +                     device_type = "cpu";
> +                     compatible = "riscv";
> +                     mmu-type = "riscv,sv39";
> +                     riscv,isa = "rv64imafdcsu";

riscv,isa is already deprecated in devicetree-binding upstream, it'll
be nice if you could provide a riscv,isa-extensions property as well.

> +                     status = "okay";
> +                     reg = <0>;
> +                     clocks = <&clk_boston BOSTON_CLK_CPU>;
> +                     clock-frequency = <20000000>;
> +                     bootph-all;

These properties should be sorted, compatible goes first, then reg, and
status should be the last property[1]. This should apply for other nodes
as well.

> +             };
> +     };

Regards,
Yao Zi

Reply via email to