master
c 327 lines 11.9 KB
Raw
1 /*
2 * ASPEED AST1040 SoC
3 *
4 * Copyright (C) 2026 ASPEED Technology Inc.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "qapi/error.h"
11 #include "system/address-spaces.h"
12 #include "system/system.h"
13 #include "hw/core/qdev-clock.h"
14 #include "hw/misc/unimp.h"
15 #include "hw/arm/aspeed_soc.h"
16
17 static const hwaddr aspeed_soc_ast1040_memmap[] = {
18 [ASPEED_DEV_SRAM1] = 0x00000000, /* Hyper RAM */
19 [ASPEED_DEV_FMC] = 0x74000000,
20 [ASPEED_DEV_SPI0] = 0x74010000,
21 [ASPEED_DEV_SPI1] = 0x74020000,
22 [ASPEED_DEV_PWM] = 0x740C0000,
23 [ASPEED_DEV_UDC] = 0x74120000,
24 [ASPEED_DEV_SRAM0] = 0x74B80000,
25 [ASPEED_DEV_ADC] = 0x74C00000,
26 [ASPEED_DEV_JTAG0] = 0x74C01000,
27 [ASPEED_DEV_SCU] = 0x74C02000,
28 [ASPEED_DEV_ESPI] = 0x74C05000,
29 [ASPEED_DEV_JTAG1] = 0x74C09000,
30 [ASPEED_DEV_GPIO] = 0x74C0B000,
31 [ASPEED_DEV_SGPIOM0] = 0x74C0C000,
32 [ASPEED_DEV_SGPIOM1] = 0x74C0D000,
33 [ASPEED_DEV_I2C] = 0x74C0F000,
34 [ASPEED_DEV_PECI] = 0x74C1F000,
35 [ASPEED_DEV_I3C] = 0x74C20000,
36 [ASPEED_DEV_UART0] = 0x74C33000,
37 [ASPEED_DEV_UART1] = 0x74C33100,
38 [ASPEED_DEV_UART2] = 0x74C33200,
39 [ASPEED_DEV_UART3] = 0x74C33300,
40 [ASPEED_DEV_UART4] = 0x74C33400,
41 [ASPEED_DEV_UART5] = 0x74C33500,
42 [ASPEED_DEV_UART6] = 0x74C33600,
43 [ASPEED_DEV_UART7] = 0x74C33700,
44 [ASPEED_DEV_UART8] = 0x74C33800,
45 [ASPEED_DEV_UART9] = 0x74C33900,
46 [ASPEED_DEV_UART10] = 0x74C33A00,
47 [ASPEED_DEV_UART11] = 0x74C33B00,
48 [ASPEED_DEV_UART12] = 0x74C33C00,
49 [ASPEED_DEV_WDT] = 0x74C37000,
50 [ASPEED_DEV_TIMER1] = 0x74C3A000,
51 };
52
53 static const int aspeed_soc_ast1040_irqmap[] = {
54 [ASPEED_DEV_ESPI] = 10,
55 [ASPEED_DEV_I2C] = 64, /* 64 ~ 77 */
56 [ASPEED_DEV_ADC] = 80,
57 [ASPEED_DEV_GPIO] = 82,
58 [ASPEED_DEV_SGPIOM0] = 85,
59 [ASPEED_DEV_SGPIOM1] = 88,
60 [ASPEED_DEV_TIMER1] = 92,
61 [ASPEED_DEV_I3C] = 96, /* 96 ~ 103 */
62 [ASPEED_DEV_WDT] = 112,
63 [ASPEED_DEV_FMC] = 121,
64 [ASPEED_DEV_SPI0] = 122,
65 [ASPEED_DEV_SPI1] = 123,
66 [ASPEED_DEV_PWM] = 125,
67 [ASPEED_DEV_UART0] = 135,
68 [ASPEED_DEV_UART1] = 136,
69 [ASPEED_DEV_UART2] = 137,
70 [ASPEED_DEV_UART3] = 138,
71 [ASPEED_DEV_UART4] = 139,
72 [ASPEED_DEV_UART5] = 140,
73 [ASPEED_DEV_UART6] = 141,
74 [ASPEED_DEV_UART7] = 142,
75 [ASPEED_DEV_UART8] = 143,
76 [ASPEED_DEV_UART9] = 144,
77 [ASPEED_DEV_UART10] = 145,
78 [ASPEED_DEV_UART11] = 146,
79 [ASPEED_DEV_UART12] = 147,
80 [ASPEED_DEV_JTAG0] = 162,
81 [ASPEED_DEV_PECI] = 164,
82 };
83
84 static qemu_irq aspeed_soc_ast1040_get_irq(AspeedSoCState *s, int dev)
85 {
86 Aspeed10x0SoCState *a = ASPEED10X0_SOC(s);
87 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
88
89 return qdev_get_gpio_in(DEVICE(&a->armv7m), sc->irqmap[dev]);
90 }
91
92 static void aspeed_soc_ast1040_init(Object *obj)
93 {
94 Aspeed10x0SoCState *a = ASPEED10X0_SOC(obj);
95 AspeedSoCState *s = ASPEED_SOC(obj);
96 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
97 int i;
98 object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
99
100 s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
101
102 /* AST1040 uses the AST2700 SCUIO model */
103 object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCUIO);
104 qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev);
105
106 object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), "hw-strap1");
107 object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), "hw-strap2");
108
109 for (i = 0; i < sc->uarts_num; i++) {
110 object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
111 }
112
113 object_initialize_child(obj, "adc", &s->adc, TYPE_ASPEED_2700_ADC);
114 object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI);
115 object_initialize_child(obj, "gpio", &s->gpio, "aspeed.gpio-ast2700");
116 for (i = 0; i < sc->sgpio_num; i++) {
117 object_initialize_child(obj, "sgpio[*]", &s->sgpiom[i],
118 "aspeed.sgpio-ast2700");
119 }
120 object_initialize_child(obj, "i2c", &s->i2c, TYPE_ASPEED_1040_I2C);
121
122 for (i = 0; i < sc->wdts_num; i++) {
123 object_initialize_child(obj, "wdt[*]", &s->wdt[i],
124 "aspeed.wdt-ast2700");
125 }
126
127 object_initialize_child(obj, "pwm", &s->pwm, TYPE_UNIMPLEMENTED_DEVICE);
128 object_initialize_child(obj, "espi", &s->espi, TYPE_UNIMPLEMENTED_DEVICE);
129 object_initialize_child(obj, "udc", &s->udc, TYPE_UNIMPLEMENTED_DEVICE);
130 object_initialize_child(obj, "jtag[0]", &s->jtag[0],
131 TYPE_UNIMPLEMENTED_DEVICE);
132 object_initialize_child(obj, "jtag[1]", &s->jtag[1],
133 TYPE_UNIMPLEMENTED_DEVICE);
134 }
135
136 static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp)
137 {
138 Aspeed10x0SoCState *a = ASPEED10X0_SOC(dev_soc);
139 AspeedSoCState *s = ASPEED_SOC(dev_soc);
140 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
141 g_autofree char *hyperram_name = NULL;
142 g_autofree char *sram_name = NULL;
143 DeviceState *armv7m;
144 Error *err = NULL;
145 int uart;
146 int i;
147
148 if (!clock_has_source(s->sysclk)) {
149 error_setg(errp, "sysclk clock must be wired up by the board code");
150 return;
151 }
152
153 /* AST1040 CPU Core */
154 armv7m = DEVICE(&a->armv7m);
155 qdev_prop_set_uint32(armv7m, "num-irq", 256);
156 qdev_prop_set_string(armv7m, "cpu-type",
157 aspeed_soc_cpu_type(sc->valid_cpu_types));
158 qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
159 object_property_set_link(OBJECT(&a->armv7m), "memory",
160 OBJECT(s->memory), &error_abort);
161 sysbus_realize(SYS_BUS_DEVICE(&a->armv7m), &error_abort);
162
163 /* Internal SRAM */
164 sram_name = g_strdup_printf("aspeed.sram.%d",
165 CPU(a->armv7m.cpu)->cpu_index);
166 memory_region_init_ram(&s->sram[0], OBJECT(s), sram_name,
167 sc->sram_size[0], &err);
168 if (err) {
169 error_propagate(errp, err);
170 return;
171 }
172 memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SRAM0],
173 &s->sram[0]);
174
175 /* Internal Hyper RAM */
176 hyperram_name = g_strdup_printf("aspeed.hyperram.%d",
177 CPU(a->armv7m.cpu)->cpu_index);
178 memory_region_init_ram(&s->sram[1], OBJECT(s), hyperram_name,
179 sc->sram_size[1], &err);
180 if (err) {
181 error_propagate(errp, err);
182 return;
183 }
184 memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SRAM1],
185 &s->sram[1]);
186
187 /* SCU */
188 if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
189 return;
190 }
191 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
192 sc->memmap[ASPEED_DEV_SCU]);
193
194 /* UART */
195 for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
196 if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
197 sc->memmap[uart], errp)) {
198 return;
199 }
200 sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
201 aspeed_soc_ast1040_get_irq(s, uart));
202 }
203
204 /* ADC */
205 if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
206 return;
207 }
208 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0,
209 sc->memmap[ASPEED_DEV_ADC]);
210 sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
211 aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_ADC));
212
213 /* PECI */
214 if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) {
215 return;
216 }
217 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0,
218 sc->memmap[ASPEED_DEV_PECI]);
219 sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0,
220 aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_PECI));
221
222 /* GPIO */
223 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
224 return;
225 }
226 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0,
227 sc->memmap[ASPEED_DEV_GPIO]);
228 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
229 aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_GPIO));
230
231 /* SGPIO */
232 for (i = 0; i < sc->sgpio_num; i++) {
233 if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) {
234 return;
235 }
236 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sgpiom[i]), 0,
237 sc->memmap[ASPEED_DEV_SGPIOM0 + i]);
238 sysbus_connect_irq(SYS_BUS_DEVICE(&s->sgpiom[i]), 0,
239 aspeed_soc_ast1040_get_irq(s, ASPEED_DEV_SGPIOM0 + i));
240 }
241
242 /* I2C */
243 object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(&s->sram[1]),
244 &error_abort);
245 if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
246 return;
247 }
248 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0,
249 sc->memmap[ASPEED_DEV_I2C]);
250 for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
251 qemu_irq irq = qdev_get_gpio_in(DEVICE(&a->armv7m),
252 sc->irqmap[ASPEED_DEV_I2C] + i);
253 /* The AST1040 I2C controller has one IRQ per bus. */
254 sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
255 }
256
257 /* Watch dog */
258 for (i = 0; i < sc->wdts_num; i++) {
259 AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
260 hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i * awc->iosize;
261
262 object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu),
263 &error_abort);
264 if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
265 return;
266 }
267 aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
268 }
269
270 /* Unimplemented peripherals */
271 aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm),
272 "aspeed.pwm",
273 sc->memmap[ASPEED_DEV_PWM], 0x10000);
274
275 aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->espi),
276 "aspeed.espi",
277 sc->memmap[ASPEED_DEV_ESPI], 0x1000);
278
279 aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->udc),
280 "aspeed.udc",
281 sc->memmap[ASPEED_DEV_UDC], 0x4000);
282
283 aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[0]),
284 "aspeed.jtag0",
285 sc->memmap[ASPEED_DEV_JTAG0], 0x100);
286
287 aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[1]),
288 "aspeed.jtag1",
289 sc->memmap[ASPEED_DEV_JTAG1], 0x100);
290 }
291
292 static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data)
293 {
294 static const char * const valid_cpu_types[] = {
295 ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO cortex-m4f */
296 NULL
297 };
298 DeviceClass *dc = DEVICE_CLASS(klass);
299 AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc);
300
301 /* Reason: The Aspeed SoC can only be instantiated from a board */
302 dc->user_creatable = false;
303 dc->realize = aspeed_soc_ast1040_realize;
304
305 sc->valid_cpu_types = valid_cpu_types;
306 sc->silicon_rev = AST1040_A0_SILICON_REV;
307 sc->sram_size[0] = 128 * KiB;
308 sc->sram_size[1] = 16 * MiB; /* Hyper RAM */
309 sc->uarts_num = 13;
310 sc->sgpio_num = 2;
311 sc->wdts_num = 8;
312 sc->uarts_base = ASPEED_DEV_UART0;
313 sc->irqmap = aspeed_soc_ast1040_irqmap;
314 sc->memmap = aspeed_soc_ast1040_memmap;
315 sc->num_cpus = 1;
316 }
317
318 static const TypeInfo aspeed_soc_ast1040_types[] = {
319 {
320 .name = "ast1040-a0",
321 .parent = TYPE_ASPEED10X0_SOC,
322 .instance_init = aspeed_soc_ast1040_init,
323 .class_init = aspeed_soc_ast1040_class_init,
324 }
325 };
326
327 DEFINE_TYPES(aspeed_soc_ast1040_types)