xref: /openbmc/qemu/hw/fsi/fsi.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1f4de3ca1SNinad Palsule /*
2f4de3ca1SNinad Palsule  * SPDX-License-Identifier: GPL-2.0-or-later
3f4de3ca1SNinad Palsule  * Copyright (C) 2024 IBM Corp.
4f4de3ca1SNinad Palsule  *
5f4de3ca1SNinad Palsule  * IBM Flexible Service Interface
6f4de3ca1SNinad Palsule  */
7f4de3ca1SNinad Palsule #include "qemu/osdep.h"
86a2897bbSNinad Palsule #include "qapi/error.h"
96a2897bbSNinad Palsule #include "qemu/log.h"
106a2897bbSNinad Palsule #include "trace.h"
11f4de3ca1SNinad Palsule 
12f4de3ca1SNinad Palsule #include "hw/fsi/fsi.h"
13f4de3ca1SNinad Palsule 
146a2897bbSNinad Palsule #define TO_REG(x)                               ((x) >> 2)
156a2897bbSNinad Palsule 
16f4de3ca1SNinad Palsule static const TypeInfo fsi_bus_info = {
17f4de3ca1SNinad Palsule     .name = TYPE_FSI_BUS,
18f4de3ca1SNinad Palsule     .parent = TYPE_BUS,
19f4de3ca1SNinad Palsule     .instance_size = sizeof(FSIBus),
20f4de3ca1SNinad Palsule };
21f4de3ca1SNinad Palsule 
fsi_slave_read(void * opaque,hwaddr addr,unsigned size)226a2897bbSNinad Palsule static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
23f4de3ca1SNinad Palsule {
246a2897bbSNinad Palsule     FSISlaveState *s = FSI_SLAVE(opaque);
256a2897bbSNinad Palsule     int reg = TO_REG(addr);
266a2897bbSNinad Palsule 
276a2897bbSNinad Palsule     trace_fsi_slave_read(addr, size);
286a2897bbSNinad Palsule 
296a2897bbSNinad Palsule     if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
306a2897bbSNinad Palsule         qemu_log_mask(LOG_GUEST_ERROR,
316a2897bbSNinad Palsule                       "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
326a2897bbSNinad Palsule                       __func__, addr, size);
336a2897bbSNinad Palsule         return 0;
34f4de3ca1SNinad Palsule     }
35f4de3ca1SNinad Palsule 
366a2897bbSNinad Palsule     return s->regs[reg];
376a2897bbSNinad Palsule }
386a2897bbSNinad Palsule 
fsi_slave_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)396a2897bbSNinad Palsule static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
406a2897bbSNinad Palsule                                  unsigned size)
416a2897bbSNinad Palsule {
426a2897bbSNinad Palsule     FSISlaveState *s = FSI_SLAVE(opaque);
436a2897bbSNinad Palsule     int reg = TO_REG(addr);
446a2897bbSNinad Palsule 
456a2897bbSNinad Palsule     trace_fsi_slave_write(addr, size, data);
466a2897bbSNinad Palsule 
476a2897bbSNinad Palsule     if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
486a2897bbSNinad Palsule         qemu_log_mask(LOG_GUEST_ERROR,
496a2897bbSNinad Palsule                       "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
506a2897bbSNinad Palsule                       __func__, addr, size);
516a2897bbSNinad Palsule         return;
526a2897bbSNinad Palsule     }
536a2897bbSNinad Palsule 
546a2897bbSNinad Palsule     s->regs[reg] = data;
556a2897bbSNinad Palsule }
566a2897bbSNinad Palsule 
576a2897bbSNinad Palsule static const struct MemoryRegionOps fsi_slave_ops = {
586a2897bbSNinad Palsule     .read = fsi_slave_read,
596a2897bbSNinad Palsule     .write = fsi_slave_write,
606a2897bbSNinad Palsule     .endianness = DEVICE_BIG_ENDIAN,
616a2897bbSNinad Palsule };
626a2897bbSNinad Palsule 
fsi_slave_reset(DeviceState * dev)636a2897bbSNinad Palsule static void fsi_slave_reset(DeviceState *dev)
646a2897bbSNinad Palsule {
656a2897bbSNinad Palsule     FSISlaveState *s = FSI_SLAVE(dev);
666a2897bbSNinad Palsule 
676a2897bbSNinad Palsule     /* Initialize registers */
686a2897bbSNinad Palsule     memset(s->regs, 0, sizeof(s->regs));
696a2897bbSNinad Palsule }
706a2897bbSNinad Palsule 
fsi_slave_init(Object * o)716a2897bbSNinad Palsule static void fsi_slave_init(Object *o)
726a2897bbSNinad Palsule {
736a2897bbSNinad Palsule     FSISlaveState *s = FSI_SLAVE(o);
746a2897bbSNinad Palsule 
756a2897bbSNinad Palsule     memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
766a2897bbSNinad Palsule                           s, TYPE_FSI_SLAVE, 0x400);
776a2897bbSNinad Palsule }
786a2897bbSNinad Palsule 
fsi_slave_class_init(ObjectClass * klass,void * data)796a2897bbSNinad Palsule static void fsi_slave_class_init(ObjectClass *klass, void *data)
806a2897bbSNinad Palsule {
816a2897bbSNinad Palsule     DeviceClass *dc = DEVICE_CLASS(klass);
826a2897bbSNinad Palsule 
836a2897bbSNinad Palsule     dc->bus_type = TYPE_FSI_BUS;
846a2897bbSNinad Palsule     dc->desc = "FSI Slave";
85*e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, fsi_slave_reset);
866a2897bbSNinad Palsule }
876a2897bbSNinad Palsule 
886a2897bbSNinad Palsule static const TypeInfo fsi_slave_info = {
896a2897bbSNinad Palsule     .name = TYPE_FSI_SLAVE,
906a2897bbSNinad Palsule     .parent = TYPE_DEVICE,
916a2897bbSNinad Palsule     .instance_init = fsi_slave_init,
926a2897bbSNinad Palsule     .instance_size = sizeof(FSISlaveState),
936a2897bbSNinad Palsule     .class_init = fsi_slave_class_init,
946a2897bbSNinad Palsule };
956a2897bbSNinad Palsule 
fsi_register_types(void)966a2897bbSNinad Palsule static void fsi_register_types(void)
976a2897bbSNinad Palsule {
986a2897bbSNinad Palsule     type_register_static(&fsi_bus_info);
996a2897bbSNinad Palsule     type_register_static(&fsi_slave_info);
1006a2897bbSNinad Palsule }
1016a2897bbSNinad Palsule 
1026a2897bbSNinad Palsule type_init(fsi_register_types);
103