Re: [PATCH v2 1/8] fsi/cfam: Add common CFAM base class
Miles Glenn <[email protected]> Fri, 31 Jul 2026 14:38:22 -0500
| Newsgroups | org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Organization | IBM |
| Message-ID | <[email protected]> |
On Thu, 2026-07-30 at 15:09 -0500, Mikail Sadic wrote: > Prepare a common CFAM parent class for CFAM-S implementation. > > Add an abstract TYPE_FSI_CFAM_COMMON with an FSICFAMCommonClass holding > what varies between types: the config table, the offsets of the FSI > responder and the local bus within the register slot, and a > realize_engines() hook for the engines on the local bus. Its realize is > driven by those fields, so one realize serves every type. TYPE_FSI_CFAM > keeps its name and becomes the first derived type, supplying the P9 > config table, its slot offsets and the scratchpad engine. The config > table becomes data, still written with the same CFAM_CONFIG_REG() > expressions, which move to the header so a derived type can describe its > own table the same way. > > No functional change: same memory map, same config words, same type and > child names. aspeed_fsi-test verified. > > Signed-off-by: Mikail Sadic <[email protected]> > --- > include/hw/fsi/cfam.h | 58 ++++++++++++++++++-- > hw/fsi/cfam.c | 123 ++++++++++++++++++++++++------------------ > hw/fsi/fsi-master.c | 2 +- > 3 files changed, 127 insertions(+), 56 deletions(-) > > diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h > index cceb4bd6f1..0f5464b4a0 100644 > --- a/include/hw/fsi/cfam.h > +++ b/include/hw/fsi/cfam.h > @@ -7,18 +7,44 @@ > #ifndef FSI_CFAM_H > #define FSI_CFAM_H > > +#include "qemu/units.h" > #include "system/memory.h" > > #include "hw/fsi/fsi.h" > #include "hw/fsi/lbus.h" > > +/* > + * All CFAM flavors present a register slot holding a config table, an FSI > + * responder and a local bus carrying the engines the config table describes. > + * That is the common model; each flavor supplies its own table, slot layout > + * and engines. > + */ > +#define TYPE_FSI_CFAM_COMMON "cfam-common" > +OBJECT_DECLARE_TYPE(FSICFAMCommonState, FSICFAMCommonClass, FSI_CFAM_COMMON) I would prefer it if you could drop the `State` suffix from the name. We probably don't need the `FSI` prefix either since I believe there are only FSI-based CFAMs, but it's already there from before so it's fine for now. > + > #define TYPE_FSI_CFAM "cfam" > -#define FSI_CFAM(obj) OBJECT_CHECK(FSICFAMState, (obj), TYPE_FSI_CFAM) > +OBJECT_DECLARE_SIMPLE_TYPE(FSICFAMState, FSI_CFAM) > > /* P9-ism */ > #define CFAM_CONFIG_NR_REGS 0x28 > > -typedef struct FSICFAMState { > +#define FSI_CFAM_SLOT_SIZE (2 * MiB) > +#define FSI_CFAM_CONFIG_SIZE 0x400 > + > +#define ENGINE_CONFIG_NEXT BIT(31) > +#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4) > +#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4) > +#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4) > + > +/* Valid, slots, version, type, crc */ > +#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC) \ > + (ENGINE_CONFIG_NEXT | \ > + 0x00010000 | \ > + (__VER) | \ > + (__TYPE) | \ > + (__CRC)) > + > +struct FSICFAMCommonState { > /* < private > */ > FSISlaveState parent; > > @@ -28,7 +54,33 @@ typedef struct FSICFAMState { > MemoryRegion mr; > > FSILBus lbus; > +}; > + > +struct FSICFAMCommonClass { > + /* < private > */ > + DeviceClass parent_class; > + > + /* < public > */ > + /* Config table served by the common ops, one word per 4-byte offset */ > + const uint32_t *config; > + unsigned config_nr; > + > + /* Layout of the register slot */ > + hwaddr responder_offset; > + hwaddr lbus_offset; > + > + /* Realize and map this flavor's local bus engines */ > + bool (*realize_engines)(FSICFAMCommonState *cfam, Error **errp); > +}; > + > +struct FSICFAMState { > + /* < private > */ > + FSICFAMCommonState parent; > + > FSIScratchPad scratchpad; > -} FSICFAMState; > +}; > + > +bool fsi_cfam_add_engine(FSICFAMCommonState *cfam, DeviceState *engine, > + hwaddr offset, Error **errp); > > #endif /* FSI_CFAM_H */ > diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c > index 54c0b05769..361cb34808 100644 > --- a/hw/fsi/cfam.c > +++ b/hw/fsi/cfam.c > @@ -16,19 +16,6 @@ > > #include "hw/core/qdev-properties.h" > > -#define ENGINE_CONFIG_NEXT BIT(31) > -#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4) > -#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4) > -#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4) > - > -/* Valid, slots, version, type, crc */ > -#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC) \ > - (ENGINE_CONFIG_NEXT | \ > - 0x00010000 | \ > - (__VER) | \ > - (__TYPE) | \ > - (__CRC)) > - > #define TO_REG(x) ((x) >> 2) > > #define CFAM_CONFIG_CHIP_ID TO_REG(0x00) > @@ -36,34 +23,33 @@ > #define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 > #define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000 > > +/* > + * Config table of the P9 CFAM: the chip ID followed by one entry per engine, > + * entry n describing the engine at address n * 4. We need to add future > + * engines from address 0x10 onwards. > + */ > +static const uint32_t cfam_p9_config[] = { > + CFAM_CONFIG_CHIP_ID_P9, > + CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc), > + CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa), > + CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7), > +}; > + > static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size) > { > + FSICFAMCommonClass *cc = FSI_CFAM_COMMON_GET_CLASS(opaque); > + unsigned int reg = TO_REG(addr); > + > trace_fsi_cfam_config_read(addr, size); > > - switch (addr) { > - case 0x00: > - return CFAM_CONFIG_CHIP_ID_P9; > - case 0x04: > - return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc); > - case 0x08: > - return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa); > - case 0xc: > - return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7); > - default: > - /* > - * The config table contains different engines from 0xc onwards. > - * The scratch pad is already added at address 0xc. We need to add > - * future engines from address 0x10 onwards. Returning 0 as engine > - * is not implemented. > - */ > - return 0; > - } > + /* Engines past the end of the table are not implemented */ > + return reg < cc->config_nr ? cc->config[reg] : 0; > } > > static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data, > unsigned size) > { > - FSICFAMState *cfam = FSI_CFAM(opaque); > + FSICFAMCommonState *cfam = FSI_CFAM_COMMON(opaque); > > trace_fsi_cfam_config_write(addr, size, data); > > @@ -109,59 +95,92 @@ static const struct MemoryRegionOps fsi_cfam_unimplemented_ops = { > .endianness = DEVICE_BIG_ENDIAN, > }; > > -static void fsi_cfam_instance_init(Object *obj) > +bool fsi_cfam_add_engine(FSICFAMCommonState *cfam, DeviceState *engine, > + hwaddr offset, Error **errp) > { > - FSICFAMState *s = FSI_CFAM(obj); > + if (!qdev_realize(engine, BUS(&cfam->lbus), errp)) { > + return false; > + } > > - object_initialize_child(obj, "scratchpad", &s->scratchpad, > - TYPE_FSI_SCRATCHPAD); > + memory_region_add_subregion(&cfam->lbus.mr, offset, > + &FSI_LBUS_DEVICE(engine)->iomem); > + return true; > } > > -static void fsi_cfam_realize(DeviceState *dev, Error **errp) > +static void fsi_cfam_common_realize(DeviceState *dev, Error **errp) > { > - FSICFAMState *cfam = FSI_CFAM(dev); > + FSICFAMCommonState *cfam = FSI_CFAM_COMMON(dev); > + FSICFAMCommonClass *cc = FSI_CFAM_COMMON_GET_CLASS(dev); > FSISlaveState *slave = FSI_SLAVE(dev); > + const char *type = object_get_typename(OBJECT(dev)); > + g_autofree char *config_name = g_strdup_printf("%s.config", type); > > /* Each slave has a 2MiB address space */ > memory_region_init_io(&cfam->mr, OBJECT(cfam), &fsi_cfam_unimplemented_ops, > - cfam, TYPE_FSI_CFAM, 2 * MiB); > + cfam, type, FSI_CFAM_SLOT_SIZE); There is now an extended addressing mode that allows a single CFAM to have 8MB instead of having 4 cascaded CFAM's sharing the 8MB space, but I understand if you don't want to implement this now. > > qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS, DEVICE(cfam), > NULL); > > memory_region_init_io(&cfam->config_iomem, OBJECT(cfam), &cfam_config_ops, > - cfam, TYPE_FSI_CFAM ".config", 0x400); > + cfam, config_name, FSI_CFAM_CONFIG_SIZE); > > memory_region_add_subregion(&cfam->mr, 0, &cfam->config_iomem); > - memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem); > - memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr); > + memory_region_add_subregion(&cfam->mr, cc->responder_offset, &slave->iomem); > + memory_region_add_subregion(&cfam->mr, cc->lbus_offset, &cfam->lbus.mr); > + > + cc->realize_engines(cfam, errp); > +} > + > +static void fsi_cfam_common_class_init(ObjectClass *klass, const void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->bus_type = TYPE_FSI_BUS; > + dc->realize = fsi_cfam_common_realize; > +} > + > +static bool fsi_cfam_realize_engines(FSICFAMCommonState *cfam, Error **errp) > +{ > + FSICFAMState *s = FSI_CFAM(cfam); > > /* Add scratchpad engine */ > - if (!qdev_realize(DEVICE(&cfam->scratchpad), BUS(&cfam->lbus), errp)) { > - return; > - } > + object_initialize_child(OBJECT(s), "scratchpad", &s->scratchpad, > + TYPE_FSI_SCRATCHPAD); > > - FSILBusDevice *fsi_dev = FSI_LBUS_DEVICE(&cfam->scratchpad); > - memory_region_add_subregion(&cfam->lbus.mr, 0, &fsi_dev->iomem); > + return fsi_cfam_add_engine(cfam, DEVICE(&s->scratchpad), 0, errp); > } > > static void fsi_cfam_class_init(ObjectClass *klass, const void *data) > { > - DeviceClass *dc = DEVICE_CLASS(klass); > - dc->bus_type = TYPE_FSI_BUS; > - dc->realize = fsi_cfam_realize; > + FSICFAMCommonClass *cc = FSI_CFAM_COMMON_CLASS(klass); > + > + cc->config = cfam_p9_config; > + cc->config_nr = ARRAY_SIZE(cfam_p9_config); > + cc->responder_offset = 0x800; > + cc->lbus_offset = 0xc00; > + cc->realize_engines = fsi_cfam_realize_engines; > } > > +static const TypeInfo fsi_cfam_common_info = { > + .name = TYPE_FSI_CFAM_COMMON, > + .parent = TYPE_FSI_SLAVE, > + .instance_size = sizeof(FSICFAMCommonState), > + .class_size = sizeof(FSICFAMCommonClass), > + .class_init = fsi_cfam_common_class_init, > + .abstract = true, > +}; > + > static const TypeInfo fsi_cfam_info = { > .name = TYPE_FSI_CFAM, > - .parent = TYPE_FSI_SLAVE, > - .instance_init = fsi_cfam_instance_init, > + .parent = TYPE_FSI_CFAM_COMMON, > .instance_size = sizeof(FSICFAMState), > .class_init = fsi_cfam_class_init, > }; > > static void fsi_cfam_register_types(void) > { > + type_register_static(&fsi_cfam_common_info); > type_register_static(&fsi_cfam_info); > } > > diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c > index 083a5507ab..d82df1c094 100644 > --- a/hw/fsi/fsi-master.c > +++ b/hw/fsi/fsi-master.c > @@ -130,7 +130,7 @@ static void fsi_master_realize(DeviceState *dev, Error **errp) > } > > /* address ? */ > - memory_region_add_subregion(&s->opb2fsi, 0, &s->cfam.mr); > + memory_region_add_subregion(&s->opb2fsi, 0, &s->cfam.parent.mr); > } > > static void fsi_master_reset(DeviceState *dev)