master
c 171 lines 4.53 KB
Raw
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/core/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, const 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
136 static void aspeed_2700_sli_class_init(ObjectClass *klass, const void *data)
137 {
138 DeviceClass *dc = DEVICE_CLASS(klass);
139
140 dc->desc = "AST2700 SLI Controller";
141 }
142
143 static void aspeed_2700_sliio_class_init(ObjectClass *klass, const void *data)
144 {
145 DeviceClass *dc = DEVICE_CLASS(klass);
146
147 dc->desc = "AST2700 I/O SLI Controller";
148 dc->realize = aspeed_sliio_realize;
149 }
150
151 static const TypeInfo aspeed_sli_types[] = {
152 {
153 .name = TYPE_ASPEED_SLI,
154 .parent = TYPE_SYS_BUS_DEVICE,
155 .instance_size = sizeof(AspeedSLIState),
156 .class_init = aspeed_sli_class_init,
157 .abstract = true,
158 },
159 {
160 .name = TYPE_ASPEED_2700_SLI,
161 .parent = TYPE_ASPEED_SLI,
162 .class_init = aspeed_2700_sli_class_init,
163 },
164 {
165 .name = TYPE_ASPEED_2700_SLIIO,
166 .parent = TYPE_ASPEED_SLI,
167 .class_init = aspeed_2700_sliio_class_init,
168 }
169 };
170
171 DEFINE_TYPES(aspeed_sli_types)