From f287ccf0cd613e04005cb98138fe1180fa26feda Mon Sep 17 00:00:00 2001 From: Andrew Baumann Date: Mon, 23 Nov 2015 15:11:56 -0800 Subject: [PATCH] bcm283* refactoring continues Cleaned up address space logic significantly, by using separate memory regions for gpu bus addresses (with all the RAM aliases) and CPU address (without). However, this required adding two new globals to find them -- I still need to figure out how to communicate this to the child devices. --- hw/arm/Makefile.objs | 2 +- hw/arm/bcm2835.c | 82 ++++ hw/arm/bcm2835_peripherals.c | 75 ++-- hw/arm/bcm2836.c | 25 +- hw/arm/raspi.c | 722 +++++++++++------------------------ hw/display/bcm2835_fb.c | 33 +- hw/dma/bcm2835_dma.c | 19 +- hw/misc/bcm2835_property.c | 114 +++--- hw/misc/bcm2835_sbm.c | 6 +- include/hw/arm/bcm2835.h | 6 +- include/hw/arm/bcm2835_common.h | 6 +- include/hw/arm/bcm2835_peripherals.h | 4 +- include/hw/arm/bcm2836.h | 1 - include/hw/arm/raspi_platform.h | 9 +- 14 files changed, 469 insertions(+), 635 deletions(-) create mode 100755 hw/arm/bcm2835.c rewrite hw/arm/raspi.c (61%) diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 8ea659d750..d48c67e155 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -11,7 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o obj-$(CONFIG_DIGIC) += digic.o obj-y += omap1.o omap2.o strongarm.o obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o -obj-$(CONFIG_RASPI) += raspi.o bcm2835_peripherals.o bcm2836.o +obj-$(CONFIG_RASPI) += raspi.o bcm2835.o bcm2835_peripherals.o bcm2836.o obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o diff --git a/hw/arm/bcm2835.c b/hw/arm/bcm2835.c new file mode 100755 index 0000000000..a811d456e8 --- /dev/null +++ b/hw/arm/bcm2835.c @@ -0,0 +1,82 @@ +#include "hw/arm/bcm2835.h" +#include "hw/arm/raspi_platform.h" +#include "hw/sysbus.h" +#include "exec/address-spaces.h" + +#define DEFAULT_VCRAM_SIZE 0x4000000 + +static void bcm2835_init(Object *obj) +{ + BCM2835State *s = BCM2835(obj); + + object_initialize(&s->cpu, sizeof(s->cpu), "arm1176-" TYPE_ARM_CPU); + object_property_add_child(obj, "cpu", OBJECT(&s->cpu), &error_abort); + + object_initialize(&s->peripherals, sizeof(s->peripherals), + TYPE_BCM2835_PERIPHERALS); + object_property_add_child(obj, "peripherals", OBJECT(&s->peripherals), + &error_abort); + qdev_set_parent_bus(DEVICE(&s->peripherals), sysbus_get_default()); +} + +static void bcm2835_realize(DeviceState *dev, Error **errp) +{ + BCM2835State *s = BCM2835(dev); + Error *err = NULL; + + /* common peripherals from bcm2835 */ + object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, + BCM2835_PERI_BASE, 1); + + object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); + if (err) { + error_report_err(err); + exit(1); + } + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); + +} + +static Property bcm2835_props[] = { + DEFINE_PROP_SIZE("vcram-size", BCM2835State, vcram_size, DEFAULT_VCRAM_SIZE), + DEFINE_PROP_END_OF_LIST() +}; + +static void bcm2835_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->props = bcm2835_props; + dc->realize = bcm2835_realize; + + /* + * Reason: creates an ARM CPU, thus use after free(), see + * arm_cpu_class_init() + */ + dc->cannot_destroy_with_object_finalize_yet = true; +} + +static const TypeInfo bcm2835_type_info = { + .name = TYPE_BCM2835, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(BCM2835State), + .instance_init = bcm2835_init, + .class_init = bcm2835_class_init, +}; + +static void bcm2835_register_types(void) +{ + type_register_static(&bcm2835_type_info); +} + +type_init(bcm2835_register_types) diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index ae5b06f86c..bbad3734ee 100755 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -1,8 +1,10 @@ #include "hw/arm/bcm2835_peripherals.h" #include "hw/arm/bcm2835_common.h" #include "hw/arm/raspi_platform.h" +#include "exec/address-spaces.h" // XXX: FIXME: +MemoryRegion *bcm2835_peripheral_mr; AddressSpace *bcm2835_peripheral_as; static void bcm2835_peripherals_init(Object *obj) @@ -10,8 +12,20 @@ static void bcm2835_peripherals_init(Object *obj) BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj); SysBusDevice *dev; - memory_region_init_io(&s->iomem, OBJECT(s), NULL, s, "mmio", 0x1000000); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); + /* We track two memory regions. One, for the peripheral devices + * themselves, which we export to our parent soc device, and + * one for the bus addresses used by the peripherals, which is + * used internally. The latter requires an alias. */ + memory_region_init_io(&s->peri_mr, OBJECT(s), NULL, s, + "bcm2835_peripherals", 0x1000000); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr); + + memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s, "bcm2835_gpu_bus", + (uint64_t)1 << 32); + + address_space_init(&s->gpu_bus_as, &s->gpu_bus_mr, "bcm2835_gpu_bus"); + bcm2835_peripheral_mr = &s->gpu_bus_mr; // XXX + bcm2835_peripheral_as = &s->gpu_bus_as; // XXX /* Interrupt Controller */ s->ic = dev = SYS_BUS_DEVICE(object_new("bcm2835_ic")); @@ -87,6 +101,7 @@ static void bcm2835_peripherals_init(Object *obj) static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) { BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev); + MemoryRegion *ram; qemu_irq pic[72]; qemu_irq mbox_irq[MBOX_CHAN_COUNT]; hwaddr tmpoffset; @@ -100,7 +115,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, ARMCTRL_IC_OFFSET, + memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(s->ic, 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), s->ic); @@ -115,7 +130,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, UART0_OFFSET, + memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, sysbus_mmio_get_region(s->uart0, 0)); sysbus_connect_irq(s->uart0, 0, pic[INTERRUPT_VC_UART]); @@ -126,7 +141,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, UART1_OFFSET, + memory_region_add_subregion(&s->peri_mr, UART1_OFFSET, sysbus_mmio_get_region(s->uart1, 0)); sysbus_connect_irq(s->uart1, 0, pic[INTERRUPT_AUX]); @@ -137,7 +152,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, ST_OFFSET, + memory_region_add_subregion(&s->peri_mr, ST_OFFSET, sysbus_mmio_get_region(s->systimer, 0)); sysbus_connect_irq(s->systimer, 0, pic[INTERRUPT_TIMER0]); sysbus_connect_irq(s->systimer, 1, pic[INTERRUPT_TIMER1]); @@ -151,7 +166,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, ARMCTRL_TIMER0_1_OFFSET, + memory_region_add_subregion(&s->peri_mr, ARMCTRL_TIMER0_1_OFFSET, sysbus_mmio_get_region(s->armtimer, 0)); sysbus_connect_irq(s->armtimer, 0, pic[INTERRUPT_ARM_TIMER]); @@ -162,7 +177,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, USB_OFFSET, + memory_region_add_subregion(&s->peri_mr, USB_OFFSET, sysbus_mmio_get_region(s->usb, 0)); sysbus_connect_irq(s->usb, 0, pic[INTERRUPT_VC_USB]); @@ -173,7 +188,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, MPHI_OFFSET, + memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET, sysbus_mmio_get_region(s->mphi, 0)); sysbus_connect_irq(s->mphi, 0, pic[INTERRUPT_HOSTPORT]); @@ -184,7 +199,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, ARMCTRL_0_SBM_OFFSET, + memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET, sysbus_mmio_get_region(s->sbm, 0)); sysbus_connect_irq(s->sbm, 0, pic[INTERRUPT_ARM_MAILBOX]); @@ -205,7 +220,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, tmpoffset + (MBOX_CHAN_POWER<<4), + memory_region_add_subregion(&s->peri_mr, tmpoffset + (MBOX_CHAN_POWER<<4), sysbus_mmio_get_region(s->power, 0)); sysbus_connect_irq(s->power, 0, mbox_irq[MBOX_CHAN_POWER]); @@ -216,7 +231,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, tmpoffset + (MBOX_CHAN_FB<<4), + memory_region_add_subregion(&s->peri_mr, tmpoffset + (MBOX_CHAN_FB<<4), sysbus_mmio_get_region(s->fb, 0)); sysbus_connect_irq(s->fb, 0, mbox_irq[MBOX_CHAN_FB]); @@ -227,7 +242,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, tmpoffset + (MBOX_CHAN_PROPERTY<<4), + memory_region_add_subregion(&s->peri_mr, tmpoffset + (MBOX_CHAN_PROPERTY<<4), sysbus_mmio_get_region(s->property, 0)); sysbus_connect_irq(s->property, 0, mbox_irq[MBOX_CHAN_PROPERTY]); @@ -238,7 +253,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, tmpoffset + (MBOX_CHAN_VCHIQ<<4), + memory_region_add_subregion(&s->peri_mr, tmpoffset + (MBOX_CHAN_VCHIQ<<4), sysbus_mmio_get_region(s->vchiq, 0)); sysbus_connect_irq(s->vchiq, 0, mbox_irq[MBOX_CHAN_VCHIQ]); @@ -249,7 +264,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, EMMC_OFFSET, + memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET, sysbus_mmio_get_region(s->emmc, 0)); sysbus_connect_irq(s->emmc, 0, pic[INTERRUPT_VC_ARASANSDIO]); @@ -260,16 +275,11 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - memory_region_add_subregion(&s->iomem, DMA_OFFSET, + memory_region_add_subregion(&s->peri_mr, DMA_OFFSET, sysbus_mmio_get_region(s->dma, 0)); - memory_region_add_subregion(&s->iomem, 0xe05000, + memory_region_add_subregion(&s->peri_mr, 0xe05000, // XXX sysbus_mmio_get_region(s->dma, 1)); - // XXX: tmp kludge - static AddressSpace tmpas; - address_space_init(&tmpas, &s->iomem, "bcm2835_peripheral_as"); - bcm2835_peripheral_as = &tmpas; - sysbus_connect_irq(s->dma, 0, pic[INTERRUPT_DMA0]); sysbus_connect_irq(s->dma, 1, pic[INTERRUPT_DMA1]); sysbus_connect_irq(s->dma, 2, pic[INTERRUPT_VC_DMA2]); @@ -283,6 +293,27 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(s->dma, 10, pic[INTERRUPT_DMA10]); sysbus_connect_irq(s->dma, 11, pic[INTERRUPT_DMA11]); sysbus_connect_irq(s->dma, 12, pic[INTERRUPT_DMA12]); + + /* 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); + + /* XXX: assume that RAM is contiguous and mapped at system address zero */ + ram = memory_region_find(get_system_memory(), 0, 1).mr; + assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 * 1024); + + /* 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, + memory_region_size(ram)); + memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30, + &s->ram_alias[n], 0); + } } static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c index f45757dbe9..3d7d5efd23 100755 --- a/hw/arm/bcm2836.c +++ b/hw/arm/bcm2836.c @@ -35,7 +35,6 @@ static void bcm2836_init(Object *obj) static void bcm2836_realize(DeviceState *dev, Error **errp) { BCM2836State *s = BCM2836(dev); - MemoryRegion *mr; Error *err = NULL; int n; @@ -46,17 +45,8 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) return; } - //sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, - // BCM2836_PERI_BASE, 1); - mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->peripherals), 0); - memory_region_init_alias(&s->peripheral_mr, OBJECT(s), - "peripheral-alias0", mr, 0, memory_region_size(mr)); - memory_region_init_alias(&s->peripheral_alias, OBJECT(s), - "peripheral-alias1", mr, 0, memory_region_size(mr)); - memory_region_add_subregion_overlap(get_system_memory(), BCM2836_PERI_BASE, - &s->peripheral_mr, 1); - memory_region_add_subregion(get_system_memory(), 0x7e000000, - &s->peripheral_alias); + 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->ic), true, "realized", &err); @@ -65,20 +55,15 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) return; } - sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->ic), 0, - BCM2836_PERI_BASE + BCM2836_CONTROL_OFFSET, 1); - mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(s->ic), 0); - memory_region_init_alias(&s->ic_alias, OBJECT(s), "ic-alias", mr, 0, - memory_region_size(mr)); - memory_region_add_subregion_overlap(get_system_memory(), - 0x7e000000 + BCM2836_CONTROL_OFFSET, - &s->ic_alias, 1); + sysbus_mmio_map(SYS_BUS_DEVICE(s->ic), 0, BCM2836_CONTROL_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, qdev_get_gpio_in_named(DEVICE(s->ic), "gpu_irq", 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, qdev_get_gpio_in_named(DEVICE(s->ic), "gpu_fiq", 0)); + /* TODO: probably shouldn't be using smp_cpus here */ + assert(smp_cpus <= BCM2836_NCPUS); for (n = 0; n < smp_cpus; n++) { /* Mirror bcm2836, which has clusterid set to 0xf */ s->cpus[n].mp_affinity = 0xF00 | n; diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c dissimilarity index 61% index 86081e1790..3a00843694 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -1,494 +1,228 @@ -/* - * Raspberry Pi emulation (c) 2012 Gregory Estrade - * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous - * - * Rasperry Pi 2 emulation Copyright (c) 2015, Microsoft - * Written by Andrew Baumann - * - * This code is licensed under the GNU GPLv2 and later. - */ - -/* Based on versatilepb.c, copyright terms below. */ - -/* - * ARM Versatile Platform/Application Baseboard System emulation. - * - * Copyright (c) 2005-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -#include "hw/arm/bcm2836.h" -#include "qemu/error-report.h" -#include "hw/boards.h" -#include "hw/devices.h" -#include "hw/loader.h" -#include "hw/sysbus.h" -#include "hw/arm/arm.h" -#include "sysemu/sysemu.h" -#include "exec/address-spaces.h" -#include "hw/arm/raspi_platform.h" -#include "hw/arm/bcm2835_common.h" - -/* #define BUS_ADDR(x) ((x) + 0x7e000000) */ - -/* Globals */ -hwaddr bcm2835_vcram_base; - -/* simple bootloader for pi1 */ -static const uint32_t bootloader_0_pi1[] = { - 0xea000006, /* b 0x20 ; reset vector: branch to the bootloader below */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - - 0xe3a00000, /* mov r0, #0 */ - 0xe3a01042, /* mov r1, #67 ; r1 = 0x42 */ - 0xe3811c0c, /* orr r1, r1, #12, 24 ; r1 |= 0xc00 (Linux MACH_BCM2708) */ - 0xe59f2000, /* ldr r2, [pc] ; 0x100 from below */ - 0xe59ff000, /* ldr pc, [pc] ; jump to 0x8000, from below */ - - /* constants */ - 0x00000100, /* (Phys addr of tag list in RAM) */ - 0x00008000 /* (Phys addr of kernel image entry, i.e. where we jump) */ -}; - -/* multi-core-aware bootloader for pi2 */ -static const uint32_t bootloader_0_pi2[] = { - 0xea000006, /* b 0x20 ; reset vector: branch to the bootloader below */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - 0xe1a00000, /* nop ; (mov r0, r0) */ - - /* start of bootloader */ - 0xE3A03902, /* mov r3, #0x8000 ; boot core entry point */ - - /* retrieve core ID */ - 0xEE100FB0, /* mrc p15, 0, r0, c0, c0, 5 ; get core ID */ - 0xE7E10050, /* ubfx r0, r0, #0, #2 ; extract LSB */ - 0xE3500000, /* cmp r0, #0 ; if zero, we're boot core */ - 0x0A000004, /* beq 2f */ - - /* busy-wait for mailbox set on secondary cores */ - 0xE59F501C, /* ldr r4, =0x400000CC ; mbox 3 read/clear base */ - 0xE7953200, /* 1: ldr r3, [r4, r0, lsl #4] ; read mbox for our core */ - 0xE3530000, /* cmp r3, #0 ; spin while zero */ - 0x0AFFFFFC, /* beq 1b */ - 0xE7853200, /* str r3, [r4, r0, lsl #4] ; clear mbox */ - - /* enter image at [r3] */ - 0xE3A00000, /* 2: mov r0, #0 */ - 0xE59F1008, /* ldr r1, =0xc43 ; Linux MACH_BCM2709 */ - 0xE3A02C01, /* ldr r2, =0x100 ; Address of ATAGS */ - 0xE12FFF13, /* bx r3 */ - - /* constants */ - 0x400000CC, - 0x00000C43, -}; - -/* ATAG "tag list" in RAM at 0x100 - * ref: http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html */ -static uint32_t bootloader_100[] = { - 0x00000005, /* length of core tag (words) */ - 0x54410001, /* ATAG_CORE */ - 0x00000001, /* flags */ - 0x00001000, /* page size (4k) */ - 0x00000000, /* root device */ - 0x00000004, /* length of mem tag (words) */ - 0x54410002, /* ATAG_MEM */ - 0x08000000, /* RAM size (to be overwritten by dynamic memory size) */ - 0x00000000, /* start of RAM */ - 0x00000000, /* "length" of none tag (magic) */ - 0x00000000 /* ATAG_NONE */ -}; - -#if 0 -static void init_pi2_cpus(const char *cpu_model, DeviceState *icdev) -{ - ObjectClass *cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); - int n; - - if (!cpu_oc) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - - for (n = 0; n < smp_cpus; n++) { - Object *cpu = object_new(object_class_get_name(cpu_oc)); - Error *err = NULL; - - /* Mirror bcm2836, which has clusterid set to 0xf */ - ARM_CPU(cpu)->mp_affinity = 0xF00 | n; - - /* set periphbase/CBAR value for CPU-local registers */ - object_property_set_int(cpu, BCM2836_PERI_BASE + MCORE_OFFSET, - "reset-cbar", &error_abort); - - object_property_set_bool(cpu, true, "realized", &err); - if (err) { - error_report_err(err); - exit(1); - } - - /* Connect irq/fiq outputs from the interrupt controller. */ - qdev_connect_gpio_out_named(icdev, "irq", n, - qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); - qdev_connect_gpio_out_named(icdev, "fiq", n, - qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ)); - - /* Connect timers from the CPU to the interrupt controller */ - ARM_CPU(cpu)->gt_timer_outputs[GTIMER_PHYS] - = qdev_get_gpio_in_named(icdev, "cntpsirq", 0); - ARM_CPU(cpu)->gt_timer_outputs[GTIMER_VIRT] - = qdev_get_gpio_in_named(icdev, "cntvirq", 0); - } -} -#endif - -static void init_ram(Object *parent, ram_addr_t ram_size) -{ - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *ram_alias = g_new(MemoryRegion, 3); - int n; - - bcm2835_vcram_base = ram_size - VCRAM_SIZE; - - /* Write real RAM size in ATAG structure */ - bootloader_100[7] = bcm2835_vcram_base; - - memory_region_allocate_system_memory(ram, parent, "ram", ram_size); - memory_region_add_subregion_overlap(sysmem, 0, ram, 0); - - for (n = 0; n < 3; n++) { - memory_region_init_alias(&ram_alias[n], parent, "ram_alias", ram, 0, - ram_size); - memory_region_add_subregion(sysmem, (hwaddr)(n+1) << 30, &ram_alias[n]); - } -} - -#if 0 -static void init_common_devices(hwaddr peribase, qemu_irq cpuirq, - qemu_irq cpufiq) -{ - MemoryRegion *sysmem = get_system_memory(); - - MemoryRegion *per_ic_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_uart0_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_uart1_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_st_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_sbm_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_power_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_fb_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_prop_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_vchiq_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_emmc_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_dma1_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_dma2_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_timer_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_usb_bus = g_new(MemoryRegion, 1); - MemoryRegion *per_mphi_bus = g_new(MemoryRegion, 1); - - MemoryRegion *mr; - qemu_irq pic[72]; - qemu_irq mbox_irq[MBOX_CHAN_COUNT]; - DeviceState *dev; - SysBusDevice *s; - hwaddr tmpoffset; - int n; - - /* Interrupt Controller */ - dev = sysbus_create_varargs("bcm2835_ic", peribase + ARMCTRL_IC_OFFSET, - cpuirq, cpufiq, NULL); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_ic_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(ARMCTRL_IC_OFFSET), - per_ic_bus); - - for (n = 0; n < 72; n++) { - pic[n] = qdev_get_gpio_in(dev, n); - } - - /* UART0 */ - dev = sysbus_create_simple("pl011", peribase + UART0_OFFSET, - pic[INTERRUPT_VC_UART]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_uart0_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(UART0_OFFSET), per_uart0_bus); - - /* UART1 */ - dev = sysbus_create_simple("bcm2835_aux", peribase + UART1_OFFSET, - pic[INTERRUPT_AUX]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_uart1_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(UART1_OFFSET), per_uart1_bus); - - /* System timer */ - dev = sysbus_create_varargs("bcm2835_st", peribase + ST_OFFSET, - pic[INTERRUPT_TIMER0], pic[INTERRUPT_TIMER1], - pic[INTERRUPT_TIMER2], pic[INTERRUPT_TIMER3], - NULL); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_st_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(ST_OFFSET), per_st_bus); - - /* ARM timer */ - dev = sysbus_create_simple("bcm2835_timer", - peribase + ARMCTRL_TIMER0_1_OFFSET, - pic[INTERRUPT_ARM_TIMER]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_timer_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(ARMCTRL_TIMER0_1_OFFSET), - per_timer_bus); - - /* USB controller */ - dev = sysbus_create_simple("bcm2835_usb", peribase + USB_OFFSET, - pic[INTERRUPT_VC_USB]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_usb_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(USB_OFFSET), per_usb_bus); - - /* MPHI - Message-based Parallel Host Interface */ - dev = sysbus_create_simple("bcm2835_mphi", peribase + MPHI_OFFSET, - pic[INTERRUPT_HOSTPORT]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_mphi_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(MPHI_OFFSET), per_mphi_bus); - - /* Semaphores / Doorbells / Mailboxes */ - dev = sysbus_create_simple("bcm2835_sbm", peribase + ARMCTRL_0_SBM_OFFSET, - pic[INTERRUPT_ARM_MAILBOX]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_sbm_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(ARMCTRL_0_SBM_OFFSET), - per_sbm_bus); - - for (n = 0; n < MBOX_CHAN_COUNT; n++) { - mbox_irq[n] = qdev_get_gpio_in(dev, n); - } - - /* Mailbox-addressable peripherals using (hopefully) free address space */ - /* locations and pseudo-irqs to dispatch mailbox requests and responses */ - /* between them. */ - - tmpoffset = ARMCTRL_0_SBM_OFFSET + 0x400; - - /* Power management */ - dev = sysbus_create_simple("bcm2835_power", - peribase + tmpoffset + (MBOX_CHAN_POWER<<4), - mbox_irq[MBOX_CHAN_POWER]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_power_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, - BUS_ADDR(tmpoffset + (MBOX_CHAN_POWER<<4)), - per_power_bus); - - /* Framebuffer */ - dev = sysbus_create_simple("bcm2835_fb", - peribase + tmpoffset + (MBOX_CHAN_FB<<4), - mbox_irq[MBOX_CHAN_FB]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_fb_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(tmpoffset + (MBOX_CHAN_FB<<4)), - per_fb_bus); - - /* Property channel */ - dev = sysbus_create_simple("bcm2835_property", - peribase + tmpoffset + (MBOX_CHAN_PROPERTY<<4), - mbox_irq[MBOX_CHAN_PROPERTY]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_prop_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, - BUS_ADDR(tmpoffset + (MBOX_CHAN_PROPERTY<<4)), - per_prop_bus); - - /* VCHIQ */ - dev = sysbus_create_simple("bcm2835_vchiq", - peribase + tmpoffset + (MBOX_CHAN_VCHIQ<<4), - mbox_irq[MBOX_CHAN_VCHIQ]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_vchiq_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, - BUS_ADDR(tmpoffset + (MBOX_CHAN_VCHIQ<<4)), - per_vchiq_bus); - - /* Extended Mass Media Controller */ - dev = sysbus_create_simple("bcm2835_emmc", peribase + EMMC_OFFSET, - pic[INTERRUPT_VC_ARASANSDIO]); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_emmc_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(EMMC_OFFSET), per_emmc_bus); - - /* DMA Channels */ - dev = qdev_create(NULL, "bcm2835_dma"); - s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, peribase + DMA_OFFSET); - sysbus_mmio_map(s, 1, peribase + 0xe05000); - s = SYS_BUS_DEVICE(dev); - mr = sysbus_mmio_get_region(s, 0); - memory_region_init_alias(per_dma1_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(DMA_OFFSET), per_dma1_bus); - mr = sysbus_mmio_get_region(s, 1); - memory_region_init_alias(per_dma2_bus, NULL, NULL, mr, 0, - memory_region_size(mr)); - memory_region_add_subregion(sysmem, BUS_ADDR(0xe05000), per_dma2_bus); - - sysbus_connect_irq(s, 0, pic[INTERRUPT_DMA0]); - sysbus_connect_irq(s, 1, pic[INTERRUPT_DMA1]); - sysbus_connect_irq(s, 2, pic[INTERRUPT_VC_DMA2]); - sysbus_connect_irq(s, 3, pic[INTERRUPT_VC_DMA3]); - sysbus_connect_irq(s, 4, pic[INTERRUPT_DMA4]); - sysbus_connect_irq(s, 5, pic[INTERRUPT_DMA5]); - sysbus_connect_irq(s, 6, pic[INTERRUPT_DMA6]); - sysbus_connect_irq(s, 7, pic[INTERRUPT_DMA7]); - sysbus_connect_irq(s, 8, pic[INTERRUPT_DMA8]); - sysbus_connect_irq(s, 9, pic[INTERRUPT_DMA9]); - sysbus_connect_irq(s, 10, pic[INTERRUPT_DMA10]); - sysbus_connect_irq(s, 11, pic[INTERRUPT_DMA11]); - sysbus_connect_irq(s, 12, pic[INTERRUPT_DMA12]); -} -#endif - -static void setup_boot(MachineState *machine, int board_id, - const uint32_t *bootloader, size_t bootloader_len) -{ - static struct arm_boot_info raspi_binfo; - int n; - - raspi_binfo.board_id = board_id; - raspi_binfo.ram_size = bcm2835_vcram_base; - - /* If the user specified a "firmware" image (e.g. UEFI), we bypass - the normal Linux boot process */ - if (machine->firmware) { - /* XXX: Kludge for Windows support: put framebuffer in BGR - * mode. We need a config switch somewhere to enable this. It - * should ultimately be emulated by looking in config.txt (as - * the real firmware does) for the relevant options */ - if (bootloader == bootloader_0_pi2) { - bcm2835_fb.pixo = 0; - } - - /* load the firmware image (typically kernel.img) at 0x8000 */ - load_image_targphys(machine->firmware, - 0x8000, - bcm2835_vcram_base - 0x8000); - - /* copy over the bootloader */ - for (n = 0; n < bootloader_len; n++) { - stl_phys(&address_space_memory, (n << 2), bootloader[n]); - } - for (n = 0; n < ARRAY_SIZE(bootloader_100); n++) { - stl_phys(&address_space_memory, 0x100 + (n << 2), - bootloader_100[n]); - } - - /* set variables so arm_load_kernel does the right thing */ - raspi_binfo.is_linux = false; - raspi_binfo.entry = 0x20; - raspi_binfo.firmware_loaded = true; - } else { - /* Just let arm_load_kernel do everything for us... */ - raspi_binfo.kernel_filename = machine->kernel_filename; - raspi_binfo.kernel_cmdline = machine->kernel_cmdline; - raspi_binfo.initrd_filename = machine->initrd_filename; - } - - arm_load_kernel(ARM_CPU(first_cpu), &raspi_binfo); -} - -#if 0 -static void raspi_init(MachineState *machine) -{ - ARMCPU *cpu; - - cpu = cpu_arm_init("arm1176"); - if (!cpu) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - - init_ram(OBJECT(machine), machine->ram_size); - - init_common_devices(BCM2835_PERI_BASE, - qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ), - qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ)); - - setup_boot(machine, 0xc42, bootloader_0_pi1, ARRAY_SIZE(bootloader_0_pi1)); -} -#endif - -static void raspi2_init(MachineState *machine) -{ - Object *bcm2836; - Error *err = NULL; - - bcm2836 = object_new(TYPE_BCM2836); - object_property_add_child(OBJECT(machine), "soc", bcm2836, &error_abort); - - object_property_set_bool(bcm2836, true, "realized", &err); - if (err) { - error_report("%s", error_get_pretty(err)); - exit(1); - } - - init_ram(OBJECT(machine), machine->ram_size); - setup_boot(machine, 0xc43, bootloader_0_pi2, ARRAY_SIZE(bootloader_0_pi2)); -} - -#if 0 -static void raspi_machine_init(MachineClass *mc) -{ - mc->desc = "Raspberry Pi"; - mc->init = raspi_init; - mc->block_default_type = IF_SD; -}; -DEFINE_MACHINE("raspi", raspi_machine_init) -#endif - -static void raspi2_machine_init(MachineClass *mc) -{ - mc->desc = "Raspberry Pi 2"; - mc->init = raspi2_init; - mc->block_default_type = IF_SD; - mc->max_cpus = 4; -}; -DEFINE_MACHINE("raspi2", raspi2_machine_init) +/* + * Raspberry Pi emulation (c) 2012 Gregory Estrade + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous + * + * Rasperry Pi 2 emulation Copyright (c) 2015, Microsoft + * Written by Andrew Baumann + * + * This code is licensed under the GNU GPLv2 and later. + */ + +/* Based on versatilepb.c, copyright terms below. */ + +/* + * ARM Versatile Platform/Application Baseboard System emulation. + * + * Copyright (c) 2005-2007 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the GPL. + */ + +#include "hw/arm/bcm2835.h" +#include "hw/arm/bcm2836.h" +#include "qemu/error-report.h" +#include "hw/boards.h" +#include "hw/devices.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/arm/arm.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "hw/arm/raspi_platform.h" +#include "hw/arm/bcm2835_common.h" + +/* Globals */ +hwaddr bcm2835_vcram_base; + +/* simple bootloader for pi1 */ +static const uint32_t bootloader_0_pi1[] = { + 0xea000006, /* b 0x20 ; reset vector: branch to the bootloader below */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + + 0xe3a00000, /* mov r0, #0 */ + 0xe3a01042, /* mov r1, #67 ; r1 = 0x42 */ + 0xe3811c0c, /* orr r1, r1, #12, 24 ; r1 |= 0xc00 (Linux MACH_BCM2708) */ + 0xe59f2000, /* ldr r2, [pc] ; 0x100 from below */ + 0xe59ff000, /* ldr pc, [pc] ; jump to 0x8000, from below */ + + /* constants */ + 0x00000100, /* (Phys addr of tag list in RAM) */ + 0x00008000 /* (Phys addr of kernel image entry, i.e. where we jump) */ +}; + +/* multi-core-aware bootloader for pi2 */ +static const uint32_t bootloader_0_pi2[] = { + 0xea000006, /* b 0x20 ; reset vector: branch to the bootloader below */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + 0xe1a00000, /* nop ; (mov r0, r0) */ + + /* start of bootloader */ + 0xE3A03902, /* mov r3, #0x8000 ; boot core entry point */ + + /* retrieve core ID */ + 0xEE100FB0, /* mrc p15, 0, r0, c0, c0, 5 ; get core ID */ + 0xE7E10050, /* ubfx r0, r0, #0, #2 ; extract LSB */ + 0xE3500000, /* cmp r0, #0 ; if zero, we're boot core */ + 0x0A000004, /* beq 2f */ + + /* busy-wait for mailbox set on secondary cores */ + 0xE59F501C, /* ldr r4, =0x400000CC ; mbox 3 read/clear base */ + 0xE7953200, /* 1: ldr r3, [r4, r0, lsl #4] ; read mbox for our core */ + 0xE3530000, /* cmp r3, #0 ; spin while zero */ + 0x0AFFFFFC, /* beq 1b */ + 0xE7853200, /* str r3, [r4, r0, lsl #4] ; clear mbox */ + + /* enter image at [r3] */ + 0xE3A00000, /* 2: mov r0, #0 */ + 0xE59F1008, /* ldr r1, =0xc43 ; Linux MACH_BCM2709 */ + 0xE3A02C01, /* ldr r2, =0x100 ; Address of ATAGS */ + 0xE12FFF13, /* bx r3 */ + + /* constants */ + 0x400000CC, + 0x00000C43, +}; + +/* ATAG "tag list" in RAM at 0x100 + * ref: http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html */ +static uint32_t bootloader_100[] = { + 0x00000005, /* length of core tag (words) */ + 0x54410001, /* ATAG_CORE */ + 0x00000001, /* flags */ + 0x00001000, /* page size (4k) */ + 0x00000000, /* root device */ + 0x00000004, /* length of mem tag (words) */ + 0x54410002, /* ATAG_MEM */ + 0x08000000, /* RAM size (to be overwritten by dynamic memory size) */ + 0x00000000, /* start of RAM */ + 0x00000000, /* "length" of none tag (magic) */ + 0x00000000 /* ATAG_NONE */ +}; + +static void init_ram(Object *parent, ram_addr_t ram_size) +{ + MemoryRegion *ram = g_new(MemoryRegion, 1); + + bcm2835_vcram_base = ram_size - VCRAM_SIZE; + + /* Write real RAM size in ATAG structure */ + bootloader_100[7] = bcm2835_vcram_base; + + memory_region_allocate_system_memory(ram, parent, "ram", ram_size); + memory_region_add_subregion_overlap(get_system_memory(), 0, ram, 0); +} + +static void setup_boot(MachineState *machine, int board_id, + const uint32_t *bootloader, size_t bootloader_len) +{ + static struct arm_boot_info raspi_binfo; + int n; + + raspi_binfo.board_id = board_id; + raspi_binfo.ram_size = bcm2835_vcram_base; + + /* If the user specified a "firmware" image (e.g. UEFI), we bypass + the normal Linux boot process */ + if (machine->firmware) { + /* XXX: Kludge for Windows support: put framebuffer in BGR + * mode. We need a config switch somewhere to enable this. It + * should ultimately be emulated by looking in config.txt (as + * the real firmware does) for the relevant options */ + if (bootloader == bootloader_0_pi2) { + bcm2835_fb.pixo = 0; + } + + /* load the firmware image (typically kernel.img) at 0x8000 */ + load_image_targphys(machine->firmware, + 0x8000, + bcm2835_vcram_base - 0x8000); + + /* copy over the bootloader */ + for (n = 0; n < bootloader_len; n++) { + stl_phys(&address_space_memory, (n << 2), bootloader[n]); + } + for (n = 0; n < ARRAY_SIZE(bootloader_100); n++) { + stl_phys(&address_space_memory, 0x100 + (n << 2), + bootloader_100[n]); + } + + /* set variables so arm_load_kernel does the right thing */ + raspi_binfo.is_linux = false; + raspi_binfo.entry = 0x20; + raspi_binfo.firmware_loaded = true; + } else { + /* Just let arm_load_kernel do everything for us... */ + raspi_binfo.kernel_filename = machine->kernel_filename; + raspi_binfo.kernel_cmdline = machine->kernel_cmdline; + raspi_binfo.initrd_filename = machine->initrd_filename; + } + + arm_load_kernel(ARM_CPU(first_cpu), &raspi_binfo); +} + +static void raspi_init(MachineState *machine) +{ + Object *bcm2835; + Error *err = NULL; + + init_ram(OBJECT(machine), machine->ram_size); + + bcm2835 = object_new(TYPE_BCM2835); + object_property_add_child(OBJECT(machine), "soc", bcm2835, &error_abort); + + object_property_set_bool(bcm2835, true, "realized", &err); + if (err) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + + setup_boot(machine, 0xc42, bootloader_0_pi1, ARRAY_SIZE(bootloader_0_pi1)); +} + +static void raspi2_init(MachineState *machine) +{ + Object *bcm2836; + Error *err = NULL; + + init_ram(OBJECT(machine), machine->ram_size); + + bcm2836 = object_new(TYPE_BCM2836); + object_property_add_child(OBJECT(machine), "soc", bcm2836, &error_abort); + + object_property_set_bool(bcm2836, true, "realized", &err); + if (err) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + + setup_boot(machine, 0xc43, bootloader_0_pi2, ARRAY_SIZE(bootloader_0_pi2)); +} + +static void raspi_machine_init(MachineClass *mc) +{ + mc->desc = "Raspberry Pi"; + mc->init = raspi_init; + mc->block_default_type = IF_SD; +}; +DEFINE_MACHINE("raspi", raspi_machine_init) + +static void raspi2_machine_init(MachineClass *mc) +{ + mc->desc = "Raspberry Pi 2"; + mc->init = raspi2_init; + mc->block_default_type = IF_SD; + mc->max_cpus = BCM2836_NCPUS; +}; +DEFINE_MACHINE("raspi2", raspi2_machine_init) diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index 2e21bf070b..a4118d3f76 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -38,6 +38,10 @@ Bcm2835Fb bcm2835_fb; +// XXX: FIXME: +extern AddressSpace *bcm2835_peripheral_as; +extern MemoryRegion *bcm2835_peripheral_mr; + #define TYPE_BCM2835_FB "bcm2835_fb" #define BCM2835_FB(obj) OBJECT_CHECK(Bcm2835FbState, (obj), TYPE_BCM2835_FB) @@ -67,7 +71,7 @@ static void draw_line_src16(void *opaque, uint8_t *d, const uint8_t *s, while (width--) { switch (bcm2835_fb.bpp) { case 8: - rgb888 = ldl_phys(&address_space_memory, + rgb888 = ldl_phys(bcm2835_peripheral_as, bcm2835_vcram_base + (*s << 2)); r = (rgb888 >> 0) & 0xff; g = (rgb888 >> 8) & 0xff; @@ -195,7 +199,7 @@ static void fb_update_display(void *opaque) if (bcm2835_fb.invalidate) { framebuffer_update_memory_section(&s->fbsection, - sysbus_address_space(&s->busdev), + bcm2835_peripheral_mr, bcm2835_fb.base, bcm2835_fb.yres, src_width); @@ -226,21 +230,16 @@ static void bcm2835_fb_mbox_push(Bcm2835FbState *s, uint32_t value) { value &= ~0xf; - /* UEFI passes a high (uncached?) address here */ - if (value >= 0xc0000000) { - value -= 0xc0000000; - } - bcm2835_fb.lock = 1; - bcm2835_fb.xres = ldl_phys(&address_space_memory, value); - bcm2835_fb.yres = ldl_phys(&address_space_memory, value + 4); - bcm2835_fb.xres_virtual = ldl_phys(&address_space_memory, value + 8); - bcm2835_fb.yres_virtual = ldl_phys(&address_space_memory, value + 12); + bcm2835_fb.xres = ldl_phys(bcm2835_peripheral_as, value); + bcm2835_fb.yres = ldl_phys(bcm2835_peripheral_as, value + 4); + bcm2835_fb.xres_virtual = ldl_phys(bcm2835_peripheral_as, value + 8); + bcm2835_fb.yres_virtual = ldl_phys(bcm2835_peripheral_as, value + 12); - bcm2835_fb.bpp = ldl_phys(&address_space_memory, value + 20); - bcm2835_fb.xoffset = ldl_phys(&address_space_memory, value + 24); - bcm2835_fb.yoffset = ldl_phys(&address_space_memory, value + 28); + bcm2835_fb.bpp = ldl_phys(bcm2835_peripheral_as, value + 20); + bcm2835_fb.xoffset = ldl_phys(bcm2835_peripheral_as, value + 24); + bcm2835_fb.yoffset = ldl_phys(bcm2835_peripheral_as, value + 28); bcm2835_fb.base = bcm2835_vcram_base | (value & 0xc0000000); bcm2835_fb.base += BCM2835_FB_OFFSET; @@ -250,9 +249,9 @@ static void bcm2835_fb_mbox_push(Bcm2835FbState *s, uint32_t value) bcm2835_fb.pitch = bcm2835_fb.xres * (bcm2835_fb.bpp >> 3); bcm2835_fb.size = bcm2835_fb.yres * bcm2835_fb.pitch; - stl_phys(&address_space_memory, value + 16, bcm2835_fb.pitch); - stl_phys(&address_space_memory, value + 32, bcm2835_fb.base); - stl_phys(&address_space_memory, value + 36, bcm2835_fb.size); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_fb.pitch); + stl_phys(bcm2835_peripheral_as, value + 32, bcm2835_fb.base); + stl_phys(bcm2835_peripheral_as, value + 36, bcm2835_fb.size); bcm2835_fb.invalidate = 1; qemu_console_resize(bcm2835_fb.con, bcm2835_fb.xres, bcm2835_fb.yres); diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c index 6ea3402644..fec774013c 100644 --- a/hw/dma/bcm2835_dma.c +++ b/hw/dma/bcm2835_dma.c @@ -6,6 +6,9 @@ #include "hw/sysbus.h" #include "exec/address-spaces.h" +// XXX: FIXME: +extern AddressSpace *bcm2835_peripheral_as; + /* DMA CS Control and Status bits */ #define BCM2708_DMA_ACTIVE (1 << 0) #define BCM2708_DMA_INT (1 << 2) @@ -88,12 +91,12 @@ static void bcm2835_dma_update(Bcm2835DmaState *s, int c) while ((s->enable & (1 << c)) && (ch->conblk_ad != 0)) { /* CB fetch */ - ch->ti = ldl_phys(&address_space_memory, ch->conblk_ad); - ch->source_ad = ldl_phys(&address_space_memory, ch->conblk_ad + 4); - ch->dest_ad = ldl_phys(&address_space_memory, ch->conblk_ad + 8); - ch->txfr_len = ldl_phys(&address_space_memory, ch->conblk_ad + 12); - ch->stride = ldl_phys(&address_space_memory, ch->conblk_ad + 16); - ch->nextconbk = ldl_phys(&address_space_memory, ch->conblk_ad + 20); + ch->ti = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad); + ch->source_ad = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad + 4); + ch->dest_ad = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad + 8); + ch->txfr_len = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad + 12); + ch->stride = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad + 16); + ch->nextconbk = ldl_phys(bcm2835_peripheral_as, ch->conblk_ad + 20); assert(!(ch->ti & BCM2708_DMA_TDMODE)); @@ -102,7 +105,7 @@ static void bcm2835_dma_update(Bcm2835DmaState *s, int c) if (ch->ti & (1 << 11)) { /* Ignore reads */ } else { - data = ldl_phys(&address_space_memory, ch->source_ad); + data = ldl_phys(bcm2835_peripheral_as, ch->source_ad); } if (ch->ti & BCM2708_DMA_S_INC) { ch->source_ad += 4; @@ -111,7 +114,7 @@ static void bcm2835_dma_update(Bcm2835DmaState *s, int c) if (ch->ti & (1 << 7)) { /* Ignore writes */ } else { - stl_phys(&address_space_memory, ch->dest_ad, data); + stl_phys(bcm2835_peripheral_as, ch->dest_ad, data); } if (ch->ti & BCM2708_DMA_D_INC) { ch->dest_ad += 4; diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index 8d9acb6721..d172531d0e 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -11,6 +11,9 @@ #include "hw/arm/bcm2835_common.h" +// XXX: FIXME: +extern AddressSpace *bcm2835_peripheral_as; + #define TYPE_BCM2835_PROPERTY "bcm2835_property" #define BCM2835_PROPERTY(obj) \ OBJECT_CHECK(Bcm2835PropertyState, (obj), TYPE_BCM2835_PROPERTY) @@ -52,31 +55,22 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, value &= ~0xf; - /* XXX: According to the doc link above, the physical address - should be used. However, the Windows UEFI loader is observed - talking to us using the uncached mapping address (of - 0xc0000000), and evidently that is expected to work as well. - */ - if (value > 0xc0000000) { - value -= 0xc0000000; - } - s->addr = value; - tot_len = ldl_phys(&address_space_memory, value); + tot_len = ldl_phys(bcm2835_peripheral_as, value); /* @(s->addr + 4) : Buffer response code */ value = s->addr + 8; while (value + 8 <= s->addr + tot_len) { - tag = ldl_phys(&address_space_memory, value); - bufsize = ldl_phys(&address_space_memory, value + 4); + tag = ldl_phys(bcm2835_peripheral_as, value); + bufsize = ldl_phys(bcm2835_peripheral_as, value + 4); /* @(value + 8) : Request/response indicator */ resplen = 0; switch (tag) { case 0x00000000: /* End tag */ break; case 0x00000001: /* Get firmware revision */ - stl_phys(&address_space_memory, value + 12, 346337); + stl_phys(bcm2835_peripheral_as, value + 12, 346337); resplen = 4; break; @@ -88,10 +82,10 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, break; case 0x00010003: /* Get board MAC address */ /* write the first four bytes of the 6-byte MAC */ - stl_phys(&address_space_memory, value + 12, 0xB827EBD0); + stl_phys(bcm2835_peripheral_as, value + 12, 0xB827EBD0); /* write the last two bytes, avoid any write past the buffer end */ - stb_phys(&address_space_memory, value + 16, 0xEE); - stb_phys(&address_space_memory, value + 17, 0xDF); + stb_phys(bcm2835_peripheral_as, value + 16, 0xEE); + stb_phys(bcm2835_peripheral_as, value + 17, 0xDF); resplen = 6; break; case 0x00010004: /* Get board serial */ @@ -99,30 +93,30 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, break; case 0x00010005: /* Get ARM memory */ /* base */ - stl_phys(&address_space_memory, value + 12, 0); + stl_phys(bcm2835_peripheral_as, value + 12, 0); /* size */ - stl_phys(&address_space_memory, value + 16, bcm2835_vcram_base); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_vcram_base); resplen = 8; break; case 0x00010006: /* Get VC memory */ /* base */ - stl_phys(&address_space_memory, value + 12, bcm2835_vcram_base); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_vcram_base); /* size */ - stl_phys(&address_space_memory, value + 16, VCRAM_SIZE); + stl_phys(bcm2835_peripheral_as, value + 16, VCRAM_SIZE); resplen = 8; break; case 0x00028001: /* Set power state */ /* Assume that whatever device they asked for exists, * and we'll just claim we set it to the desired state */ - tmp = ldl_phys(&address_space_memory, value + 16); - stl_phys(&address_space_memory, value + 16, (tmp & 1)); + tmp = ldl_phys(bcm2835_peripheral_as, value + 16); + stl_phys(bcm2835_peripheral_as, value + 16, (tmp & 1)); resplen = 8; break; /* Clocks */ case 0x00030001: /* Get clock state */ - stl_phys(&address_space_memory, value + 16, 0x1); + stl_phys(bcm2835_peripheral_as, value + 16, 0x1); resplen = 8; break; @@ -133,15 +127,15 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, case 0x00030002: /* Get clock rate */ case 0x00030004: /* Get max clock rate */ case 0x00030007: /* Get min clock rate */ - switch (ldl_phys(&address_space_memory, value + 12)) { + switch (ldl_phys(bcm2835_peripheral_as, value + 12)) { case 1: /* EMMC */ - stl_phys(&address_space_memory, value + 16, 50000000); + stl_phys(bcm2835_peripheral_as, value + 16, 50000000); break; case 2: /* UART */ - stl_phys(&address_space_memory, value + 16, 3000000); + stl_phys(bcm2835_peripheral_as, value + 16, 3000000); break; default: - stl_phys(&address_space_memory, value + 16, 700000000); + stl_phys(bcm2835_peripheral_as, value + 16, 700000000); break; } resplen = 8; @@ -156,12 +150,12 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, /* Temperature */ case 0x00030006: /* Get temperature */ - stl_phys(&address_space_memory, value + 16, 25000); + stl_phys(bcm2835_peripheral_as, value + 16, 25000); resplen = 8; break; case 0x0003000A: /* Get max temperature */ - stl_phys(&address_space_memory, value + 16, 99000); + stl_phys(bcm2835_peripheral_as, value + 16, 99000); resplen = 8; break; @@ -169,8 +163,8 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, /* Frame buffer */ case 0x00040001: /* Allocate buffer */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.base); - stl_phys(&address_space_memory, value + 16, bcm2835_fb.size); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.base); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_fb.size); resplen = 8; break; case 0x00048001: /* Release buffer */ @@ -181,8 +175,8 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, break; case 0x00040003: /* Get display width/height */ case 0x00040004: - stl_phys(&address_space_memory, value + 12, bcm2835_fb.xres); - stl_phys(&address_space_memory, value + 16, bcm2835_fb.yres); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.xres); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_fb.yres); resplen = 8; break; case 0x00044003: /* Test display width/height */ @@ -191,94 +185,94 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, break; case 0x00048003: /* Set display width/height */ case 0x00048004: - bcm2835_fb.xres = ldl_phys(&address_space_memory, value + 12); - bcm2835_fb.yres = ldl_phys(&address_space_memory, value + 16); + bcm2835_fb.xres = ldl_phys(bcm2835_peripheral_as, value + 12); + bcm2835_fb.yres = ldl_phys(bcm2835_peripheral_as, value + 16); update_fb(); resplen = 8; break; case 0x00040005: /* Get depth */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.bpp); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.bpp); resplen = 4; break; case 0x00044005: /* Test depth */ resplen = 4; break; case 0x00048005: /* Set depth */ - bcm2835_fb.bpp = ldl_phys(&address_space_memory, value + 12); + bcm2835_fb.bpp = ldl_phys(bcm2835_peripheral_as, value + 12); update_fb(); resplen = 4; break; case 0x00040006: /* Get pixel order */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.pixo); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.pixo); resplen = 4; break; case 0x00044006: /* Test pixel order */ resplen = 4; break; case 0x00048006: /* Set pixel order */ - bcm2835_fb.pixo = ldl_phys(&address_space_memory, value + 12); + bcm2835_fb.pixo = ldl_phys(bcm2835_peripheral_as, value + 12); update_fb(); resplen = 4; break; case 0x00040007: /* Get alpha */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.alpha); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.alpha); resplen = 4; break; case 0x00044007: /* Test pixel alpha */ resplen = 4; break; case 0x00048007: /* Set alpha */ - bcm2835_fb.alpha = ldl_phys(&address_space_memory, value + 12); + bcm2835_fb.alpha = ldl_phys(bcm2835_peripheral_as, value + 12); update_fb(); resplen = 4; break; case 0x00040008: /* Get pitch */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.pitch); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.pitch); resplen = 4; break; case 0x00040009: /* Get virtual offset */ - stl_phys(&address_space_memory, value + 12, bcm2835_fb.xoffset); - stl_phys(&address_space_memory, value + 16, bcm2835_fb.yoffset); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.xoffset); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_fb.yoffset); resplen = 8; break; case 0x00044009: /* Test virtual offset */ resplen = 8; break; case 0x00048009: /* Set virtual offset */ - bcm2835_fb.xoffset = ldl_phys(&address_space_memory, value + 12); - bcm2835_fb.yoffset = ldl_phys(&address_space_memory, value + 16); + bcm2835_fb.xoffset = ldl_phys(bcm2835_peripheral_as, value + 12); + bcm2835_fb.yoffset = ldl_phys(bcm2835_peripheral_as, value + 16); update_fb(); - stl_phys(&address_space_memory, value + 12, bcm2835_fb.xres); - stl_phys(&address_space_memory, value + 16, bcm2835_fb.yres); + stl_phys(bcm2835_peripheral_as, value + 12, bcm2835_fb.xres); + stl_phys(bcm2835_peripheral_as, value + 16, bcm2835_fb.yres); resplen = 8; break; case 0x0004000a: /* Get/Test/Set overscan */ case 0x0004400a: case 0x0004800a: - stl_phys(&address_space_memory, value + 12, 0); - stl_phys(&address_space_memory, value + 16, 0); - stl_phys(&address_space_memory, value + 20, 0); - stl_phys(&address_space_memory, value + 24, 0); + stl_phys(bcm2835_peripheral_as, value + 12, 0); + stl_phys(bcm2835_peripheral_as, value + 16, 0); + stl_phys(bcm2835_peripheral_as, value + 20, 0); + stl_phys(bcm2835_peripheral_as, value + 24, 0); resplen = 16; break; case 0x0004800b: /* Set palette */ - offset = ldl_phys(&address_space_memory, value + 12); - length = ldl_phys(&address_space_memory, value + 16); + offset = ldl_phys(bcm2835_peripheral_as, value + 12); + length = ldl_phys(bcm2835_peripheral_as, value + 16); n = 0; while (n < length - offset) { - color = ldl_phys(&address_space_memory, value + 20 + (n << 2)); - stl_phys(&address_space_memory, + color = ldl_phys(bcm2835_peripheral_as, value + 20 + (n << 2)); + stl_phys(bcm2835_peripheral_as, bcm2835_vcram_base + ((offset + n) << 2), color); n++; } - stl_phys(&address_space_memory, value + 12, 0); + stl_phys(bcm2835_peripheral_as, value + 12, 0); resplen = 4; break; case 0x00060001: /* Get DMA channels */ /* channels 2-5 */ - stl_phys(&address_space_memory, value + 12, 0x003C); + stl_phys(bcm2835_peripheral_as, value + 12, 0x003C); resplen = 4; break; @@ -296,12 +290,12 @@ static void bcm2835_property_mbox_push(Bcm2835PropertyState *s, break; } - stl_phys(&address_space_memory, value + 8, (1 << 31) | resplen); + stl_phys(bcm2835_peripheral_as, value + 8, (1 << 31) | resplen); value += bufsize + 12; } /* Buffer response code */ - stl_phys(&address_space_memory, s->addr + 4, (1 << 31)); + stl_phys(bcm2835_peripheral_as, s->addr + 4, (1 << 31)); if (bcm2835_fb.lock) { bcm2835_fb.invalidate = 1; diff --git a/hw/misc/bcm2835_sbm.c b/hw/misc/bcm2835_sbm.c index 9871526bd0..62f58873cd 100644 --- a/hw/misc/bcm2835_sbm.c +++ b/hw/misc/bcm2835_sbm.c @@ -104,7 +104,7 @@ static void bcm2835_sbm_update(Bcm2835SbmState *s) for (n = 0; n < MBOX_CHAN_COUNT; n++) { if (s->available[n]) { value = ldl_phys(bcm2835_peripheral_as, - ARMCTRL_0_SBM_OFFSET + 0x400 + (n<<4)); + BCM2835_VC_PERI_BASE + ARMCTRL_0_SBM_OFFSET + 0x400 + (n<<4)); if (value != MBOX_INVALID_DATA) { mbox_push(&s->mbox[0], value); } else { @@ -215,12 +215,12 @@ static void bcm2835_sbm_write(void *opaque, hwaddr offset, ch = value & 0xf; if (ch < MBOX_CHAN_COUNT) { if (ldl_phys(bcm2835_peripheral_as, - ARMCTRL_0_SBM_OFFSET + 0x400 + (ch<<4) + 4)) { + BCM2835_VC_PERI_BASE + ARMCTRL_0_SBM_OFFSET + 0x400 + (ch<<4) + 4)) { /* Push delayed, push it in the arm->vc mbox */ mbox_push(&s->mbox[1], value); } else { stl_phys(bcm2835_peripheral_as, - ARMCTRL_0_SBM_OFFSET + 0x400 + (ch<<4), value); + BCM2835_VC_PERI_BASE + ARMCTRL_0_SBM_OFFSET + 0x400 + (ch<<4), value); } } else { /* Invalid channel number */ diff --git a/include/hw/arm/bcm2835.h b/include/hw/arm/bcm2835.h index 18198e0978..7c85b5af57 100755 --- a/include/hw/arm/bcm2835.h +++ b/include/hw/arm/bcm2835.h @@ -2,6 +2,7 @@ #define BCM2835_H #include "hw/arm/arm.h" +#include "bcm2835_peripherals.h" #define TYPE_BCM2835 "bcm2835" #define BCM2835(obj) OBJECT_CHECK(BCM2835State, (obj), TYPE_BCM2835) @@ -11,11 +12,10 @@ typedef struct BCM2835State { DeviceState parent_obj; /*< public >*/ - MemoryRegion sdram; - MemoryRegion peripherals; ARMCPU cpu; + BCM2835PeripheralState peripherals; - size_t vcram_size; + uint64_t vcram_size; } BCM2835State; #endif /* BCM2835_H */ diff --git a/include/hw/arm/bcm2835_common.h b/include/hw/arm/bcm2835_common.h index adabd68a33..54903bddbe 100644 --- a/include/hw/arm/bcm2835_common.h +++ b/include/hw/arm/bcm2835_common.h @@ -11,10 +11,10 @@ extern hwaddr bcm2835_vcram_base; #define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ #define MBOX_CHAN_COUNT 9 -#define MBOX_SIZE 32 -#define MBOX_INVALID_DATA 0x0f +#define MBOX_SIZE 32 +#define MBOX_INVALID_DATA 0x0f -#define BCM2835_FB_OFFSET 0x00100000 +#define BCM2835_FB_OFFSET 0x00100000 typedef struct { QemuConsole *con; diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index 05bb47588c..84209031d1 100755 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -13,7 +13,9 @@ typedef struct BCM2835PeripheralState { SysBusDevice parent_obj; /*< public >*/ - MemoryRegion iomem; + MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr; + AddressSpace gpu_bus_as; + MemoryRegion ram_alias[4]; qemu_irq irq, fiq; SysBusDevice *ic, *uart0, *uart1, *systimer, *armtimer, *usb, *mphi, *sbm, diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h index cff7b9d0d7..80011bf935 100755 --- a/include/hw/arm/bcm2836.h +++ b/include/hw/arm/bcm2836.h @@ -17,7 +17,6 @@ typedef struct BCM2836State { ARMCPU cpus[BCM2836_NCPUS]; SysBusDevice *ic; BCM2835PeripheralState peripherals; - MemoryRegion peripheral_mr, peripheral_alias, ic_alias; uint64_t vcram_size; } BCM2836State; diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h index 872f17d29a..4b094546fb 100644 --- a/include/hw/arm/raspi_platform.h +++ b/include/hw/arm/raspi_platform.h @@ -26,10 +26,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Pi1 and Pi2 differ only in their peripheral base addresses */ +/* Peripheral base address on the VC (GPU) system bus */ +#define BCM2835_VC_PERI_BASE 0x7e000000 + +/* Peripheral base addresses seen by the CPU: Pi1 and Pi2 differ */ #define BCM2835_PERI_BASE 0x20000000 #define BCM2836_PERI_BASE 0x3F000000 +/* "QA7" (Pi2) interrupt controller and mailboxes etc. */ +#define BCM2836_CONTROL_BASE 0x40000000 + #define MCORE_OFFSET 0x0000 /* Fake frame buffer device * (the multicore sync block) */ #define IC0_OFFSET 0x2000 @@ -57,7 +63,6 @@ #define SMI_OFFSET 0x600000 /* SMI */ #define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */ #define USB_OFFSET 0x980000 /* DTC_OTG USB controller */ -#define BCM2836_CONTROL_OFFSET 0x1000000 /* "QA7" (Pi2) interrupt controller */ /* * Interrupt assignments -- 2.11.4.GIT