master
c 477 lines 15.3 KB
Raw
1 /*
2 * MIPS Boston-aia development board emulation.
3 *
4 * Copyright (c) 2016 Imagination Technologies
5 *
6 * Copyright (c) 2025 MIPS
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 *
10 */
11
12 #include "qemu/osdep.h"
13 #include "qemu/units.h"
14
15 #include "hw/core/boards.h"
16 #include "hw/char/serial-mm.h"
17 #include "hw/ide/pci.h"
18 #include "hw/ide/ahci-pci.h"
19 #include "hw/core/loader.h"
20 #include "hw/riscv/cps.h"
21 #include "hw/riscv/machines-qom.h"
22 #include "hw/pci-host/xilinx-pcie.h"
23 #include "hw/core/qdev-properties.h"
24 #include "qapi/error.h"
25 #include "qemu/error-report.h"
26 #include "qemu/log.h"
27 #include "chardev/char.h"
28 #include "system/address-spaces.h"
29 #include "system/device_tree.h"
30 #include "system/system.h"
31 #include "system/qtest.h"
32 #include "system/runstate.h"
33
34 #include <libfdt.h>
35 #include "qom/object.h"
36
37 #define TYPE_MIPS_BOSTON_AIA "mips-boston-aia"
38 typedef struct BostonState BostonState;
39 DECLARE_INSTANCE_CHECKER(BostonState, BOSTON,
40 TYPE_MIPS_BOSTON_AIA)
41
42 enum {
43 BOSTON_PCIE2,
44 BOSTON_PCIE2_MMIO,
45 BOSTON_PLATREG,
46 BOSTON_UART,
47 BOSTON_LCD,
48 BOSTON_FLASH,
49 BOSTON_HIGHDDR,
50 };
51
52 static const MemMapEntry boston_memmap[] = {
53 [BOSTON_PCIE2] = { 0x14000000, 0x2000000 },
54 [BOSTON_PCIE2_MMIO] = { 0x16000000, 0x100000 },
55 [BOSTON_PLATREG] = { 0x17ffd000, 0x1000 },
56 [BOSTON_UART] = { 0x17ffe000, 0x20 },
57 [BOSTON_LCD] = { 0x17fff000, 0x8 },
58 [BOSTON_FLASH] = { 0x18000000, 0x8000000 },
59 [BOSTON_HIGHDDR] = { 0x80000000, 0x0 },
60 };
61
62 /* Interrupt numbers for APLIC. */
63 #define UART_INT 4
64 #define PCIE2_INT 7
65
66 struct BostonState {
67 SysBusDevice parent_obj;
68
69 MachineState *mach;
70 RISCVCPSState cps;
71 SerialMM *uart;
72
73 CharFrontend lcd_display;
74 char lcd_content[8];
75 bool lcd_inited;
76 };
77
78 enum boston_plat_reg {
79 PLAT_FPGA_BUILD = 0x00,
80 PLAT_CORE_CL = 0x04,
81 PLAT_WRAPPER_CL = 0x08,
82 PLAT_SYSCLK_STATUS = 0x0c,
83 PLAT_SOFTRST_CTL = 0x10,
84 #define PLAT_SOFTRST_CTL_SYSRESET (1 << 4)
85 PLAT_DDR3_STATUS = 0x14,
86 #define PLAT_DDR3_STATUS_LOCKED (1 << 0)
87 #define PLAT_DDR3_STATUS_CALIBRATED (1 << 2)
88 #define PLAT_DDR3_INTERFACE_RESET (1 << 3)
89 PLAT_PCIE_STATUS = 0x18,
90 #define PLAT_PCIE_STATUS_PCIE0_LOCKED (1 << 0)
91 #define PLAT_PCIE_STATUS_PCIE1_LOCKED (1 << 8)
92 #define PLAT_PCIE_STATUS_PCIE2_LOCKED (1 << 16)
93 PLAT_FLASH_CTL = 0x1c,
94 PLAT_SPARE0 = 0x20,
95 PLAT_SPARE1 = 0x24,
96 PLAT_SPARE2 = 0x28,
97 PLAT_SPARE3 = 0x2c,
98 PLAT_MMCM_DIV = 0x30,
99 #define PLAT_MMCM_DIV_CLK0DIV_SHIFT 0
100 #define PLAT_MMCM_DIV_INPUT_SHIFT 8
101 #define PLAT_MMCM_DIV_MUL_SHIFT 16
102 #define PLAT_MMCM_DIV_CLK1DIV_SHIFT 24
103 PLAT_BUILD_CFG = 0x34,
104 #define PLAT_BUILD_CFG_IOCU_EN (1 << 0)
105 #define PLAT_BUILD_CFG_PCIE0_EN (1 << 1)
106 #define PLAT_BUILD_CFG_PCIE1_EN (1 << 2)
107 #define PLAT_BUILD_CFG_PCIE2_EN (1 << 3)
108 PLAT_DDR_CFG = 0x38,
109 #define PLAT_DDR_CFG_SIZE (0xf << 0)
110 #define PLAT_DDR_CFG_MHZ (0xfff << 4)
111 PLAT_NOC_PCIE0_ADDR = 0x3c,
112 PLAT_NOC_PCIE1_ADDR = 0x40,
113 PLAT_NOC_PCIE2_ADDR = 0x44,
114 PLAT_SYS_CTL = 0x48,
115 };
116
117 static void boston_lcd_event(void *opaque, QEMUChrEvent event)
118 {
119 BostonState *s = opaque;
120 if (event == CHR_EVENT_OPENED && !s->lcd_inited) {
121 qemu_chr_fe_printf(&s->lcd_display, " ");
122 s->lcd_inited = true;
123 }
124 }
125
126 static uint64_t boston_lcd_read(void *opaque, hwaddr addr,
127 unsigned size)
128 {
129 BostonState *s = opaque;
130 uint64_t val = 0;
131
132 switch (size) {
133 case 8:
134 val |= (uint64_t)s->lcd_content[(addr + 7) & 0x7] << 56;
135 val |= (uint64_t)s->lcd_content[(addr + 6) & 0x7] << 48;
136 val |= (uint64_t)s->lcd_content[(addr + 5) & 0x7] << 40;
137 val |= (uint64_t)s->lcd_content[(addr + 4) & 0x7] << 32;
138 /* fall through */
139 case 4:
140 val |= (uint64_t)s->lcd_content[(addr + 3) & 0x7] << 24;
141 val |= (uint64_t)s->lcd_content[(addr + 2) & 0x7] << 16;
142 /* fall through */
143 case 2:
144 val |= (uint64_t)s->lcd_content[(addr + 1) & 0x7] << 8;
145 /* fall through */
146 case 1:
147 val |= (uint64_t)s->lcd_content[(addr + 0) & 0x7];
148 break;
149 }
150
151 return val;
152 }
153
154 static void boston_lcd_write(void *opaque, hwaddr addr,
155 uint64_t val, unsigned size)
156 {
157 BostonState *s = opaque;
158
159 switch (size) {
160 case 8:
161 s->lcd_content[(addr + 7) & 0x7] = val >> 56;
162 s->lcd_content[(addr + 6) & 0x7] = val >> 48;
163 s->lcd_content[(addr + 5) & 0x7] = val >> 40;
164 s->lcd_content[(addr + 4) & 0x7] = val >> 32;
165 /* fall through */
166 case 4:
167 s->lcd_content[(addr + 3) & 0x7] = val >> 24;
168 s->lcd_content[(addr + 2) & 0x7] = val >> 16;
169 /* fall through */
170 case 2:
171 s->lcd_content[(addr + 1) & 0x7] = val >> 8;
172 /* fall through */
173 case 1:
174 s->lcd_content[(addr + 0) & 0x7] = val;
175 break;
176 }
177
178 qemu_chr_fe_printf(&s->lcd_display,
179 "\r%-8.8s", s->lcd_content);
180 }
181
182 static const MemoryRegionOps boston_lcd_ops = {
183 .read = boston_lcd_read,
184 .write = boston_lcd_write,
185 .endianness = DEVICE_LITTLE_ENDIAN,
186 };
187
188 static uint64_t boston_platreg_read(void *opaque, hwaddr addr,
189 unsigned size)
190 {
191 BostonState *s = opaque;
192 uint32_t gic_freq, val;
193
194 switch (addr & 0xffff) {
195 case PLAT_FPGA_BUILD:
196 case PLAT_CORE_CL:
197 case PLAT_WRAPPER_CL:
198 return 0;
199 case PLAT_DDR3_STATUS:
200 return PLAT_DDR3_STATUS_LOCKED | PLAT_DDR3_STATUS_CALIBRATED
201 | PLAT_DDR3_INTERFACE_RESET;
202 case PLAT_MMCM_DIV:
203 gic_freq = 25000000 / 1000000;
204 val = gic_freq << PLAT_MMCM_DIV_INPUT_SHIFT;
205 val |= 1 << PLAT_MMCM_DIV_MUL_SHIFT;
206 val |= 1 << PLAT_MMCM_DIV_CLK0DIV_SHIFT;
207 val |= 1 << PLAT_MMCM_DIV_CLK1DIV_SHIFT;
208 return val;
209 case PLAT_BUILD_CFG:
210 val = PLAT_BUILD_CFG_PCIE0_EN;
211 val |= PLAT_BUILD_CFG_PCIE1_EN;
212 val |= PLAT_BUILD_CFG_PCIE2_EN;
213 return val;
214 case PLAT_DDR_CFG:
215 val = s->mach->ram_size / GiB;
216 assert(!(val & ~PLAT_DDR_CFG_SIZE));
217 val |= PLAT_DDR_CFG_MHZ;
218 return val;
219 default:
220 qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx "\n",
221 addr & 0xffff);
222 return 0;
223 }
224 }
225
226 static void boston_platreg_write(void *opaque, hwaddr addr,
227 uint64_t val, unsigned size)
228 {
229 if (size != 4) {
230 qemu_log_mask(LOG_UNIMP, "%uB platform register write\n", size);
231 return;
232 }
233
234 switch (addr & 0xffff) {
235 case PLAT_FPGA_BUILD:
236 case PLAT_CORE_CL:
237 case PLAT_WRAPPER_CL:
238 case PLAT_DDR3_STATUS:
239 case PLAT_PCIE_STATUS:
240 case PLAT_MMCM_DIV:
241 case PLAT_BUILD_CFG:
242 case PLAT_DDR_CFG:
243 /* read only */
244 break;
245 case PLAT_SOFTRST_CTL:
246 if (val & PLAT_SOFTRST_CTL_SYSRESET) {
247 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
248 }
249 break;
250 default:
251 qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx
252 " = 0x%" PRIx64 "\n", addr & 0xffff, val);
253 break;
254 }
255 }
256
257 static const MemoryRegionOps boston_platreg_ops = {
258 .read = boston_platreg_read,
259 .write = boston_platreg_write,
260 .endianness = DEVICE_LITTLE_ENDIAN,
261 .impl = {
262 .min_access_size = 4,
263 .max_access_size = 4,
264 },
265 };
266
267 static const TypeInfo boston_device = {
268 .name = TYPE_MIPS_BOSTON_AIA,
269 .parent = TYPE_SYS_BUS_DEVICE,
270 .instance_size = sizeof(BostonState),
271 };
272
273 static void boston_register_types(void)
274 {
275 type_register_static(&boston_device);
276 }
277 type_init(boston_register_types)
278
279 #define NUM_INSNS 6
280 static void gen_firmware(uint32_t *p)
281 {
282 int i;
283 uint32_t reset_vec[NUM_INSNS] = {
284 /* CM relocate */
285 0x1fb802b7, /* li t0,0x1fb80000 */
286 0x16100337, /* li t1,0x16100000 */
287 0x0062b423, /* sd t1,8(t0) */
288 /* Jump to 0x80000000 */
289 0x00100293, /* li t0,1 */
290 0x01f29293, /* slli t0,t0,1f */
291 0x00028067 /* jr t0 */
292 };
293
294 for (i = 0; i < NUM_INSNS; i++) {
295 *p++ = reset_vec[i];
296 }
297 }
298
299 static inline XilinxPCIEHost *
300 xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr,
301 hwaddr cfg_base, uint64_t cfg_size,
302 hwaddr mmio_base, uint64_t mmio_size,
303 qemu_irq irq)
304 {
305 DeviceState *dev;
306 MemoryRegion *cfg, *mmio;
307
308 dev = qdev_new(TYPE_XILINX_PCIE_HOST);
309
310 qdev_prop_set_uint32(dev, "bus_nr", bus_nr);
311 qdev_prop_set_uint64(dev, "cfg_base", cfg_base);
312 qdev_prop_set_uint64(dev, "cfg_size", cfg_size);
313 qdev_prop_set_uint64(dev, "mmio_base", mmio_base);
314 qdev_prop_set_uint64(dev, "mmio_size", mmio_size);
315
316 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
317
318 cfg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
319 memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0);
320
321 mmio = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
322 memory_region_add_subregion_overlap(sys_mem, 0, mmio, 0);
323
324 qdev_connect_gpio_out_named(dev, "interrupt_out", 0, irq);
325
326 return XILINX_PCIE_HOST(dev);
327 }
328
329 static void boston_mach_init(MachineState *machine)
330 {
331 DeviceState *dev;
332 BostonState *s;
333 MemoryRegion *flash, *ddr_low_alias, *lcd, *platreg;
334 MemoryRegion *sys_mem = get_system_memory();
335 XilinxPCIEHost *pcie2;
336 PCIDevice *pdev;
337 AHCIPCIState *ich9;
338 DriveInfo *hd[6];
339 Chardev *chr;
340 int fw_size;
341
342 if ((machine->ram_size % GiB) ||
343 (machine->ram_size > (4 * GiB))) {
344 error_report("Memory size must be 1GB, 2GB, 3GB, or 4GB");
345 exit(1);
346 }
347
348 if (machine->smp.cpus / machine->smp.cores / machine->smp.threads > 1) {
349 error_report(
350 "Invalid -smp x,cores=y,threads=z. The max number of clusters "
351 "supported is 1");
352 exit(1);
353 }
354
355 dev = qdev_new(TYPE_MIPS_BOSTON_AIA);
356 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
357
358 s = BOSTON(dev);
359 s->mach = machine;
360
361 object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_RISCV_CPS);
362 object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type,
363 &error_fatal);
364 object_property_set_uint(OBJECT(&s->cps), "num-vp", machine->smp.cpus,
365 &error_fatal);
366 object_property_set_uint(OBJECT(&s->cps), "num-hart", machine->smp.threads,
367 &error_fatal);
368 object_property_set_uint(OBJECT(&s->cps), "num-core", machine->smp.cores,
369 &error_fatal);
370 object_property_set_uint(OBJECT(&s->cps), "gcr-base", GCR_BASE_ADDR,
371 &error_fatal);
372 sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal);
373
374 sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
375
376 flash = g_new(MemoryRegion, 1);
377 memory_region_init_rom(flash, NULL, "boston.flash",
378 boston_memmap[BOSTON_FLASH].size, &error_fatal);
379 memory_region_add_subregion_overlap(sys_mem,
380 boston_memmap[BOSTON_FLASH].base,
381 flash, 0);
382
383 memory_region_add_subregion_overlap(sys_mem,
384 boston_memmap[BOSTON_HIGHDDR].base,
385 machine->ram, 0);
386
387 ddr_low_alias = g_new(MemoryRegion, 1);
388 memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr",
389 machine->ram, 0,
390 MIN(machine->ram_size, (256 * MiB)));
391 memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0);
392
393 pcie2 = xilinx_pcie_init(sys_mem, 2,
394 boston_memmap[BOSTON_PCIE2].base,
395 boston_memmap[BOSTON_PCIE2].size,
396 boston_memmap[BOSTON_PCIE2_MMIO].base,
397 boston_memmap[BOSTON_PCIE2_MMIO].size,
398 qdev_get_gpio_in(s->cps.aplic, PCIE2_INT));
399
400 platreg = g_new(MemoryRegion, 1);
401 memory_region_init_io(platreg, NULL, &boston_platreg_ops, s,
402 "boston-platregs",
403 boston_memmap[BOSTON_PLATREG].size);
404 memory_region_add_subregion_overlap(sys_mem,
405 boston_memmap[BOSTON_PLATREG].base, platreg, 0);
406
407 s->uart = serial_mm_init(sys_mem, boston_memmap[BOSTON_UART].base, 2,
408 qdev_get_gpio_in(s->cps.aplic, UART_INT), 10000000,
409 serial_hd(0), DEVICE_LITTLE_ENDIAN);
410
411 lcd = g_new(MemoryRegion, 1);
412 memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8);
413 memory_region_add_subregion_overlap(sys_mem,
414 boston_memmap[BOSTON_LCD].base, lcd, 0);
415
416 chr = qemu_chr_new("lcd", "vc:320x240", NULL);
417 qemu_chr_fe_init(&s->lcd_display, chr, NULL);
418 qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
419 boston_lcd_event, NULL, s, NULL, true);
420
421 pdev = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus,
422 PCI_DEVFN(0, 0), TYPE_ICH9_AHCI);
423 ich9 = ICH9_AHCI(pdev);
424 g_assert(ARRAY_SIZE(hd) == ich9->ahci.ports);
425 ide_drive_get(hd, ich9->ahci.ports);
426 ahci_ide_create_devs(&ich9->ahci, hd);
427
428 /* Create e1000e using slot 0 func 1 */
429 pci_init_nic_in_slot(&PCI_BRIDGE(&pcie2->root)->sec_bus, "e1000e", NULL,
430 "00.1");
431 pci_init_nic_devices(&PCI_BRIDGE(&pcie2->root)->sec_bus, "e1000e");
432
433 if (machine->firmware) {
434 fw_size = load_image_targphys(machine->firmware,
435 0x1fc00000, 4 * MiB, NULL);
436 if (fw_size == -1) {
437 error_report("unable to load firmware image '%s'",
438 machine->firmware);
439 exit(1);
440 }
441 if (machine->kernel_filename) {
442 fw_size = load_image_targphys(machine->kernel_filename,
443 0x80000000, 64 * MiB, NULL);
444 if (fw_size == -1) {
445 error_report("unable to load kernel image '%s'",
446 machine->kernel_filename);
447 exit(1);
448 }
449 }
450 } else if (machine->kernel_filename) {
451 fw_size = load_image_targphys(machine->kernel_filename,
452 0x80000000, 64 * MiB, NULL);
453 if (fw_size == -1) {
454 error_report("unable to load kernel image '%s'",
455 machine->kernel_filename);
456 exit(1);
457 }
458
459 gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000);
460 } else if (!qtest_enabled()) {
461 error_report("Please provide either a -kernel or -bios argument");
462 exit(1);
463 }
464 }
465
466 static void boston_mach_class_init(MachineClass *mc)
467 {
468 mc->desc = "MIPS Boston-aia";
469 mc->init = boston_mach_init;
470 mc->block_default_type = IF_IDE;
471 mc->default_ram_size = 2 * GiB;
472 mc->default_ram_id = "boston.ddr";
473 mc->max_cpus = MAX_HARTS;
474 mc->default_cpu_type = TYPE_RISCV_CPU_MIPS_P8700;
475 }
476
477 DEFINE_MACHINE_RISCV64("boston-aia", boston_mach_class_init)