199f0c046SNinad Palsule /* 299f0c046SNinad Palsule * SPDX-License-Identifier: GPL-2.0-or-later 399f0c046SNinad Palsule * Copyright (C) 2024 IBM Corp. 499f0c046SNinad Palsule * 599f0c046SNinad Palsule * IBM Local bus where FSI slaves are connected 699f0c046SNinad Palsule */ 799f0c046SNinad Palsule 899f0c046SNinad Palsule #include "qemu/osdep.h" 999f0c046SNinad Palsule #include "qapi/error.h" 1099f0c046SNinad Palsule #include "hw/fsi/lbus.h" 1199f0c046SNinad Palsule #include "hw/qdev-properties.h" 12ca782334SNinad Palsule #include "qemu/log.h" 1399f0c046SNinad Palsule #include "trace.h" 1499f0c046SNinad Palsule 15ca782334SNinad Palsule #define TO_REG(offset) ((offset) >> 2) 16ca782334SNinad Palsule 1799f0c046SNinad Palsule static void fsi_lbus_init(Object *o) 1899f0c046SNinad Palsule { 1999f0c046SNinad Palsule FSILBus *lbus = FSI_LBUS(o); 2099f0c046SNinad Palsule 2199f0c046SNinad Palsule memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS, 1 * MiB); 2299f0c046SNinad Palsule } 2399f0c046SNinad Palsule 2499f0c046SNinad Palsule static const TypeInfo fsi_lbus_info = { 2599f0c046SNinad Palsule .name = TYPE_FSI_LBUS, 2699f0c046SNinad Palsule .parent = TYPE_BUS, 2799f0c046SNinad Palsule .instance_init = fsi_lbus_init, 2899f0c046SNinad Palsule .instance_size = sizeof(FSILBus), 2999f0c046SNinad Palsule }; 3099f0c046SNinad Palsule 3199f0c046SNinad Palsule static const TypeInfo fsi_lbus_device_type_info = { 3299f0c046SNinad Palsule .name = TYPE_FSI_LBUS_DEVICE, 3399f0c046SNinad Palsule .parent = TYPE_DEVICE, 3499f0c046SNinad Palsule .instance_size = sizeof(FSILBusDevice), 3599f0c046SNinad Palsule .abstract = true, 3699f0c046SNinad Palsule }; 3799f0c046SNinad Palsule 38ca782334SNinad Palsule static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size) 39ca782334SNinad Palsule { 40ca782334SNinad Palsule FSIScratchPad *s = SCRATCHPAD(opaque); 41ca782334SNinad Palsule int reg = TO_REG(addr); 42ca782334SNinad Palsule 43ca782334SNinad Palsule trace_fsi_scratchpad_read(addr, size); 44ca782334SNinad Palsule 45ca782334SNinad Palsule if (reg >= FSI_SCRATCHPAD_NR_REGS) { 46ca782334SNinad Palsule qemu_log_mask(LOG_GUEST_ERROR, 47ca782334SNinad Palsule "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 48ca782334SNinad Palsule __func__, addr); 49ca782334SNinad Palsule return 0; 50ca782334SNinad Palsule } 51ca782334SNinad Palsule 52ca782334SNinad Palsule return s->regs[reg]; 53ca782334SNinad Palsule } 54ca782334SNinad Palsule 55ca782334SNinad Palsule static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data, 56ca782334SNinad Palsule unsigned size) 57ca782334SNinad Palsule { 58ca782334SNinad Palsule FSIScratchPad *s = SCRATCHPAD(opaque); 59ca782334SNinad Palsule 60ca782334SNinad Palsule trace_fsi_scratchpad_write(addr, size, data); 61ca782334SNinad Palsule int reg = TO_REG(addr); 62ca782334SNinad Palsule 63ca782334SNinad Palsule if (reg >= FSI_SCRATCHPAD_NR_REGS) { 64ca782334SNinad Palsule qemu_log_mask(LOG_GUEST_ERROR, 65ca782334SNinad Palsule "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 66ca782334SNinad Palsule __func__, addr); 67ca782334SNinad Palsule return; 68ca782334SNinad Palsule } 69ca782334SNinad Palsule 70ca782334SNinad Palsule s->regs[reg] = data; 71ca782334SNinad Palsule } 72ca782334SNinad Palsule 73ca782334SNinad Palsule static const struct MemoryRegionOps scratchpad_ops = { 74ca782334SNinad Palsule .read = fsi_scratchpad_read, 75ca782334SNinad Palsule .write = fsi_scratchpad_write, 76ca782334SNinad Palsule .endianness = DEVICE_BIG_ENDIAN, 77ca782334SNinad Palsule }; 78ca782334SNinad Palsule 79ca782334SNinad Palsule static void fsi_scratchpad_realize(DeviceState *dev, Error **errp) 80ca782334SNinad Palsule { 81ca782334SNinad Palsule FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev); 82ca782334SNinad Palsule 83ca782334SNinad Palsule memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops, 84ca782334SNinad Palsule ldev, TYPE_FSI_SCRATCHPAD, 0x400); 85ca782334SNinad Palsule } 86ca782334SNinad Palsule 87ca782334SNinad Palsule static void fsi_scratchpad_reset(DeviceState *dev) 88ca782334SNinad Palsule { 89ca782334SNinad Palsule FSIScratchPad *s = SCRATCHPAD(dev); 90ca782334SNinad Palsule 91ca782334SNinad Palsule memset(s->regs, 0, sizeof(s->regs)); 92ca782334SNinad Palsule } 93ca782334SNinad Palsule 94ca782334SNinad Palsule static void fsi_scratchpad_class_init(ObjectClass *klass, void *data) 95ca782334SNinad Palsule { 96ca782334SNinad Palsule DeviceClass *dc = DEVICE_CLASS(klass); 97ca782334SNinad Palsule 98ca782334SNinad Palsule dc->bus_type = TYPE_FSI_LBUS; 99ca782334SNinad Palsule dc->realize = fsi_scratchpad_realize; 100*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, fsi_scratchpad_reset); 101ca782334SNinad Palsule } 102ca782334SNinad Palsule 103ca782334SNinad Palsule static const TypeInfo fsi_scratchpad_info = { 104ca782334SNinad Palsule .name = TYPE_FSI_SCRATCHPAD, 105ca782334SNinad Palsule .parent = TYPE_FSI_LBUS_DEVICE, 106ca782334SNinad Palsule .instance_size = sizeof(FSIScratchPad), 107ca782334SNinad Palsule .class_init = fsi_scratchpad_class_init, 108ca782334SNinad Palsule }; 109ca782334SNinad Palsule 11099f0c046SNinad Palsule static void fsi_lbus_register_types(void) 11199f0c046SNinad Palsule { 11299f0c046SNinad Palsule type_register_static(&fsi_lbus_info); 11399f0c046SNinad Palsule type_register_static(&fsi_lbus_device_type_info); 114ca782334SNinad Palsule type_register_static(&fsi_scratchpad_info); 11599f0c046SNinad Palsule } 11699f0c046SNinad Palsule 11799f0c046SNinad Palsule type_init(fsi_lbus_register_types); 118