mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-12-22 06:12:02 +00:00
Initial platform support for ESWIN Computing EIC7700 based on public SoC
datasheet[1] and tested on HiFive Premier P550. Vendor U-boot/Linux boots
fine, and I've tested Geekbench 6.5.0 Preview and got scores on par with
the vendor OpenSBI. System shutdown/reboot for HiFive Premier P550 and
other boards will be implemented in subsequent commits. At this point,
only SoC-level warm reset is implemented.
The files and functions are intentionally named as eic770x in many places
for future enhancements to support the 2 die version of the same SoC,
namely EIC7702, seen on DC-ROMA AI PC FML13V03 [2]. This patch set only
deals with the single die version, and the assumption is we can be either
die with id=0 or id=1, but there's only a single die in the system, or we
are only using a single die out of 2. However, the way the SoC handles 2-
die greatly affects how we configure it in a 1-die setup. EIC770X address
map has die 0/1 memory regions interleaved (see comments in eic770x.c).
If only 1 die is connected or active, it creates holes in the address map
for those regions corresponding to the remote die. When speculative-
execution or HW prefetcher touches data-cacheable regions that happen to
fall into those holes, it can trigger bus error. Specifically:
- Remote (non-existent) die L3 zero device
- Remote (non-existent) die cached memory region
- Other holes in Memory Port
To make matters worse, EIC770X doesn't have cache coherent DMA, and due
to the fact that the P550 core lacks Svpbmt, the SoC maps main memory
twice as different regions, so it can bypass cache and fetch the data
directly from memory. In address space, we have two memory regions, one
as cached, the other as uncached. Thus, we also need an extra PMP entry
to protect OpenSBI blob from the uncached window. To do this, platform
code requires single_fw_region, otherwise, we'll run out of PMP entries.
EIC770X also have several feature disable/enable CSRs accessible in M
mode. By default many core features such as speculation and HW prefetch
are disabled, and M mode software is responsible of enabling. Hence,
introduce 4 new build time tunable parameters to Kconfig, which reflects
the values get updated to those CSRs:
- ESWIN_EIC770X_FEAT0_CFG
- ESWIN_EIC770X_FEAT1_CFG
- ESWIN_EIC770X_L1_HWPF_CFG
- ESWIN_EIC770X_L2_HWPF_CFG
The default values are somewhat optimal for generic workloads. They are
dumped when running SiFive's vendor OpenSBI, and in addition, with my
own tuning to address the perf regression reported by drmpeg [3]
To build the firmware+u-boot blob, Use the following, and docs [4] for
testing it with UART boot without flashing:
make FW_TEXT_START=0x80000000 \
FW_PAYLOAD_OFFSET=0x200000 \
FW_PAYLOAD_PATH=u-boot-nodtb.bin \
FW_PAYLOAD_FDT_ADDR=0xf8000000 \
FW_FDT_PATH=u-boot.dtb
[1] https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual
[2] https://github.com/geerlingguy/sbc-reviews/issues/82
[3] https://forums.sifive.com/t/low-1-core-stream-bandwidth/7274/15
[4] https://github.com/ganboing/EIC770x-Docs/blob/main/p550/bootchain/UART-Boot.md
Signed-off-by: Bo Gan <ganboing@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20251218104243.562667-6-ganboing@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
80 lines
2.8 KiB
C
80 lines
2.8 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2025 Bo Gan <ganboing@gmail.com>
|
|
*
|
|
*/
|
|
|
|
#ifndef __EIC770X_H__
|
|
#define __EIC770X_H__
|
|
|
|
#include <sbi/riscv_asm.h>
|
|
|
|
struct eic770x_board_override {
|
|
struct sbi_system_reset_device *reset_dev;
|
|
};
|
|
|
|
/* CSRs */
|
|
#define EIC770X_CSR_BRPREDICT 0x7c0
|
|
#define EIC770X_CSR_FEAT0 0x7c1
|
|
#define EIC770X_CSR_FEAT1 0x7c2
|
|
#define EIC770X_CSR_L1_HWPF 0x7c3
|
|
#define EIC770X_CSR_L2_HWPF 0x7c4
|
|
|
|
/* Hart ID to core/die conversion */
|
|
#define CPU_CORE_BITS 2
|
|
#define CPU_CORE_MASK ((1 << CPU_CORE_BITS) - 1)
|
|
#define CPU_DIE_SHIFT CPU_CORE_BITS
|
|
#define CPU_DIE_BITS 1
|
|
#define CPU_DIE_MASK ((1 << CPU_DIE_BITS) - 1)
|
|
|
|
#define hart_core(i) ((i) & CPU_CORE_MASK)
|
|
#define hart_die(i) (((i) >> CPU_DIE_SHIFT) & CPU_DIE_MASK)
|
|
#define current_hart_core() hart_core(current_hartid())
|
|
#define current_hart_die() hart_die(current_hartid())
|
|
|
|
/* P550 Internal and System Port 0 */
|
|
#define EIC770X_P550INT_SIZE 0x20000000UL
|
|
#define EIC770X_P550INT_BASE(d) (0UL + EIC770X_P550INT_SIZE * (d))
|
|
#define EIC770X_P550INT_LOCAL EIC770X_P550INT_BASE(current_hart_die())
|
|
#define EIC770X_TL64D2D_OUT (EIC770X_P550INT_LOCAL + 0x200000)
|
|
#define EIC770X_TL256D2D_OUT (EIC770X_P550INT_LOCAL + 0x202000)
|
|
#define EIC770X_TL256D2D_IN (EIC770X_P550INT_LOCAL + 0x204000)
|
|
#define EIC770X_L3_ZERO_SIZE 0x400000UL
|
|
#define EIC770X_L3_ZERO_BASE(d) (EIC770X_P550INT_BASE(d) + 0x1a000000)
|
|
#define EIC770X_L3_ZERO_LOCAL EIC770X_L3_ZERO_BASE(current_hart_die())
|
|
#define EIC770X_L3_ZERO_REMOTE EIC770X_L3_ZERO_BASE(1 - current_hart_die())
|
|
|
|
#define EIC770X_SYSPORT_SIZE 0x20000000UL
|
|
#define EIC770X_SYSPORT_BASE(d) (0x40000000UL + EIC770X_SYSPORT_SIZE * (d))
|
|
#define EIC770X_SYSPORT_LOCAL EIC770X_SYSPORT_BASE(current_hart_die())
|
|
#define EIC770X_SYSCRG (EIC770X_SYSPORT_LOCAL + 0x11828000UL)
|
|
#define EIC770X_SYSCRG_RST (EIC770X_SYSCRG + 0x300UL)
|
|
#define EIC770X_SYSCRG_RST_VAL 0x1AC0FFE6UL
|
|
|
|
/* Memory Ports */
|
|
#define EIC770X_MEMPORT_BASE 0x0080000000UL // 2G
|
|
#define EIC770X_MEMPORT_SIZE 0x7f80000000UL // +510G
|
|
#define EIC770X_MEMPORT_LIMIT (EIC770X_MEMPORT_BASE + EIC770X_MEMPORT_SIZE)
|
|
#define EIC770X_D0_MEM_BASE 0x0080000000UL // 2G
|
|
#define EIC770X_D0_MEM_SIZE 0x0f80000000UL // +62G
|
|
#define EIC770X_D0_MEM_LIMIT (EIC770X_D0_MEM_BASE + EIC770X_D0_MEM_SIZE)
|
|
#define EIC770X_D1_MEM_BASE 0x2000000000UL // 128G
|
|
#define EIC770X_D1_MEM_SIZE 0x1000000000UL // +64G
|
|
#define EIC770X_D1_MEM_LIMIT (EIC770X_D1_MEM_BASE + EIC770X_D1_MEM_SIZE)
|
|
#define EIC770X_CACHED_BASE (current_hart_die() ? \
|
|
EIC770X_D1_MEM_BASE : \
|
|
EIC770X_D0_MEM_BASE)
|
|
|
|
/* Uncached memory mapped in System Port 1 */
|
|
#define EIC770X_D0_UC_BASE 0xc000000000UL
|
|
#define EIC770X_D1_UC_BASE 0xe000000000UL
|
|
#define EIC770X_UNCACHED_BASE (current_hart_die() ? \
|
|
EIC770X_D1_UC_BASE : \
|
|
EIC770X_D0_UC_BASE)
|
|
|
|
#define EIC770X_TO_UNCACHED(x) ((x) - EIC770X_CACHED_BASE + \
|
|
EIC770X_UNCACHED_BASE)
|
|
|
|
#endif
|