diff options
author | Richard Henderson | 2022-06-30 18:34:12 +0200 |
---|---|---|
committer | Richard Henderson | 2022-06-30 18:34:12 +0200 |
commit | d495e432c04a6394126c35cf96517749708b410f (patch) | |
tree | 847312bcb99b4f486ed20bae9dfd4aaf76bef4fc /hw/misc/aspeed_peci.c | |
parent | Merge tag 'trivial-branch-for-7.1-pull-request' of https://gitlab.com/laurent... (diff) | |
parent | hw/misc/aspeed: Add PECI controller (diff) | |
download | qemu-d495e432c04a6394126c35cf96517749708b410f.tar.gz qemu-d495e432c04a6394126c35cf96517749708b410f.tar.xz qemu-d495e432c04a6394126c35cf96517749708b410f.zip |
Merge tag 'pull-aspeed-20220630' of https://github.com/legoater/qemu into staging
aspeed queue:
* m25p80 improvements (Iris)
* Code cleanup in preparation of multi SoC machine (Peter)
* New MAX31785 model (Mahesh)
* New Qualcomm machines (Jae and Graeme)
* Core I2C slave mode (Klaus)
* Aspeed I2C slave mode for old and new register interface (Peter and Klaus)
* New Aspeed PECI model (Peter)
* Various small fixes
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmK9UfQACgkQUaNDx8/7
# 7KFYWhAAtlx3aaEacrn/ONNHjk6G9Fxku56gAbaIiuiaIWNOj3/T2frPsnmbO8x8
# EKrgUYB8i8PFve/fJYA5vZUzIddPTaHkULZ12JQoGVg0L9hDBbizslN5lJWRXoSv
# 9r3DF9nahzLKRNvzoBfuKjHDQ2cwHoFgYmKmlYpDcgfmBcl16uzZy8jvxg/Tghur
# umH4IJMjeDNz/kLfINoO/m+kuFPVXmbTJNwl8uK5MUVDTgVSqharywWlUizugBVH
# StLE+GmBPylTuYXyiOzLTkoGJeeHp3sQ1DmyI4DD83odjnfxa0BGMGDVhD35exXi
# 9tLY9FgQ4smATuyN0UGAKZTBmzpI+ov0HMzvH4lUMR8i8daBuEet3RVr/DqkOP4h
# LEVTRWTaTJip24ohgw4K/b86pI9nTJWVPGV56eZGYmnqufnvf/upNU65/nCsF/xD
# i1TdS+zJWxhjgGEepg9cTmxxUlA4jVNNbl6dvAgS5Jr6Igrd1BlCSXjmyhO3NRPZ
# bgOuvCb3RyxAY4+/9wphx2/t5X2VIU6R8EAjnh+7nIgBhOQU5SZ6uefFVYZq8xx+
# IYEDHj3saiRa4FHmyOgeRxRaQj/Vvs83PPti2rPmJuieqiClJmbE+XfTIamoxVIv
# 5USlKmMRRVI69MjsjwFi/gOaV/N1EUgcFoYbnvwZ+Md3fg5+70M=
# =oUKu
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 30 Jun 2022 01:04:12 PM +0530
# gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1
* tag 'pull-aspeed-20220630' of https://github.com/legoater/qemu: (27 commits)
hw/misc/aspeed: Add PECI controller
hw/i2c/aspeed: Add new-registers DMA slave mode RX support
hw/i2c/aspeed: add slave device in old register mode
hw/i2c: add asynchronous send
hw/i2c: support multiple masters
hw/i2c/aspeed: Fix MASTER_EN missing error message
hw/i2c/aspeed: Fix DMA len write-enable bit handling
hw/i2c/aspeed: Fix R_I2CD_FUN_CTRL reference
hw/arm/aspeed: firework: add I2C MUXes for VR channels
hw/arm/aspeed: firework: Add Thermal Diodes
hw/arm/aspeed: Add MAX31785 Fan controllers
hw/sensor: add Maxim MAX31785 device
hw/i2c: pmbus: Page #255 is valid page for read requests.
hw/arm/aspeed: add Qualcomm Firework BMC machine
hw/arm/aspeed: add support for the Qualcomm DC-SCM v1 board
aspeed: Remove use of qemu_get_cpu
aspeed: Map unimplemented devices in SoC memory
aspeed: Remove usage of sysbus_mmio_map
aspeed: Add memory property to Aspeed SoC
aspeed: Set CPU memory property explicitly
...
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw/misc/aspeed_peci.c')
-rw-r--r-- | hw/misc/aspeed_peci.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/hw/misc/aspeed_peci.c b/hw/misc/aspeed_peci.c new file mode 100644 index 0000000000..93cc672e96 --- /dev/null +++ b/hw/misc/aspeed_peci.c @@ -0,0 +1,152 @@ +/* + * 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" +#include "hw/registerfields.h" +#include "trace.h" + +#define ASPEED_PECI_CC_RSP_SUCCESS (0x40U) + +/* Command Register */ +REG32(PECI_CMD, 0x08) + FIELD(PECI_CMD, FIRE, 0, 1) + +/* Interrupt Control Register */ +REG32(PECI_INT_CTRL, 0x18) + +/* Interrupt Status Register */ +REG32(PECI_INT_STS, 0x1C) + FIELD(PECI_INT_STS, CMD_DONE, 0, 1) + +/* Rx/Tx Data Buffer Registers */ +REG32(PECI_WR_DATA0, 0x20) +REG32(PECI_RD_DATA0, 0x30) + +static void aspeed_peci_raise_interrupt(AspeedPECIState *s, uint32_t status) +{ + trace_aspeed_peci_raise_interrupt(s->regs[R_PECI_INT_CTRL], status); + + s->regs[R_PECI_INT_STS] = s->regs[R_PECI_INT_CTRL] & status; + if (!s->regs[R_PECI_INT_STS]) { + return; + } + qemu_irq_raise(s->irq); +} + +static uint64_t aspeed_peci_read(void *opaque, hwaddr offset, unsigned size) +{ + AspeedPECIState *s = ASPEED_PECI(opaque); + uint64_t data; + + if (offset >= ASPEED_PECI_NR_REGS << 2) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + return 0; + } + data = s->regs[offset >> 2]; + + trace_aspeed_peci_read(offset, data); + return data; +} + +static void aspeed_peci_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedPECIState *s = ASPEED_PECI(opaque); + + trace_aspeed_peci_write(offset, data); + + if (offset >= ASPEED_PECI_NR_REGS << 2) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + return; + } + + switch (offset) { + case A_PECI_INT_STS: + s->regs[R_PECI_INT_STS] &= ~data; + if (!s->regs[R_PECI_INT_STS]) { + qemu_irq_lower(s->irq); + } + break; + case A_PECI_CMD: + /* + * Only the FIRE bit is writable. Once the command is complete, it + * should be cleared. Since we complete the command immediately, the + * value is not stored in the register array. + */ + if (!FIELD_EX32(data, PECI_CMD, FIRE)) { + break; + } + if (s->regs[R_PECI_INT_STS]) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Interrupt status must be " + "cleared before firing another command: 0x%08x\n", + __func__, s->regs[R_PECI_INT_STS]); + break; + } + s->regs[R_PECI_RD_DATA0] = ASPEED_PECI_CC_RSP_SUCCESS; + s->regs[R_PECI_WR_DATA0] = ASPEED_PECI_CC_RSP_SUCCESS; + aspeed_peci_raise_interrupt(s, + FIELD_DP32(0, PECI_INT_STS, CMD_DONE, 1)); + break; + default: + s->regs[offset / sizeof(s->regs[0])] = data; + 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_types[] = { + { + .name = TYPE_ASPEED_PECI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedPECIState), + .class_init = aspeed_peci_class_init, + .abstract = false, + }, +}; + +DEFINE_TYPES(aspeed_peci_types); |