master
c 273 lines 9.42 KB
Raw
1 /*
2 * ASPEED AST1700 IO Expander
3 *
4 * Copyright (C) 2025 ASPEED Technology Inc.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "hw/core/boards.h"
11 #include "qom/object.h"
12 #include "qapi/error.h"
13 #include "hw/core/qdev-properties.h"
14 #include "hw/arm/aspeed_ast1700.h"
15
16 #define AST2700_SOC_LTPI_SIZE 0x01000000
17 #define AST1700_SOC_SRAM_SIZE 0x00040000
18 #define AST1700_SOC_I3C_SIZE 0x00010000
19
20 enum {
21 ASPEED_AST1700_DEV_SPI0,
22 ASPEED_AST1700_DEV_PWM,
23 ASPEED_AST1700_DEV_SRAM,
24 ASPEED_AST1700_DEV_ADC,
25 ASPEED_AST1700_DEV_SCU,
26 ASPEED_AST1700_DEV_GPIO,
27 ASPEED_AST1700_DEV_SGPIOM0,
28 ASPEED_AST1700_DEV_SGPIOM1,
29 ASPEED_AST1700_DEV_I2C,
30 ASPEED_AST1700_DEV_I3C,
31 ASPEED_AST1700_DEV_UART12,
32 ASPEED_AST1700_DEV_LTPI_CTRL,
33 ASPEED_AST1700_DEV_WDT,
34 ASPEED_AST1700_DEV_SPI0_MEM,
35 };
36
37 static const hwaddr aspeed_ast1700_io_memmap[] = {
38 [ASPEED_AST1700_DEV_SPI0] = 0x00030000,
39 [ASPEED_AST1700_DEV_PWM] = 0x000C0000,
40 [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000,
41 [ASPEED_AST1700_DEV_ADC] = 0x00C00000,
42 [ASPEED_AST1700_DEV_SCU] = 0x00C02000,
43 [ASPEED_AST1700_DEV_GPIO] = 0x00C0B000,
44 [ASPEED_AST1700_DEV_SGPIOM0] = 0x00C0C000,
45 [ASPEED_AST1700_DEV_SGPIOM1] = 0x00C0D000,
46 [ASPEED_AST1700_DEV_I2C] = 0x00C0F000,
47 [ASPEED_AST1700_DEV_I3C] = 0x00C20000,
48 [ASPEED_AST1700_DEV_UART12] = 0x00C33B00,
49 [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000,
50 [ASPEED_AST1700_DEV_WDT] = 0x00C37000,
51 [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000,
52 };
53
54 static void aspeed_ast1700_realize(DeviceState *dev, Error **errp)
55 {
56 AspeedAST1700SoCState *s = ASPEED_AST1700(dev);
57 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
58 char dev_name[32];
59
60 if (!s->dram_mr) {
61 error_setg(errp, TYPE_ASPEED_AST1700 ": 'dram' link not set");
62 return;
63 }
64
65 /* Occupy memory space for all controllers in AST1700 */
66 memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700,
67 AST2700_SOC_LTPI_SIZE);
68 sysbus_init_mmio(sbd, &s->iomem);
69
70 /* SRAM */
71 snprintf(dev_name, sizeof(dev_name), "aspeed.ioexp-sram.%d", s->board_idx);
72 memory_region_init_ram(&s->sram, OBJECT(s), dev_name,
73 AST1700_SOC_SRAM_SIZE, errp);
74 memory_region_add_subregion(&s->iomem,
75 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SRAM],
76 &s->sram);
77
78 /* UART */
79 qdev_prop_set_uint8(DEVICE(&s->uart), "regshift", 2);
80 qdev_prop_set_uint32(DEVICE(&s->uart), "baudbase", 38400);
81 qdev_prop_set_uint8(DEVICE(&s->uart), "endianness", DEVICE_LITTLE_ENDIAN);
82 if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
83 return;
84 }
85 memory_region_add_subregion(&s->iomem,
86 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_UART12],
87 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0));
88
89 /* SPI */
90 object_property_set_link(OBJECT(&s->spi), "dram",
91 OBJECT(s->dram_mr), errp);
92 if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi), errp)) {
93 return;
94 }
95 memory_region_add_subregion(&s->iomem,
96 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0],
97 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 0));
98
99 memory_region_add_subregion(&s->iomem,
100 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0_MEM],
101 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 1));
102
103 /* ADC */
104 if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
105 return;
106 }
107 memory_region_add_subregion(&s->iomem,
108 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_ADC],
109 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->adc), 0));
110
111 /* SCU */
112 qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
113 s->silicon_rev);
114 if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
115 return;
116 }
117 memory_region_add_subregion(&s->iomem,
118 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SCU],
119 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->scu), 0));
120
121 /* GPIO */
122 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
123 return;
124 }
125 memory_region_add_subregion(&s->iomem,
126 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_GPIO],
127 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
128
129 /* I2C */
130 snprintf(dev_name, sizeof(dev_name), "ioexp%d", s->board_idx);
131 qdev_prop_set_string(DEVICE(&s->i2c), "bus-label", dev_name);
132
133 object_property_set_link(OBJECT(&s->i2c), "dram",
134 OBJECT(s->dram_mr), errp);
135 if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
136 return;
137 }
138 memory_region_add_subregion(&s->iomem,
139 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I2C],
140 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c), 0));
141
142 /* PWM */
143 if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm), errp)) {
144 return;
145 }
146 memory_region_add_subregion(&s->iomem,
147 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_PWM],
148 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pwm), 0));
149
150 /* LTPI controller */
151 if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) {
152 return;
153 }
154 memory_region_add_subregion(&s->iomem,
155 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_LTPI_CTRL],
156 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ltpi), 0));
157
158 /* SGPIOM */
159 for (int i = 0; i < AST1700_SGPIO_NUM; i++) {
160 if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) {
161 return;
162 }
163 memory_region_add_subregion(&s->iomem,
164 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SGPIOM0 + i],
165 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sgpiom[i]), 0));
166 }
167
168 /* WDT */
169 for (int i = 0; i < AST1700_WDT_NUM; i++) {
170 AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
171 hwaddr wdt_offset = aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_WDT] +
172 i * awc->iosize;
173
174 object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu),
175 errp);
176 if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
177 return;
178 }
179 memory_region_add_subregion(&s->iomem,
180 wdt_offset,
181 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->wdt[i]), 0));
182 }
183
184 /* I3C */
185 qdev_prop_set_string(DEVICE(&s->i3c), "name", "ioexp-i3c");
186 qdev_prop_set_uint64(DEVICE(&s->i3c), "size", AST1700_SOC_I3C_SIZE);
187 sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp);
188 memory_region_add_subregion_overlap(&s->iomem,
189 aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I3C],
190 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i3c), 0),
191 -1000);
192 }
193
194 static void aspeed_ast1700_instance_init(Object *obj)
195 {
196 AspeedAST1700SoCState *s = ASPEED_AST1700(obj);
197
198 /* UART */
199 object_initialize_child(obj, "uart", &s->uart,
200 TYPE_SERIAL_MM);
201
202 /* SPI */
203 object_initialize_child(obj, "ioexp-spi", &s->spi,
204 "aspeed.spi0-ast2700");
205
206 /* ADC */
207 object_initialize_child(obj, "ioexp-adc", &s->adc,
208 "aspeed.adc-ast2700");
209
210 /* SCU */
211 object_initialize_child(obj, "ioexp-scu", &s->scu,
212 TYPE_ASPEED_2700_SCU);
213
214 /* GPIO */
215 object_initialize_child(obj, "ioexp-gpio", &s->gpio,
216 "aspeed.gpio-ast2700");
217
218 /* I2C */
219 object_initialize_child(obj, "ioexp-i2c", &s->i2c,
220 "aspeed.i2c-ast2700");
221
222 /* PWM */
223 object_initialize_child(obj, "pwm", &s->pwm, TYPE_ASPEED_PWM);
224
225 /* LTPI controller */
226 object_initialize_child(obj, "ltpi-ctrl",
227 &s->ltpi, TYPE_ASPEED_LTPI);
228
229 /* SGPIOM */
230 for (int i = 0; i < AST1700_SGPIO_NUM; i++) {
231 object_initialize_child(obj, "ioexp-sgpiom[*]", &s->sgpiom[i],
232 "aspeed.sgpio-ast2700");
233 }
234
235 /* WDT */
236 for (int i = 0; i < AST1700_WDT_NUM; i++) {
237 object_initialize_child(obj, "ioexp-wdt[*]",
238 &s->wdt[i], "aspeed.wdt-ast2700");
239 }
240
241 /* I3C */
242 object_initialize_child(obj, "ioexp-i3c", &s->i3c,
243 TYPE_UNIMPLEMENTED_DEVICE);
244
245 return;
246 }
247
248 static const Property aspeed_ast1700_props[] = {
249 DEFINE_PROP_UINT8("board-idx", AspeedAST1700SoCState, board_idx, 0),
250 DEFINE_PROP_UINT32("silicon-rev", AspeedAST1700SoCState, silicon_rev, 0),
251 DEFINE_PROP_LINK("dram", AspeedAST1700SoCState, dram_mr,
252 TYPE_MEMORY_REGION, MemoryRegion *),
253 };
254
255 static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data)
256 {
257 DeviceClass *dc = DEVICE_CLASS(klass);
258
259 dc->realize = aspeed_ast1700_realize;
260 device_class_set_props(dc, aspeed_ast1700_props);
261 }
262
263 static const TypeInfo aspeed_ast1700_types[] = {
264 {
265 .name = TYPE_ASPEED_AST1700,
266 .parent = TYPE_SYS_BUS_DEVICE,
267 .instance_size = sizeof(AspeedAST1700SoCState),
268 .class_init = aspeed_ast1700_class_init,
269 .instance_init = aspeed_ast1700_instance_init,
270 }
271 };
272
273 DEFINE_TYPES(aspeed_ast1700_types)