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_AST2700A1FC MACHINE_TYPE_NAME("ast2700fc")
27 OBJECT_DECLARE_SIMPLE_TYPE(Ast2700FCState, AST2700A1FC);
28
29 static struct arm_boot_info ast2700fc_board_info = {
30 .board_id = -1, /* device-tree-only board */
31 };
32
33 struct Ast2700FCState {
34 MachineState parent_obj;
35
36 MemoryRegion ca35_memory;
37 MemoryRegion ca35_dram;
38 MemoryRegion ssp_memory;
39 MemoryRegion tsp_memory;
40
41 Clock *ssp_sysclk;
42 Clock *tsp_sysclk;
43
44 Aspeed27x0SoCState ca35;
45 Aspeed27x0SSPSoCState ssp;
46 Aspeed27x0TSPSoCState tsp;
47
48 bool mmio_exec;
49 };
50
51 #define AST2700FC_BMC_RAM_SIZE (1 * GiB)
52 #define AST2700FC_CM4_DRAM_SIZE (32 * MiB)
53
54 #define AST2700FC_HW_STRAP1 0x000000C0
55 #define AST2700FC_HW_STRAP2 0x00000003
56 #define AST2700FC_FMC_MODEL "w25q01jvq"
57 #define AST2700FC_SPI_MODEL "w25q512jv"
58
ast2700fc_ca35_init(MachineState * machine)59 static void ast2700fc_ca35_init(MachineState *machine)
60 {
61 Ast2700FCState *s = AST2700A1FC(machine);
62 AspeedSoCState *soc;
63 AspeedSoCClass *sc;
64
65 object_initialize_child(OBJECT(s), "ca35", &s->ca35, "ast2700-a1");
66 soc = ASPEED_SOC(&s->ca35);
67 sc = ASPEED_SOC_GET_CLASS(soc);
68
69 memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory",
70 UINT64_MAX);
71 memory_region_add_subregion(get_system_memory(), 0, &s->ca35_memory);
72
73 if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram",
74 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
75 return;
76 }
77 if (!object_property_set_link(OBJECT(&s->ca35), "memory",
78 OBJECT(&s->ca35_memory),
79 &error_abort)) {
80 return;
81 };
82 if (!object_property_set_link(OBJECT(&s->ca35), "dram",
83 OBJECT(&s->ca35_dram), &error_abort)) {
84 return;
85 }
86 if (!object_property_set_int(OBJECT(&s->ca35), "ram-size",
87 AST2700FC_BMC_RAM_SIZE, &error_abort)) {
88 return;
89 }
90
91 for (int i = 0; i < sc->macs_num; i++) {
92 if (!qemu_configure_nic_device(DEVICE(&soc->ftgmac100[i]),
93 true, NULL)) {
94 break;
95 }
96 }
97 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1",
98 AST2700FC_HW_STRAP1, &error_abort)) {
99 return;
100 }
101 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap2",
102 AST2700FC_HW_STRAP2, &error_abort)) {
103 return;
104 }
105 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0));
106 if (!qdev_realize(DEVICE(&s->ca35), NULL, &error_abort)) {
107 return;
108 }
109
110 /*
111 * AST2700 EVB has a LM75 temperature sensor on I2C bus 0 at address 0x4d.
112 */
113 i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "tmp105", 0x4d);
114
115 aspeed_board_init_flashes(&soc->fmc, AST2700FC_FMC_MODEL, 2, 0);
116 aspeed_board_init_flashes(&soc->spi[0], AST2700FC_SPI_MODEL, 1, 2);
117
118 ast2700fc_board_info.ram_size = machine->ram_size;
119 ast2700fc_board_info.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
120
121 arm_load_kernel(ARM_CPU(first_cpu), machine, &ast2700fc_board_info);
122 }
123
ast2700fc_ssp_init(MachineState * machine)124 static void ast2700fc_ssp_init(MachineState *machine)
125 {
126 AspeedSoCState *soc;
127 Ast2700FCState *s = AST2700A1FC(machine);
128 s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK");
129 clock_set_hz(s->ssp_sysclk, 200000000ULL);
130
131 object_initialize_child(OBJECT(s), "ssp", &s->ssp, TYPE_ASPEED27X0SSP_SOC);
132 memory_region_init(&s->ssp_memory, OBJECT(&s->ssp), "ssp-memory",
133 UINT64_MAX);
134
135 qdev_connect_clock_in(DEVICE(&s->ssp), "sysclk", s->ssp_sysclk);
136 if (!object_property_set_link(OBJECT(&s->ssp), "memory",
137 OBJECT(&s->ssp_memory), &error_abort)) {
138 return;
139 }
140
141 soc = ASPEED_SOC(&s->ssp);
142 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(1));
143 if (!qdev_realize(DEVICE(&s->ssp), NULL, &error_abort)) {
144 return;
145 }
146 }
147
ast2700fc_tsp_init(MachineState * machine)148 static void ast2700fc_tsp_init(MachineState *machine)
149 {
150 AspeedSoCState *soc;
151 Ast2700FCState *s = AST2700A1FC(machine);
152 s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK");
153 clock_set_hz(s->tsp_sysclk, 200000000ULL);
154
155 object_initialize_child(OBJECT(s), "tsp", &s->tsp, TYPE_ASPEED27X0TSP_SOC);
156 memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory",
157 UINT64_MAX);
158
159 qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk);
160 if (!object_property_set_link(OBJECT(&s->tsp), "memory",
161 OBJECT(&s->tsp_memory), &error_abort)) {
162 return;
163 }
164
165 soc = ASPEED_SOC(&s->tsp);
166 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART7, serial_hd(2));
167 if (!qdev_realize(DEVICE(&s->tsp), NULL, &error_abort)) {
168 return;
169 }
170 }
171
ast2700fc_init(MachineState * machine)172 static void ast2700fc_init(MachineState *machine)
173 {
174 ast2700fc_ca35_init(machine);
175 ast2700fc_ssp_init(machine);
176 ast2700fc_tsp_init(machine);
177 }
178
ast2700fc_class_init(ObjectClass * oc,const void * data)179 static void ast2700fc_class_init(ObjectClass *oc, const void *data)
180 {
181 MachineClass *mc = MACHINE_CLASS(oc);
182
183 mc->alias = "ast2700fc";
184 mc->desc = "ast2700 full core support";
185 mc->init = ast2700fc_init;
186 mc->no_floppy = 1;
187 mc->no_cdrom = 1;
188 mc->min_cpus = mc->max_cpus = mc->default_cpus = 6;
189 }
190
191 static const TypeInfo ast2700fc_types[] = {
192 {
193 .name = MACHINE_TYPE_NAME("ast2700fc"),
194 .parent = TYPE_MACHINE,
195 .class_init = ast2700fc_class_init,
196 .instance_size = sizeof(Ast2700FCState),
197 },
198 };
199
200 DEFINE_TYPES(ast2700fc_types)
201