xref: /qemu/hw/fsi/lbus.c (revision ca782334cb821a84d701133a6421516d264cf0d3)
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"
12*ca782334SNinad Palsule #include "qemu/log.h"
1399f0c046SNinad Palsule #include "trace.h"
1499f0c046SNinad Palsule 
15*ca782334SNinad Palsule #define TO_REG(offset) ((offset) >> 2)
16*ca782334SNinad 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 
38*ca782334SNinad Palsule static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size)
39*ca782334SNinad Palsule {
40*ca782334SNinad Palsule     FSIScratchPad *s = SCRATCHPAD(opaque);
41*ca782334SNinad Palsule     int reg = TO_REG(addr);
42*ca782334SNinad Palsule 
43*ca782334SNinad Palsule     trace_fsi_scratchpad_read(addr, size);
44*ca782334SNinad Palsule 
45*ca782334SNinad Palsule     if (reg >= FSI_SCRATCHPAD_NR_REGS) {
46*ca782334SNinad Palsule         qemu_log_mask(LOG_GUEST_ERROR,
47*ca782334SNinad Palsule                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
48*ca782334SNinad Palsule                       __func__, addr);
49*ca782334SNinad Palsule         return 0;
50*ca782334SNinad Palsule     }
51*ca782334SNinad Palsule 
52*ca782334SNinad Palsule     return s->regs[reg];
53*ca782334SNinad Palsule }
54*ca782334SNinad Palsule 
55*ca782334SNinad Palsule static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
56*ca782334SNinad Palsule                                  unsigned size)
57*ca782334SNinad Palsule {
58*ca782334SNinad Palsule     FSIScratchPad *s = SCRATCHPAD(opaque);
59*ca782334SNinad Palsule 
60*ca782334SNinad Palsule     trace_fsi_scratchpad_write(addr, size, data);
61*ca782334SNinad Palsule     int reg = TO_REG(addr);
62*ca782334SNinad Palsule 
63*ca782334SNinad Palsule     if (reg >= FSI_SCRATCHPAD_NR_REGS) {
64*ca782334SNinad Palsule         qemu_log_mask(LOG_GUEST_ERROR,
65*ca782334SNinad Palsule                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
66*ca782334SNinad Palsule                       __func__, addr);
67*ca782334SNinad Palsule         return;
68*ca782334SNinad Palsule     }
69*ca782334SNinad Palsule 
70*ca782334SNinad Palsule     s->regs[reg] = data;
71*ca782334SNinad Palsule }
72*ca782334SNinad Palsule 
73*ca782334SNinad Palsule static const struct MemoryRegionOps scratchpad_ops = {
74*ca782334SNinad Palsule     .read = fsi_scratchpad_read,
75*ca782334SNinad Palsule     .write = fsi_scratchpad_write,
76*ca782334SNinad Palsule     .endianness = DEVICE_BIG_ENDIAN,
77*ca782334SNinad Palsule };
78*ca782334SNinad Palsule 
79*ca782334SNinad Palsule static void fsi_scratchpad_realize(DeviceState *dev, Error **errp)
80*ca782334SNinad Palsule {
81*ca782334SNinad Palsule     FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
82*ca782334SNinad Palsule 
83*ca782334SNinad Palsule     memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops,
84*ca782334SNinad Palsule                           ldev, TYPE_FSI_SCRATCHPAD, 0x400);
85*ca782334SNinad Palsule }
86*ca782334SNinad Palsule 
87*ca782334SNinad Palsule static void fsi_scratchpad_reset(DeviceState *dev)
88*ca782334SNinad Palsule {
89*ca782334SNinad Palsule     FSIScratchPad *s = SCRATCHPAD(dev);
90*ca782334SNinad Palsule 
91*ca782334SNinad Palsule     memset(s->regs, 0, sizeof(s->regs));
92*ca782334SNinad Palsule }
93*ca782334SNinad Palsule 
94*ca782334SNinad Palsule static void fsi_scratchpad_class_init(ObjectClass *klass, void *data)
95*ca782334SNinad Palsule {
96*ca782334SNinad Palsule     DeviceClass *dc = DEVICE_CLASS(klass);
97*ca782334SNinad Palsule 
98*ca782334SNinad Palsule     dc->bus_type = TYPE_FSI_LBUS;
99*ca782334SNinad Palsule     dc->realize = fsi_scratchpad_realize;
100*ca782334SNinad Palsule     dc->reset = fsi_scratchpad_reset;
101*ca782334SNinad Palsule }
102*ca782334SNinad Palsule 
103*ca782334SNinad Palsule static const TypeInfo fsi_scratchpad_info = {
104*ca782334SNinad Palsule     .name = TYPE_FSI_SCRATCHPAD,
105*ca782334SNinad Palsule     .parent = TYPE_FSI_LBUS_DEVICE,
106*ca782334SNinad Palsule     .instance_size = sizeof(FSIScratchPad),
107*ca782334SNinad Palsule     .class_init = fsi_scratchpad_class_init,
108*ca782334SNinad Palsule };
109*ca782334SNinad 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);
114*ca782334SNinad Palsule     type_register_static(&fsi_scratchpad_info);
11599f0c046SNinad Palsule }
11699f0c046SNinad Palsule 
11799f0c046SNinad Palsule type_init(fsi_lbus_register_types);
118