Re: [PATCH 04/26] hw/misc: pfsoc: Model L2 cache controller registers
Alistair <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 2026-07-23 at 23:18 +0800, Bin Meng wrote: > 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); Again, non-legacy reset would be best Otherwise: Acked-by: Alistair Francis <[email protected]> Alistair > +} > + > +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'))