Lines Matching +full:fpga +full:- +full:based

2  * Arm MPS3 board emulation for Cortex-R-based FPGA images.
3 * (For M-profile images see mps2.c and mps2tz.c.)
14 * The MPS3 is an FPGA based dev board. This file handles FPGA images
15 * which use the Cortex-R CPUs. We model these separately from the
16 * M-profile images, because on M-profile the FPGA image is based on
18 * the R-profile FPGA images don't have that abstraction layer.
20 * We model the following FPGA images here:
21 * "mps3-an536" -- dual Cortex-R52 as documented in Arm Application Note AN536
31 #include "system/address-spaces.h"
35 #include "hw/or-irq.h"
36 #include "hw/qdev-clock.h"
37 #include "hw/qdev-properties.h"
40 #include "hw/char/cmsdk-apb-uart.h"
43 #include "hw/misc/mps2-scc.h"
44 #include "hw/misc/mps2-fpgaio.h"
49 #include "hw/timer/cmsdk-apb-dualtimer.h"
50 #include "hw/watchdog/cmsdk-apb-watchdog.h"
57 int mrindex; /* index into rams[]; -1 for the system RAM block */
62 * The MPS3 DDR is 3GiB, but on a 32-bit host QEMU doesn't permit
74 * IS_ROM: this area is read-only
106 /* per-CPU UARTs followed by the shared UARTs */
122 #define TYPE_MPS3R_AN536_MACHINE MACHINE_TYPE_NAME("mps3-an536")
155 .mrindex = -1,
207 if (raminfo->mrindex < 0) { in mr_for_raminfo()
210 assert(!(raminfo->flags & IS_ROM)); in mr_for_raminfo()
211 return machine->ram; in mr_for_raminfo()
214 assert(raminfo->mrindex < MPS3R_RAM_MAX); in mr_for_raminfo()
215 ram = &mms->ram[raminfo->mrindex]; in mr_for_raminfo()
217 memory_region_init_ram(ram, NULL, raminfo->name, in mr_for_raminfo()
218 raminfo->size, &error_fatal); in mr_for_raminfo()
219 if (raminfo->flags & IS_ROM) { in mr_for_raminfo()
231 * put the secondary CPU into power-off state (as if the user on the
250 object_property_set_bool(OBJECT(cs), "start-powered-off", true, in mps3r_write_secondary_boot()
268 object_initialize_child(OBJECT(mms), "gic", &mms->gic, TYPE_ARM_GICV3); in create_gic()
269 gicdev = DEVICE(&mms->gic); in create_gic()
270 qdev_prop_set_uint32(gicdev, "num-cpu", machine->smp.cpus); in create_gic()
271 qdev_prop_set_uint32(gicdev, "num-irq", NUM_SPIS + GIC_INTERNAL); in create_gic()
273 qlist_append_int(redist_region_count, machine->smp.cpus); in create_gic()
274 qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count); in create_gic()
275 object_property_set_link(OBJECT(&mms->gic), "sysmem", in create_gic()
277 sysbus_realize(SYS_BUS_DEVICE(&mms->gic), &error_fatal); in create_gic()
278 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->gic), 0, PERIPHBASE); in create_gic()
279 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->gic), 1, PERIPHBASE + 0x100000); in create_gic()
285 for (int i = 0; i < machine->smp.cpus; i++) { in create_gic()
286 DeviceState *cpudev = DEVICE(mms->cpu[i]); in create_gic()
287 SysBusDevice *gicsbd = SYS_BUS_DEVICE(&mms->gic); in create_gic()
307 qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, in create_gic()
311 qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, in create_gic()
317 sysbus_connect_irq(gicsbd, i + machine->smp.cpus, in create_gic()
319 sysbus_connect_irq(gicsbd, i + 2 * machine->smp.cpus, in create_gic()
321 sysbus_connect_irq(gicsbd, i + 3 * machine->smp.cpus, in create_gic()
338 assert(uartno < ARRAY_SIZE(mms->uart)); in create_uart()
339 object_initialize_child(OBJECT(mms), s, &mms->uart[uartno], in create_uart()
341 qdev_prop_set_uint32(DEVICE(&mms->uart[uartno]), "pclk-frq", CLK_FRQ); in create_uart()
342 qdev_prop_set_chr(DEVICE(&mms->uart[uartno]), "chardev", serial_hd(uartno)); in create_uart()
343 sbd = SYS_BUS_DEVICE(&mms->uart[uartno]); in create_uart()
362 mms->clk = clock_new(OBJECT(machine), "CLK"); in mps3r_common_init()
363 clock_set_hz(mms->clk, CLK_FRQ); in mps3r_common_init()
365 for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) { in mps3r_common_init()
367 memory_region_add_subregion(sysmem, ri->base, mr); in mps3r_common_init()
370 assert(machine->smp.cpus <= MPS3R_CPU_MAX); in mps3r_common_init()
371 for (int i = 0; i < machine->smp.cpus; i++) { in mps3r_common_init()
372 g_autofree char *sysmem_name = g_strdup_printf("cpu-%d-memory", i); in mps3r_common_init()
373 g_autofree char *ramname = g_strdup_printf("cpu-%d-memory", i); in mps3r_common_init()
374 g_autofree char *alias_name = g_strdup_printf("sysmem-alias-%d", i); in mps3r_common_init()
378 * which will house those, with the whole-machine system memory being in mps3r_common_init()
379 * used where there's no CPU-specific device. Note that we need the in mps3r_common_init()
383 memory_region_init(&mms->cpu_sysmem[i], OBJECT(machine), in mps3r_common_init()
385 memory_region_init_alias(&mms->sysmem_alias[i], OBJECT(machine), in mps3r_common_init()
387 memory_region_add_subregion_overlap(&mms->cpu_sysmem[i], 0, in mps3r_common_init()
388 &mms->sysmem_alias[i], -1); in mps3r_common_init()
390 mms->cpu[i] = object_new(machine->cpu_type); in mps3r_common_init()
391 object_property_set_link(mms->cpu[i], "memory", in mps3r_common_init()
392 OBJECT(&mms->cpu_sysmem[i]), &error_abort); in mps3r_common_init()
393 object_property_set_int(mms->cpu[i], "reset-cbar", in mps3r_common_init()
395 qdev_realize(DEVICE(mms->cpu[i]), NULL, &error_fatal); in mps3r_common_init()
396 object_unref(mms->cpu[i]); in mps3r_common_init()
398 /* Per-CPU RAM */ in mps3r_common_init()
399 memory_region_init_ram(&mms->cpu_ram[i], NULL, ramname, in mps3r_common_init()
401 memory_region_add_subregion(&mms->cpu_sysmem[i], 0xe7c01000, in mps3r_common_init()
402 &mms->cpu_ram[i]); in mps3r_common_init()
406 gicdev = DEVICE(&mms->gic); in mps3r_common_init()
409 * UARTs 0 and 1 are per-CPU; their interrupts are wired to in mps3r_common_init()
412 for (int i = 0; i < machine->smp.cpus; i++) { in mps3r_common_init()
414 g_autofree char *s = g_strdup_printf("cpu-uart-oflow-orgate%d", i); in mps3r_common_init()
418 object_initialize_child(OBJECT(mms), s, &mms->cpu_uart_oflow[i], in mps3r_common_init()
420 orgate = DEVICE(&mms->cpu_uart_oflow[i]); in mps3r_common_init()
421 qdev_prop_set_uint32(orgate, "num-lines", 2); in mps3r_common_init()
426 create_uart(mms, i, &mms->cpu_sysmem[i], 0xe7c00000, in mps3r_common_init()
434 * UARTs 2 to 5 are whole-system; all overflow IRQs are ORed in mps3r_common_init()
437 object_initialize_child(OBJECT(mms), "uart-oflow-orgate", in mps3r_common_init()
438 &mms->uart_oflow, TYPE_OR_IRQ); in mps3r_common_init()
439 qdev_prop_set_uint32(DEVICE(&mms->uart_oflow), "num-lines", in mps3r_common_init()
441 qdev_realize(DEVICE(&mms->uart_oflow), NULL, &error_fatal); in mps3r_common_init()
442 qdev_connect_gpio_out(DEVICE(&mms->uart_oflow), 0, in mps3r_common_init()
452 qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2), in mps3r_common_init()
453 qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2 + 1), in mps3r_common_init()
463 object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog, in mps3r_common_init()
465 qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->clk); in mps3r_common_init()
466 sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal); in mps3r_common_init()
467 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0, in mps3r_common_init()
469 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0xe0100000); in mps3r_common_init()
471 object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer, in mps3r_common_init()
473 qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->clk); in mps3r_common_init()
474 sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal); in mps3r_common_init()
475 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0, in mps3r_common_init()
477 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 1, in mps3r_common_init()
479 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 2, in mps3r_common_init()
481 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0xe0101000); in mps3r_common_init()
483 for (int i = 0; i < ARRAY_SIZE(mms->i2c); i++) { in mps3r_common_init()
491 object_initialize_child(OBJECT(mms), s, &mms->i2c[i], in mps3r_common_init()
493 sysbus_realize(SYS_BUS_DEVICE(&mms->i2c[i]), &error_fatal); in mps3r_common_init()
494 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->i2c[i]), 0, i2cbase[i]); in mps3r_common_init()
497 * internal-only bus: mark it full to avoid user-created in mps3r_common_init()
500 qbus_mark_full(qdev_get_child_bus(DEVICE(&mms->i2c[i]), "i2c")); in mps3r_common_init()
504 for (int i = 0; i < ARRAY_SIZE(mms->spi); i++) { in mps3r_common_init()
508 object_initialize_child(OBJECT(mms), s, &mms->spi[i], TYPE_PL022); in mps3r_common_init()
509 sysbus_realize(SYS_BUS_DEVICE(&mms->spi[i]), &error_fatal); in mps3r_common_init()
510 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->spi[i]), 0, baseaddr); in mps3r_common_init()
511 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->spi[i]), 0, in mps3r_common_init()
515 object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC); in mps3r_common_init()
516 qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg0", 0); in mps3r_common_init()
517 qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg4", 0x2); in mps3r_common_init()
518 qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-aid", 0x00200008); in mps3r_common_init()
519 qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-id", 0x41055360); in mps3r_common_init()
524 qdev_prop_set_array(DEVICE(&mms->scc), "oscclk", oscclk); in mps3r_common_init()
525 sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal); in mps3r_common_init()
526 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->scc), 0, 0xe0200000); in mps3r_common_init()
528 create_unimplemented_device("i2s-audio", 0xe0201000, 0x1000); in mps3r_common_init()
530 object_initialize_child(OBJECT(mms), "fpgaio", &mms->fpgaio, in mps3r_common_init()
532 qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", an536_oscclk[1]); in mps3r_common_init()
533 qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "num-leds", 10); in mps3r_common_init()
534 qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-switches", true); in mps3r_common_init()
535 qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-dbgctrl", false); in mps3r_common_init()
536 sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal); in mps3r_common_init()
537 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0xe0202000); in mps3r_common_init()
541 object_initialize_child(OBJECT(mms), "rtc", &mms->rtc, TYPE_PL031); in mps3r_common_init()
542 sysbus_realize(SYS_BUS_DEVICE(&mms->rtc), &error_fatal); in mps3r_common_init()
543 sysbus_mmio_map(SYS_BUS_DEVICE(&mms->rtc), 0, 0xe020a000); in mps3r_common_init()
544 sysbus_connect_irq(SYS_BUS_DEVICE(&mms->rtc), 0, in mps3r_common_init()
549 * except that it doesn't support the checksum-offload feature. in mps3r_common_init()
555 create_unimplemented_device("qspi-write-config", 0xe0600000, 0x1000); in mps3r_common_init()
557 mms->bootinfo.ram_size = machine->ram_size; in mps3r_common_init()
558 mms->bootinfo.board_id = -1; in mps3r_common_init()
559 mms->bootinfo.loader_start = mmc->loader_start; in mps3r_common_init()
560 mms->bootinfo.write_secondary_boot = mps3r_write_secondary_boot; in mps3r_common_init()
561 mms->bootinfo.secondary_cpu_reset_hook = mps3r_secondary_cpu_reset; in mps3r_common_init()
562 arm_load_kernel(ARM_CPU(mms->cpu[0]), machine, &mms->bootinfo); in mps3r_common_init()
568 * Set mc->default_ram_size and default_ram_id from the in mps3r_set_default_ram_info()
569 * information in mmc->raminfo. in mps3r_set_default_ram_info()
574 for (p = mmc->raminfo; p->name; p++) { in mps3r_set_default_ram_info()
575 if (p->mrindex < 0) { in mps3r_set_default_ram_info()
577 mc->default_ram_size = p->size; in mps3r_set_default_ram_info()
578 mc->default_ram_id = p->name; in mps3r_set_default_ram_info()
579 mmc->loader_start = p->base; in mps3r_set_default_ram_info()
590 mc->init = mps3r_common_init; in mps3r_class_init()
598 ARM_CPU_TYPE_NAME("cortex-r52"), in mps3r_an536_class_init()
602 mc->desc = "ARM MPS3 with AN536 FPGA image for Cortex-R52"; in mps3r_an536_class_init()
604 * In the real FPGA image there are always two cores, but the standard in mps3r_an536_class_init()
608 * since on the real FPGA image it is not possible to use LDREX/STREX in mps3r_an536_class_init()
611 * As QEMU's equivalent of this, we support both -smp 1 and -smp 2, in mps3r_an536_class_init()
612 * with the default being -smp 1. This seems a more intuitive UI for in mps3r_an536_class_init()
616 mc->default_cpus = 1; in mps3r_an536_class_init()
617 mc->min_cpus = 1; in mps3r_an536_class_init()
618 mc->max_cpus = 2; in mps3r_an536_class_init()
619 mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-r52"); in mps3r_an536_class_init()
620 mc->valid_cpu_types = valid_cpu_types; in mps3r_an536_class_init()
621 mmc->raminfo = an536_raminfo; in mps3r_an536_class_init()