summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-05-12 15:55:45 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-05-12 15:55:45 +0100
commite4f70d635863cfc3e3fa7d9a6e37b569ae94d82f (patch)
treee78b4881f2ed4be84792356761ddf2dcdf8e71d8 /hw
parent6ddeeffffecf1f78acf6c93cbf267a8abe755836 (diff)
parent0bc91ab3bb70f836d5a7a3ef6f800ef8c22e936f (diff)
downloadqemu-e4f70d635863cfc3e3fa7d9a6e37b569ae94d82f.tar.gz
qemu-e4f70d635863cfc3e3fa7d9a6e37b569ae94d82f.tar.bz2
qemu-e4f70d635863cfc3e3fa7d9a6e37b569ae94d82f.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160512' into staging
target-arm queue: * blizzard, omap_lcdc: code cleanup to remove DEPTH != 32 dead code * QOMify various ARM devices * bcm2835_property: use cached values when querying framebuffer * hw/arm/nseries: don't allocate large sized array on the stack * fix LPAE descriptor address masking (only visible for EL2) * fix stage 2 exec permission handling for AArch32 * first part of supporting syndrome info for data aborts to EL2 * virt: NUMA support * work towards i.MX6 support * avoid unnecessary TLB flush on TCR_EL2, TCR_EL3 writes # gpg: Signature made Thu 12 May 2016 14:29:14 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" * remotes/pmaydell/tags/pull-target-arm-20160512: (43 commits) hw/arm: QOM'ify versatilepb.c hw/arm: QOM'ify strongarm.c hw/arm: QOM'ify stellaris.c hw/arm: QOM'ify spitz.c hw/arm: QOM'ify pxa2xx_pic.c hw/arm: QOM'ify pxa2xx.c hw/arm: QOM'ify integratorcp.c hw/arm: QOM'ify highbank.c hw/arm: QOM'ify armv7m.c target-arm: Avoid unnecessary TLB flush on TCR_EL2, TCR_EL3 writes hw/display/blizzard: Remove blizzard_template.h hw/display/blizzard: Expand out macros i.MX: Add sabrelite i.MX6 emulation. i.MX: Add i.MX6 SOC implementation. i.MX: Add the Freescale SPI Controller FIFO: Add a FIFO32 implementation i.MX: Add i.MX6 System Reset Controller device. ARM: Factor out ARM on/off PSCI control functions ACPI: Virt: Generate SRAT table ACPI: move acpi_build_srat_memory to common place ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/aml-build.c11
-rw-r--r--hw/arm/Makefile.objs1
-rw-r--r--hw/arm/armv7m.c11
-rw-r--r--hw/arm/boot.c43
-rw-r--r--hw/arm/fsl-imx6.c449
-rw-r--r--hw/arm/highbank.c12
-rw-r--r--hw/arm/integratorcp.c32
-rw-r--r--hw/arm/nseries.c3
-rw-r--r--hw/arm/pxa2xx.c26
-rw-r--r--hw/arm/pxa2xx_pic.c7
-rw-r--r--hw/arm/sabrelite.c121
-rw-r--r--hw/arm/spitz.c23
-rw-r--r--hw/arm/stellaris.c48
-rw-r--r--hw/arm/strongarm.c66
-rw-r--r--hw/arm/versatilepb.c13
-rw-r--r--hw/arm/virt-acpi-build.c52
-rw-r--r--hw/arm/virt.c8
-rw-r--r--hw/display/blizzard.c120
-rw-r--r--hw/display/blizzard_template.h146
-rw-r--r--hw/display/exynos4210_fimd.c19
-rw-r--r--hw/display/omap_lcd_template.h10
-rw-r--r--hw/display/omap_lcdc.c48
-rw-r--r--hw/i386/acpi-build.c41
-rw-r--r--hw/intc/etraxfs_pic.c13
-rw-r--r--hw/intc/exynos4210_combiner.c14
-rw-r--r--hw/intc/exynos4210_gic.c39
-rw-r--r--hw/intc/grlib_irqmp.c27
-rw-r--r--hw/intc/imx_avic.c15
-rw-r--r--hw/intc/omap_intc.c64
-rw-r--r--hw/intc/pl190.c13
-rw-r--r--hw/intc/slavio_intctl.c14
-rw-r--r--hw/misc/Makefile.objs1
-rw-r--r--hw/misc/bcm2835_property.c33
-rw-r--r--hw/misc/imx6_src.c264
-rw-r--r--hw/ssi/Makefile.objs1
-rw-r--r--hw/ssi/imx_spi.c454
36 files changed, 1740 insertions, 522 deletions
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ab89ca6380..cedb74e7cf 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1563,3 +1563,14 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
build_header(linker, table_data,
(void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
}
+
+void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+ uint64_t len, int node, MemoryAffinityFlags flags)
+{
+ numamem->type = ACPI_SRAT_MEMORY;
+ numamem->length = sizeof(*numamem);
+ numamem->proximity = cpu_to_le32(node);
+ numamem->flags = cpu_to_le32(flags);
+ numamem->base_addr = cpu_to_le64(base);
+ numamem->range_length = cpu_to_le64(len);
+}
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 954c9fe15e..12764ef2b7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -16,4 +16,5 @@ 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
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
+obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index bb2a22d967..49d30782c8 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -132,14 +132,14 @@ typedef struct {
uint32_t base;
} BitBandState;
-static int bitband_init(SysBusDevice *dev)
+static void bitband_init(Object *obj)
{
- BitBandState *s = BITBAND(dev);
+ BitBandState *s = BITBAND(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
+ memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base,
"bitband", 0x02000000);
sysbus_init_mmio(dev, &s->iomem);
- return 0;
}
static void armv7m_bitband_init(void)
@@ -244,9 +244,7 @@ static Property bitband_properties[] = {
static void bitband_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = bitband_init;
dc->props = bitband_properties;
}
@@ -254,6 +252,7 @@ static const TypeInfo bitband_info = {
.name = TYPE_BITBAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(BitBandState),
+ .instance_init = bitband_init,
.class_init = bitband_class_init,
};
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 5876945575..1b913a43ca 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -14,6 +14,7 @@
#include "hw/arm/linux-boot-if.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
+#include "sysemu/numa.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "elf.h"
@@ -405,6 +406,9 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
void *fdt = NULL;
int size, rc;
uint32_t acells, scells;
+ char *nodename;
+ unsigned int i;
+ hwaddr mem_base, mem_len;
if (binfo->dtb_filename) {
char *filename;
@@ -456,12 +460,39 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
goto fail;
}
- rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
- acells, binfo->loader_start,
- scells, binfo->ram_size);
- if (rc < 0) {
- fprintf(stderr, "couldn't set /memory/reg\n");
- goto fail;
+ if (nb_numa_nodes > 0) {
+ /*
+ * Turn the /memory node created before into a NOP node, then create
+ * /memory@addr nodes for all numa nodes respectively.
+ */
+ qemu_fdt_nop_node(fdt, "/memory");
+ mem_base = binfo->loader_start;
+ for (i = 0; i < nb_numa_nodes; i++) {
+ mem_len = numa_info[i].node_mem;
+ nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+ rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
+ acells, mem_base,
+ scells, mem_len);
+ if (rc < 0) {
+ fprintf(stderr, "couldn't set %s/reg for node %d\n", nodename,
+ i);
+ goto fail;
+ }
+
+ qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", i);
+ mem_base += mem_len;
+ g_free(nodename);
+ }
+ } else {
+ rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
+ acells, binfo->loader_start,
+ scells, binfo->ram_size);
+ if (rc < 0) {
+ fprintf(stderr, "couldn't set /memory/reg\n");
+ goto fail;
+ }
}
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
new file mode 100644
index 0000000000..a5331bfd33
--- /dev/null
+++ b/hw/arm/fsl-imx6.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * i.MX6 SOC emulation.
+ *
+ * Based on hw/arm/fsl-imx31.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/fsl-imx6.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/char.h"
+#include "qemu/error-report.h"
+
+#define NAME_SIZE 20
+
+static void fsl_imx6_init(Object *obj)
+{
+ FslIMX6State *s = FSL_IMX6(obj);
+ char name[NAME_SIZE];
+ int i;
+
+ if (smp_cpus > FSL_IMX6_NUM_CPUS) {
+ error_report("%s: Only %d CPUs are supported (%d requested)",
+ TYPE_FSL_IMX6, FSL_IMX6_NUM_CPUS, smp_cpus);
+ exit(1);
+ }
+
+ for (i = 0; i < smp_cpus; i++) {
+ object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
+ "cortex-a9-" TYPE_ARM_CPU);
+ snprintf(name, NAME_SIZE, "cpu%d", i);
+ object_property_add_child(obj, name, OBJECT(&s->cpu[i]), NULL);
+ }
+
+ object_initialize(&s->a9mpcore, sizeof(s->a9mpcore), TYPE_A9MPCORE_PRIV);
+ qdev_set_parent_bus(DEVICE(&s->a9mpcore), sysbus_get_default());
+ object_property_add_child(obj, "a9mpcore", OBJECT(&s->a9mpcore), NULL);
+
+ object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX6_CCM);
+ qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
+ object_property_add_child(obj, "ccm", OBJECT(&s->ccm), NULL);
+
+ object_initialize(&s->src, sizeof(s->src), TYPE_IMX6_SRC);
+ qdev_set_parent_bus(DEVICE(&s->src), sysbus_get_default());
+ object_property_add_child(obj, "src", OBJECT(&s->src), NULL);
+
+ for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) {
+ object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
+ qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "uart%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->uart[i]), NULL);
+ }
+
+ object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT);
+ qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
+ object_property_add_child(obj, "gpt", OBJECT(&s->gpt), NULL);
+
+ for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) {
+ object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
+ qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "epit%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->epit[i]), NULL);
+ }
+
+ for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) {
+ object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
+ qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "i2c%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL);
+ }
+
+ for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) {
+ object_initialize(&s->gpio[i], sizeof(s->gpio[i]), TYPE_IMX_GPIO);
+ qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "gpio%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->gpio[i]), NULL);
+ }
+
+ for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
+ object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI);
+ qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
+ }
+
+ for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
+ object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI);
+ qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
+ snprintf(name, NAME_SIZE, "spi%d", i + 1);
+ object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL);
+ }
+}
+
+static void fsl_imx6_realize(DeviceState *dev, Error **errp)
+{
+ FslIMX6State *s = FSL_IMX6(dev);
+ uint16_t i;
+ Error *err = NULL;
+
+ for (i = 0; i < smp_cpus; i++) {
+
+ /* On uniprocessor, the CBAR is set to 0 */
+ if (smp_cpus > 1) {
+ object_property_set_int(OBJECT(&s->cpu[i]), FSL_IMX6_A9MPCORE_ADDR,
+ "reset-cbar", &error_abort);
+ }
+
+ /* All CPU but CPU 0 start in power off mode */
+ if (i) {
+ object_property_set_bool(OBJECT(&s->cpu[i]), true,
+ "start-powered-off", &error_abort);
+ }
+
+ object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ }
+
+ object_property_set_int(OBJECT(&s->a9mpcore), smp_cpus, "num-cpu",
+ &error_abort);
+
+ object_property_set_int(OBJECT(&s->a9mpcore),
+ FSL_IMX6_MAX_IRQ + GIC_INTERNAL, "num-irq",
+ &error_abort);
+
+ object_property_set_bool(OBJECT(&s->a9mpcore), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, FSL_IMX6_A9MPCORE_ADDR);
+
+ for (i = 0; i < smp_cpus; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + smp_cpus,
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
+ }
+
+ object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6_CCM_ADDR);
+
+ object_property_set_bool(OBJECT(&s->src), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6_SRC_ADDR);
+
+ /* Initialize all UARTs */
+ for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } serial_table[FSL_IMX6_NUM_UARTS] = {
+ { FSL_IMX6_UART1_ADDR, FSL_IMX6_UART1_IRQ },
+ { FSL_IMX6_UART2_ADDR, FSL_IMX6_UART2_IRQ },
+ { FSL_IMX6_UART3_ADDR, FSL_IMX6_UART3_IRQ },
+ { FSL_IMX6_UART4_ADDR, FSL_IMX6_UART4_IRQ },
+ { FSL_IMX6_UART5_ADDR, FSL_IMX6_UART5_IRQ },
+ };
+
+ if (i < MAX_SERIAL_PORTS) {
+ CharDriverState *chr;
+
+ chr = serial_hds[i];
+
+ if (!chr) {
+ char *label = g_strdup_printf("imx6.uart%d", i + 1);
+ chr = qemu_chr_new(label, "null", NULL);
+ g_free(label);
+ serial_hds[i] = chr;
+ }
+
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
+ }
+
+ object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ serial_table[i].irq));
+ }
+
+ s->gpt.ccm = IMX_CCM(&s->ccm);
+
+ object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt), 0, FSL_IMX6_GPT_ADDR);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ FSL_IMX6_GPT_IRQ));
+
+ /* Initialize all EPIT timers */
+ for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } epit_table[FSL_IMX6_NUM_EPITS] = {
+ { FSL_IMX6_EPIT1_ADDR, FSL_IMX6_EPIT1_IRQ },
+ { FSL_IMX6_EPIT2_ADDR, FSL_IMX6_EPIT2_IRQ },
+ };
+
+ s->epit[i].ccm = IMX_CCM(&s->ccm);
+
+ object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ epit_table[i].irq));
+ }
+
+ /* Initialize all I2C */
+ for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } i2c_table[FSL_IMX6_NUM_I2CS] = {
+ { FSL_IMX6_I2C1_ADDR, FSL_IMX6_I2C1_IRQ },
+ { FSL_IMX6_I2C2_ADDR, FSL_IMX6_I2C2_IRQ },
+ { FSL_IMX6_I2C3_ADDR, FSL_IMX6_I2C3_IRQ }
+ };
+
+ object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ i2c_table[i].irq));
+ }
+
+ /* Initialize all GPIOs */
+ for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq_low;
+ unsigned int irq_high;
+ } gpio_table[FSL_IMX6_NUM_GPIOS] = {
+ {
+ FSL_IMX6_GPIO1_ADDR,
+ FSL_IMX6_GPIO1_LOW_IRQ,
+ FSL_IMX6_GPIO1_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO2_ADDR,
+ FSL_IMX6_GPIO2_LOW_IRQ,
+ FSL_IMX6_GPIO2_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO3_ADDR,
+ FSL_IMX6_GPIO3_LOW_IRQ,
+ FSL_IMX6_GPIO3_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO4_ADDR,
+ FSL_IMX6_GPIO4_LOW_IRQ,
+ FSL_IMX6_GPIO4_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO5_ADDR,
+ FSL_IMX6_GPIO5_LOW_IRQ,
+ FSL_IMX6_GPIO5_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO6_ADDR,
+ FSL_IMX6_GPIO6_LOW_IRQ,
+ FSL_IMX6_GPIO6_HIGH_IRQ
+ },
+ {
+ FSL_IMX6_GPIO7_ADDR,
+ FSL_IMX6_GPIO7_LOW_IRQ,
+ FSL_IMX6_GPIO7_HIGH_IRQ
+ },
+ };
+
+ object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-edge-sel",
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-upper-pin-irq",
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ gpio_table[i].irq_low));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ gpio_table[i].irq_high));
+ }
+
+ /* Initialize all SDHC */
+ for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } esdhc_table[FSL_IMX6_NUM_ESDHCS] = {
+ { FSL_IMX6_uSDHC1_ADDR, FSL_IMX6_uSDHC1_IRQ },
+ { FSL_IMX6_uSDHC2_ADDR, FSL_IMX6_uSDHC2_IRQ },
+ { FSL_IMX6_uSDHC3_ADDR, FSL_IMX6_uSDHC3_IRQ },
+ { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
+ };
+
+ object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ esdhc_table[i].irq));
+ }
+
+ /* Initialize all ECSPI */
+ for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } spi_table[FSL_IMX6_NUM_ECSPIS] = {
+ { FSL_IMX6_eCSPI1_ADDR, FSL_IMX6_ECSPI1_IRQ },
+ { FSL_IMX6_eCSPI2_ADDR, FSL_IMX6_ECSPI2_IRQ },
+ { FSL_IMX6_eCSPI3_ADDR, FSL_IMX6_ECSPI3_IRQ },
+ { FSL_IMX6_eCSPI4_ADDR, FSL_IMX6_ECSPI4_IRQ },
+ { FSL_IMX6_eCSPI5_ADDR, FSL_IMX6_ECSPI5_IRQ },
+ };
+
+ /* Initialize the SPI */
+ object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ spi_table[i].irq));
+ }
+
+ /* ROM memory */
+ memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx6.rom",
+ FSL_IMX6_ROM_SIZE, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6_ROM_ADDR,
+ &s->rom);
+
+ /* CAAM memory */
+ memory_region_init_rom_device(&s->caam, NULL, NULL, NULL, "imx6.caam",
+ FSL_IMX6_CAAM_MEM_SIZE, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6_CAAM_MEM_ADDR,
+ &s->caam);
+
+ /* OCRAM memory */
+ memory_region_init_ram(&s->ocram, NULL, "imx6.ocram", FSL_IMX6_OCRAM_SIZE,
+ &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ADDR,
+ &s->ocram);
+ vmstate_register_ram_global(&s->ocram);
+
+ /* internal OCRAM (256 KB) is aliased over 1 MB */
+ memory_region_init_alias(&s->ocram_alias, NULL, "imx6.ocram_alias",
+ &s->ocram, 0, FSL_IMX6_OCRAM_ALIAS_SIZE);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ALIAS_ADDR,
+ &s->ocram_alias);
+}
+
+static void fsl_imx6_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = fsl_imx6_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
+ dc->desc = "i.MX6 SOC";
+}
+
+static const TypeInfo fsl_imx6_type_info = {
+ .name = TYPE_FSL_IMX6,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(FslIMX6State),
+ .instance_init = fsl_imx6_init,
+ .class_init = fsl_imx6_class_init,
+};
+
+static void fsl_imx6_register_types(void)
+{
+ type_register_static(&fsl_imx6_type_info);
+}
+
+type_init(fsl_imx6_register_types)
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index d9930c0d34..41029a651d 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -168,23 +168,20 @@ static void highbank_regs_reset(DeviceState *dev)
s->regs[0x43] = 0x05F40121;
}
-static int highbank_regs_init(SysBusDevice *dev)
+static void highbank_regs_init(Object *obj)
{
- HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
+ HighbankRegsState *s = HIGHBANK_REGISTERS(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, OBJECT(s), &hb_mem_ops, s->regs,
+ memory_region_init_io(&s->iomem, obj, &hb_mem_ops, s->regs,
"highbank_regs", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
}
static void highbank_regs_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- sbc->init = highbank_regs_init;
dc->desc = "Calxeda Highbank registers";
dc->vmsd = &vmstate_highbank_regs;
dc->reset = highbank_regs_reset;
@@ -194,6 +191,7 @@ static const TypeInfo highbank_regs_info = {
.name = TYPE_HIGHBANK_REGISTERS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(HighbankRegsState),
+ .instance_init = highbank_regs_init,
.class_init = highbank_regs_class_init,
};
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index e31bca6e72..24f16874f9 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -242,9 +242,10 @@ static const MemoryRegionOps integratorcm_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int integratorcm_init(SysBusDevice *dev)
+static void integratorcm_init(Object *obj)
{
- IntegratorCMState *s = INTEGRATOR_CM(dev);
+ IntegratorCMState *s = INTEGRATOR_CM(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
s->cm_osc = 0x01000048;
/* ??? What should the high bits of this value be? */
@@ -269,17 +270,16 @@ static int integratorcm_init(SysBusDevice *dev)
s->cm_init = 0x00000112;
s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
1000);
- memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000,
+ memory_region_init_ram(&s->flash, obj, "integrator.flash", 0x100000,
&error_fatal);
vmstate_register_ram_global(&s->flash);
- memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s,
+ memory_region_init_io(&s->iomem, obj, &integratorcm_ops, s,
"integratorcm", 0x00800000);
sysbus_init_mmio(dev, &s->iomem);
integratorcm_do_remap(s);
/* ??? Save/restore. */
- return 0;
}
/* Integrator/CP hardware emulation. */
@@ -394,18 +394,18 @@ static const MemoryRegionOps icp_pic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int icp_pic_init(SysBusDevice *sbd)
+static void icp_pic_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- icp_pic_state *s = INTEGRATOR_PIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ icp_pic_state *s = INTEGRATOR_PIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
sysbus_init_irq(sbd, &s->parent_irq);
sysbus_init_irq(sbd, &s->parent_fiq);
- memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s,
+ memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
"icp-pic", 0x00800000);
sysbus_init_mmio(sbd, &s->iomem);
- return 0;
}
/* CP control registers. */
@@ -630,9 +630,7 @@ static Property core_properties[] = {
static void core_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = integratorcm_init;
dc->props = core_properties;
}
@@ -640,21 +638,15 @@ static const TypeInfo core_info = {
.name = TYPE_INTEGRATOR_CM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IntegratorCMState),
+ .instance_init = integratorcm_init,
.class_init = core_class_init,
};
-static void icp_pic_class_init(ObjectClass *klass, void *data)
-{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = icp_pic_init;
-}
-
static const TypeInfo icp_pic_info = {
.name = TYPE_INTEGRATOR_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(icp_pic_state),
- .class_init = icp_pic_class_init,
+ .instance_init = icp_pic_init,
};
static const TypeInfo icp_ctrl_regs_info = {
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 5382505559..c7068c0d38 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -1364,7 +1364,7 @@ static void n8x0_init(MachineState *machine,
if (option_rom[0].name &&
(machine->boot_order[0] == 'n' || !machine->kernel_filename)) {
- uint8_t nolo_tags[0x10000];
+ uint8_t *nolo_tags = g_new(uint8_t, 0x10000);
/* No, wait, better start at the ROM. */
s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
@@ -1383,6 +1383,7 @@ static void n8x0_init(MachineState *machine,
n800_setup_nolo_tags(nolo_tags);
cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
+ g_free(nolo_tags);
}
}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 1a8c36033a..e41a7c92ab 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1107,9 +1107,10 @@ static const MemoryRegionOps pxa2xx_rtc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int pxa2xx_rtc_init(SysBusDevice *dev)
+static void pxa2xx_rtc_init(Object *obj)
{
- PXA2xxRTCState *s = PXA2XX_RTC(dev);
+ PXA2xxRTCState *s = PXA2XX_RTC(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
struct tm tm;
int wom;
@@ -1138,11 +1139,9 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->rtc_irq);
- memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_rtc_ops, s,
+ memory_region_init_io(&s->iomem, obj, &pxa2xx_rtc_ops, s,
"pxa2xx-rtc", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
}
static void pxa2xx_rtc_pre_save(void *opaque)
@@ -1195,9 +1194,7 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pxa2xx_rtc_init;
dc->desc = "PXA2xx RTC Controller";
dc->vmsd = &vmstate_pxa2xx_rtc_regs;
}
@@ -1206,6 +1203,7 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = {
.name = TYPE_PXA2XX_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxRTCState),
+ .instance_init = pxa2xx_rtc_init,
.class_init = pxa2xx_rtc_sysbus_class_init,
};
@@ -1501,19 +1499,18 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
return s;
}
-static int pxa2xx_i2c_initfn(SysBusDevice *sbd)
+static void pxa2xx_i2c_initfn(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- PXA2xxI2CState *s = PXA2XX_I2C(dev);
+ DeviceState *dev = DEVICE(obj);
+ PXA2xxI2CState *s = PXA2XX_I2C(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
s->bus = i2c_init_bus(dev, "i2c");
- memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s,
+ memory_region_init_io(&s->iomem, obj, &pxa2xx_i2c_ops, s,
"pxa2xx-i2c", s->region_size);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
-
- return 0;
}
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
@@ -1530,9 +1527,7 @@ static Property pxa2xx_i2c_properties[] = {
static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pxa2xx_i2c_initfn;
dc->desc = "PXA2xx I2C Bus Controller";
dc->vmsd = &vmstate_pxa2xx_i2c;
dc->props = pxa2xx_i2c_properties;
@@ -1542,6 +1537,7 @@ static const TypeInfo pxa2xx_i2c_info = {
.name = TYPE_PXA2XX_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxI2CState),
+ .instance_init = pxa2xx_i2c_initfn,
.class_init = pxa2xx_i2c_class_init,
};
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 7e51532cde..b516ced8c0 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -310,17 +310,10 @@ static VMStateDescription vmstate_pxa2xx_pic_regs = {
},
};
-static int pxa2xx_pic_initfn(SysBusDevice *dev)
-{
- return 0;
-}
-
static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pxa2xx_pic_initfn;
dc->desc = "PXA2xx PIC";
dc->vmsd = &vmstate_pxa2xx_pic_regs;
}
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
new file mode 100644
index 0000000000..776c51e398
--- /dev/null
+++ b/hw/arm/sabrelite.c
@@ -0,0 +1,121 @@
+/*
+ * SABRELITE Board System emulation.
+ *
+ * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This code is licensed under the GPL, version 2 or later.
+ * See the file `COPYING' in the top level directory.
+ *
+ * It (partially) emulates a sabrelite board, with a Freescale
+ * i.MX6 SoC
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/fsl-imx6.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "sysemu/qtest.h"
+
+typedef struct IMX6Sabrelite {
+ FslIMX6State soc;
+ MemoryRegion ram;
+} IMX6Sabrelite;
+
+static struct arm_boot_info sabrelite_binfo = {
+ /* DDR memory start */
+ .loader_start = FSL_IMX6_MMDC_ADDR,
+ /* No board ID, we boot from DT tree */
+ .board_id = -1,
+};
+
+/* No need to do any particular setup for secondary boot */
+static void sabrelite_write_secondary(ARMCPU *cpu,
+ const struct arm_boot_info *info)
+{
+}
+
+/* Secondary cores are reset through SRC device */
+static void sabrelite_reset_secondary(ARMCPU *cpu,
+ const struct arm_boot_info *info)
+{
+}
+
+static void sabrelite_init(MachineState *machine)
+{
+ IMX6Sabrelite *s = g_new0(IMX6Sabrelite, 1);
+ Error *err = NULL;
+
+ /* Check the amount of memory is compatible with the SOC */
+ if (machine->ram_size > FSL_IMX6_MMDC_SIZE) {
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
+ machine->ram_size, FSL_IMX6_MMDC_SIZE);
+ exit(1);
+ }
+
+ object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX6);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
+ &error_abort);
+
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
+ if (err != NULL) {
+ error_report("%s", error_get_pretty(err));
+ exit(1);
+ }
+
+ memory_region_allocate_system_memory(&s->ram, NULL, "sabrelite.ram",
+ machine->ram_size);
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
+ &s->ram);
+
+ {
+ /*
+ * TODO: Ideally we would expose the chip select and spi bus on the
+ * SoC object using alias properties; then we would not need to
+ * directly access the underlying spi device object.
+ */
+ /* Add the sst25vf016b NOR FLASH memory to first SPI */
+ Object *spi_dev;
+
+ spi_dev = object_resolve_path_component(OBJECT(&s->soc), "spi1");
+ if (spi_dev) {
+ SSIBus *spi_bus;
+
+ spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(spi_dev), "spi");
+ if (spi_bus) {
+ DeviceState *flash_dev;
+
+ flash_dev = ssi_create_slave(spi_bus, "sst25vf016b");
+ if (flash_dev) {
+ qemu_irq cs_line = qdev_get_gpio_in_named(flash_dev,
+ SSI_GPIO_CS, 0);
+ sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line);
+ }
+ }
+ }
+ }
+
+ sabrelite_binfo.ram_size = machine->ram_size;
+ sabrelite_binfo.kernel_filename = machine->kernel_filename;
+ sabrelite_binfo.kernel_cmdline = machine->kernel_cmdline;
+ sabrelite_binfo.initrd_filename = machine->initrd_filename;
+ sabrelite_binfo.nb_cpus = smp_cpus;
+ sabrelite_binfo.secure_boot = true;
+ sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
+ sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
+
+ if (!qtest_enabled()) {
+ arm_load_kernel(&s->soc.cpu[0], &sabrelite_binfo);
+ }
+}
+
+static void sabrelite_machine_init(MachineClass *mc)
+{
+ mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
+ mc->init = sabrelite_init;
+ mc->max_cpus = FSL_IMX6_NUM_CPUS;
+}
+
+DEFINE_MACHINE("sabrelite", sabrelite_machine_init)
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index bf61d63b58..ba40f8302b 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -164,9 +164,10 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
}
-static int sl_nand_init(SysBusDevice *dev)
+static void sl_nand_init(Object *obj)
{
- SLNANDState *s = SL_NAND(dev);
+ SLNANDState *s = SL_NAND(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
DriveInfo *nand;
s->ctl = 0;
@@ -175,10 +176,8 @@ static int sl_nand_init(SysBusDevice *dev)
s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
s->manf_id, s->chip_id);
- memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
+ memory_region_init_io(&s->iomem, obj, &sl_ops, s, "sl", 0x40);
sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
}
/* Spitz Keyboard */
@@ -501,10 +500,10 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
}
-static int spitz_keyboard_init(SysBusDevice *sbd)
+static void spitz_keyboard_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- SpitzKeyboardState *s = SPITZ_KEYBOARD(dev);
+ DeviceState *dev = DEVICE(obj);
+ SpitzKeyboardState *s = SPITZ_KEYBOARD(obj);
int i, j;
for (i = 0; i < 0x80; i ++)
@@ -519,8 +518,6 @@ static int spitz_keyboard_init(SysBusDevice *sbd)
s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s);
qdev_init_gpio_in(dev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
qdev_init_gpio_out(dev, s->sense, SPITZ_KEY_SENSE_NUM);
-
- return 0;
}
/* LCD backlight controller */
@@ -1065,9 +1062,7 @@ static Property sl_nand_properties[] = {
static void sl_nand_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = sl_nand_init;
dc->vmsd = &vmstate_sl_nand_info;
dc->props = sl_nand_properties;
/* Reason: init() method uses drive_get() */
@@ -1078,6 +1073,7 @@ static const TypeInfo sl_nand_info = {
.name = TYPE_SL_NAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLNANDState),
+ .instance_init = sl_nand_init,
.class_init = sl_nand_class_init,
};
@@ -1097,9 +1093,7 @@ static VMStateDescription vmstate_spitz_kbd = {
static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = spitz_keyboard_init;
dc->vmsd = &vmstate_spitz_kbd;
}
@@ -1107,6 +1101,7 @@ static const TypeInfo spitz_keyboard_info = {
.name = TYPE_SPITZ_KEYBOARD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SpitzKeyboardState),
+ .instance_init = spitz_keyboard_init,
.class_init = spitz_keyboard_class_init,
};
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index c1766f856a..f90b9fd190 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -316,23 +316,22 @@ static const VMStateDescription vmstate_stellaris_gptm = {
}
};
-static int stellaris_gptm_init(SysBusDevice *sbd)
+static void stellaris_gptm_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- gptm_state *s = STELLARIS_GPTM(dev);
+ DeviceState *dev = DEVICE(obj);
+ gptm_state *s = STELLARIS_GPTM(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_out(dev, &s->trigger, 1);
- memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s,
+ memory_region_init_io(&s->iomem, obj, &gptm_ops, s,
"gptm", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
s->opaque[0] = s->opaque[1] = s;
s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
- vmstate_register(dev, -1, &vmstate_stellaris_gptm, s);
- return 0;
}
@@ -873,23 +872,22 @@ static const VMStateDescription vmstate_stellaris_i2c = {
}
};
-static int stellaris_i2c_init(SysBusDevice *sbd)
+static void stellaris_i2c_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- stellaris_i2c_state *s = STELLARIS_I2C(dev);
+ DeviceState *dev = DEVICE(obj);
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
I2CBus *bus;
sysbus_init_irq(sbd, &s->irq);
bus = i2c_init_bus(dev, "i2c");
s->bus = bus;
- memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s,
+ memory_region_init_io(&s->iomem, obj, &stellaris_i2c_ops, s,
"i2c", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
- vmstate_register(dev, -1, &vmstate_stellaris_i2c, s);
- return 0;
}
/* Analogue to Digital Converter. This is only partially implemented,
@@ -1160,23 +1158,22 @@ static const VMStateDescription vmstate_stellaris_adc = {
}
};
-static int stellaris_adc_init(SysBusDevice *sbd)
+static void stellaris_adc_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- stellaris_adc_state *s = STELLARIS_ADC(dev);
+ DeviceState *dev = DEVICE(obj);
+ stellaris_adc_state *s = STELLARIS_ADC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
int n;
for (n = 0; n < 4; n++) {
sysbus_init_irq(sbd, &s->irq[n]);
}
- memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s,
+ memory_region_init_io(&s->iomem, obj, &stellaris_adc_ops, s,
"adc", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
stellaris_adc_reset(s);
qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
- vmstate_register(dev, -1, &vmstate_stellaris_adc, s);
- return 0;
}
static
@@ -1425,43 +1422,46 @@ type_init(stellaris_machine_init)
static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = stellaris_i2c_init;
+ dc->vmsd = &vmstate_stellaris_i2c;
}
static const TypeInfo stellaris_i2c_info = {
.name = TYPE_STELLARIS_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_i2c_state),
+ .instance_init = stellaris_i2c_init,
.class_init = stellaris_i2c_class_init,
};
static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = stellaris_gptm_init;
+ dc->vmsd = &vmstate_stellaris_gptm;
}
static const TypeInfo stellaris_gptm_info = {
.name = TYPE_STELLARIS_GPTM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(gptm_state),
+ .instance_init = stellaris_gptm_init,
.class_init = stellaris_gptm_class_init,
};
static void stellaris_adc_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = stellaris_adc_init;
+ dc->vmsd = &vmstate_stellaris_adc;
}
static const TypeInfo stellaris_adc_info = {
.name = TYPE_STELLARIS_ADC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_adc_state),
+ .instance_init = stellaris_adc_init,
.class_init = stellaris_adc_class_init,
};
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 1eeb1ab391..3bc8a98150 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -179,19 +179,18 @@ static const MemoryRegionOps strongarm_pic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_pic_initfn(SysBusDevice *sbd)
+static void strongarm_pic_initfn(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- StrongARMPICState *s = STRONGARM_PIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ StrongARMPICState *s = STRONGARM_PIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
qdev_init_gpio_in(dev, strongarm_pic_set_irq, SA_PIC_SRCS);
- memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s,
+ memory_region_init_io(&s->iomem, obj, &strongarm_pic_ops, s,
"pic", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
-
- return 0;
}
static int strongarm_pic_post_load(void *opaque, int version_id)
@@ -217,9 +216,7 @@ static VMStateDescription vmstate_strongarm_pic_regs = {
static void strongarm_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = strongarm_pic_initfn;
dc->desc = "StrongARM PIC";
dc->vmsd = &vmstate_strongarm_pic_regs;
}
@@ -228,6 +225,7 @@ static const TypeInfo strongarm_pic_info = {
.name = TYPE_STRONGARM_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPICState),
+ .instance_init = strongarm_pic_initfn,
.class_init = strongarm_pic_class_init,
};
@@ -381,9 +379,10 @@ static const MemoryRegionOps strongarm_rtc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_rtc_init(SysBusDevice *dev)
+static void strongarm_rtc_init(Object *obj)
{
- StrongARMRTCState *s = STRONGARM_RTC(dev);
+ StrongARMRTCState *s = STRONGARM_RTC(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
struct tm tm;
s->rttr = 0x0;
@@ -400,11 +399,9 @@ static int strongarm_rtc_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->rtc_irq);
sysbus_init_irq(dev, &s->rtc_hz_irq);
- memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_rtc_ops, s,
+ memory_region_init_io(&s->iomem, obj, &strongarm_rtc_ops, s,
"rtc", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
}
static void strongarm_rtc_pre_save(void *opaque)
@@ -443,9 +440,7 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = {
static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = strongarm_rtc_init;
dc->desc = "StrongARM RTC Controller";
dc->vmsd = &vmstate_strongarm_rtc_regs;
}
@@ -454,6 +449,7 @@ static const TypeInfo strongarm_rtc_sysbus_info = {
.name = TYPE_STRONGARM_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMRTCState),
+ .instance_init = strongarm_rtc_init,
.class_init = strongarm_rtc_sysbus_class_init,
};
@@ -646,16 +642,17 @@ static DeviceState *strongarm_gpio_init(hwaddr base,
return dev;
}
-static int strongarm_gpio_initfn(SysBusDevice *sbd)
+static void strongarm_gpio_initfn(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- StrongARMGPIOInfo *s = STRONGARM_GPIO(dev);
+ DeviceState *dev = DEVICE(obj);
+ StrongARMGPIOInfo *s = STRONGARM_GPIO(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
int i;
qdev_init_gpio_in(dev, strongarm_gpio_set, 28);
qdev_init_gpio_out(dev, s->handler, 28);
- memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s,
+ memory_region_init_io(&s->iomem, obj, &strongarm_gpio_ops, s,
"gpio", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
@@ -663,8 +660,6 @@ static int strongarm_gpio_initfn(SysBusDevice *sbd)
sysbus_init_irq(sbd, &s->irqs[i]);
}
sysbus_init_irq(sbd, &s->irqX);
-
- return 0;
}
static const VMStateDescription vmstate_strongarm_gpio_regs = {
@@ -687,9 +682,7 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = {
static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = strongarm_gpio_initfn;
dc->desc = "StrongARM GPIO controller";
dc->vmsd = &vmstate_strongarm_gpio_regs;
}
@@ -698,6 +691,7 @@ static const TypeInfo strongarm_gpio_info = {
.name = TYPE_STRONGARM_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMGPIOInfo),
+ .instance_init = strongarm_gpio_initfn,
.class_init = strongarm_gpio_class_init,
};
@@ -824,20 +818,19 @@ static const MemoryRegionOps strongarm_ppc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_ppc_init(SysBusDevice *sbd)
+static void strongarm_ppc_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- StrongARMPPCInfo *s = STRONGARM_PPC(dev);
+ DeviceState *dev = DEVICE(obj);
+ StrongARMPPCInfo *s = STRONGARM_PPC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
qdev_init_gpio_in(dev, strongarm_ppc_set, 22);
qdev_init_gpio_out(dev, s->handler, 22);
- memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s,
+ memory_region_init_io(&s->iomem, obj, &strongarm_ppc_ops, s,
"ppc", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
-
- return 0;
}
static const VMStateDescription vmstate_strongarm_ppc_regs = {
@@ -859,9 +852,7 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = {
static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = strongarm_ppc_init;
dc->desc = "StrongARM PPC controller";
dc->vmsd = &vmstate_strongarm_ppc_regs;
}
@@ -870,6 +861,7 @@ static const TypeInfo strongarm_ppc_info = {
.name = TYPE_STRONGARM_PPC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPPCInfo),
+ .instance_init = strongarm_ppc_init,
.class_init = strongarm_ppc_class_init,
};
@@ -1231,11 +1223,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_uart_init(SysBusDevice *dev)
+static void strongarm_uart_init(Object *obj)
{
- StrongARMUARTState *s = STRONGARM_UART(dev);
+ StrongARMUARTState *s = STRONGARM_UART(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s,
+ memory_region_init_io(&s->iomem, obj, &strongarm_uart_ops, s,
"uart", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
@@ -1250,8 +1243,6 @@ static int strongarm_uart_init(SysBusDevice *dev)
strongarm_uart_event,
s);
}
-
- return 0;
}
static void strongarm_uart_reset(DeviceState *dev)
@@ -1321,9 +1312,7 @@ static Property strongarm_uart_properties[] = {
static void strongarm_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = strongarm_uart_init;
dc->desc = "StrongARM UART controller";
dc->reset = strongarm_uart_reset;
dc->vmsd = &vmstate_strongarm_uart_regs;
@@ -1334,6 +1323,7 @@ static const TypeInfo strongarm_uart_info = {
.name = TYPE_STRONGARM_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMUARTState),
+ .instance_init = strongarm_uart_init,
.class_init = strongarm_uart_class_init,
};
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index e5a80c2d2c..d079bc9e82 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -153,10 +153,11 @@ static const MemoryRegionOps vpb_sic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int vpb_sic_init(SysBusDevice *sbd)
+static void vpb_sic_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- vpb_sic_state *s = VERSATILE_PB_SIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ vpb_sic_state *s = VERSATILE_PB_SIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
int i;
qdev_init_gpio_in(dev, vpb_sic_set_irq, 32);
@@ -164,10 +165,9 @@ static int vpb_sic_init(SysBusDevice *sbd)
sysbus_init_irq(sbd, &s->parent[i]);
}
s->irq = 31;
- memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s,
+ memory_region_init_io(&s->iomem, obj, &vpb_sic_ops, s,
"vpb-sic", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
- return 0;
}
/* Board init. */
@@ -427,9 +427,7 @@ type_init(versatile_machine_init)
static void vpb_sic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = vpb_sic_init;
dc->vmsd = &vmstate_vpb_sic;
}
@@ -437,6 +435,7 @@ static const TypeInfo vpb_sic_info = {
.name = TYPE_VERSATILE_PB_SIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(vpb_sic_state),
+ .instance_init = vpb_sic_init,
.class_init = vpb_sic_class_init,
};
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f51fe396ce..26a7bac48f 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -43,6 +43,7 @@
#include "hw/acpi/aml-build.h"
#include "hw/pci/pcie_host.h"
#include "hw/pci/pci.h"
+#include "sysemu/numa.h"
#define ARM_SPI_BASE 32
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -414,6 +415,52 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
}
static void
+build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+{
+ AcpiSystemResourceAffinityTable *srat;
+ AcpiSratProcessorGiccAffinity *core;
+ AcpiSratMemoryAffinity *numamem;
+ int i, j, srat_start;
+ uint64_t mem_base;
+ uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t));
+
+ for (i = 0; i < guest_info->smp_cpus; i++) {
+ for (j = 0; j < nb_numa_nodes; j++) {
+ if (test_bit(i, numa_info[j].node_cpu)) {
+ cpu_node[i] = j;
+ break;
+ }
+ }
+ }
+
+ srat_start = table_data->len;
+ srat = acpi_data_push(table_data, sizeof(*srat));
+ srat->reserved1 = cpu_to_le32(1);
+
+ for (i = 0; i < guest_info->smp_cpus; ++i) {
+ core = acpi_data_push(table_data, sizeof(*core));
+ core->type = ACPI_SRAT_PROCESSOR_GICC;
+ core->length = sizeof(*core);
+ core->proximity = cpu_to_le32(cpu_node[i]);
+ core->acpi_processor_uid = cpu_to_le32(i);
+ core->flags = cpu_to_le32(1);
+ }
+ g_free(cpu_node);
+
+ mem_base = guest_info->memmap[VIRT_MEM].base;
+ for (i = 0; i < nb_numa_nodes; ++i) {
+ numamem = acpi_data_push(table_data, sizeof(*numamem));
+ build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i,
+ MEM_AFFINITY_ENABLED);
+ mem_base += numa_info[i].node_mem;
+ }
+
+ build_header(linker, table_data,
+ (void *)(table_data->data + srat_start), "SRAT",
+ table_data->len - srat_start, 3, NULL, NULL);
+}
+
+static void
build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
AcpiTableMcfg *mcfg;
@@ -638,6 +685,11 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_spcr(tables_blob, tables->linker, guest_info);
+ if (nb_numa_nodes > 0) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_srat(tables_blob, tables->linker, guest_info);
+ }
+
/* RSDT is pointed to by RSDP */
rsdt = tables_blob->len;
build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 56d35c7716..fe6b11d24e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -38,6 +38,7 @@
#include "net/net.h"
#include "sysemu/block-backend.h"
#include "sysemu/device_tree.h"
+#include "sysemu/numa.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "hw/boards.h"
@@ -329,6 +330,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
{
int cpu;
int addr_cells = 1;
+ unsigned int i;
/*
* From Documentation/devicetree/bindings/arm/cpus.txt
@@ -378,6 +380,12 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
armcpu->mp_affinity);
}
+ for (i = 0; i < nb_numa_nodes; i++) {
+ if (test_bit(cpu, numa_info[i].node_cpu)) {
+ qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i);
+ }
+ }
+
g_free(nodename);
}
}
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
index c231960d96..cbf07d14d9 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -925,16 +925,83 @@ static void blizzard_update_display(void *opaque)
s->my[1] = 0;
}
-#define DEPTH 8
-#include "blizzard_template.h"
-#define DEPTH 15
-#include "blizzard_template.h"
-#define DEPTH 16
-#include "blizzard_template.h"
-#define DEPTH 24
-#include "blizzard_template.h"
-#define DEPTH 32
-#include "blizzard_template.h"
+static void blizzard_draw_line16_32(uint32_t *dest,
+ const uint16_t *src, unsigned int width)
+{
+ uint16_t data;
+ unsigned int r, g, b;
+ const uint16_t *end = (const void *) src + width;
+ while (src < end) {
+ data = *src ++;
+ b = (data & 0x1f) << 3;
+ data >>= 5;
+ g = (data & 0x3f) << 2;
+ data >>= 6;
+ r = (data & 0x1f) << 3;
+ data >>= 5;
+ *dest++ = rgb_to_pixel32(r, g, b);
+ }
+}
+
+static void blizzard_draw_line24mode1_32(uint32_t *dest,
+ const uint8_t *src, unsigned int width)
+{
+ /* TODO: check if SDL 24-bit planes are not in the same format and
+ * if so, use memcpy */
+ unsigned int r[2], g[2], b[2];
+ const uint8_t *end = src + width;
+ while (src < end) {
+ g[0] = *src ++;
+ r[0] = *src ++;
+ r[1] = *src ++;
+ b[0] = *src ++;
+ *dest++ = rgb_to_pixel32(r[0], g[0], b[0]);
+ b[1] = *src ++;
+ g[1] = *src ++;
+ *dest++ = rgb_to_pixel32(r[1], g[1], b[1]);
+ }
+}
+
+static void blizzard_draw_line24mode2_32(uint32_t *dest,
+ const uint8_t *src, unsigned int width)
+{
+ unsigned int r, g, b;
+ const uint8_t *end = src + width;
+ while (src < end) {
+ r = *src ++;
+ src ++;
+ b = *src ++;
+ g = *src ++;
+ *dest++ = rgb_to_pixel32(r, g, b);
+ }
+}
+
+/* No rotation */
+static blizzard_fn_t blizzard_draw_fn_32[0x10] = {
+ NULL,
+ /* RGB 5:6:5*/
+ (blizzard_fn_t) blizzard_draw_line16_32,
+ /* RGB 6:6:6 mode 1 */
+ (blizzard_fn_t) blizzard_draw_line24mode1_32,
+ /* RGB 8:8:8 mode 1 */
+ (blizzard_fn_t) blizzard_draw_line24mode1_32,
+ NULL, NULL,
+ /* RGB 6:6:6 mode 2 */
+ (blizzard_fn_t) blizzard_draw_line24mode2_32,
+ /* RGB 8:8:8 mode 2 */
+ (blizzard_fn_t) blizzard_draw_line24mode2_32,
+ /* YUV 4:2:2 */
+ NULL,
+ /* YUV 4:2:0 */
+ NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+/* 90deg, 180deg and 270deg rotation */
+static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = {
+ /* TODO */
+ [0 ... 0xf] = NULL,
+};
static const GraphicHwOps blizzard_ops = {
.invalidate = blizzard_invalidate_display,
@@ -951,35 +1018,10 @@ void *s1d13745_init(qemu_irq gpio_int)
s->con = graphic_console_init(NULL, 0, &blizzard_ops, s);
surface = qemu_console_surface(s->con);
- switch (surface_bits_per_pixel(surface)) {
- case 0:
- s->line_fn_tab[0] = s->line_fn_tab[1] =
- g_malloc0(sizeof(blizzard_fn_t) * 0x10);
- break;
- case 8:
- s->line_fn_tab[0] = blizzard_draw_fn_8;
- s->line_fn_tab[1] = blizzard_draw_fn_r_8;
- break;
- case 15:
- s->line_fn_tab[0] = blizzard_draw_fn_15;
- s->line_fn_tab[1] = blizzard_draw_fn_r_15;
- break;
- case 16:
- s->line_fn_tab[0] = blizzard_draw_fn_16;
- s->line_fn_tab[1] = blizzard_draw_fn_r_16;
- break;
- case 24:
- s->line_fn_tab[0] = blizzard_draw_fn_24;
- s->line_fn_tab[1] = blizzard_draw_fn_r_24;
- break;
- case 32:
- s->line_fn_tab[0] = blizzard_draw_fn_32;
- s->line_fn_tab[1] = blizzard_draw_fn_r_32;
- break;
- default:
- fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
- exit(1);
- }
+ assert(surface_bits_per_pixel(surface) == 32);
+
+ s->line_fn_tab[0] = blizzard_draw_fn_32;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_32;
blizzard_reset(s);
diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h
deleted file mode 100644
index b7ef27c808..0000000000
--- a/hw/display/blizzard_template.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * QEMU Epson S1D13744/S1D13745 templates
- *
- * Copyright (C) 2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#define SKIP_PIXEL(to) (to += deststep)
-#if DEPTH == 8
-# define PIXEL_TYPE uint8_t
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
-# define COPY_PIXEL1(to, from) (*to++ = from)
-#elif DEPTH == 15 || DEPTH == 16
-# define PIXEL_TYPE uint16_t
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
-# define COPY_PIXEL1(to, from) (*to++ = from)
-#elif DEPTH == 24
-# define PIXEL_TYPE uint8_t
-# define COPY_PIXEL(to, from) \
- do { \
- to[0] = from; \
- to[1] = (from) >> 8; \
- to[2] = (from) >> 16; \
- SKIP_PIXEL(to); \
- } while (0)
-
-# define COPY_PIXEL1(to, from) \
- do { \
- *to++ = from; \
- *to++ = (from) >> 8; \
- *to++ = (from) >> 16; \
- } while (0)
-#elif DEPTH == 32
-# define PIXEL_TYPE uint32_t
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
-# define COPY_PIXEL1(to, from) (*to++ = from)
-#else
-# error unknown bit depth
-#endif
-
-#ifdef HOST_WORDS_BIGENDIAN
-# define SWAP_WORDS 1
-#endif
-
-static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest,
- const uint16_t *src, unsigned int width)
-{
-#if !defined(SWAP_WORDS) && DEPTH == 16
- memcpy(dest, src, width);
-#else
- uint16_t data;
- unsigned int r, g, b;
- const uint16_t *end = (const void *) src + width;
- while (src < end) {
- data = *src ++;
- b = (data & 0x1f) << 3;
- data >>= 5;
- g = (data & 0x3f) << 2;
- data >>= 6;
- r = (data & 0x1f) << 3;
- data >>= 5;
- COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
- }
-#endif
-}
-
-static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest,
- const uint8_t *src, unsigned int width)
-{
- /* TODO: check if SDL 24-bit planes are not in the same format and
- * if so, use memcpy */
- unsigned int r[2], g[2], b[2];
- const uint8_t *end = src + width;
- while (src < end) {
- g[0] = *src ++;
- r[0] = *src ++;
- r[1] = *src ++;
- b[0] = *src ++;
- COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0]));
- b[1] = *src ++;
- g[1] = *src ++;
- COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1]));
- }
-}
-
-static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest,
- const uint8_t *src, unsigned int width)
-{
- unsigned int r, g, b;
- const uint8_t *end = src + width;
- while (src < end) {
- r = *src ++;
- src ++;
- b = *src ++;
- g = *src ++;
- COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
- }
-}
-
-/* No rotation */
-static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = {
- NULL,
- /* RGB 5:6:5*/
- (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH),
- /* RGB 6:6:6 mode 1 */
- (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
- /* RGB 8:8:8 mode 1 */
- (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
- NULL, NULL,
- /* RGB 6:6:6 mode 2 */
- (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
- /* RGB 8:8:8 mode 2 */
- (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
- /* YUV 4:2:2 */
- NULL,
- /* YUV 4:2:0 */
- NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
-};
-
-/* 90deg, 180deg and 270deg rotation */
-static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = {
- /* TODO */
- [0 ... 0xf] = NULL,
-};
-
-#undef DEPTH
-#undef SKIP_PIXEL
-#undef COPY_PIXEL
-#undef COPY_PIXEL1
-#undef PIXEL_TYPE
-
-#undef SWAP_WORDS
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 728eb214a4..e5be713406 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1909,9 +1909,10 @@ static const GraphicHwOps exynos4210_fimd_ops = {
.gfx_update = exynos4210_fimd_update,
};
-static int exynos4210_fimd_init(SysBusDevice *dev)
+static void exynos4210_fimd_init(Object *obj)
{
- Exynos4210fimdState *s = EXYNOS4210_FIMD(dev);
+ Exynos4210fimdState *s = EXYNOS4210_FIMD(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
s->ifb = NULL;
@@ -1919,28 +1920,32 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq[1]);
sysbus_init_irq(dev, &s->irq[2]);
- memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s,
+ memory_region_init_io(&s->iomem, obj, &exynos4210_fimd_mmio_ops, s,
"exynos4210.fimd", FIMD_REGS_SIZE);
sysbus_init_mmio(dev, &s->iomem);
- s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s);
+}
- return 0;
+static void exynos4210_fimd_realize(DeviceState *dev, Error **errp)
+{
+ Exynos4210fimdState *s = EXYNOS4210_FIMD(dev);
+
+ s->console = graphic_console_init(dev, 0, &exynos4210_fimd_ops, s);
}
static void exynos4210_fimd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
dc->vmsd = &exynos4210_fimd_vmstate;
dc->reset = exynos4210_fimd_reset;
- k->init = exynos4210_fimd_init;
+ dc->realize = exynos4210_fimd_realize;
}
static const TypeInfo exynos4210_fimd_info = {
.name = TYPE_EXYNOS4210_FIMD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210fimdState),
+ .instance_init = exynos4210_fimd_init,
.class_init = exynos4210_fimd_class_init,
};
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
index f0ce71fd66..1025ff3825 100644
--- a/hw/display/omap_lcd_template.h
+++ b/hw/display/omap_lcd_template.h
@@ -27,13 +27,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if DEPTH == 8
-# define BPP 1
-# define PIXEL_TYPE uint8_t
-#elif DEPTH == 15 || DEPTH == 16
-# define BPP 2
-# define PIXEL_TYPE uint16_t
-#elif DEPTH == 32
+#if DEPTH == 32
# define BPP 4
# define PIXEL_TYPE uint32_t
#else
@@ -152,7 +146,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
static void glue(draw_line16_, DEPTH)(void *opaque,
uint8_t *d, const uint8_t *s, int width, int deststep)
{
-#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
uint16_t v;
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index ce1058bf85..07a5effe04 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -71,47 +71,9 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
#define draw_line_func drawfn
-#define DEPTH 8
-#include "omap_lcd_template.h"
-#define DEPTH 15
-#include "omap_lcd_template.h"
-#define DEPTH 16
-#include "omap_lcd_template.h"
#define DEPTH 32
#include "omap_lcd_template.h"
-static draw_line_func draw_line_table2[33] = {
- [0 ... 32] = NULL,
- [8] = draw_line2_8,
- [15] = draw_line2_15,
- [16] = draw_line2_16,
- [32] = draw_line2_32,
-}, draw_line_table4[33] = {
- [0 ... 32] = NULL,
- [8] = draw_line4_8,
- [15] = draw_line4_15,
- [16] = draw_line4_16,
- [32] = draw_line4_32,
-}, draw_line_table8[33] = {
- [0 ... 32] = NULL,
- [8] = draw_line8_8,
- [15] = draw_line8_15,
- [16] = draw_line8_16,
- [32] = draw_line8_32,
-}, draw_line_table12[33] = {
- [0 ... 32] = NULL,
- [8] = draw_line12_8,
- [15] = draw_line12_15,
- [16] = draw_line12_16,
- [32] = draw_line12_32,
-}, draw_line_table16[33] = {
- [0 ... 32] = NULL,
- [8] = draw_line16_8,
- [15] = draw_line16_15,
- [16] = draw_line16_16,
- [32] = draw_line16_32,
-};
-
static void omap_update_display(void *opaque)
{
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
@@ -143,25 +105,25 @@ static void omap_update_display(void *opaque)
/* Colour depth */
switch ((omap_lcd->palette[0] >> 12) & 7) {
case 1:
- draw_line = draw_line_table2[surface_bits_per_pixel(surface)];
+ draw_line = draw_line2_32;
bpp = 2;
break;
case 2:
- draw_line = draw_line_table4[surface_bits_per_pixel(surface)];
+ draw_line = draw_line4_32;
bpp = 4;
break;
case 3:
- draw_line = draw_line_table8[surface_bits_per_pixel(surface)];
+ draw_line = draw_line8_32;
bpp = 8;
break;
case 4 ... 7:
if (!omap_lcd->tft)
- draw_line = draw_line_table12[surface_bits_per_pixel(surface)];
+ draw_line = draw_line12_32;
else
- draw_line = draw_line_table16[surface_bits_per_pixel(surface)];
+ draw_line = draw_line16_32;
bpp = 16;
break;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 64770034ff..279f0d7d05 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2427,26 +2427,6 @@ build_tpm2(GArray *table_data, GArray *linker)
(void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
}
-typedef enum {
- MEM_AFFINITY_NOFLAGS = 0,
- MEM_AFFINITY_ENABLED = (1 << 0),
- MEM_AFFINITY_HOTPLUGGABLE = (1 << 1),
- MEM_AFFINITY_NON_VOLATILE = (1 << 2),
-} MemoryAffinityFlags;
-
-static void
-acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
- uint64_t len, int node, MemoryAffinityFlags flags)
-{
- numamem->type = ACPI_SRAT_MEMORY;
- numamem->length = sizeof(*numamem);
- memset(numamem->proximity, 0, 4);
- numamem->proximity[0] = node;
- numamem->flags = cpu_to_le32(flags);
- numamem->base_addr = cpu_to_le64(base);
- numamem->range_length = cpu_to_le64(len);
-}
-
static void
build_srat(GArray *table_data, GArray *linker, MachineState *machine)
{
@@ -2474,7 +2454,7 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine)
int apic_id = apic_ids->cpus[i].arch_id;
core = acpi_data_push(table_data, sizeof *core);
- core->type = ACPI_SRAT_PROCESSOR;
+ core->type = ACPI_SRAT_PROCESSOR_APIC;
core->length = sizeof(*core);
core->local_apic_id = apic_id;
curnode = pcms->node_cpu[apic_id];
@@ -2492,7 +2472,7 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine)
numa_start = table_data->len;
numamem = acpi_data_push(table_data, sizeof *numamem);
- acpi_build_srat_memory(numamem, 0, 640*1024, 0, MEM_AFFINITY_ENABLED);
+ build_srat_memory(numamem, 0, 640 * 1024, 0, MEM_AFFINITY_ENABLED);
next_base = 1024 * 1024;
for (i = 1; i < pcms->numa_nodes + 1; ++i) {
mem_base = next_base;
@@ -2508,21 +2488,21 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine)
mem_len -= next_base - pcms->below_4g_mem_size;
if (mem_len > 0) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1,
- MEM_AFFINITY_ENABLED);
+ build_srat_memory(numamem, mem_base, mem_len, i - 1,
+ MEM_AFFINITY_ENABLED);
}
mem_base = 1ULL << 32;
mem_len = next_base - pcms->below_4g_mem_size;
next_base += (1ULL << 32) - pcms->below_4g_mem_size;
}
numamem = acpi_data_push(table_data, sizeof *numamem);
- acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1,
- MEM_AFFINITY_ENABLED);
+ build_srat_memory(numamem, mem_base, mem_len, i - 1,
+ MEM_AFFINITY_ENABLED);
}
slots = (table_data->len - numa_start) / sizeof *numamem;
for (; slots < pcms->numa_nodes + 2; slots++) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- acpi_build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
+ build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
}
/*
@@ -2532,10 +2512,9 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine)
*/
if (hotplugabble_address_space_size) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- acpi_build_srat_memory(numamem, pcms->hotplug_memory.base,
- hotplugabble_address_space_size, 0,
- MEM_AFFINITY_HOTPLUGGABLE |
- MEM_AFFINITY_ENABLED);
+ build_srat_memory(numamem, pcms->hotplug_memory.base,
+ hotplugabble_address_space_size, 0,
+ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
}
build_header(linker, table_data,
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 48f9477065..64a6f4b4ba 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -146,19 +146,19 @@ static void irq_handler(void *opaque, int irq, int level)
pic_update(fs);
}
-static int etraxfs_pic_init(SysBusDevice *sbd)
+static void etraxfs_pic_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- struct etrax_pic *s = ETRAX_FS_PIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ struct etrax_pic *s = ETRAX_FS_PIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
qdev_init_gpio_in(dev, irq_handler, 32);
sysbus_init_irq(sbd, &s->parent_irq);
sysbus_init_irq(sbd, &s->parent_nmi);
- memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s,
+ memory_region_init_io(&s->mmio, obj, &pic_ops, s,
"etraxfs-pic", R_MAX * 4);
sysbus_init_mmio(sbd, &s->mmio);
- return 0;
}
static Property etraxfs_pic_properties[] = {
@@ -169,9 +169,7 @@ static Property etraxfs_pic_properties[] = {
static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = etraxfs_pic_init;
dc->props = etraxfs_pic_properties;
/*
* Note: pointer property "interrupt_vector" may remain null, thus
@@ -183,6 +181,7 @@ static const TypeInfo etraxfs_pic_info = {
.name = TYPE_ETRAX_FS_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct etrax_pic),
+ .instance_init = etraxfs_pic_init,
.class_init = etraxfs_pic_class_init,
};
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index dc0c903266..f19a7062be 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -406,10 +406,11 @@ static const MemoryRegionOps exynos4210_combiner_ops = {
/*
* Internal Combiner initialization.
*/
-static int exynos4210_combiner_init(SysBusDevice *sbd)
+static void exynos4210_combiner_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- Exynos4210CombinerState *s = EXYNOS4210_COMBINER(dev);
+ DeviceState *dev = DEVICE(obj);
+ Exynos4210CombinerState *s = EXYNOS4210_COMBINER(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
unsigned int i;
/* Allocate general purpose input signals and connect a handler to each of
@@ -421,11 +422,9 @@ static int exynos4210_combiner_init(SysBusDevice *sbd)
sysbus_init_irq(sbd, &s->output_irq[i]);
}
- memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s,
+ memory_region_init_io(&s->iomem, obj, &exynos4210_combiner_ops, s,
"exynos4210-combiner", IIC_REGION_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
-
- return 0;
}
static Property exynos4210_combiner_properties[] = {
@@ -436,9 +435,7 @@ static Property exynos4210_combiner_properties[] = {
static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = exynos4210_combiner_init;
dc->reset = exynos4210_combiner_reset;
dc->props = exynos4210_combiner_properties;
dc->vmsd = &vmstate_exynos4210_combiner;
@@ -448,6 +445,7 @@ static const TypeInfo exynos4210_combiner_info = {
.name = TYPE_EXYNOS4210_COMBINER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210CombinerState),
+ .instance_init = exynos4210_combiner_init,
.class_init = exynos4210_combiner_class_init,
};
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index 4f7e89f7b8..fd7a8f3058 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -281,10 +281,11 @@ static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
-static int exynos4210_gic_init(SysBusDevice *sbd)
+static void exynos4210_gic_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- Exynos4210GicState *s = EXYNOS4210_GIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ Exynos4210GicState *s = EXYNOS4210_GIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
uint32_t i;
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
const char dist_prefix[] = "exynos4210-gic-alias_dist";
@@ -305,15 +306,15 @@ static int exynos4210_gic_init(SysBusDevice *sbd)
qdev_init_gpio_in(dev, exynos4210_gic_set_irq,
EXYNOS4210_GIC_NIRQ - 32);
- memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container",
+ memory_region_init(&s->cpu_container, obj, "exynos4210-cpu-container",
EXYNOS4210_EXT_GIC_CPU_REGION_SIZE);
- memory_region_init(&s->dist_container, OBJECT(s), "exynos4210-dist-container",
+ memory_region_init(&s->dist_container, obj, "exynos4210-dist-container",
EXYNOS4210_EXT_GIC_DIST_REGION_SIZE);
for (i = 0; i < s->num_cpu; i++) {
/* Map CPU interface per SMP Core */
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
- memory_region_init_alias(&s->cpu_alias[i], OBJECT(s),
+ memory_region_init_alias(&s->cpu_alias[i], obj,
cpu_alias_name,
sysbus_mmio_get_region(busdev, 1),
0,
@@ -323,7 +324,7 @@ static int exynos4210_gic_init(SysBusDevice *sbd)
/* Map Distributor per SMP Core */
sprintf(dist_alias_name, "%s%x", dist_prefix, i);
- memory_region_init_alias(&s->dist_alias[i], OBJECT(s),
+ memory_region_init_alias(&s->dist_alias[i], obj,
dist_alias_name,
sysbus_mmio_get_region(busdev, 0),
0,
@@ -334,8 +335,6 @@ static int exynos4210_gic_init(SysBusDevice *sbd)
sysbus_init_mmio(sbd, &s->cpu_container);
sysbus_init_mmio(sbd, &s->dist_container);
-
- return 0;
}
static Property exynos4210_gic_properties[] = {
@@ -346,9 +345,7 @@ static Property exynos4210_gic_properties[] = {
static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = exynos4210_gic_init;
dc->props = exynos4210_gic_properties;
}
@@ -356,6 +353,7 @@ static const TypeInfo exynos4210_gic_info = {
.name = TYPE_EXYNOS4210_GIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210GicState),
+ .instance_init = exynos4210_gic_init,
.class_init = exynos4210_gic_class_init,
};
@@ -430,9 +428,16 @@ static void exynos4210_irq_gate_reset(DeviceState *d)
/*
* IRQ Gate initialization.
*/
-static int exynos4210_irq_gate_init(SysBusDevice *sbd)
+static void exynos4210_irq_gate_init(Object *obj)
+{
+ Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ sysbus_init_irq(sbd, &s->out);
+}
+
+static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
/* Allocate general purpose input signals and connect a handler to each of
@@ -440,27 +445,23 @@ static int exynos4210_irq_gate_init(SysBusDevice *sbd)
qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
s->level = g_malloc0(s->n_in * sizeof(*s->level));
-
- sysbus_init_irq(sbd, &s->out);
-
- return 0;
}
static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = exynos4210_irq_gate_init;
dc->reset = exynos4210_irq_gate_reset;
dc->vmsd = &vmstate_exynos4210_irq_gate;
dc->props = exynos4210_irq_gate_properties;
+ dc->realize = exynos4210_irq_gate_realize;
}
static const TypeInfo exynos4210_irq_gate_info = {
.name = TYPE_EXYNOS4210_IRQ_GATE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210IRQGateState),
+ .instance_init = exynos4210_irq_gate_init,
.class_init = exynos4210_irq_gate_class_init,
};
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index f5ca8f752b..ac7e63f38b 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -31,6 +31,7 @@
#include "hw/sparc/grlib.h"
#include "trace.h"
+#include "qapi/error.h"
#define IRQMP_MAX_CPU 16
#define IRQMP_REG_SIZE 256 /* Size of memory mapped registers */
@@ -323,23 +324,27 @@ static void grlib_irqmp_reset(DeviceState *d)
irqmp->state->parent = irqmp;
}
-static int grlib_irqmp_init(SysBusDevice *dev)
+static void grlib_irqmp_init(Object *obj)
{
- IRQMP *irqmp = GRLIB_IRQMP(dev);
-
- /* Check parameters */
- if (irqmp->set_pil_in == NULL) {
- return -1;
- }
+ IRQMP *irqmp = GRLIB_IRQMP(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp,
+ memory_region_init_io(&irqmp->iomem, obj, &grlib_irqmp_ops, irqmp,
"irqmp", IRQMP_REG_SIZE);
irqmp->state = g_malloc0(sizeof *irqmp->state);
sysbus_init_mmio(dev, &irqmp->iomem);
+}
- return 0;
+static void grlib_irqmp_realize(DeviceState *dev, Error **errp)
+{
+ IRQMP *irqmp = GRLIB_IRQMP(dev);
+
+ /* Check parameters */
+ if (irqmp->set_pil_in == NULL) {
+ error_setg(errp, "set_pil_in cannot be NULL.");
+ }
}
static Property grlib_irqmp_properties[] = {
@@ -351,19 +356,19 @@ static Property grlib_irqmp_properties[] = {
static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = grlib_irqmp_init;
dc->reset = grlib_irqmp_reset;
dc->props = grlib_irqmp_properties;
/* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */
dc->cannot_instantiate_with_device_add_yet = true;
+ dc->realize = grlib_irqmp_realize;
}
static const TypeInfo grlib_irqmp_info = {
.name = TYPE_GRLIB_IRQMP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IRQMP),
+ .instance_init = grlib_irqmp_init,
.class_init = grlib_irqmp_class_init,
};
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index 7027655774..d21cb97451 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -321,28 +321,26 @@ static void imx_avic_reset(DeviceState *dev)
memset(s->prio, 0, sizeof s->prio);
}
-static int imx_avic_init(SysBusDevice *sbd)
+static void imx_avic_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- IMXAVICState *s = IMX_AVIC(dev);
+ DeviceState *dev = DEVICE(obj);
+ IMXAVICState *s = IMX_AVIC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
+ memory_region_init_io(&s->iomem, obj, &imx_avic_ops, s,
TYPE_IMX_AVIC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
-
- return 0;
}
static void imx_avic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = imx_avic_init;
+
dc->vmsd = &vmstate_imx_avic;
dc->reset = imx_avic_reset;
dc->desc = "i.MX Advanced Vector Interrupt Controller";
@@ -352,6 +350,7 @@ static const TypeInfo imx_avic_info = {
.name = TYPE_IMX_AVIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXAVICState),
+ .instance_init = imx_avic_init,
.class_init = imx_avic_class_init,
};
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 336882510b..877be67971 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -22,6 +22,7 @@
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
#include "qemu/error-report.h"
+#include "qapi/error.h"
/* Interrupt Handlers */
struct omap_intr_handler_bank_s {
@@ -363,23 +364,28 @@ static void omap_inth_reset(DeviceState *dev)
qemu_set_irq(s->parent_intr[1], 0);
}
-static int omap_intc_init(SysBusDevice *sbd)
+static void omap_intc_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
+ DeviceState *dev = DEVICE(obj);
+ struct omap_intr_handler_s *s = OMAP_INTC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- if (!s->iclk) {
- error_report("omap-intc: clk not connected");
- return -1;
- }
s->nbanks = 1;
sysbus_init_irq(sbd, &s->parent_intr[0]);
sysbus_init_irq(sbd, &s->parent_intr[1]);
qdev_init_gpio_in(dev, omap_set_intr, s->nbanks * 32);
- memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s,
+ memory_region_init_io(&s->mmio, obj, &omap_inth_mem_ops, s,
"omap-intc", s->size);
sysbus_init_mmio(sbd, &s->mmio);
- return 0;
+}
+
+static void omap_intc_realize(DeviceState *dev, Error **errp)
+{
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+
+ if (!s->iclk) {
+ error_setg(errp, "omap-intc: clk not connected");
+ }
}
static Property omap_intc_properties[] = {
@@ -391,18 +397,18 @@ static Property omap_intc_properties[] = {
static void omap_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = omap_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap_intc_properties;
/* Reason: pointer property "clk" */
dc->cannot_instantiate_with_device_add_yet = true;
+ dc->realize = omap_intc_realize;
}
static const TypeInfo omap_intc_info = {
.name = "omap-intc",
.parent = TYPE_OMAP_INTC,
+ .instance_init = omap_intc_init,
.class_init = omap_intc_class_init,
};
@@ -605,28 +611,34 @@ static const MemoryRegionOps omap2_inth_mem_ops = {
},
};
-static int omap2_intc_init(SysBusDevice *sbd)
+static void omap2_intc_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
+ DeviceState *dev = DEVICE(obj);
+ struct omap_intr_handler_s *s = OMAP_INTC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- if (!s->iclk) {
- error_report("omap2-intc: iclk not connected");
- return -1;
- }
- if (!s->fclk) {
- error_report("omap2-intc: fclk not connected");
- return -1;
- }
s->level_only = 1;
s->nbanks = 3;
sysbus_init_irq(sbd, &s->parent_intr[0]);
sysbus_init_irq(sbd, &s->parent_intr[1]);
qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32);
- memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s,
+ memory_region_init_io(&s->mmio, obj, &omap2_inth_mem_ops, s,
"omap2-intc", 0x1000);
sysbus_init_mmio(sbd, &s->mmio);
- return 0;
+}
+
+static void omap2_intc_realize(DeviceState *dev, Error **errp)
+{
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+
+ if (!s->iclk) {
+ error_setg(errp, "omap2-intc: iclk not connected");
+ return;
+ }
+ if (!s->fclk) {
+ error_setg(errp, "omap2-intc: fclk not connected");
+ return;
+ }
}
static Property omap2_intc_properties[] = {
@@ -640,18 +652,18 @@ static Property omap2_intc_properties[] = {
static void omap2_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = omap2_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap2_intc_properties;
/* Reason: pointer property "iclk", "fclk" */
dc->cannot_instantiate_with_device_add_yet = true;
+ dc->realize = omap2_intc_realize;
}
static const TypeInfo omap2_intc_info = {
.name = "omap2-intc",
.parent = TYPE_OMAP_INTC,
+ .instance_init = omap2_intc_init,
.class_init = omap2_intc_class_init,
};
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index 5ecbc4a485..1e50baf237 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -236,17 +236,17 @@ static void pl190_reset(DeviceState *d)
pl190_update_vectors(s);
}
-static int pl190_init(SysBusDevice *sbd)
+static void pl190_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- PL190State *s = PL190(dev);
+ DeviceState *dev = DEVICE(obj);
+ PL190State *s = PL190(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000);
+ memory_region_init_io(&s->iomem, obj, &pl190_ops, s, "pl190", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, pl190_set_irq, 32);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
- return 0;
}
static const VMStateDescription vmstate_pl190 = {
@@ -271,9 +271,7 @@ static const VMStateDescription vmstate_pl190 = {
static void pl190_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pl190_init;
dc->reset = pl190_reset;
dc->vmsd = &vmstate_pl190;
}
@@ -282,6 +280,7 @@ static const TypeInfo pl190_info = {
.name = TYPE_PL190,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PL190State),
+ .instance_init = pl190_init,
.class_init = pl190_class_init,
};
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index c9486ed999..e82e893628 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -418,15 +418,16 @@ static void slavio_intctl_reset(DeviceState *d)
slavio_check_interrupts(s, 0);
}
-static int slavio_intctl_init1(SysBusDevice *sbd)
+static void slavio_intctl_init(Object *obj)
{
- DeviceState *dev = DEVICE(sbd);
- SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev);
+ DeviceState *dev = DEVICE(obj);
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
unsigned int i, j;
char slave_name[45];
qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS);
- memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s,
+ memory_region_init_io(&s->iomem, obj, &slavio_intctlm_mem_ops, s,
"master-interrupt-controller", INTCTLM_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
@@ -443,16 +444,12 @@ static int slavio_intctl_init1(SysBusDevice *sbd)
s->slaves[i].cpu = i;
s->slaves[i].master = s;
}
-
- return 0;
}
static void slavio_intctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = slavio_intctl_init1;
dc->reset = slavio_intctl_reset;
dc->vmsd = &vmstate_intctl;
}
@@ -461,6 +458,7 @@ static const TypeInfo slavio_intctl_info = {
.name = TYPE_SLAVIO_INTCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLAVIO_INTCTLState),
+ .instance_init = slavio_intctl_init,
.class_init = slavio_intctl_class_init,
};
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 93f952880a..bc0dd2cc75 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -29,6 +29,7 @@ obj-$(CONFIG_IMX) += imx_ccm.o
obj-$(CONFIG_IMX) += imx31_ccm.o
obj-$(CONFIG_IMX) += imx25_ccm.o
obj-$(CONFIG_IMX) += imx6_ccm.o
+obj-$(CONFIG_IMX) += imx6_src.o
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 530411f841..34473469d4 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -21,6 +21,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
int n;
uint32_t offset, length, color;
uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
+ uint32_t tmp_xres, tmp_yres, tmp_xoffset, tmp_yoffset;
+ uint32_t tmp_bpp, tmp_pixo, tmp_alpha;
uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
*newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;
@@ -139,7 +141,11 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
case 0x00040001: /* Allocate buffer */
stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
- stl_le_phys(&s->dma_as, value + 16, s->fbdev->size);
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
+ stl_le_phys(&s->dma_as, value + 16,
+ tmp_xres * tmp_yres * tmp_bpp / 8);
resplen = 8;
break;
case 0x00048001: /* Release buffer */
@@ -150,8 +156,10 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
break;
case 0x00040003: /* Get display width/height */
case 0x00040004:
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres);
- stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres);
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
+ stl_le_phys(&s->dma_as, value + 12, tmp_xres);
+ stl_le_phys(&s->dma_as, value + 16, tmp_yres);
resplen = 8;
break;
case 0x00044003: /* Test display width/height */
@@ -167,7 +175,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 8;
break;
case 0x00040005: /* Get depth */
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp);
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
+ stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
resplen = 4;
break;
case 0x00044005: /* Test depth */
@@ -179,7 +188,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040006: /* Get pixel order */
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo);
+ tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->pixo;
+ stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
resplen = 4;
break;
case 0x00044006: /* Test pixel order */
@@ -191,7 +201,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040007: /* Get alpha */
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha);
+ tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->alpha;
+ stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
resplen = 4;
break;
case 0x00044007: /* Test pixel alpha */
@@ -203,12 +214,16 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040008: /* Get pitch */
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch);
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
+ stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
resplen = 4;
break;
case 0x00040009: /* Get virtual offset */
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset);
- stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset);
+ tmp_xoffset = newxoffset != NULL ? *newxoffset : s->fbdev->xoffset;
+ tmp_yoffset = newyoffset != NULL ? *newyoffset : s->fbdev->yoffset;
+ stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
+ stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
resplen = 8;
break;
case 0x00044009: /* Test virtual offset */
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
new file mode 100644
index 0000000000..6b026b459f
--- /dev/null
+++ b/hw/misc/imx6_src.c
@@ -0,0 +1,264 @@
+/*
+ * IMX6 System Reset Controller
+ *
+ * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx6_src.h"
+#include "sysemu/sysemu.h"
+#include "qemu/bitops.h"
+#include "arm-powerctl.h"
+
+#ifndef DEBUG_IMX6_SRC
+#define DEBUG_IMX6_SRC 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (DEBUG_IMX6_SRC) { \
+ fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_SRC, \
+ __func__, ##args); \
+ } \
+ } while (0)
+
+static char const *imx6_src_reg_name(uint32_t reg)
+{
+ static char unknown[20];
+
+ switch (reg) {
+ case SRC_SCR:
+ return "SRC_SCR";
+ case SRC_SBMR1:
+ return "SRC_SBMR1";
+ case SRC_SRSR:
+ return "SRC_SRSR";
+ case SRC_SISR:
+ return "SRC_SISR";
+ case SRC_SIMR:
+ return "SRC_SIMR";
+ case SRC_SBMR2:
+ return "SRC_SBMR2";
+ case SRC_GPR1:
+ return "SRC_GPR1";
+ case SRC_GPR2:
+ return "SRC_GPR2";
+ case SRC_GPR3:
+ return "SRC_GPR3";
+ case SRC_GPR4:
+ return "SRC_GPR4";
+ case SRC_GPR5:
+ return "SRC_GPR5";
+ case SRC_GPR6:
+ return "SRC_GPR6";
+ case SRC_GPR7:
+ return "SRC_GPR7";
+ case SRC_GPR8:
+ return "SRC_GPR8";
+ case SRC_GPR9:
+ return "SRC_GPR9";
+ case SRC_GPR10:
+ return "SRC_GPR10";
+ default:
+ sprintf(unknown, "%d ?", reg);
+ return unknown;
+ }
+}
+
+static const VMStateDescription vmstate_imx6_src = {
+ .name = TYPE_IMX6_SRC,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, IMX6SRCState, SRC_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx6_src_reset(DeviceState *dev)
+{
+ IMX6SRCState *s = IMX6_SRC(dev);
+
+ DPRINTF("\n");
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ /* Set reset values */
+ s->regs[SRC_SCR] = 0x521;
+ s->regs[SRC_SRSR] = 0x1;
+ s->regs[SRC_SIMR] = 0x1F;
+}
+
+static uint64_t imx6_src_read(void *opaque, hwaddr offset, unsigned size)
+{
+ uint32_t value = 0;
+ IMX6SRCState *s = (IMX6SRCState *)opaque;
+ uint32_t index = offset >> 2;
+
+ if (index < SRC_MAX) {
+ value = s->regs[index];
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);
+
+ }
+
+ DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_src_reg_name(index), value);
+
+ return value;
+}
+
+static void imx6_src_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ IMX6SRCState *s = (IMX6SRCState *)opaque;
+ uint32_t index = offset >> 2;
+ unsigned long change_mask;
+ unsigned long current_value = value;
+
+ if (index >= SRC_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);
+ return;
+ }
+
+ DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_src_reg_name(index),
+ (uint32_t)current_value);
+
+ change_mask = s->regs[index] ^ (uint32_t)current_value;
+
+ switch (index) {
+ case SRC_SCR:
+ /*
+ * On real hardware when the system reset controller starts a
+ * secondary CPU it runs through some boot ROM code which reads
+ * the SRC_GPRX registers controlling the start address and branches
+ * to it.
+ * Here we are taking a short cut and branching directly to the
+ * requested address (we don't want to run the boot ROM code inside
+ * QEMU)
+ */
+ if (EXTRACT(change_mask, CORE3_ENABLE)) {
+ if (EXTRACT(current_value, CORE3_ENABLE)) {
+ /* CORE 3 is brought up */
+ arm_set_cpu_on(3, s->regs[SRC_GPR7], s->regs[SRC_GPR8],
+ 3, false);
+ } else {
+ /* CORE 3 is shut down */
+ arm_set_cpu_off(3);
+ }
+ /* We clear the reset bits as the processor changed state */
+ clear_bit(CORE3_RST_SHIFT, &current_value);
+ clear_bit(CORE3_RST_SHIFT, &change_mask);
+ }
+ if (EXTRACT(change_mask, CORE2_ENABLE)) {
+ if (EXTRACT(current_value, CORE2_ENABLE)) {
+ /* CORE 2 is brought up */
+ arm_set_cpu_on(2, s->regs[SRC_GPR5], s->regs[SRC_GPR6],
+ 3, false);
+ } else {
+ /* CORE 3 is shut down */
+ arm_set_cpu_off(2);
+ }
+ /* We clear the reset bits as the processor changed state */
+ clear_bit(CORE2_RST_SHIFT, &current_value);
+ clear_bit(CORE2_RST_SHIFT, &change_mask);
+ }
+ if (EXTRACT(change_mask, CORE1_ENABLE)) {
+ if (EXTRACT(current_value, CORE1_ENABLE)) {
+ /* CORE 1 is brought up */
+ arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4],
+ 3, false);
+ } else {
+ /* CORE 3 is shut down */
+ arm_set_cpu_off(1);
+ }
+ /* We clear the reset bits as the processor changed state */
+ clear_bit(CORE1_RST_SHIFT, &current_value);
+ clear_bit(CORE1_RST_SHIFT, &change_mask);
+ }
+ if (EXTRACT(change_mask, CORE0_RST)) {
+ arm_reset_cpu(0);
+ clear_bit(CORE0_RST_SHIFT, &current_value);
+ }
+ if (EXTRACT(change_mask, CORE1_RST)) {
+ arm_reset_cpu(1);
+ clear_bit(CORE1_RST_SHIFT, &current_value);
+ }
+ if (EXTRACT(change_mask, CORE2_RST)) {
+ arm_reset_cpu(2);
+ clear_bit(CORE2_RST_SHIFT, &current_value);
+ }
+ if (EXTRACT(change_mask, CORE3_RST)) {
+ arm_reset_cpu(3);
+ clear_bit(CORE3_RST_SHIFT, &current_value);
+ }
+ if (EXTRACT(change_mask, SW_IPU2_RST)) {
+ /* We pretend the IPU2 is reset */
+ clear_bit(SW_IPU2_RST_SHIFT, &current_value);
+ }
+ if (EXTRACT(change_mask, SW_IPU1_RST)) {
+ /* We pretend the IPU1 is reset */
+ clear_bit(SW_IPU1_RST_SHIFT, &current_value);
+ }
+ s->regs[index] = current_value;
+ break;
+ default:
+ s->regs[index] = current_value;
+ break;
+ }
+}
+
+static const struct MemoryRegionOps imx6_src_ops = {
+ .read = imx6_src_read,
+ .write = imx6_src_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx6_src_realize(DeviceState *dev, Error **errp)
+{
+ IMX6SRCState *s = IMX6_SRC(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx6_src_ops, s,
+ TYPE_IMX6_SRC, 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+}
+
+static void imx6_src_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = imx6_src_realize;
+ dc->reset = imx6_src_reset;
+ dc->vmsd = &vmstate_imx6_src;
+ dc->desc = "i.MX6 System Reset Controller";
+}
+
+static const TypeInfo imx6_src_info = {
+ .name = TYPE_IMX6_SRC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX6SRCState),
+ .class_init = imx6_src_class_init,
+};
+
+static void imx6_src_register_types(void)
+{
+ type_register_static(&imx6_src_info);
+}
+
+type_init(imx6_src_register_types)
diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 9555825aca..fcbb79ef01 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
obj-$(CONFIG_OMAP) += omap_spi.o
+obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
new file mode 100644
index 0000000000..d5dd42aca6
--- /dev/null
+++ b/hw/ssi/imx_spi.c
@@ -0,0 +1,454 @@
+/*
+ * IMX SPI Controller
+ *
+ * Copyright (c) 2016 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/ssi/imx_spi.h"
+#include "sysemu/sysemu.h"
+
+#ifndef DEBUG_IMX_SPI
+#define DEBUG_IMX_SPI 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (DEBUG_IMX_SPI) { \
+ fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \
+ __func__, ##args); \
+ } \
+ } while (0)
+
+static char const *imx_spi_reg_name(uint32_t reg)
+{
+ static char unknown[20];
+
+ switch (reg) {
+ case ECSPI_RXDATA:
+ return "ECSPI_RXDATA";
+ case ECSPI_TXDATA:
+ return "ECSPI_TXDATA";
+ case ECSPI_CONREG:
+ return "ECSPI_CONREG";
+ case ECSPI_CONFIGREG:
+ return "ECSPI_CONFIGREG";
+ case ECSPI_INTREG:
+ return "ECSPI_INTREG";
+ case ECSPI_DMAREG:
+ return "ECSPI_DMAREG";
+ case ECSPI_STATREG:
+ return "ECSPI_STATREG";
+ case ECSPI_PERIODREG:
+ return "ECSPI_PERIODREG";
+ case ECSPI_TESTREG:
+ return "ECSPI_TESTREG";
+ case ECSPI_MSGDATA:
+ return "ECSPI_MSGDATA";
+ default:
+ sprintf(unknown, "%d ?", reg);
+ return unknown;
+ }
+}
+
+static const VMStateDescription vmstate_imx_spi = {
+ .name = TYPE_IMX_SPI,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_FIFO32(tx_fifo, IMXSPIState),
+ VMSTATE_FIFO32(rx_fifo, IMXSPIState),
+ VMSTATE_INT16(burst_length, IMXSPIState),
+ VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx_spi_txfifo_reset(IMXSPIState *s)
+{
+ fifo32_reset(&s->tx_fifo);
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+static void imx_spi_rxfifo_reset(IMXSPIState *s)
+{
+ fifo32_reset(&s->rx_fifo);
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO;
+}
+
+static void imx_spi_update_irq(IMXSPIState *s)
+{
+ int level;
+
+ if (fifo32_is_empty(&s->rx_fifo)) {
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+ } else {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR;
+ }
+
+ if (fifo32_is_full(&s->rx_fifo)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF;
+ } else {
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+ }
+
+ if (fifo32_is_empty(&s->tx_fifo)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+ } else {
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE;
+ }
+
+ if (fifo32_is_full(&s->tx_fifo)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF;
+ } else {
+ s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+ }
+
+ level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0;
+
+ qemu_set_irq(s->irq, level);
+
+ DPRINTF("IRQ level is %d\n", level);
+}
+
+static uint8_t imx_spi_selected_channel(IMXSPIState *s)
+{
+ return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_SELECT);
+}
+
+static uint32_t imx_spi_burst_length(IMXSPIState *s)
+{
+ return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_BURST_LENGTH) + 1;
+}
+
+static bool imx_spi_is_enabled(IMXSPIState *s)
+{
+ return s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN;
+}
+
+static bool imx_spi_channel_is_master(IMXSPIState *s)
+{
+ uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_MODE);
+
+ return (mode & (1 << imx_spi_selected_channel(s))) ? true : false;
+}
+
+static bool imx_spi_is_multiple_master_burst(IMXSPIState *s)
+{
+ uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], ECSPI_CONFIGREG_SS_CTL);
+
+ return imx_spi_channel_is_master(s) &&
+ !(s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC) &&
+ ((wave & (1 << imx_spi_selected_channel(s))) ? true : false);
+}
+
+static void imx_spi_flush_txfifo(IMXSPIState *s)
+{
+ uint32_t tx;
+ uint32_t rx;
+
+ DPRINTF("Begin: TX Fifo Size = %d, RX Fifo Size = %d\n",
+ fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo));
+
+ while (!fifo32_is_empty(&s->tx_fifo)) {
+ int tx_burst = 0;
+ int index = 0;
+
+ if (s->burst_length <= 0) {
+ s->burst_length = imx_spi_burst_length(s);
+
+ DPRINTF("Burst length = %d\n", s->burst_length);
+
+ if (imx_spi_is_multiple_master_burst(s)) {
+ s->regs[ECSPI_CONREG] |= ECSPI_CONREG_XCH;
+ }
+ }
+
+ tx = fifo32_pop(&s->tx_fifo);
+
+ DPRINTF("data tx:0x%08x\n", tx);
+
+ tx_burst = MIN(s->burst_length, 32);
+
+ rx = 0;
+
+ while (tx_burst) {
+ uint8_t byte = tx & 0xff;
+
+ DPRINTF("writing 0x%02x\n", (uint32_t)byte);
+
+ /* We need to write one byte at a time */
+ byte = ssi_transfer(s->bus, byte);
+
+ DPRINTF("0x%02x read\n", (uint32_t)byte);
+
+ tx = tx >> 8;
+ rx |= (byte << (index * 8));
+
+ /* Remove 8 bits from the actual burst */
+ tx_burst -= 8;
+ s->burst_length -= 8;
+ index++;
+ }
+
+ DPRINTF("data rx:0x%08x\n", rx);
+
+ if (fifo32_is_full(&s->rx_fifo)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO;
+ } else {
+ fifo32_push(&s->rx_fifo, (uint8_t)rx);
+ }
+
+ if (s->burst_length <= 0) {
+ s->regs[ECSPI_CONREG] &= ~ECSPI_CONREG_XCH;
+
+ if (!imx_spi_is_multiple_master_burst(s)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
+ break;
+ }
+ }
+ }
+
+ if (fifo32_is_empty(&s->tx_fifo)) {
+ s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
+ }
+
+ /* TODO: We should also use TDR and RDR bits */
+
+ DPRINTF("End: TX Fifo Size = %d, RX Fifo Size = %d\n",
+ fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo));
+}
+
+static void imx_spi_reset(DeviceState *dev)
+{
+ IMXSPIState *s = IMX_SPI(dev);
+
+ DPRINTF("\n");
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ s->regs[ECSPI_STATREG] = 0x00000003;
+
+ imx_spi_rxfifo_reset(s);
+ imx_spi_txfifo_reset(s);
+
+ imx_spi_update_irq(s);
+
+ s->burst_length = 0;
+}
+
+static uint64_t imx_spi_read(void *opaque, hwaddr offset, unsigned size)
+{
+ uint32_t value = 0;
+ IMXSPIState *s = opaque;
+ uint32_t index = offset >> 2;
+
+ if (index >= ECSPI_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset);
+ return 0;
+ }
+
+ switch (index) {
+ case ECSPI_RXDATA:
+ if (!imx_spi_is_enabled(s)) {
+ value = 0;
+ } else if (fifo32_is_empty(&s->rx_fifo)) {
+ /* value is undefined */
+ value = 0xdeadbeef;
+ } else {
+ /* read from the RX FIFO */
+ value = fifo32_pop(&s->rx_fifo);
+ }
+
+ break;
+ case ECSPI_TXDATA:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from TX FIFO\n",
+ TYPE_IMX_SPI, __func__);
+
+ /* Reading from TXDATA gives 0 */
+
+ break;
+ case ECSPI_MSGDATA:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from MSG FIFO\n",
+ TYPE_IMX_SPI, __func__);
+
+ /* Reading from MSGDATA gives 0 */
+
+ break;
+ default:
+ value = s->regs[index];
+ break;
+ }
+
+ DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_spi_reg_name(index), value);
+
+ imx_spi_update_irq(s);
+
+ return (uint64_t)value;
+}
+
+static void imx_spi_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ IMXSPIState *s = opaque;
+ uint32_t index = offset >> 2;
+ uint32_t change_mask;
+
+ if (index >= ECSPI_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset);
+ return;
+ }
+
+ DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_spi_reg_name(index),
+ (uint32_t)value);
+
+ change_mask = s->regs[index] ^ value;
+
+ switch (index) {
+ case ECSPI_RXDATA:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to write to RX FIFO\n",
+ TYPE_IMX_SPI, __func__);
+ break;
+ case ECSPI_TXDATA:
+ case ECSPI_MSGDATA:
+ /* Is there any difference between TXDATA and MSGDATA ? */
+ /* I'll have to look in the linux driver */
+ if (!imx_spi_is_enabled(s)) {
+ /* Ignore writes if device is disabled */
+ break;
+ } else if (fifo32_is_full(&s->tx_fifo)) {
+ /* Ignore writes if queue is full */
+ break;
+ }
+
+ fifo32_push(&s->tx_fifo, (uint32_t)value);
+
+ if (imx_spi_channel_is_master(s) &&
+ (s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC)) {
+ /*
+ * Start emitting if current channel is master and SMC bit is
+ * set.
+ */
+ imx_spi_flush_txfifo(s);
+ }
+
+ break;
+ case ECSPI_STATREG:
+ /* the RO and TC bits are write-one-to-clear */
+ value &= ECSPI_STATREG_RO | ECSPI_STATREG_TC;
+ s->regs[ECSPI_STATREG] &= ~value;
+
+ break;
+ case ECSPI_CONREG:
+ s->regs[ECSPI_CONREG] = value;
+
+ if (!imx_spi_is_enabled(s)) {
+ /* device is disabled, so this is a reset */
+ imx_spi_reset(DEVICE(s));
+ return;
+ }
+
+ if (imx_spi_channel_is_master(s)) {
+ int i;
+
+ /* We are in master mode */
+
+ for (i = 0; i < 4; i++) {
+ qemu_set_irq(s->cs_lines[i],
+ i == imx_spi_selected_channel(s) ? 0 : 1);
+ }
+
+ if ((value & change_mask & ECSPI_CONREG_SMC) &&
+ !fifo32_is_empty(&s->tx_fifo)) {
+ /* SMC bit is set and TX FIFO has some slots filled in */
+ imx_spi_flush_txfifo(s);
+ } else if ((value & change_mask & ECSPI_CONREG_XCH) &&
+ !(value & ECSPI_CONREG_SMC)) {
+ /* This is a request to start emitting */
+ imx_spi_flush_txfifo(s);
+ }
+ }
+
+ break;
+ default:
+ s->regs[index] = value;
+
+ break;
+ }
+
+ imx_spi_update_irq(s);
+}
+
+static const struct MemoryRegionOps imx_spi_ops = {
+ .read = imx_spi_read,
+ .write = imx_spi_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx_spi_realize(DeviceState *dev, Error **errp)
+{
+ IMXSPIState *s = IMX_SPI(dev);
+ int i;
+
+ s->bus = ssi_create_bus(dev, "spi");
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx_spi_ops, s,
+ TYPE_IMX_SPI, 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+
+ ssi_auto_connect_slaves(dev, s->cs_lines, s->bus);
+
+ for (i = 0; i < 4; ++i) {
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cs_lines[i]);
+ }
+
+ s->burst_length = 0;
+
+ fifo32_create(&s->tx_fifo, ECSPI_FIFO_SIZE);
+ fifo32_create(&s->rx_fifo, ECSPI_FIFO_SIZE);
+}
+
+static void imx_spi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = imx_spi_realize;
+ dc->vmsd = &vmstate_imx_spi;
+ dc->reset = imx_spi_reset;
+ dc->desc = "i.MX SPI Controller";
+}
+
+static const TypeInfo imx_spi_info = {
+ .name = TYPE_IMX_SPI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXSPIState),
+ .class_init = imx_spi_class_init,
+};
+
+static void imx_spi_register_types(void)
+{
+ type_register_static(&imx_spi_info);
+}
+
+type_init(imx_spi_register_types)