[PATCH 04/26] hw/misc: pfsoc: Model L2 cache controller registers
Bin Meng <[email protected]> Thu, 23 Jul 2026 23:18:31 +0800
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Implement the Config, WayEnable, and per-master WayMask registers described by the PolarFire SoC MSS reference manual. Make WayEnable monotonic and report the remaining register space as unimplemented. Signed-off-by: Bin Meng <[email protected]> --- MAINTAINERS | 2 + include/hw/misc/mchp_pfsoc_l2cc.h | 30 +++++ hw/misc/mchp_pfsoc_l2cc.c | 180 ++++++++++++++++++++++++++++++ hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + 5 files changed, 216 insertions(+) create mode 100644 include/hw/misc/mchp_pfsoc_l2cc.h create mode 100644 hw/misc/mchp_pfsoc_l2cc.c diff --git a/MAINTAINERS b/MAINTAINERS index a28935c898..c0bb18c47a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1770,11 +1770,13 @@ F: hw/riscv/microchip_pfsoc.c F: hw/char/mchp_pfsoc_mmuart.c F: hw/misc/mchp_pfsoc_dmc.c F: hw/misc/mchp_pfsoc_ioscb.c +F: hw/misc/mchp_pfsoc_l2cc.c F: hw/misc/mchp_pfsoc_sysreg.c F: include/hw/riscv/microchip_pfsoc.h F: include/hw/char/mchp_pfsoc_mmuart.h F: include/hw/misc/mchp_pfsoc_dmc.h F: include/hw/misc/mchp_pfsoc_ioscb.h +F: include/hw/misc/mchp_pfsoc_l2cc.h F: include/hw/misc/mchp_pfsoc_sysreg.h Shakti C class SoC diff --git a/include/hw/misc/mchp_pfsoc_l2cc.h b/include/hw/misc/mchp_pfsoc_l2cc.h new file mode 100644 index 0000000000..1b5b3888d5 --- /dev/null +++ b/include/hw/misc/mchp_pfsoc_l2cc.h @@ -0,0 +1,30 @@ +/* + * Microchip PolarFire SoC L2 cache controller + * + * Copyright (c) 2026 Process Mission + * + * Author: + * Bin Meng <[email protected]> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef MCHP_PFSOC_L2CC_H +#define MCHP_PFSOC_L2CC_H + +#include "hw/core/register.h" +#include "hw/core/sysbus.h" + +#define MCHP_PFSOC_L2CC_REG_SIZE 0x1000 +#define MCHP_PFSOC_L2CC_REG_NUM (MCHP_PFSOC_L2CC_REG_SIZE / 8) + +typedef struct MchpPfSoCL2ccState { + SysBusDevice parent; + uint64_t regs[MCHP_PFSOC_L2CC_REG_NUM]; + RegisterInfo regs_info[MCHP_PFSOC_L2CC_REG_NUM]; +} MchpPfSoCL2ccState; + +#define TYPE_MCHP_PFSOC_L2CC "mchp.pfsoc.l2cc" +OBJECT_DECLARE_SIMPLE_TYPE(MchpPfSoCL2ccState, MCHP_PFSOC_L2CC) + +#endif diff --git a/hw/misc/mchp_pfsoc_l2cc.c b/hw/misc/mchp_pfsoc_l2cc.c new file mode 100644 index 0000000000..b320356572 --- /dev/null +++ b/hw/misc/mchp_pfsoc_l2cc.c @@ -0,0 +1,180 @@ +/* + * Microchip PolarFire SoC L2 cache controller + * + * Copyright (c) 2026 Process Mission + * + * Author: + * Bin Meng <[email protected]> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/core/register.h" +#include "hw/core/registerfields.h" +#include "hw/misc/mchp_pfsoc_l2cc.h" + +REG64(L2_CONFIG, 0x000) + FIELD(L2_CONFIG, BANKS, 0, 8) + FIELD(L2_CONFIG, WAYS, 8, 8) + FIELD(L2_CONFIG, SETS, 16, 8) + FIELD(L2_CONFIG, BYTES, 24, 8) +REG64(L2_WAY_ENABLE, 0x008) + FIELD(L2_WAY_ENABLE, VALUE, 0, 8) +REG64(L2_WAY_MASK_DMA, 0x800) +REG64(L2_WAY_MASK_AXI4_PORT_0, 0x808) +REG64(L2_WAY_MASK_AXI4_PORT_1, 0x810) +REG64(L2_WAY_MASK_AXI4_PORT_2, 0x818) +REG64(L2_WAY_MASK_AXI4_PORT_3, 0x820) +REG64(L2_WAY_MASK_HART0_DCACHE, 0x828) +REG64(L2_WAY_MASK_HART0_ICACHE, 0x830) +REG64(L2_WAY_MASK_HART1_DCACHE, 0x838) +REG64(L2_WAY_MASK_HART1_ICACHE, 0x840) +REG64(L2_WAY_MASK_HART2_DCACHE, 0x848) +REG64(L2_WAY_MASK_HART2_ICACHE, 0x850) +REG64(L2_WAY_MASK_HART3_DCACHE, 0x858) +REG64(L2_WAY_MASK_HART3_ICACHE, 0x860) +REG64(L2_WAY_MASK_HART4_DCACHE, 0x868) +REG64(L2_WAY_MASK_HART4_ICACHE, 0x870) + +#define L2_CONFIG_RESET 0x06091004 + +static uint64_t mchp_pfsoc_l2cc_way_enable_pre_write(RegisterInfo *reg, + uint64_t value) +{ + uint64_t current = *(uint64_t *)reg->data; + + return MAX(current, value); +} + +#define WAY_MASK_REGISTER(_name) \ + { \ + .name = "WAY_MASK_" #_name, \ + .addr = A_L2_WAY_MASK_ ## _name, \ + .reset = UINT64_MAX, \ + } + +static const RegisterAccessInfo mchp_pfsoc_l2cc_regs_info[] = { + { + .name = "CONFIG", + .addr = A_L2_CONFIG, + .reset = L2_CONFIG_RESET, + .ro = UINT64_MAX, + }, { + .name = "WAY_ENABLE", + .addr = A_L2_WAY_ENABLE, + .rsvd = ~R_L2_WAY_ENABLE_VALUE_MASK, + .pre_write = mchp_pfsoc_l2cc_way_enable_pre_write, + }, + WAY_MASK_REGISTER(DMA), + WAY_MASK_REGISTER(AXI4_PORT_0), + WAY_MASK_REGISTER(AXI4_PORT_1), + WAY_MASK_REGISTER(AXI4_PORT_2), + WAY_MASK_REGISTER(AXI4_PORT_3), + WAY_MASK_REGISTER(HART0_DCACHE), + WAY_MASK_REGISTER(HART0_ICACHE), + WAY_MASK_REGISTER(HART1_DCACHE), + WAY_MASK_REGISTER(HART1_ICACHE), + WAY_MASK_REGISTER(HART2_DCACHE), + WAY_MASK_REGISTER(HART2_ICACHE), + WAY_MASK_REGISTER(HART3_DCACHE), + WAY_MASK_REGISTER(HART3_ICACHE), + WAY_MASK_REGISTER(HART4_DCACHE), + WAY_MASK_REGISTER(HART4_ICACHE), +}; + +static bool mchp_pfsoc_l2cc_register_implemented(hwaddr offset) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(mchp_pfsoc_l2cc_regs_info); i++) { + if (mchp_pfsoc_l2cc_regs_info[i].addr == offset) { + return true; + } + } + + return false; +} + +static uint64_t mchp_pfsoc_l2cc_read(void *opaque, hwaddr offset, + unsigned size) +{ + if (mchp_pfsoc_l2cc_register_implemented(offset)) { + return register_read_memory(opaque, offset, size); + } + + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %u, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + return 0; +} + +static void mchp_pfsoc_l2cc_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + if (mchp_pfsoc_l2cc_register_implemented(offset)) { + register_write_memory(opaque, offset, value, size); + return; + } + + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %u, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_l2cc_ops = { + .read = mchp_pfsoc_l2cc_read, + .write = mchp_pfsoc_l2cc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { .min_access_size = 1, .max_access_size = 8 }, + .impl = { .min_access_size = 1, .max_access_size = 8 }, +}; + +static void mchp_pfsoc_l2cc_reset(DeviceState *dev) +{ + MchpPfSoCL2ccState *s = MCHP_PFSOC_L2CC(dev); + size_t i; + + memset(s->regs, 0, sizeof(s->regs)); + for (i = 0; i < ARRAY_SIZE(mchp_pfsoc_l2cc_regs_info); i++) { + hwaddr addr = mchp_pfsoc_l2cc_regs_info[i].addr; + + register_reset(&s->regs_info[addr / sizeof(uint64_t)]); + } +} + +static void mchp_pfsoc_l2cc_init(Object *obj) +{ + MchpPfSoCL2ccState *s = MCHP_PFSOC_L2CC(obj); + RegisterInfoArray *reg_array; + + reg_array = register_init_block64( + DEVICE(obj), mchp_pfsoc_l2cc_regs_info, + ARRAY_SIZE(mchp_pfsoc_l2cc_regs_info), s->regs_info, s->regs, + &mchp_pfsoc_l2cc_ops, false, MCHP_PFSOC_L2CC_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), ®_array->mem); +} + +static void mchp_pfsoc_l2cc_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, mchp_pfsoc_l2cc_reset); +} + +static const TypeInfo mchp_pfsoc_l2cc_info = { + .name = TYPE_MCHP_PFSOC_L2CC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCL2ccState), + .instance_init = mchp_pfsoc_l2cc_init, + .class_init = mchp_pfsoc_l2cc_class_init, +}; + +static void mchp_pfsoc_l2cc_register_types(void) +{ + type_register_static(&mchp_pfsoc_l2cc_info); +} + +type_init(mchp_pfsoc_l2cc_register_types) diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 1543ee6653..772a2d87b3 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -203,6 +203,9 @@ config MCHP_PFSOC_DMC config MCHP_PFSOC_IOSCB bool +config MCHP_PFSOC_L2CC + bool + config MCHP_PFSOC_SYSREG bool diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 23265f6035..5f45861d8a 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -30,6 +30,7 @@ system_ss.add(when: 'CONFIG_VIRT_CTRL', if_true: files('virt_ctrl.c')) # RISC-V devices system_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: files('mchp_pfsoc_dmc.c')) system_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: files('mchp_pfsoc_ioscb.c')) +system_ss.add(when: 'CONFIG_MCHP_PFSOC_L2CC', if_true: files('mchp_pfsoc_l2cc.c')) system_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true: files('mchp_pfsoc_sysreg.c')) system_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c')) system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c')) -- 2.34.1