xref: /openbmc/qemu/hw/misc/aspeed_sli.c (revision 79e6ec66ba1067a135394a330fec14b50cf49534)
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