1 /*
2 * ASPEED SoC 2700 family
3 *
4 * Copyright (C) 2025 ASPEED Technology Inc.
5 *
6 * This code is licensed under the GPL version 2 or later. See
7 * the COPYING file in the top-level directory.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "qemu/osdep.h"
13 #include "qemu/units.h"
14 #include "qapi/error.h"
15 #include "system/block-backend.h"
16 #include "system/system.h"
17 #include "hw/arm/aspeed.h"
18 #include "hw/boards.h"
19 #include "hw/qdev-clock.h"
20 #include "hw/arm/aspeed_soc.h"
21 #include "hw/loader.h"
22 #include "hw/arm/boot.h"
23 #include "hw/block/flash.h"
24
25
26 #define TYPE_AST2700A0FC MACHINE_TYPE_NAME("ast2700fc-a0")
27 OBJECT_DECLARE_SIMPLE_TYPE(Ast2700a0FCState, AST2700A0FC);
28 #define TYPE_AST2700A1FC MACHINE_TYPE_NAME("ast2700fc-a1")
29 OBJECT_DECLARE_SIMPLE_TYPE(Ast2700a1FCState, AST2700A1FC);
30
31 static struct arm_boot_info ast2700fc_board_info = {
32 .board_id = -1, /* device-tree-only board */
33 };
34
35 struct Ast2700a0FCState {
36 MachineState parent_obj;
37
38 MemoryRegion ca35_memory;
39 MemoryRegion ca35_dram;
40 MemoryRegion ssp_memory;
41 MemoryRegion tsp_memory;
42
43 Clock *ssp_sysclk;
44 Clock *tsp_sysclk;
45
46 Aspeed27x0SoCState ca35;
47 Aspeed27x0SSPSoCState ssp;
48 Aspeed27x0TSPSoCState tsp;
49
50 bool mmio_exec;
51 };
52
53 struct Ast2700a1FCState {
54 MachineState parent_obj;
55
56 MemoryRegion ca35_memory;
57 MemoryRegion ca35_dram;
58 MemoryRegion ssp_memory;
59 MemoryRegion tsp_memory;
60
61 Clock *ssp_sysclk;
62 Clock *tsp_sysclk;
63
64 Aspeed27x0SoCState ca35;
65 Aspeed27x0SSPSoCState ssp;
66 Aspeed27x0TSPSoCState tsp;
67
68 bool mmio_exec;
69 };
70
71 #define AST2700FC_BMC_RAM_SIZE (2 * GiB)
72 #define AST2700FC_CM4_DRAM_SIZE (32 * MiB)
73
74 #define AST2700FC_HW_STRAP1 0x000000C0
75 #define AST2700FC_HW_STRAP2 0x00000003
76 #define AST2700FC_FMC_MODEL "w25q01jvq"
77 #define AST2700FC_SPI_MODEL "w25q512jv"
78
ast2700a0fc_ca35_init(MachineState * machine)79 static void ast2700a0fc_ca35_init(MachineState *machine)
80 {
81 Ast2700a0FCState *s = AST2700A0FC(machine);
82 AspeedSoCState *soc;
83 AspeedSoCClass *sc;
84
85 object_initialize_child(OBJECT(s), "ca35", &s->ca35, "ast2700-a0");
86 soc = ASPEED_SOC(&s->ca35);
87 sc = ASPEED_SOC_GET_CLASS(soc);
88
89 memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory",
90 UINT64_MAX);
91
92 if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram",
93 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
94 return;
95 }
96 if (!object_property_set_link(OBJECT(&s->ca35), "memory",
97 OBJECT(&s->ca35_memory),
98 &error_abort)) {
99 return;
100 };
101 if (!object_property_set_link(OBJECT(&s->ca35), "dram",
102 OBJECT(&s->ca35_dram), &error_abort)) {
103 return;
104 }
105 if (!object_property_set_int(OBJECT(&s->ca35), "ram-size",
106 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
107 return;
108 }
109 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1",
110 AST2700FC_HW_STRAP1, &error_abort)) {
111 return;
112 }
113 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap2",
114 AST2700FC_HW_STRAP2, &error_abort)) {
115 return;
116 }
117 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0));
118 if (!qdev_realize(DEVICE(&s->ca35), NULL, &error_abort)) {
119 return;
120 }
121 /*
122 * AST2700 EVB has a LM75 temperature sensor on I2C bus 0 at address 0x4d.
123 */
124 i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "tmp105", 0x4d);
125
126 aspeed_board_init_flashes(&soc->fmc, AST2700FC_FMC_MODEL, 2, 0);
127 aspeed_board_init_flashes(&soc->spi[0], AST2700FC_SPI_MODEL, 1, 2);
128
129 ast2700fc_board_info.ram_size = machine->ram_size;
130 ast2700fc_board_info.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
131
132 arm_load_kernel(ARM_CPU(first_cpu), machine, &ast2700fc_board_info);
133 }
134
ast2700a1fc_ca35_init(MachineState * machine)135 static void ast2700a1fc_ca35_init(MachineState *machine)
136 {
137 Ast2700a1FCState *s = AST2700A1FC(machine);
138 AspeedSoCState *soc;
139 AspeedSoCClass *sc;
140
141 object_initialize_child(OBJECT(s), "ca35", &s->ca35, "ast2700-a1");
142 soc = ASPEED_SOC(&s->ca35);
143 sc = ASPEED_SOC_GET_CLASS(soc);
144
145 memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory",
146 UINT64_MAX);
147
148 if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram",
149 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
150 return;
151 }
152 if (!object_property_set_link(OBJECT(&s->ca35), "memory",
153 OBJECT(&s->ca35_memory),
154 &error_abort)) {
155 return;
156 };
157 if (!object_property_set_link(OBJECT(&s->ca35), "dram",
158 OBJECT(&s->ca35_dram), &error_abort)) {
159 return;
160 }
161 if (!object_property_set_int(OBJECT(&s->ca35), "ram-size",
162 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
163 return;
164 }
165 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1",
166 AST2700FC_HW_STRAP1, &error_abort)) {
167 return;
168 }
169 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap2",
170 AST2700FC_HW_STRAP2, &error_abort)) {
171 return;
172 }
173 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0));
174 if (!qdev_realize(DEVICE(&s->ca35), NULL, &error_abort)) {
175 return;
176 }
177
178 /*
179 * AST2700 EVB has a LM75 temperature sensor on I2C bus 0 at address 0x4d.
180 */
181 i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "tmp105", 0x4d);
182
183 aspeed_board_init_flashes(&soc->fmc, AST2700FC_FMC_MODEL, 2, 0);
184 aspeed_board_init_flashes(&soc->spi[0], AST2700FC_SPI_MODEL, 1, 2);
185
186 ast2700fc_board_info.ram_size = machine->ram_size;
187 ast2700fc_board_info.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
188
189 arm_load_kernel(ARM_CPU(first_cpu), machine, &ast2700fc_board_info);
190 }
191
ast2700a0fc_ssp_init(MachineState * machine)192 static void ast2700a0fc_ssp_init(MachineState *machine)
193 {
194 AspeedSoCState *soc;
195 Ast2700a0FCState *s = AST2700A0FC(machine);
196 s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK");
197 clock_set_hz(s->ssp_sysclk, 200000000ULL);
198
199 object_initialize_child(OBJECT(s), "ssp", &s->ssp, "ast2700ssp-a0");
200 memory_region_init(&s->ssp_memory, OBJECT(&s->ssp), "ssp-memory",
201 UINT64_MAX);
202
203 qdev_connect_clock_in(DEVICE(&s->ssp), "sysclk", s->ssp_sysclk);
204 if (!object_property_set_link(OBJECT(&s->ssp), "memory",
205 OBJECT(&s->ssp_memory), &error_abort)) {
206 return;
207 }
208
209 soc = ASPEED_SOC(&s->ssp);
210 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(1));
211 if (!qdev_realize(DEVICE(&s->ssp), NULL, &error_abort)) {
212 return;
213 }
214 }
215
ast2700a1fc_ssp_init(MachineState * machine)216 static void ast2700a1fc_ssp_init(MachineState *machine)
217 {
218 AspeedSoCState *soc;
219 Ast2700a1FCState *s = AST2700A1FC(machine);
220 s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK");
221 clock_set_hz(s->ssp_sysclk, 200000000ULL);
222
223 object_initialize_child(OBJECT(s), "ssp", &s->ssp, "ast2700ssp-a1");
224 memory_region_init(&s->ssp_memory, OBJECT(&s->ssp), "ssp-memory",
225 UINT64_MAX);
226
227 qdev_connect_clock_in(DEVICE(&s->ssp), "sysclk", s->ssp_sysclk);
228 if (!object_property_set_link(OBJECT(&s->ssp), "memory",
229 OBJECT(&s->ssp_memory), &error_abort)) {
230 return;
231 }
232
233 soc = ASPEED_SOC(&s->ssp);
234 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(1));
235 if (!qdev_realize(DEVICE(&s->ssp), NULL, &error_abort)) {
236 return;
237 }
238 }
239
ast2700a0fc_tsp_init(MachineState * machine)240 static void ast2700a0fc_tsp_init(MachineState *machine)
241 {
242 AspeedSoCState *soc;
243 Ast2700a0FCState *s = AST2700A0FC(machine);
244 s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK");
245 clock_set_hz(s->tsp_sysclk, 200000000ULL);
246
247 object_initialize_child(OBJECT(s), "tsp", &s->tsp, "ast2700tsp-a0");
248 memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory",
249 UINT64_MAX);
250
251 qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk);
252 if (!object_property_set_link(OBJECT(&s->tsp), "memory",
253 OBJECT(&s->tsp_memory), &error_abort)) {
254 return;
255 }
256
257 soc = ASPEED_SOC(&s->tsp);
258 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(2));
259 if (!qdev_realize(DEVICE(&s->tsp), NULL, &error_abort)) {
260 return;
261 }
262 }
263
ast2700a1fc_tsp_init(MachineState * machine)264 static void ast2700a1fc_tsp_init(MachineState *machine)
265 {
266 AspeedSoCState *soc;
267 Ast2700a1FCState *s = AST2700A1FC(machine);
268 s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK");
269 clock_set_hz(s->tsp_sysclk, 200000000ULL);
270
271 object_initialize_child(OBJECT(s), "tsp", &s->tsp, "ast2700tsp-a1");
272 memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory",
273 UINT64_MAX);
274
275 qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk);
276 if (!object_property_set_link(OBJECT(&s->tsp), "memory",
277 OBJECT(&s->tsp_memory), &error_abort)) {
278 return;
279 }
280
281 soc = ASPEED_SOC(&s->tsp);
282 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART7, serial_hd(2));
283 if (!qdev_realize(DEVICE(&s->tsp), NULL, &error_abort)) {
284 return;
285 }
286 }
287
ast2700a0fc_init(MachineState * machine)288 static void ast2700a0fc_init(MachineState *machine)
289 {
290 ast2700a0fc_ca35_init(machine);
291 ast2700a0fc_ssp_init(machine);
292 ast2700a0fc_tsp_init(machine);
293 }
294
ast2700a1fc_init(MachineState * machine)295 static void ast2700a1fc_init(MachineState *machine)
296 {
297 ast2700a1fc_ca35_init(machine);
298 ast2700a1fc_ssp_init(machine);
299 ast2700a1fc_tsp_init(machine);
300 }
301
ast2700a0fc_class_init(ObjectClass * oc,void * data)302 static void ast2700a0fc_class_init(ObjectClass *oc, void *data)
303 {
304 MachineClass *mc = MACHINE_CLASS(oc);
305
306 mc->desc = "ast2700-a0 full core support";
307 mc->init = ast2700a0fc_init;
308 mc->no_floppy = 1;
309 mc->no_cdrom = 1;
310 mc->min_cpus = mc->max_cpus = mc->default_cpus = 6;
311 }
312
ast2700a1fc_class_init(ObjectClass * oc,void * data)313 static void ast2700a1fc_class_init(ObjectClass *oc, void *data)
314 {
315 MachineClass *mc = MACHINE_CLASS(oc);
316
317 mc->alias = "ast2700fc";
318 mc->desc = "ast2700-a1 full core support";
319 mc->init = ast2700a1fc_init;
320 mc->no_floppy = 1;
321 mc->no_cdrom = 1;
322 mc->min_cpus = mc->max_cpus = mc->default_cpus = 6;
323 }
324
325 static const TypeInfo ast2700fc_types[] = {
326 {
327 .name = MACHINE_TYPE_NAME("ast2700fc-a0"),
328 .parent = TYPE_MACHINE,
329 .class_init = ast2700a0fc_class_init,
330 .instance_size = sizeof(Ast2700a0FCState),
331 },
332 {
333 .name = MACHINE_TYPE_NAME("ast2700fc-a1"),
334 .parent = TYPE_MACHINE,
335 .class_init = ast2700a1fc_class_init,
336 .instance_size = sizeof(Ast2700a1FCState),
337 },
338 };
339
340 DEFINE_TYPES(ast2700fc_types)
341