> On Jun 27, 2022, at 11:47 PM, Cédric Le Goater <c...@kaod.org> wrote: > > On 6/27/22 21:54, Peter Delevoryas wrote: > > Could we have some short intro ? :)
Yes, definitely, I’ll resubmit with some more details. > >> Signed-off-by: Peter Delevoryas <p...@fb.com> >> --- >> hw/arm/aspeed_ast10x0.c | 11 ++ >> hw/misc/aspeed_peci.c | 225 ++++++++++++++++++++++++++++++++++ >> hw/misc/meson.build | 3 +- >> include/hw/arm/aspeed_soc.h | 3 + >> include/hw/misc/aspeed_peci.h | 34 +++++ >> 5 files changed, 275 insertions(+), 1 deletion(-) >> create mode 100644 hw/misc/aspeed_peci.c >> create mode 100644 include/hw/misc/aspeed_peci.h >> diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c >> index 5df480a21f..780841ea84 100644 >> --- a/hw/arm/aspeed_ast10x0.c >> +++ b/hw/arm/aspeed_ast10x0.c >> @@ -47,6 +47,7 @@ static const hwaddr aspeed_soc_ast1030_memmap[] = { >> [ASPEED_DEV_UART13] = 0x7E790700, >> [ASPEED_DEV_WDT] = 0x7E785000, >> [ASPEED_DEV_LPC] = 0x7E789000, >> + [ASPEED_DEV_PECI] = 0x7E78B000, >> [ASPEED_DEV_I2C] = 0x7E7B0000, >> }; >> @@ -75,6 +76,7 @@ static const int aspeed_soc_ast1030_irqmap[] = { >> [ASPEED_DEV_TIMER8] = 23, >> [ASPEED_DEV_WDT] = 24, >> [ASPEED_DEV_LPC] = 35, >> + [ASPEED_DEV_PECI] = 38, >> [ASPEED_DEV_FMC] = 39, >> [ASPEED_DEV_PWM] = 44, >> [ASPEED_DEV_ADC] = 46, >> @@ -133,6 +135,8 @@ static void aspeed_soc_ast1030_init(Object *obj) >> object_initialize_child(obj, "lpc", &s->lpc, TYPE_ASPEED_LPC); >> + object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); >> + >> object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); >> for (i = 0; i < sc->wdts_num; i++) { >> @@ -238,6 +242,13 @@ static void aspeed_soc_ast1030_realize(DeviceState >> *dev_soc, Error **errp) >> /* UART */ >> aspeed_soc_uart_init(s); >> + /* PECI */ >> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) { >> + return; >> + } >> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->peci), 0, >> sc->memmap[ASPEED_DEV_PECI]); >> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, aspeed_soc_get_irq(s, >> ASPEED_DEV_PECI)); >> + >> /* Timer */ >> object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), >> &error_abort); >> diff --git a/hw/misc/aspeed_peci.c b/hw/misc/aspeed_peci.c >> new file mode 100644 >> index 0000000000..670e532fc0 >> --- /dev/null >> +++ b/hw/misc/aspeed_peci.c >> @@ -0,0 +1,225 @@ >> +/* >> + * Aspeed PECI Controller >> + * >> + * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com) >> + * >> + * This code is licensed under the GPL version 2 or later. See the COPYING >> + * file in the top-level directory. >> + */ >> + >> +#include "qemu/osdep.h" >> +#include "qemu/log.h" >> +#include "hw/irq.h" >> +#include "hw/misc/aspeed_peci.h" >> + >> +#define U(x) (x##U) >> +#define GENMASK(h, l) \ >> + (((~U(0)) - (U(1) << (l)) + 1) & \ >> + (~U(0) >> (32 - 1 - (h)))) > > I beleive QEMU has similar macros to generate masks. Ah yes good catch, I can probably fix that pretty easily. > > >> +/* ASPEED PECI Registers */ >> +/* Control Register */ >> +#define ASPEED_PECI_CTRL (0x00 / 4) >> +#define ASPEED_PECI_CTRL_SAMPLING_MASK GENMASK(19, 16) >> +#define ASPEED_PECI_CTRL_RD_MODE_MASK GENMASK(13, 12) >> +#define ASPEED_PECI_CTRL_RD_MODE_DBG BIT(13) >> +#define ASPEED_PECI_CTRL_RD_MODE_COUNT BIT(12) >> +#define ASPEED_PECI_CTRL_CLK_SRC_HCLK BIT(11) >> +#define ASPEED_PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8) >> +#define ASPEED_PECI_CTRL_INVERT_OUT BIT(7) >> +#define ASPEED_PECI_CTRL_INVERT_IN BIT(6) >> +#define ASPEED_PECI_CTRL_BUS_CONTENTION_EN BIT(5) >> +#define ASPEED_PECI_CTRL_PECI_EN BIT(4) >> +#define ASPEED_PECI_CTRL_PECI_CLK_EN BIT(0) >> + >> +/* Timing Negotiation Register */ >> +#define ASPEED_PECI_TIMING_NEGOTIATION (0x04 / 4) >> +#define ASPEED_PECI_T_NEGO_MSG_MASK GENMASK(15, 8) >> +#define ASPEED_PECI_T_NEGO_ADDR_MASK GENMASK(7, 0) >> + >> +/* Command Register */ >> +#define ASPEED_PECI_CMD (0x08 / 4) >> +#define ASPEED_PECI_CMD_PIN_MONITORING BIT(31) >> +#define ASPEED_PECI_CMD_STS_MASK GENMASK(27, 24) >> +#define ASPEED_PECI_CMD_STS_ADDR_T_NEGO 0x3 >> +#define ASPEED_PECI_CMD_IDLE_MASK \ >> + (ASPEED_PECI_CMD_STS_MASK | ASPEED_PECI_CMD_PIN_MONITORING) >> +#define ASPEED_PECI_CMD_FIRE BIT(0) >> + >> +/* Read/Write Length Register */ >> +#define ASPEED_PECI_RW_LENGTH (0x0c / 4) >> +#define ASPEED_PECI_AW_FCS_EN BIT(31) >> +#define ASPEED_PECI_RD_LEN_MASK GENMASK(23, 16) >> +#define ASPEED_PECI_WR_LEN_MASK GENMASK(15, 8) >> +#define ASPEED_PECI_TARGET_ADDR_MASK GENMASK(7, 0) >> + >> +/* Expected FCS Data Register */ >> +#define ASPEED_PECI_EXPECTED_FCS (0x10 / 4) >> +#define ASPEED_PECI_EXPECTED_RD_FCS_MASK GENMASK(23, 16) >> +#define ASPEED_PECI_EXPECTED_AW_FCS_AUTO_MASK GENMASK(15, 8) >> +#define ASPEED_PECI_EXPECTED_WR_FCS_MASK GENMASK(7, 0) >> + >> +/* Captured FCS Data Register */ >> +#define ASPEED_PECI_CAPTURED_FCS (0x14 / 4) >> +#define ASPEED_PECI_CAPTURED_RD_FCS_MASK GENMASK(23, 16) >> +#define ASPEED_PECI_CAPTURED_WR_FCS_MASK GENMASK(7, 0) >> + >> +/* Interrupt Register */ >> +#define ASPEED_PECI_INT_CTRL (0x18 / 4) >> +#define ASPEED_PECI_TIMING_NEGO_SEL_MASK GENMASK(31, 30) >> +#define ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO 0 >> +#define ASPEED_PECI_2ND_BIT_OF_ADDR_NEGO 1 >> +#define ASPEED_PECI_MESSAGE_NEGO 2 >> +#define ASPEED_PECI_INT_MASK GENMASK(4, 0) >> +#define ASPEED_PECI_INT_BUS_TIMEOUT BIT(4) >> +#define ASPEED_PECI_INT_BUS_CONTENTION BIT(3) >> +#define ASPEED_PECI_INT_WR_FCS_BAD BIT(2) >> +#define ASPEED_PECI_INT_WR_FCS_ABORT BIT(1) >> +#define ASPEED_PECI_INT_CMD_DONE BIT(0) >> + >> +/* Interrupt Status Register */ >> +#define ASPEED_PECI_INT_STS (0x1c / 4) >> +#define ASPEED_PECI_INT_TIMING_RESULT_MASK GENMASK(29, 16) >> + /* bits[4..0]: Same bit fields in the 'Interrupt Register' */ >> + >> +/* Rx/Tx Data Buffer Registers */ >> +#define ASPEED_PECI_WR_DATA0 (0x20 / 4) >> +#define ASPEED_PECI_WR_DATA1 (0x24 / 4) >> +#define ASPEED_PECI_WR_DATA2 (0x28 / 4) >> +#define ASPEED_PECI_WR_DATA3 (0x2c / 4) >> +#define ASPEED_PECI_RD_DATA0 (0x30 / 4) >> +#define ASPEED_PECI_RD_DATA1 (0x34 / 4) >> +#define ASPEED_PECI_RD_DATA2 (0x38 / 4) >> +#define ASPEED_PECI_RD_DATA3 (0x3c / 4) >> +#define ASPEED_PECI_WR_DATA4 (0x40 / 4) >> +#define ASPEED_PECI_WR_DATA5 (0x44 / 4) >> +#define ASPEED_PECI_WR_DATA6 (0x48 / 4) >> +#define ASPEED_PECI_WR_DATA7 (0x4c / 4) >> +#define ASPEED_PECI_RD_DATA4 (0x50 / 4) >> +#define ASPEED_PECI_RD_DATA5 (0x54 / 4) >> +#define ASPEED_PECI_RD_DATA6 (0x58 / 4) >> +#define ASPEED_PECI_RD_DATA7 (0x5c / 4) >> +#define ASPEED_PECI_DATA_BUF_SIZE_MAX 32 >> + >> +/** PECI read/write supported responses */ >> +#define PECI_CC_RSP_SUCCESS (0x40U) >> +#define PECI_CC_RSP_TIMEOUT (0x80U) >> +#define PECI_CC_OUT_OF_RESOURCES_TIMEOUT (0x81U) >> +#define PECI_CC_RESOURCES_LOWPWR_TIMEOUT (0x82U) >> +#define PECI_CC_ILLEGAL_REQUEST (0x90U) >> + >> +static void aspeed_peci_instance_init(Object *obj) >> +{ >> +} > > May be drop this routine if it is empty. Agreed, will do. > >> +static uint64_t aspeed_peci_read(void *opaque, hwaddr addr, unsigned size) >> +{ >> + AspeedPECIState *s = ASPEED_PECI(opaque); >> + >> + if (addr >= ASPEED_PECI_NR_REGS << 2) { >> + qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds read at offset >> 0x%" HWADDR_PRIx "\n", >> + __func__, addr); >> + return 0; >> + } >> + addr >>= 2; >> + >> + uint32_t reg = s->regs[addr]; >> + //printf("%s: 0x%08lx 0x%08x %u\n", __func__, addr << 2, reg, size); > > Convert to trace event ? or please remove. Arg yes, I’ll fix this. > >> + >> + return reg; >> +} >> + >> +static void aspeed_peci_write(void *opaque, hwaddr addr, uint64_t data, >> unsigned size) >> +{ >> + AspeedPECIState *s = ASPEED_PECI(opaque); >> + >> + //printf("%s: 0x%08lx 0x%08x %u\n", __func__, addr, reg, size); >> + >> + if (addr >= ASPEED_PECI_NR_REGS << 2) { >> + qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds write at offset >> 0x%" HWADDR_PRIx "\n", >> + __func__, addr); >> + return; >> + } >> + addr >>= 2; >> + >> + switch (addr) { >> + case ASPEED_PECI_INT_STS: >> + s->regs[addr] &= ~data; >> + break; >> + default: >> + s->regs[addr] = data; >> + break; >> + } >> + >> + switch (addr) { >> + case ASPEED_PECI_CMD: >> + if (!(s->regs[ASPEED_PECI_CMD] & ASPEED_PECI_CMD_FIRE)) { >> + break; >> + } >> + s->regs[ASPEED_PECI_RD_DATA0] = PECI_CC_RSP_SUCCESS; >> + s->regs[ASPEED_PECI_WR_DATA0] = PECI_CC_RSP_SUCCESS; >> + >> + s->regs[ASPEED_PECI_INT_STS] |= ASPEED_PECI_INT_CMD_DONE; >> + qemu_irq_raise(s->irq); >> + break; >> + case ASPEED_PECI_INT_STS: >> + if (s->regs[ASPEED_PECI_INT_STS]) { >> + break; >> + } >> + qemu_irq_lower(s->irq); >> + break; >> + default: >> + qemu_log_mask(LOG_UNIMP, "%s: register 0x%03" HWADDR_PRIx " writes >> unimplemented\n", >> + __func__, addr); >> + break; >> + } >> +} >> + >> +static const MemoryRegionOps aspeed_peci_ops = { >> + .read = aspeed_peci_read, >> + .write = aspeed_peci_write, >> + .endianness = DEVICE_LITTLE_ENDIAN, >> +}; >> + >> +static void aspeed_peci_realize(DeviceState *dev, Error **errp) >> +{ >> + AspeedPECIState *s = ASPEED_PECI(dev); >> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); >> + >> + memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_peci_ops, s, >> TYPE_ASPEED_PECI, 0x1000); >> + sysbus_init_mmio(sbd, &s->mmio); >> + sysbus_init_irq(sbd, &s->irq); >> +} >> + >> +static void aspeed_peci_reset(DeviceState *dev) >> +{ >> + AspeedPECIState *s = ASPEED_PECI(dev); >> + >> + memset(s->regs, 0, sizeof(s->regs)); >> +} >> + >> +static void aspeed_peci_class_init(ObjectClass *klass, void *data) >> +{ >> + DeviceClass *dc = DEVICE_CLASS(klass); >> + >> + dc->realize = aspeed_peci_realize; >> + dc->reset = aspeed_peci_reset; >> + dc->desc = "Aspeed PECI Controller"; >> +} >> + >> +static const TypeInfo aspeed_peci_info = { >> + .name = TYPE_ASPEED_PECI, >> + .parent = TYPE_SYS_BUS_DEVICE, >> + .instance_init = aspeed_peci_instance_init, >> + .instance_size = sizeof(AspeedPECIState), >> + .class_init = aspeed_peci_class_init, >> + .class_size = sizeof(AspeedPECIClass), >> + .abstract = false, >> +}; >> + >> +static void aspeed_peci_register_types(void) >> +{ >> + type_register_static(&aspeed_peci_info); >> +} >> + >> +type_init(aspeed_peci_register_types); >> diff --git a/hw/misc/meson.build b/hw/misc/meson.build >> index 132b7b7344..95268eddc0 100644 >> --- a/hw/misc/meson.build >> +++ b/hw/misc/meson.build >> @@ -116,7 +116,8 @@ softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( >> 'aspeed_scu.c', >> 'aspeed_sbc.c', >> 'aspeed_sdmc.c', >> - 'aspeed_xdma.c')) >> + 'aspeed_xdma.c', >> + 'aspeed_peci.c')) >> softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c')) >> softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) >> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h >> index 02a5a9ffcb..fd2aa1880a 100644 >> --- a/include/hw/arm/aspeed_soc.h >> +++ b/include/hw/arm/aspeed_soc.h >> @@ -34,6 +34,7 @@ >> #include "hw/usb/hcd-ehci.h" >> #include "qom/object.h" >> #include "hw/misc/aspeed_lpc.h" >> +#include "hw/misc/aspeed_peci.h" >> #define ASPEED_SPIS_NUM 2 >> #define ASPEED_EHCIS_NUM 2 >> @@ -73,6 +74,7 @@ struct AspeedSoCState { >> AspeedSDHCIState sdhci; >> AspeedSDHCIState emmc; >> AspeedLPCState lpc; >> + AspeedPECIState peci; >> uint32_t uart_default; >> Clock *sysclk; >> }; >> @@ -161,6 +163,7 @@ enum { >> ASPEED_DEV_DPMCU, >> ASPEED_DEV_DP, >> ASPEED_DEV_I3C, >> + ASPEED_DEV_PECI, >> }; >> qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); >> diff --git a/include/hw/misc/aspeed_peci.h b/include/hw/misc/aspeed_peci.h >> new file mode 100644 >> index 0000000000..81c7d31700 >> --- /dev/null >> +++ b/include/hw/misc/aspeed_peci.h >> @@ -0,0 +1,34 @@ >> +/* >> + * Aspeed PECI Controller >> + * >> + * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com) >> + * >> + * This code is licensed under the GPL version 2 or later. See the COPYING >> + * file in the top-level directory. >> + */ >> + >> +#ifndef ASPEED_PECI_H >> +#define ASPEED_PECI_H >> + >> +#include "hw/sysbus.h" >> + >> +#define TYPE_ASPEED_PECI "aspeed.peci" >> +OBJECT_DECLARE_TYPE(AspeedPECIState, AspeedPECIClass, ASPEED_PECI); >> + >> +#define ASPEED_PECI_NR_REGS ((0xFC + 4) >> 2) >> + >> +struct AspeedPECIState { >> + /* <private> */ >> + SysBusDevice parent; >> + >> + MemoryRegion mmio; >> + qemu_irq irq; >> + >> + uint32_t regs[ASPEED_PECI_NR_REGS]; >> +}; >> + >> +struct AspeedPECIClass { >> + SysBusDeviceClass parent_class; >> +}; >> + >> +#endif >