mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-12-15 03:31:49 +00:00
lib: utils/cache: Add SiFive PL2 controller
SiFive Private L2(PL2) cache is a private cache owned by each hart. Add this driver to support private cache flush operations via the MMIO registers. Co-developed-by: Eric Lin <eric.lin@sifive.com> Signed-off-by: Eric Lin <eric.lin@sifive.com> Co-developed-by: Zong Li <zong.li@sifive.com> Signed-off-by: Zong Li <zong.li@sifive.com> Co-developed-by: Vincent Chen <vincent.chen@sifive.com> Signed-off-by: Vincent Chen <vincent.chen@sifive.com> Co-developed-by: Samuel Holland <samuel.holland@sifive.com> Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Signed-off-by: Nick Hu <nick.hu@sifive.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20251114-sifive-cache-drivers-v1-2-8423a721924c@sifive.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
4
lib/utils/cache/Kconfig
vendored
4
lib/utils/cache/Kconfig
vendored
@@ -14,6 +14,10 @@ config FDT_CACHE_SIFIVE_CCACHE
|
||||
bool "SiFive CCACHE FDT cache driver"
|
||||
default n
|
||||
|
||||
config FDT_CACHE_SIFIVE_PL2
|
||||
bool "SiFive PL2 FDT cache driver"
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
config CACHE
|
||||
|
||||
139
lib/utils/cache/fdt_sifive_pl2.c
vendored
Normal file
139
lib/utils/cache/fdt_sifive_pl2.c
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 SiFive Inc.
|
||||
*/
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <sbi/riscv_io.h>
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_heap.h>
|
||||
#include <sbi_utils/cache/fdt_cache.h>
|
||||
#include <sbi_utils/fdt/fdt_driver.h>
|
||||
|
||||
#define FLUSH64_CMD_TARGET_ALL (0x2 << 3)
|
||||
#define FLUSH64_CMD_TYPE_FLUSH 0x3ULL
|
||||
|
||||
#define SIFIVE_PL2CACHE_CMD_QLEN 0xff
|
||||
|
||||
#define SIFIVE_PL2CACHE_FLUSH64_OFF 0x200ULL
|
||||
#define SIFIVE_PL2CACHE_STATUS_OFF 0x208ULL
|
||||
#define SIFIVE_PL2CACHE_CONFIG1_OFF 0x1000ULL
|
||||
#define SIFIVE_PL2CACHE_CONFIG0_OFF 0x1008ULL
|
||||
|
||||
#define FLUSH64_CMD_POS 56
|
||||
#define REGIONCLOCKDISABLE_MASK BIT(3)
|
||||
|
||||
#define CONFIG0_ACCEPT_DIRTY_DATA_ENABLE BIT(24)
|
||||
|
||||
struct sifive_pl2_quirks {
|
||||
bool no_dirty_fill;
|
||||
};
|
||||
|
||||
struct sifive_pl2 {
|
||||
struct cache_device dev;
|
||||
void *addr;
|
||||
bool no_dirty_fill;
|
||||
};
|
||||
|
||||
#define to_pl2(_dev) container_of(_dev, struct sifive_pl2, dev)
|
||||
|
||||
static int sifive_pl2_flush_all(struct cache_device *dev)
|
||||
{
|
||||
struct sifive_pl2 *pl2_dev = to_pl2(dev);
|
||||
char *addr = pl2_dev->addr;
|
||||
u64 cmd = (FLUSH64_CMD_TARGET_ALL | FLUSH64_CMD_TYPE_FLUSH) << FLUSH64_CMD_POS;
|
||||
u32 config0;
|
||||
|
||||
/*
|
||||
* While flushing pl2 cache, a speculative load might causes a dirty line pull
|
||||
* into PL2. It will cause the SiFive SMC0 refuse to enter the power gating.
|
||||
* Disable the ACCEPT_DIRTY_DATA_ENABLE to avoid the issue.
|
||||
*/
|
||||
if (pl2_dev->no_dirty_fill) {
|
||||
config0 = readl((void *)addr + SIFIVE_PL2CACHE_CONFIG0_OFF);
|
||||
config0 &= ~CONFIG0_ACCEPT_DIRTY_DATA_ENABLE;
|
||||
writel(config0, (void *)addr + SIFIVE_PL2CACHE_CONFIG0_OFF);
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
writeq(cmd, addr + SIFIVE_PL2CACHE_FLUSH64_OFF);
|
||||
#else
|
||||
writel((u32)cmd, addr + SIFIVE_PL2CACHE_FLUSH64_OFF);
|
||||
writel((u32)(cmd >> 32), addr + SIFIVE_PL2CACHE_FLUSH64_OFF + sizeof(u32));
|
||||
#endif
|
||||
do {} while (readl(addr + SIFIVE_PL2CACHE_STATUS_OFF) & SIFIVE_PL2CACHE_CMD_QLEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sifive_pl2_warm_init(struct cache_device *dev)
|
||||
{
|
||||
struct sifive_pl2 *pl2_dev = to_pl2(dev);
|
||||
char *addr = pl2_dev->addr;
|
||||
u32 val;
|
||||
|
||||
/* Enabling the clock gating */
|
||||
val = readl(addr + SIFIVE_PL2CACHE_CONFIG1_OFF);
|
||||
val &= (~REGIONCLOCKDISABLE_MASK);
|
||||
writel(val, addr + SIFIVE_PL2CACHE_CONFIG1_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cache_ops sifive_pl2_ops = {
|
||||
.warm_init = sifive_pl2_warm_init,
|
||||
.cache_flush_all = sifive_pl2_flush_all,
|
||||
};
|
||||
|
||||
static int sifive_pl2_cold_init(const void *fdt, int nodeoff, const struct fdt_match *match)
|
||||
{
|
||||
const struct sifive_pl2_quirks *quirk = match->data;
|
||||
struct sifive_pl2 *pl2_dev;
|
||||
struct cache_device *dev;
|
||||
u64 reg_addr;
|
||||
int rc;
|
||||
|
||||
/* find the pl2 control base address */
|
||||
rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, NULL);
|
||||
if (rc < 0 && reg_addr)
|
||||
return SBI_ENODEV;
|
||||
|
||||
pl2_dev = sbi_zalloc(sizeof(*pl2_dev));
|
||||
if (!pl2_dev)
|
||||
return SBI_ENOMEM;
|
||||
|
||||
dev = &pl2_dev->dev;
|
||||
dev->ops = &sifive_pl2_ops;
|
||||
dev->cpu_private = true;
|
||||
|
||||
rc = fdt_cache_add(fdt, nodeoff, dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pl2_dev->addr = (void *)(uintptr_t)reg_addr;
|
||||
if (quirk)
|
||||
pl2_dev->no_dirty_fill = quirk->no_dirty_fill;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sifive_pl2_quirks pl2cache2_quirks = {
|
||||
.no_dirty_fill = true,
|
||||
};
|
||||
|
||||
static const struct sifive_pl2_quirks pl2cache0_quirks = {
|
||||
.no_dirty_fill = false,
|
||||
};
|
||||
|
||||
static const struct fdt_match sifive_pl2_match[] = {
|
||||
{ .compatible = "sifive,pl2cache2", .data = &pl2cache2_quirks },
|
||||
{ .compatible = "sifive,pl2cache1", .data = &pl2cache0_quirks },
|
||||
{ .compatible = "sifive,pl2cache0", .data = &pl2cache0_quirks },
|
||||
{},
|
||||
};
|
||||
|
||||
struct fdt_driver fdt_sifive_pl2 = {
|
||||
.match_table = sifive_pl2_match,
|
||||
.init = sifive_pl2_cold_init,
|
||||
};
|
||||
3
lib/utils/cache/objects.mk
vendored
3
lib/utils/cache/objects.mk
vendored
@@ -11,4 +11,7 @@ libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cmo_helper.o
|
||||
carray-fdt_cache_drivers-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += fdt_sifive_ccache
|
||||
libsbiutils-objs-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += cache/fdt_sifive_ccache.o
|
||||
|
||||
carray-fdt_cache_drivers-$(CONFIG_FDT_CACHE_SIFIVE_PL2) += fdt_sifive_pl2
|
||||
libsbiutils-objs-$(CONFIG_FDT_CACHE_SIFIVE_PL2) += cache/fdt_sifive_pl2.o
|
||||
|
||||
libsbiutils-objs-$(CONFIG_CACHE) += cache/cache.o
|
||||
|
||||
@@ -13,6 +13,7 @@ CONFIG_PLATFORM_MIPS_P8700=y
|
||||
CONFIG_PLATFORM_SPACEMIT_K1=y
|
||||
CONFIG_FDT_CACHE=y
|
||||
CONFIG_FDT_CACHE_SIFIVE_CCACHE=y
|
||||
CONFIG_FDT_CACHE_SIFIVE_PL2=y
|
||||
CONFIG_FDT_CPPC=y
|
||||
CONFIG_FDT_CPPC_RPMI=y
|
||||
CONFIG_FDT_GPIO=y
|
||||
|
||||
Reference in New Issue
Block a user