1 /* 2 * ASPEED SLI Controller 3 * 4 * Copyright (C) 2024 ASPEED Technology Inc. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/log.h" 11 #include "qemu/error-report.h" 12 #include "hw/qdev-properties.h" 13 #include "hw/misc/aspeed_sli.h" 14 #include "qapi/error.h" 15 #include "migration/vmstate.h" 16 #include "trace.h" 17 18 #define SLI_REGION_SIZE 0x500 19 #define TO_REG(addr) ((addr) >> 2) 20 21 static uint64_t aspeed_sli_read(void *opaque, hwaddr addr, unsigned int size) 22 { 23 AspeedSLIState *s = ASPEED_SLI(opaque); 24 int reg = TO_REG(addr); 25 26 if (reg >= ARRAY_SIZE(s->regs)) { 27 qemu_log_mask(LOG_GUEST_ERROR, 28 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 29 __func__, addr); 30 return 0; 31 } 32 33 trace_aspeed_sli_read(addr, size, s->regs[reg]); 34 return s->regs[reg]; 35 } 36 37 static void aspeed_sli_write(void *opaque, hwaddr addr, uint64_t data, 38 unsigned int size) 39 { 40 AspeedSLIState *s = ASPEED_SLI(opaque); 41 int reg = TO_REG(addr); 42 43 if (reg >= ARRAY_SIZE(s->regs)) { 44 qemu_log_mask(LOG_GUEST_ERROR, 45 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 46 __func__, addr); 47 return; 48 } 49 50 trace_aspeed_sli_write(addr, size, data); 51 s->regs[reg] = data; 52 } 53 54 static uint64_t aspeed_sliio_read(void *opaque, hwaddr addr, unsigned int size) 55 { 56 AspeedSLIState *s = ASPEED_SLI(opaque); 57 int reg = TO_REG(addr); 58 59 if (reg >= ARRAY_SIZE(s->regs)) { 60 qemu_log_mask(LOG_GUEST_ERROR, 61 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 62 __func__, addr); 63 return 0; 64 } 65 66 trace_aspeed_sliio_read(addr, size, s->regs[reg]); 67 return s->regs[reg]; 68 } 69 70 static void aspeed_sliio_write(void *opaque, hwaddr addr, uint64_t data, 71 unsigned int size) 72 { 73 AspeedSLIState *s = ASPEED_SLI(opaque); 74 int reg = TO_REG(addr); 75 76 if (reg >= ARRAY_SIZE(s->regs)) { 77 qemu_log_mask(LOG_GUEST_ERROR, 78 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 79 __func__, addr); 80 return; 81 } 82 83 trace_aspeed_sliio_write(addr, size, data); 84 s->regs[reg] = data; 85 } 86 87 static const MemoryRegionOps aspeed_sli_ops = { 88 .read = aspeed_sli_read, 89 .write = aspeed_sli_write, 90 .endianness = DEVICE_LITTLE_ENDIAN, 91 .valid = { 92 .min_access_size = 1, 93 .max_access_size = 4, 94 }, 95 }; 96 97 static const MemoryRegionOps aspeed_sliio_ops = { 98 .read = aspeed_sliio_read, 99 .write = aspeed_sliio_write, 100 .endianness = DEVICE_LITTLE_ENDIAN, 101 .valid = { 102 .min_access_size = 1, 103 .max_access_size = 4, 104 }, 105 }; 106 107 static void aspeed_sli_realize(DeviceState *dev, Error **errp) 108 { 109 AspeedSLIState *s = ASPEED_SLI(dev); 110 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 111 112 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sli_ops, s, 113 TYPE_ASPEED_SLI, SLI_REGION_SIZE); 114 sysbus_init_mmio(sbd, &s->iomem); 115 } 116 117 static void aspeed_sliio_realize(DeviceState *dev, Error **errp) 118 { 119 AspeedSLIState *s = ASPEED_SLI(dev); 120 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 121 122 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sliio_ops, s, 123 TYPE_ASPEED_SLI, SLI_REGION_SIZE); 124 sysbus_init_mmio(sbd, &s->iomem); 125 } 126 127 static void aspeed_sli_class_init(ObjectClass *klass, void *data) 128 { 129 DeviceClass *dc = DEVICE_CLASS(klass); 130 131 dc->desc = "Aspeed SLI Controller"; 132 dc->realize = aspeed_sli_realize; 133 } 134 135 static const TypeInfo aspeed_sli_info = { 136 .name = TYPE_ASPEED_SLI, 137 .parent = TYPE_SYS_BUS_DEVICE, 138 .instance_size = sizeof(AspeedSLIState), 139 .class_init = aspeed_sli_class_init, 140 .abstract = true, 141 }; 142 143 static void aspeed_2700_sli_class_init(ObjectClass *klass, void *data) 144 { 145 DeviceClass *dc = DEVICE_CLASS(klass); 146 147 dc->desc = "AST2700 SLI Controller"; 148 } 149 150 static void aspeed_2700_sliio_class_init(ObjectClass *klass, void *data) 151 { 152 DeviceClass *dc = DEVICE_CLASS(klass); 153 154 dc->desc = "AST2700 I/O SLI Controller"; 155 dc->realize = aspeed_sliio_realize; 156 } 157 158 static const TypeInfo aspeed_2700_sli_info = { 159 .name = TYPE_ASPEED_2700_SLI, 160 .parent = TYPE_ASPEED_SLI, 161 .class_init = aspeed_2700_sli_class_init, 162 }; 163 164 static const TypeInfo aspeed_2700_sliio_info = { 165 .name = TYPE_ASPEED_2700_SLIIO, 166 .parent = TYPE_ASPEED_SLI, 167 .class_init = aspeed_2700_sliio_class_init, 168 }; 169 170 static void aspeed_sli_register_types(void) 171 { 172 type_register_static(&aspeed_sli_info); 173 type_register_static(&aspeed_2700_sli_info); 174 type_register_static(&aspeed_2700_sliio_info); 175 } 176 177 type_init(aspeed_sli_register_types); 178