static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque, const char *name, hwaddr size) { CMSDKAPBUART *uart = opaque; int i = uart - &mms->uart[0]; int rxirqno = i * 2; int txirqno = i * 2 + 1; int combirqno = i + 10; SysBusDevice *s; DeviceState *iotkitdev = DEVICE(&mms->iotkit); DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate); sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART); qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ); object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal); s = SYS_BUS_DEVICE(uart); sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", txirqno)); sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", rxirqno)); sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2)); sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1)); sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", combirqno)); return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); }
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, const char *name, hwaddr size) { PL080State *dma = opaque; int i = dma - &mms->dma[0]; SysBusDevice *s; char *mscname = g_strdup_printf("%s-msc", name); TZMSC *msc = &mms->msc[i]; DeviceState *iotkitdev = DEVICE(&mms->iotkit); MemoryRegion *msc_upstream; MemoryRegion *msc_downstream; /* * Each DMA device is a PL081 whose transaction master interface * is guarded by a Master Security Controller. The downstream end of * the MSC connects to the IoTKit AHB Slave Expansion port, so the * DMA devices can see all devices and memory that the CPU does. */ sysbus_init_child_obj(OBJECT(mms), mscname, msc, sizeof(*msc), TYPE_TZ_MSC); msc_downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit), 0); object_property_set_link(OBJECT(msc), OBJECT(msc_downstream), "downstream", &error_fatal); object_property_set_link(OBJECT(msc), OBJECT(mms), "idau", &error_fatal); object_property_set_bool(OBJECT(msc), true, "realized", &error_fatal); qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0, qdev_get_gpio_in_named(iotkitdev, "mscexp_status", i)); qdev_connect_gpio_out_named(iotkitdev, "mscexp_clear", i, qdev_get_gpio_in_named(DEVICE(msc), "irq_clear", 0)); qdev_connect_gpio_out_named(iotkitdev, "mscexp_ns", i, qdev_get_gpio_in_named(DEVICE(msc), "cfg_nonsec", 0)); qdev_connect_gpio_out(DEVICE(&mms->sec_resp_splitter), ARRAY_SIZE(mms->ppc) + i, qdev_get_gpio_in_named(DEVICE(msc), "cfg_sec_resp", 0)); msc_upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0); sysbus_init_child_obj(OBJECT(mms), name, dma, sizeof(*dma), TYPE_PL081); object_property_set_link(OBJECT(dma), OBJECT(msc_upstream), "downstream", &error_fatal); object_property_set_bool(OBJECT(dma), true, "realized", &error_fatal); s = SYS_BUS_DEVICE(dma); /* Wire up DMACINTR, DMACINTERR, DMACINTTC */ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3)); sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3)); sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3)); g_free(mscname); return sysbus_mmio_get_region(s, 0); }
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno) { /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); assert(irqno < MPS2TZ_NUMIRQ); switch (mmc->fpga_type) { case FPGA_AN505: return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno); case FPGA_AN521: return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0); default: g_assert_not_reached(); } }
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque, const char *name, hwaddr size) { SysBusDevice *s; DeviceState *iotkitdev = DEVICE(&mms->iotkit); NICInfo *nd = &nd_table[0]; /* In hardware this is a LAN9220; the LAN9118 is software compatible * except that it doesn't support the checksum-offload feature. */ qemu_check_nic_model(nd, "lan9118"); mms->lan9118 = qdev_create(NULL, "lan9118"); qdev_set_nic_properties(mms->lan9118, nd); qdev_init_nofail(mms->lan9118); s = SYS_BUS_DEVICE(mms->lan9118); sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16)); return sysbus_mmio_get_region(s, 0); }
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, Error **errp) { int i ; for (i = 0; i < s->num_cs; ++i) { AspeedSMCFlash *fl = &s->flashes[i]; DriveInfo *dinfo = drive_get_next(IF_MTD); qemu_irq cs_line; fl->flash = ssi_create_slave_no_init(s->spi, flashtype); if (dinfo) { qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo), errp); } qdev_init_nofail(fl->flash); cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line); } }
static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, bool is_qspi) { DeviceState *dev; SysBusDevice *busdev; SSIBus *spi; DeviceState *flash_dev; int i, j; int num_busses = is_qspi ? NUM_QSPI_BUSSES : 1; int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES; dev = qdev_create(NULL, is_qspi ? "xlnx.ps7-qspi" : "xlnx.ps7-spi"); qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1); qdev_prop_set_uint8(dev, "num-ss-bits", num_ss); qdev_prop_set_uint8(dev, "num-busses", num_busses); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, base_addr); if (is_qspi) { sysbus_mmio_map(busdev, 1, 0xFC000000); } sysbus_connect_irq(busdev, 0, irq); for (i = 0; i < num_busses; ++i) { char bus_name[16]; qemu_irq cs_line; snprintf(bus_name, 16, "spi%d", i); spi = (SSIBus *)qdev_get_child_bus(dev, bus_name); for (j = 0; j < num_ss; ++j) { flash_dev = ssi_create_slave(spi, "n25q128"); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); } } }
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque, const char *name, hwaddr size) { TZMPC *mpc = opaque; int i = mpc - &mms->ssram_mpc[0]; MemoryRegion *ssram = &mms->ssram[i]; MemoryRegion *upstream; char *mpcname = g_strdup_printf("%s-mpc", name); static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 }; static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 }; memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal); sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC); object_property_set_link(OBJECT(mpc), OBJECT(ssram), "downstream", &error_fatal); object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal); /* Map the upstream end of the MPC into system memory */ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); memory_region_add_subregion(get_system_memory(), rambase[i], upstream); /* and connect its interrupt to the IoTKit */ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "mpcexp_status", i)); /* The first SSRAM is a special case as it has an alias; accesses to * the alias region at 0x00400000 must also go to the MPC upstream. */ if (i == 0) { make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000); } g_free(mpcname); /* Return the register interface MR for our caller to map behind the PPC */ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); }
static void petalogix_ml605_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev, *dma, *eth0; Object *ds, *cs; MicroBlazeCPU *cpu; SysBusDevice *busdev; DriveInfo *dinfo; int i; MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32]; /* init CPUs */ cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); object_property_set_str(OBJECT(cpu), "8.10.a", "version", &error_abort); /* Use FPU but don't use floating point conversion and square * root instructions */ object_property_set_int(OBJECT(cpu), 1, "use-fpu", &error_abort); object_property_set_bool(OBJECT(cpu), true, "dcache-writeback", &error_abort); object_property_set_bool(OBJECT(cpu), true, "endianness", &error_abort); object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort); /* Attach emulated BRAM through the LMB. */ memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", LMB_BRAM_SIZE, &error_fatal); vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram); memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size, &error_fatal); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, MEMORY_BASEADDR, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); /* 5th parameter 2 means bank-width * 10th paremeter 0 means little-endian */ pflash_cfi01_register(FLASH_BASEADDR, NULL, "petalogix_ml605.flash", FLASH_SIZE, dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, (64 * 1024), FLASH_SIZE >> 16, 2, 0x89, 0x18, 0x0000, 0x0, 0); dev = qdev_create(NULL, "xlnx.xps-intc"); qdev_prop_set_uint32(dev, "kind-of-intr", 1 << TIMER_IRQ); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ)); for (i = 0; i < 32; i++) { irq[i] = qdev_get_gpio_in(dev, i); } serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2, irq[UART16550_IRQ], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN); /* 2 timers at irq 2 @ 100 Mhz. */ dev = qdev_create(NULL, "xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", 0); qdev_prop_set_uint32(dev, "clock-frequency", 100 * 1000000); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]); /* axi ethernet and dma initialization. */ qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet"); eth0 = qdev_create(NULL, "xlnx.axi-ethernet"); dma = qdev_create(NULL, "xlnx.axi-dma"); /* FIXME: attach to the sysbus instead */ object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0), NULL); object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma), NULL); ds = object_property_get_link(OBJECT(dma), "axistream-connected-target", NULL); cs = object_property_get_link(OBJECT(dma), "axistream-control-connected-target", NULL); qdev_set_nic_properties(eth0, &nd_table[0]); qdev_prop_set_uint32(eth0, "rxmem", 0x1000); qdev_prop_set_uint32(eth0, "txmem", 0x1000); object_property_set_link(OBJECT(eth0), OBJECT(ds), "axistream-connected", &error_abort); object_property_set_link(OBJECT(eth0), OBJECT(cs), "axistream-control-connected", &error_abort); qdev_init_nofail(eth0); sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(eth0), 0, irq[AXIENET_IRQ]); ds = object_property_get_link(OBJECT(eth0), "axistream-connected-target", NULL); cs = object_property_get_link(OBJECT(eth0), "axistream-control-connected-target", NULL); qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000); object_property_set_link(OBJECT(dma), OBJECT(ds), "axistream-connected", &error_abort); object_property_set_link(OBJECT(dma), OBJECT(cs), "axistream-control-connected", &error_abort); qdev_init_nofail(dma); sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dma), 0, irq[AXIDMA_IRQ0]); sysbus_connect_irq(SYS_BUS_DEVICE(dma), 1, irq[AXIDMA_IRQ1]); { SSIBus *spi; dev = qdev_create(NULL, "xlnx.xps-spi"); qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, SPI_BASEADDR); sysbus_connect_irq(busdev, 0, irq[SPI_IRQ]); spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); for (i = 0; i < NUM_SPI_FLASHES; i++) { qemu_irq cs_line; dev = ssi_create_slave(spi, "n25q128"); cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0); sysbus_connect_irq(busdev, i+1, cs_line); } } /* setup PVR to match kernel settings */ cpu->env.pvr.regs[4] = 0xc56b8000; cpu->env.pvr.regs[5] = 0xc56be000; cpu->env.pvr.regs[10] = 0x0e000000; /* virtex 6 */ microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size, machine->initrd_filename, BINARY_DEVICE_TREE_FILE, NULL); }
static void sun4uv_init(MemoryRegion *address_space_mem, MachineState *machine, const struct hwdef *hwdef) { SPARCCPU *cpu; Nvram *nvram; unsigned int i; uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry; SabreState *sabre; PCIBus *pci_bus, *pci_busA, *pci_busB; PCIDevice *ebus, *pci_dev; SysBusDevice *s; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DeviceState *iommu, *dev; FWCfgState *fw_cfg; NICInfo *nd; MACAddr macaddr; bool onboard_nic; /* init CPUs */ cpu = sparc64_cpu_devinit(machine->cpu_type, hwdef->prom_addr); /* IOMMU */ iommu = qdev_create(NULL, TYPE_SUN4U_IOMMU); qdev_init_nofail(iommu); /* set up devices */ ram_init(0, machine->ram_size); prom_init(hwdef->prom_addr, bios_name); /* Init sabre (PCI host bridge) */ sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE)); qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE); qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE); object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu", &error_abort); qdev_init_nofail(DEVICE(sabre)); /* Wire up PCI interrupts to CPU */ for (i = 0; i < IVEC_MAX; i++) { qdev_connect_gpio_out_named(DEVICE(sabre), "ivec-irq", i, qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i)); } pci_bus = PCI_HOST_BRIDGE(sabre)->bus; pci_busA = pci_bridge_get_sec_bus(sabre->bridgeA); pci_busB = pci_bridge_get_sec_bus(sabre->bridgeB); /* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is reserved (leaving no slots free after on-board devices) however slots 0-3 are free on busB */ pci_bus->slot_reserved_mask = 0xfffffffc; pci_busA->slot_reserved_mask = 0xfffffff1; pci_busB->slot_reserved_mask = 0xfffffff0; ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS); qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base", hwdef->console_serial_base); qdev_init_nofail(DEVICE(ebus)); /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */ qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7, qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_LPT_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6, qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_FDD_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1, qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_KBD_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12, qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_MSE_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4, qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ)); pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA"); memset(&macaddr, 0, sizeof(MACAddr)); onboard_nic = false; for (i = 0; i < nb_nics; i++) { nd = &nd_table[i]; if (!nd->model || strcmp(nd->model, "sunhme") == 0) { if (!onboard_nic) { pci_dev = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 1), true, "sunhme"); memcpy(&macaddr, &nd->macaddr.a, sizeof(MACAddr)); onboard_nic = true; } else { pci_dev = pci_create(pci_busB, -1, "sunhme"); } } else { pci_dev = pci_create(pci_busB, -1, nd->model); } dev = &pci_dev->qdev; qdev_set_nic_properties(dev, nd); qdev_init_nofail(dev); } /* If we don't have an onboard NIC, grab a default MAC address so that * we have a valid machine id */ if (!onboard_nic) { qemu_macaddr_default_if_unset(&macaddr); } ide_drive_get(hd, ARRAY_SIZE(hd)); pci_dev = pci_create(pci_busA, PCI_DEVFN(3, 0), "cmd646-ide"); qdev_prop_set_uint32(&pci_dev->qdev, "secondary", 1); qdev_init_nofail(&pci_dev->qdev); pci_ide_create_devs(pci_dev, hd); /* Map NVRAM into I/O (ebus) space */ nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59); s = SYS_BUS_DEVICE(nvram); memory_region_add_subregion(pci_address_space_io(ebus), 0x2000, sysbus_mmio_get_region(s, 0)); initrd_size = 0; initrd_addr = 0; kernel_size = sun4u_load_kernel(machine->kernel_filename, machine->initrd_filename, ram_size, &initrd_size, &initrd_addr, &kernel_addr, &kernel_entry); sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", machine->ram_size, machine->boot_order, kernel_addr, kernel_size, machine->kernel_cmdline, initrd_addr, initrd_size, /* XXX: need an option to load a NVRAM image */ 0, graphic_width, graphic_height, graphic_depth, (uint8_t *)&macaddr); dev = qdev_create(NULL, TYPE_FW_CFG_IO); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev), NULL); qdev_init_nofail(dev); memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT, &FW_CFG_IO(dev)->comb_iomem); fw_cfg = FW_CFG(dev); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (machine->kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(machine->kernel_cmdline) + 1); fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0); } fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr); fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]); fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
static void mps2tz_common_init(MachineState *machine) { MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); MemoryRegion *system_memory = get_system_memory(); DeviceState *iotkitdev; DeviceState *dev_splitter; int i; if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { error_report("This board can only be used with CPU %s", mc->default_cpu_type); exit(1); } sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit, sizeof(mms->iotkit), TYPE_IOTKIT); iotkitdev = DEVICE(&mms->iotkit); object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory), "memory", &error_abort); qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92); qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ); object_property_set_bool(OBJECT(&mms->iotkit), true, "realized", &error_fatal); /* The sec_resp_cfg output from the IoTKit must be split into multiple * lines, one for each of the PPCs we create here. */ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter), TYPE_SPLIT_IRQ); object_property_add_child(OBJECT(machine), "sec-resp-splitter", OBJECT(&mms->sec_resp_splitter), &error_abort); object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5, "num-lines", &error_fatal); object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, "realized", &error_fatal); dev_splitter = DEVICE(&mms->sec_resp_splitter); qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0, qdev_get_gpio_in(dev_splitter, 0)); /* The IoTKit sets up much of the memory layout, including * the aliases between secure and non-secure regions in the * address space. The FPGA itself contains: * * 0x00000000..0x003fffff SSRAM1 * 0x00400000..0x007fffff alias of SSRAM1 * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3 * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices * 0x80000000..0x80ffffff 16MB PSRAM */ /* The FPGA images have an odd combination of different RAMs, * because in hardware they are different implementations and * connected to different buses, giving varying performance/size * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily * call the 16MB our "system memory", as it's the largest lump. */ memory_region_allocate_system_memory(&mms->psram, NULL, "mps.ram", 0x01000000); memory_region_add_subregion(system_memory, 0x80000000, &mms->psram); /* The overflow IRQs for all UARTs are ORed together. * Tx, Rx and "combined" IRQs are sent to the NVIC separately. * Create the OR gate for this. */ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate), TYPE_OR_IRQ); object_property_add_child(OBJECT(mms), "uart-irq-orgate", OBJECT(&mms->uart_irq_orgate), &error_abort); object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines", &error_fatal); object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true, "realized", &error_fatal); qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15)); /* Most of the devices in the FPGA are behind Peripheral Protection * Controllers. The required order for initializing things is: * + initialize the PPC * + initialize, configure and realize downstream devices * + connect downstream device MemoryRegions to the PPC * + realize the PPC * + map the PPC's MemoryRegions to the places in the address map * where the downstream devices should appear * + wire up the PPC's control lines to the IoTKit object */ const PPCInfo ppcs[] = { { .name = "apb_ppcexp0", .ports = { { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 }, { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 }, { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 }, }, }, { .name = "apb_ppcexp1",
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) { BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev); Object *obj; MemoryRegion *ram; Error *err = NULL; uint64_t ram_size, vcram_size; int n; obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } ram = MEMORY_REGION(obj); ram_size = memory_region_size(ram); /* Map peripherals and RAM into the GPU address space. */ memory_region_init_alias(&s->peri_mr_alias, OBJECT(s), "bcm2835-peripherals", &s->peri_mr, 0, memory_region_size(&s->peri_mr)); memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE, &s->peri_mr_alias, 1); /* RAM is aliased four times (different cache configurations) on the GPU */ for (n = 0; n < 4; n++) { memory_region_init_alias(&s->ram_alias[n], OBJECT(s), "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size); memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30, &s->ram_alias[n], 0); } /* Interrupt Controller */ object_property_set_bool(OBJECT(&s->ic), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* UART0 */ qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hds[0]); object_property_set_bool(OBJECT(s->uart0), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, sysbus_mmio_get_region(s->uart0, 0)); sysbus_connect_irq(s->uart0, 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_UART)); /* AUX / UART1 */ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hds[1]); object_property_set_bool(OBJECT(&s->aux), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_AUX)); /* Mailboxes */ object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_MAILBOX)); /* Framebuffer */ vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err); if (err) { error_propagate(errp, err); return; } object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size, "vcram-base", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->fb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB)); /* Property channel */ object_property_set_bool(OBJECT(&s->property), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY)); /* Random Number Generator */ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, RNG_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0)); /* Extended Mass Media Controller */ object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); /* SDHOST */ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_SDIO)); /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, DMA_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0)); memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1)); for (n = 0; n <= 12; n++) { sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } /* GPIO */ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } }
static void bcm2836_realize(DeviceState *dev, Error **errp) { BCM2836State *s = BCM2836(dev); Object *obj; Error *err = NULL; int n; /* common peripherals from bcm2835 */ obj = OBJECT(dev); for (n = 0; n < BCM2836_NCPUS; n++) { object_initialize(&s->cpus[n], sizeof(s->cpus[n]), s->cpu_type); object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]), &error_abort); } obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj, &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err); if (err) { error_propagate(errp, err); return; } object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, BCM2836_PERI_BASE, 1); /* bcm2836 interrupt controller (and mailboxes, etc.) */ object_property_set_bool(OBJECT(&s->control), true, "realized", &err); if (err) { error_propagate(errp, err); return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, BCM2836_CONTROL_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0)); for (n = 0; n < BCM2836_NCPUS; n++) { /* Mirror bcm2836, which has clusterid set to 0xf * TODO: this should be converted to a property of ARM_CPU */ s->cpus[n].mp_affinity = 0xF00 | n; /* set periphbase/CBAR value for CPU-local registers */ object_property_set_int(OBJECT(&s->cpus[n]), BCM2836_PERI_BASE + MCORE_OFFSET, "reset-cbar", &err); if (err) { error_propagate(errp, err); return; } /* start powered off if not enabled */ object_property_set_bool(OBJECT(&s->cpus[n]), n >= s->enabled_cpus, "start-powered-off", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err); if (err) { error_propagate(errp, err); return; } /* Connect irq/fiq outputs from the interrupt controller. */ qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n, qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_IRQ)); qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n, qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_FIQ)); /* Connect timers from the CPU to the interrupt controller */ qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_PHYS, qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_VIRT, qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_HYP, qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_SEC, qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n)); } }
static qemu_irq fdt_get_gpio(FDTMachineInfo *fdti, char *node_path, int* cur_cell, qemu_irq input, const FDTGenericGPIOSet *gpio_set, const char *debug_success, bool *end) { void *fdt = fdti->fdt; uint32_t parent_phandle, parent_cells = 0, cells[32]; char parent_node_path[DT_PATH_LENGTH]; DeviceState *parent; int i; Error *errp = NULL; const char *reason; bool free_reason = false; const char *propname = gpio_set->names->propname; const char *cells_propname = gpio_set->names->cells_propname; cells[0] = 0; parent_phandle = qemu_fdt_getprop_cell(fdt, node_path, propname, (*cur_cell)++, false, &errp); if (errp) { reason = g_strdup_printf("Cant get phandle from \"%s\" property\n", propname); *end = true; free_reason = true; goto fail_silent; } if (qemu_devtree_get_node_by_phandle(fdt, parent_node_path, parent_phandle)) { *end = true; reason = "cant get node from phandle\n"; goto fail; } parent_cells = qemu_fdt_getprop_cell(fdt, parent_node_path, cells_propname, 0, false, &errp); if (errp) { *end = true; reason = g_strdup_printf("cant get the property \"%s\" from the " \ "parent \"%s\"\n", cells_propname, parent_node_path); free_reason = true; goto fail; } for (i = 0; i < parent_cells; ++i) { cells[i] = qemu_fdt_getprop_cell(fdt, node_path, propname, (*cur_cell)++, false, &errp); if (errp) { *end = true; reason = "cant get cell value"; goto fail; } } while (!fdt_init_has_opaque(fdti, parent_node_path)) { fdt_init_yield(fdti); } parent = DEVICE(fdt_init_get_opaque(fdti, parent_node_path)); if (!parent) { reason = "parent is not a device"; goto fail_silent; } while (!parent->realized) { fdt_init_yield(fdti); } { const FDTGenericGPIOConnection *fgg_con = NULL; uint16_t range, idx; const char *gpio_name = NULL; qemu_irq ret; if (object_dynamic_cast(OBJECT(parent), TYPE_FDT_GENERIC_GPIO)) { const FDTGenericGPIOSet *set; FDTGenericGPIOClass *parent_fggc = FDT_GENERIC_GPIO_GET_CLASS(parent); for (set = parent_fggc->controller_gpios; set && set->names; set++) { if (!strcmp(gpio_set->names->cells_propname, set->names->cells_propname)) { fgg_con = set->gpios; break; } } } /* FIXME: cells[0] is not always the fdt indexing match system */ idx = cells[0] & ~(1ul << 31); if (fgg_con) { range = fgg_con->range ? fgg_con->range : 1; while (!(idx >= fgg_con->fdt_index && idx < (fgg_con->fdt_index + range)) && fgg_con->name) { fgg_con++; } if (!fgg_con) { goto fail; } idx -= fgg_con->fdt_index; gpio_name = fgg_con->name; } if (input) { FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1); bool (*merge_fn)(bool *, int) = qemu_irq_shared_or_handler; /* FIXME: I am kind of stealing here. Use the msb of the first * cell to indicate the merge function. This needs to be discussed * with device-tree community on how this should be done properly. */ if (cells[0] & (1 << 31)) { merge_fn = qemu_irq_shared_and_handler; } DB_PRINT_NP(1, "%s GPIO output %s[%d] on %s\n", debug_success, gpio_name ? gpio_name : "unnamed", idx, parent_node_path); *irq = (FDTIRQConnection) { .dev = parent, .name = gpio_name, .merge_fn = merge_fn, .i = idx, .irq = input, .sink_info = NULL, /* FIMXE */ .next = fdti->irqs }; fdti->irqs = irq; } ret = qdev_get_gpio_in_named(parent, gpio_name, idx); if (ret) { DB_PRINT_NP(1, "wiring GPIO input %s on %s ... \n", fgg_con ? fgg_con->name : "unnamed", parent_node_path); } return ret; } fail: fprintf(stderr, "%s Failed: %s\n", node_path, reason); fail_silent: if (free_reason) { g_free((void *)reason); } return NULL; } static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret, char *intc_node_path, uint32_t *cells, uint32_t num_cells, uint32_t max, Error **errp) { FDTGenericIntcClass *intc_fdt_class; DeviceState *intc; while (!fdt_init_has_opaque(fdti, intc_node_path)) { fdt_init_yield(fdti); } intc = DEVICE(fdt_init_get_opaque(fdti, intc_node_path)); if (!intc) { goto fail; } while (!intc->realized) { fdt_init_yield(fdti); } intc_fdt_class = FDT_GENERIC_INTC_GET_CLASS(intc); if (!intc_fdt_class) { goto fail; } intc_fdt_class->get_irq(FDT_GENERIC_INTC(intc), ret, cells, num_cells, max, errp); return; fail: error_setg(errp, "%s", __func__); }
static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState *machine) { int i; uint64_t ram_size = machine->ram_size; /* Create the memory region to pass to the SoC */ if (ram_size > XLNX_ZYNQMP_MAX_RAM_SIZE) { error_report("ERROR: RAM size 0x%" PRIx64 " above max supported of " "0x%llx", ram_size, XLNX_ZYNQMP_MAX_RAM_SIZE); exit(1); } if (ram_size < 0x08000000) { qemu_log("WARNING: RAM size 0x%" PRIx64 " is small for ZCU102", ram_size); } memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram", ram_size); object_initialize(&s->soc, sizeof(s->soc), TYPE_XLNX_ZYNQMP); object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); object_property_set_link(OBJECT(&s->soc), OBJECT(&s->ddr_ram), "ddr-ram", &error_abort); object_property_set_bool(OBJECT(&s->soc), s->secure, "secure", &error_fatal); object_property_set_bool(OBJECT(&s->soc), s->virt, "virtualization", &error_fatal); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); /* Create and plug in the SD cards */ for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { BusState *bus; DriveInfo *di = drive_get_next(IF_SD); BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *carddev; char *bus_name; bus_name = g_strdup_printf("sd-bus%d", i); bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name); g_free(bus_name); if (!bus) { error_report("No SD bus found for SD card %d", i); exit(1); } carddev = qdev_create(bus, TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal); } for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) { SSIBus *spi_bus; DeviceState *flash_dev; qemu_irq cs_line; DriveInfo *dinfo = drive_get_next(IF_MTD); gchar *bus_name = g_strdup_printf("spi%d", i); spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name); g_free(bus_name); flash_dev = ssi_create_slave_no_init(spi_bus, "sst25wf080"); if (dinfo) { qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), &error_fatal); } qdev_init_nofail(flash_dev); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line); } for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_FLASH; i++) { SSIBus *spi_bus; DeviceState *flash_dev; qemu_irq cs_line; DriveInfo *dinfo = drive_get_next(IF_MTD); int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS; gchar *bus_name = g_strdup_printf("qspi%d", bus); spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name); g_free(bus_name); flash_dev = ssi_create_slave_no_init(spi_bus, "n25q512a11"); if (dinfo) { qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), &error_fatal); } qdev_init_nofail(flash_dev); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.qspi), i + 1, cs_line); } /* TODO create and connect IDE devices for ide_drive_get() */ xlnx_zcu102_binfo.ram_size = ram_size; xlnx_zcu102_binfo.kernel_filename = machine->kernel_filename; xlnx_zcu102_binfo.kernel_cmdline = machine->kernel_cmdline; xlnx_zcu102_binfo.initrd_filename = machine->initrd_filename; xlnx_zcu102_binfo.loader_start = 0; arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_zcu102_binfo); }
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) { BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev); Object *obj; MemoryRegion *ram; Error *err = NULL; uint64_t ram_size, vcram_size; int n; obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } ram = MEMORY_REGION(obj); ram_size = memory_region_size(ram); /* Map peripherals and RAM into the GPU address space. */ memory_region_init_alias(&s->peri_mr_alias, OBJECT(s), "bcm2835-peripherals", &s->peri_mr, 0, memory_region_size(&s->peri_mr)); memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE, &s->peri_mr_alias, 1); /* RAM is aliased four times (different cache configurations) on the GPU */ for (n = 0; n < 4; n++) { memory_region_init_alias(&s->ram_alias[n], OBJECT(s), "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size); memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30, &s->ram_alias[n], 0); } /* Interrupt Controller */ object_property_set_bool(OBJECT(&s->ic), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* UART0 */ qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hd(0)); object_property_set_bool(OBJECT(s->uart0), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, sysbus_mmio_get_region(s->uart0, 0)); sysbus_connect_irq(s->uart0, 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_UART)); /* AUX / UART1 */ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hd(1)); object_property_set_bool(OBJECT(&s->aux), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_AUX)); /* System timer */ object_property_set_bool(OBJECT(&s->st), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ST_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->st), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 1, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER1)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 2, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER2)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 3, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER3)); /* ARM timer */ object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_TIMER0_1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_TIMER)); /* USB controller */ object_property_set_bool(OBJECT(&s->usb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, USB_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->usb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_USB)); /* MPHI - Message-based Parallel Host Interface */ object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_HOSTPORT)); /* Mailboxes */ object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_MAILBOX)); /* Power management */ object_property_set_bool(OBJECT(&s->power), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_POWER << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->power), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->power), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_POWER)); /* Framebuffer */ vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err); if (err) { error_propagate(errp, err); return; } object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size, "vcram-base", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->fb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB)); /* Property channel */ object_property_set_bool(OBJECT(&s->property), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY)); /* Random Number Generator */ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, RNG_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0)); /* Extended Mass Media Controller * * Compatible with: * - SD Host Controller Specification Version 3.0 Draft 1.0 * - SDIO Specification Version 3.0 * - MMC Specification Version 4.4 * * For the exact details please refer to the Arasan documentation: * SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf */ object_property_set_uint(OBJECT(&s->sdhci), 3, "sd-spec-version", &err); object_property_set_uint(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg", &err); object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); /* SDHOST */ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_SDIO)); /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, DMA_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0)); memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1)); for (n = 0; n <= 12; n++) { sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } /* GPIO */ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } }