xref: /openbmc/qemu/hw/misc/aspeed_sli.c (revision f944890d)
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 
aspeed_sli_read(void * opaque,hwaddr addr,unsigned int size)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 
aspeed_sli_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)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 
aspeed_sliio_read(void * opaque,hwaddr addr,unsigned int size)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 
aspeed_sliio_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)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 
aspeed_sli_realize(DeviceState * dev,Error ** errp)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 
aspeed_sliio_realize(DeviceState * dev,Error ** errp)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 
aspeed_sli_class_init(ObjectClass * klass,void * data)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 
aspeed_2700_sli_class_init(ObjectClass * klass,void * data)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 
aspeed_2700_sliio_class_init(ObjectClass * klass,void * data)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 
aspeed_sli_register_types(void)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