mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-02-28 02:01:50 +00:00
In the multi-cluster system each cluster has its own CM (Coherency Manager). Every CM has its "global" memory address where it is accessible from any bus master. Initially, all CMs accessible from the local cluster using same "local" address. Transactions by local address are not routed through system bus and thus are faster. Remap CM in every cluster to the local address matching its global address. Then, every CM is always accessed using same address, but when transaction initiated from the local cluster it is routed internally. This removes need for 2 PMP regions covering local address access. CM accessor functions simplified because there's no need to detect whether transaction is local or global Access timer always in cluster 0 Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-7-621d004d1a21@mobileye.com Signed-off-by: Anup Patel <anup@brainfault.org>
83 lines
2.4 KiB
C
83 lines
2.4 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2025 MIPS
|
|
*
|
|
*/
|
|
|
|
#ifndef __MIPS_CM_H__
|
|
#define __MIPS_CM_H__
|
|
|
|
#include <mips/p8700.h>
|
|
#include <sbi/sbi_console.h>
|
|
|
|
/* Define 1 to print out CM read and write info */
|
|
#define DEBUG_CM 0
|
|
|
|
extern long GLOBAL_CM_BASE[];
|
|
|
|
|
|
#define CPS_ACCESSOR_R(unit, sz, off, name) \
|
|
static inline u##sz read_##unit##_##name(u32 hartid) \
|
|
{ \
|
|
u##sz value; \
|
|
int cl = cpu_cluster(hartid); \
|
|
int co = cpu_core(hartid); \
|
|
long cmd_reg = GLOBAL_CM_BASE[cl] + (co << CM_BASE_CORE_SHIFT) \
|
|
+ off; \
|
|
if (DEBUG_CM) \
|
|
sbi_printf("CM_READ%d(0x%lx) ...\n", sz, cmd_reg); \
|
|
if (sz == 32) \
|
|
asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
|
|
else if (sz == 64) \
|
|
asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
|
|
asm volatile("fence"); \
|
|
if (DEBUG_CM) \
|
|
sbi_printf("CM_READ%d(0x%lx) -> 0x%lx\n", sz, cmd_reg, (unsigned long)value); \
|
|
return value; \
|
|
}
|
|
|
|
#define CPS_ACCESSOR_W(unit, sz, off, name) \
|
|
static inline void write_##unit##_##name(u32 hartid, u##sz value) \
|
|
{ \
|
|
int cl = cpu_cluster(hartid); \
|
|
int co = cpu_core(hartid); \
|
|
long cmd_reg = GLOBAL_CM_BASE[cl] + (co << CM_BASE_CORE_SHIFT) \
|
|
+ off; \
|
|
if (DEBUG_CM) \
|
|
sbi_printf("CM_WRITE%d(0x%lx, 0x%lx)\n", sz, \
|
|
cmd_reg, (unsigned long)value); \
|
|
if (sz == 32) \
|
|
asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
|
|
else if (sz == 64) \
|
|
asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
|
|
asm volatile("fence"); \
|
|
}
|
|
|
|
#define CPS_ACCESSOR_RW(unit, sz, off, name) \
|
|
CPS_ACCESSOR_R(unit, sz, off, name) \
|
|
CPS_ACCESSOR_W(unit, sz, off, name)
|
|
|
|
#define CPC_CX_ACCESSOR_RW(sz, off, name) \
|
|
CPS_ACCESSOR_RW(cpc, sz, CPC_OFFSET + CPC_OFF_LOCAL + (off), co_##name)
|
|
|
|
#define GCR_CX_ACCESSOR_RW(sz, off, name) \
|
|
CPS_ACCESSOR_RW(gcr, sz, GCR_OFF_LOCAL + (off), co_##name)
|
|
|
|
GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
|
|
GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
|
|
GCR_CX_ACCESSOR_RW(64, GCR_BASE_OFFSET, base)
|
|
|
|
CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
|
|
CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
|
|
CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
|
|
CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
|
|
|
|
#define CPC_ACCESSOR_RW(sz, off, name) \
|
|
CPS_ACCESSOR_RW(cpc, sz, CPC_OFFSET + (off), name)
|
|
|
|
CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
|
|
CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
|
|
|
|
#endif
|