/* * ARM Versatile Express emulation. * * Copyright (c) 2010 - 2011 B Labs Ltd. * Copyright (c) 2011 Linaro Limited * Written by Bahadir Balban, Amit Mahajan, Peter Maydell * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . * * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/datadir.h" #include "cpu.h" #include "hw/sysbus.h" #include "hw/arm/boot.h" #include "hw/arm/primecell.h" #include "net/net.h" #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/loader.h" #include "sysemu/device_tree.h" #include "qemu/error-report.h" #include #include "hw/char/bcm2835_aux.h" // #include "hw/cpu/a9mpcore.h" #include "hw/sd/sd.h" #include "qom/object.h" #include "kvm_arm.h" /* Number of virtio transports to create (0..8; limited by * number of available IRQ lines). */ #define NUM_VIRTIO_TRANSPORTS 4 /* Address maps for peripherals: * the Versatile Express motherboard has two possible maps, * the "legacy" one (used for A9) and the "Cortex-A Series" * map (used for newer cores). * Individual daughterboards can also have different maps for * their peripherals. */ enum { VE_NORFLASH0, VE_SYSREGS, VE_UART0, VE_UART1, VE_TIMER01, VE_SRAM, VE_VIRTIO }; static hwaddr motherboard_aseries_map[] = { [VE_NORFLASH0] = 0x00000000, [VE_SYSREGS] = 0x01000000, [VE_UART0] = 0x021C0000, [VE_UART1] = 0x021D0000, [VE_TIMER01] = 0x01EE1000, [VE_SRAM] = 0x80000000, }; typedef struct LSDBoardInfo LSDBoardInfo; struct LayerscpMachineClass { MachineClass parent; LSDBoardInfo *daughterboard; }; struct LayerscpMachineState { MachineState parent; bool secure; bool virt; uint32_t gic_version; }; #define TYPE_LS1046A_MACHINE "ls1046a" #define TYPE_LS1046A_1_MACHINE MACHINE_TYPE_NAME("ls1046a-1") //#define LS1046A_MACHINE_CLASS(klass) OBJECT_CLASS_CHECK(LayerscpMachineClass, klass, TYPE_LS1046A_MACHINE) OBJECT_DECLARE_TYPE(LayerscpMachineState, LayerscpMachineClass, LS1046A_MACHINE) typedef void DBoardInitFn(const LayerscpMachineState *machine, ram_addr_t ram_size, const char *cpu_type, qemu_irq *gic); struct LSDBoardInfo { struct arm_boot_info bootinfo; const hwaddr *motherboard_map; hwaddr loader_start; const hwaddr gic_cpu_if_addr; uint32_t proc_id; uint32_t num_voltage_sensors; const uint32_t *voltages; uint32_t num_clocks; const uint32_t *clocks; DBoardInitFn *init; }; static void init_cpus(MachineState *ms, const char *cpu_type, const char *privdev, hwaddr periphbase, qemu_irq *gic, bool secure, bool virt) { DeviceState *dev; SysBusDevice *busdev; int n; unsigned int smp_cpus = ms->smp.cpus; const char *gictype; //gictype = gicv3_class_name(); /* Create the actual CPUs */ printf("smp_cpus: %u\n", smp_cpus); printf("cpu_type: %s\n", cpu_type); for (n = 0; n < smp_cpus; n++) { Object *cpuobj = object_new(cpu_type); if (!secure) { object_property_set_bool(cpuobj, "has_el3", false, NULL); } if (!virt) { if (object_property_find(cpuobj, "has_el2")) { object_property_set_bool(cpuobj, "has_el2", false, NULL); } } if (object_property_find(cpuobj, "reset-cbar")) { object_property_set_int(cpuobj, "reset-cbar", periphbase, &error_abort); } qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); } /* Create the private peripheral devices (including the GIC); * this must happen after the CPUs are created because a15mpcore_priv * wires itself up to the CPU's generic_timer gpio out lines. */ dev = qdev_new(privdev); //dev = qdev_new(gictype);; qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); busdev = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, periphbase); ///* Connect the CPUs to the GIC */ //for (n = 0; n < smp_cpus; n++) { // DeviceState *cpudev = DEVICE(qemu_get_cpu(n)); // // sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); // sysbus_connect_irq(busdev, n + smp_cpus, // qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); // sysbus_connect_irq(busdev, n + 2 * smp_cpus, // qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); // sysbus_connect_irq(busdev, n + 3 * smp_cpus, // qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); //} } static void a72_daughterboard_init(const LayerscpMachineState *vms, ram_addr_t ram_size, const char *cpu_type, qemu_irq *gic) { MachineState *machine = MACHINE(vms); MemoryRegion *sysmem = get_system_memory(); MemoryRegion *lowram = g_new(MemoryRegion, 1); ram_addr_t low_ram_size; if (ram_size > 0x80000000U) { /* 2GB is the maximum the address space permits */ error_report("ls1046a-a72: cannot model more than 2GB RAM"); exit(1); } low_ram_size = ram_size; if (low_ram_size > 0x80000000U) { low_ram_size = 0x80000000U; } /* RAM is from 0x60000000 upwards. The bottom 64MB of the * address space should in theory be remappable to various * things including ROM or RAM; we always map the RAM there. */ memory_region_init_alias(lowram, NULL, "ls1046a.lowmem", machine->ram, 0, low_ram_size); memory_region_add_subregion(sysmem, 0x0, lowram); memory_region_add_subregion(sysmem, 0x80000000, machine->ram); /* 0x1400000 private memory region */ init_cpus(machine, cpu_type, "a9mpcore_priv", 0x1400000, gic, vms->secure, vms->virt); /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */ /* 0x10020000 PL111 CLCD (daughterboard) */ // sysbus_create_simple("pl111", 0x10020000, gic[44]); /* 0x10060000 AXI RAM */ /* 0x100e0000 PL341 Dynamic Memory Controller */ /* 0x100e1000 PL354 Static Memory Controller */ /* 0x100e2000 System Configuration Controller */ // sysbus_create_simple("sp804", 0x100e4000, gic[48]); /* 0x100e5000 SP805 Watchdog module */ /* 0x100e6000 BP147 TrustZone Protection Controller */ /* 0x100e9000 PL301 'Fast' AXI matrix */ /* 0x100ea000 PL301 'Slow' AXI matrix */ /* 0x100ec000 TrustZone Address Space Controller */ /* 0x10200000 CoreSight debug APB */ /* 0x1e00a000 PL310 L2 Cache Controller */ // sysbus_create_varargs("l2x0", 0x1e00a000, NULL); } /* Voltage values for SYS_CFG_VOLT daughterboard registers; * values are in microvolts. */ static const uint32_t a72_voltages[] = { 1000000, /* VD10 : 1.0V : SoC internal logic voltage */ 1000000, /* VD10_S2 : 1.0V : PL310, L2 cache, RAM, non-PL310 logic */ 1000000, /* VD10_S3 : 1.0V : Cortex-A9, cores, MPEs, SCU, PL310 logic */ 1800000, /* VCC1V8 : 1.8V : DDR2 SDRAM, test chip DDR2 I/O supply */ 900000, /* DDR2VTT : 0.9V : DDR2 SDRAM VTT termination voltage */ 3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */ }; /* Reset values for daughterboard oscillators (in Hz) */ static const uint32_t a72_clocks[] = { 45000000, /* AMBA AXI ACLK: 45MHz */ 23750000, /* daughterboard CLCD clock: 23.75MHz */ 66670000, /* Test chip reference clock: 66.67MHz */ }; static LSDBoardInfo a72_daughterboard = { .motherboard_map = motherboard_aseries_map, .loader_start = 0x80004000, .gic_cpu_if_addr = 0x01420000, .proc_id = 0x0c000191, .num_voltage_sensors = ARRAY_SIZE(a72_voltages), .voltages = a72_voltages, .num_clocks = ARRAY_SIZE(a72_clocks), .clocks = a72_clocks, .init = a72_daughterboard_init, }; static int add_virtio_mmio_node(void *fdt, uint32_t acells, uint32_t scells, hwaddr addr, hwaddr size, uint32_t intc, int irq) { /* Add a virtio_mmio node to the device tree blob: * virtio_mmio@ADDRESS { * compatible = "virtio,mmio"; * reg = ; * interrupt-parent = <&intc>; * interrupts = <0, irq, 1>; * } * (Note that the format of the interrupts property is dependent on the * interrupt controller that interrupt-parent points to; these are for * the ARM GIC and indicate an SPI interrupt, rising-edge-triggered.) */ int rc; char *nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, addr); rc = qemu_fdt_add_subnode(fdt, nodename); rc |= qemu_fdt_setprop_string(fdt, nodename, "compatible", "virtio,mmio"); rc |= qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells, addr, scells, size); qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", intc); qemu_fdt_setprop_cells(fdt, nodename, "interrupts", 0, irq, 1); qemu_fdt_setprop(fdt, nodename, "dma-coherent", NULL, 0); g_free(nodename); if (rc) { return -1; } return 0; } static uint32_t find_int_controller(void *fdt) { /* Find the FDT node corresponding to the interrupt controller * for virtio-mmio devices. We do this by scanning the fdt for * a node with the right compatibility, since we know there is * only one GIC on a ls1046a board. * We return the phandle of the node, or 0 if none was found. */ const char *compat = "arm,cortex-a72-gic"; int offset; offset = fdt_node_offset_by_compatible(fdt, -1, compat); if (offset >= 0) { return fdt_get_phandle(fdt, offset); } return 0; } static void ls1046a_modify_dtb(const struct arm_boot_info *info, void *fdt) { uint32_t acells, scells, intc; const LSDBoardInfo *daughterboard = (const LSDBoardInfo *)info; acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells", NULL, &error_fatal); scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells", NULL, &error_fatal); intc = find_int_controller(fdt); if (!intc) { /* Not fatal, we just won't provide virtio. This will * happen with older device tree blobs. */ warn_report("couldn't find interrupt controller in " "dtb; will not include virtio-mmio devices in the dtb"); } else { int i; const hwaddr *map = daughterboard->motherboard_map; /* We iterate backwards here because adding nodes * to the dtb puts them in last-first. */ // for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) { // add_virtio_mmio_node(fdt, acells, scells, // map[VE_VIRTIO] + 0x200 * i, // 0x200, intc, 40 + i); // } } } static void ls1046a_common_init(MachineState *machine) { LayerscpMachineState *vms = LS1046A_MACHINE(machine); LayerscpMachineClass *vmc = LS1046A_MACHINE_GET_CLASS(machine); LSDBoardInfo *daughterboard = vmc->daughterboard; DeviceState *dev, *sysctl, *serdev; qemu_irq pic[64]; qemu_irq gic[64]; ram_addr_t sram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *sram = g_new(MemoryRegion, 1); const hwaddr *map = daughterboard->motherboard_map; int i; daughterboard->init(vms, machine->ram_size, machine->cpu_type, pic); /* * If a bios file was provided, attempt to map it into memory */ if (machine->firmware) { char *fn; int image_size; if (drive_get(IF_PFLASH, 0, 0)) { error_report("The contents of the first flash device may be " "specified with -bios or with -drive if=pflash... " "but you cannot use both options at once"); exit(1); } fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!fn) { error_report("Could not find ROM image '%s'", machine->firmware); exit(1); } // image_size = load_image_targphys(fn, map[VE_NORFLASH0], // LS1046A_FLASH_SIZE); // g_free(fn); // if (image_size < 0) { // error_report("Could not load ROM image '%s'", machine->firmware); // exit(1); // } } sysbus_realize_and_unref(SYS_BUS_DEVICE(sysctl), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); serdev = qdev_new("duart1"); // pl011_create(, gic[5], serial_hd(0)); sysbus_mmio_map(SYS_BUS_DEVICE(serdev), 0, map[VE_UART0]); // sysbus_mmio_map(SYS_BUS_DEVICE(serdev), 0, map[VE_UART1]); // pl011_create(map[VE_UART1], gic[6], serial_hd(1)); sysbus_create_simple("sp804", map[VE_TIMER01], gic[2]); sram_size = 0x80000000; memory_region_init_ram(sram, NULL, "ls1046a.sram", sram_size, &error_fatal); memory_region_add_subregion(sysmem, map[VE_SRAM], sram); /* VE_USB: not modelled */ /* VE_DAPROM: not modelled */ /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. */ // for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) { // sysbus_create_simple("virtio-mmio", map[VE_VIRTIO] + 0x200 * i, // gic[40 + i]); // } daughterboard->bootinfo.ram_size = machine->ram_size; daughterboard->bootinfo.board_id = 0x12345678; daughterboard->bootinfo.loader_start = daughterboard->loader_start; daughterboard->bootinfo.smp_loader_start = map[VE_SRAM]; daughterboard->bootinfo.smp_bootreg_addr = map[VE_SRAM] + 0x4000; daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr; daughterboard->bootinfo.modify_dtb = ls1046a_modify_dtb; /* When booting Linux we should be in secure state if the CPU has one. */ daughterboard->bootinfo.secure_boot = vms->secure; arm_load_kernel(ARM_CPU(first_cpu), machine, &daughterboard->bootinfo); } static bool ls1046a_get_secure(Object *obj, Error **errp) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); return vms->secure; } static void ls1046a_set_secure(Object *obj, bool value, Error **errp) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); vms->secure = value; } static void ls1046a_set_gic_version(Object *obj, const char *value, Error **errp) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); if (!strcmp(value, "4")) { vms->gic_version = 4; } else if (!strcmp(value, "3")) { vms->gic_version = 3; } else if (!strcmp(value, "2")) { vms->gic_version = 2; } else if (!strcmp(value, "host")) { vms->gic_version = 1; /* Will probe later */ } else if (!strcmp(value, "max")) { vms->gic_version = 0; /* Will probe later */ } else { error_setg(errp, "Invalid gic-version value"); error_append_hint(errp, "Valid values are 3, 2, host, max.\n"); } } static bool ls1046a_get_virt(Object *obj, Error **errp) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); return vms->virt; } static void ls1046a_set_virt(Object *obj, bool value, Error **errp) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); vms->virt = value; } static void layerscape_instance_init(Object *obj) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); /* EL3 is enabled by default on ls1046a */ vms->secure = true; vms->virt = true; //vms->gic = 3; } static void ls1046a_instance_init(Object *obj) { LayerscpMachineState *vms = LS1046A_MACHINE(obj); /* EL3 is enabled by default on ls1046a */ vms->secure = true; vms->virt = true; //vms->gic = 3; } static void layerscape_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "ARM Real Time Experiment (RTX)"; mc->init = ls1046a_common_init; mc->max_cpus = 4; // single core mc->ignore_memory_transaction_failures = true; mc->default_ram_id = "ls1046a.highmem"; } static void ls1046a_class_init(ObjectClass *oc, void *data) { const char gic_ver[2] = "2"; MachineClass *mc = MACHINE_CLASS(oc); LayerscpMachineClass *vmc = LS1046A_MACHINE_CLASS(oc); mc->desc = "Layerscape 1046ARDB"; mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a72"); vmc->daughterboard = &a72_daughterboard; } static const TypeInfo layerscape_info = { .name = TYPE_LS1046A_MACHINE, .parent = TYPE_MACHINE, .abstract = true, .instance_size = sizeof(LayerscpMachineState), .instance_init = layerscape_instance_init, .class_size = sizeof(LayerscpMachineClass), .class_init = layerscape_class_init, }; static const TypeInfo ls1046a_info = { .name = TYPE_LS1046A_1_MACHINE, .parent = TYPE_LS1046A_MACHINE, //.parent = TYPE_MACHINE, .instance_init = ls1046a_instance_init, .class_init = ls1046a_class_init, }; static void ls1046a_machine_init(void) { type_register_static(&layerscape_info); type_register_static(&ls1046a_info); } type_init(ls1046a_machine_init);