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