summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/generic_event_device.c29
-rw-r--r--hw/arm/Kconfig8
-rw-r--r--hw/arm/aspeed.c16
-rw-r--r--hw/arm/cubieboard.c2
-rw-r--r--hw/arm/exynos4210.c2
-rw-r--r--hw/arm/imx25_pdk.c2
-rw-r--r--hw/arm/mcimx6ul-evk.c2
-rw-r--r--hw/arm/mcimx7d-sabre.c2
-rw-r--r--hw/arm/mps2-tz.c23
-rw-r--r--hw/arm/mps2.c67
-rw-r--r--hw/arm/msf2-som.c4
-rw-r--r--hw/arm/nseries.c4
-rw-r--r--hw/arm/orangepi.c2
-rw-r--r--hw/arm/raspi.c2
-rw-r--r--hw/arm/realview.c3
-rw-r--r--hw/arm/sabrelite.c6
-rw-r--r--hw/arm/versatilepb.c3
-rw-r--r--hw/arm/vexpress.c6
-rw-r--r--hw/arm/virt.c63
-rw-r--r--hw/arm/xilinx_zynq.c7
-rw-r--r--hw/arm/xlnx-versal-virt.c2
-rw-r--r--hw/arm/xlnx-zcu102.c10
-rw-r--r--hw/block/fdc.c82
-rw-r--r--hw/block/nand.c2
-rw-r--r--hw/block/pflash_cfi01.c6
-rw-r--r--hw/block/pflash_cfi02.c2
-rw-r--r--hw/core/qdev-properties-system.c151
-rw-r--r--hw/core/qdev-properties.c17
-rw-r--r--hw/i2c/versatile_i2c.c38
-rw-r--r--hw/i386/pc.c8
-rw-r--r--hw/ide/qdev.c4
-rw-r--r--hw/isa/isa-superio.c18
-rw-r--r--hw/m68k/q800.c3
-rw-r--r--hw/microblaze/petalogix_ml605_mmu.c5
-rw-r--r--hw/ppc/pnv.c3
-rw-r--r--hw/ppc/spapr.c4
-rw-r--r--hw/scsi/scsi-bus.c2
-rw-r--r--hw/sd/milkymist-memcard.c2
-rw-r--r--hw/sd/pxa2xx_mmci.c15
-rw-r--r--hw/sd/sd.c2
-rw-r--r--hw/sd/ssi-sd.c3
-rw-r--r--hw/sparc64/sun4u.c9
-rw-r--r--hw/tpm/Kconfig21
-rw-r--r--hw/tpm/Makefile.objs3
-rw-r--r--hw/tpm/tpm_crb.c4
-rw-r--r--hw/tpm/tpm_emulator.c997
-rw-r--r--hw/tpm/tpm_int.h75
-rw-r--r--hw/tpm/tpm_ioctl.h271
-rw-r--r--hw/tpm/tpm_passthrough.c405
-rw-r--r--hw/tpm/tpm_ppi.c1
-rw-r--r--hw/tpm/tpm_ppi.h1
-rw-r--r--hw/tpm/tpm_prop.h31
-rw-r--r--hw/tpm/tpm_spapr.c4
-rw-r--r--hw/tpm/tpm_tis.h1
-rw-r--r--hw/tpm/tpm_tis_common.c11
-rw-r--r--hw/tpm/tpm_tis_isa.c3
-rw-r--r--hw/tpm/tpm_tis_sysbus.c3
-rw-r--r--hw/tpm/tpm_util.c377
-rw-r--r--hw/tpm/tpm_util.h85
-rw-r--r--hw/tpm/trace-events34
-rw-r--r--hw/watchdog/cmsdk-apb-watchdog.c1
-rw-r--r--hw/watchdog/trace-events1
-rw-r--r--hw/xtensa/xtfpga.c3
63 files changed, 467 insertions, 2506 deletions
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 1cb34111e5..b8abdefa1c 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -193,6 +193,33 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
     }
 }
 
+static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
+                                       DeviceState *dev, Error **errp)
+{
+    AcpiGedState *s = ACPI_GED(hotplug_dev);
+
+    if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
+                       !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
+        acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
+    } else {
+        error_setg(errp, "acpi: device unplug request for unsupported device"
+                   " type: %s", object_get_typename(OBJECT(dev)));
+    }
+}
+
+static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
+                               DeviceState *dev, Error **errp)
+{
+    AcpiGedState *s = ACPI_GED(hotplug_dev);
+
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
+    } else {
+        error_setg(errp, "acpi: device unplug for unsupported device"
+                   " type: %s", object_get_typename(OBJECT(dev)));
+    }
+}
+
 static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
 {
     AcpiGedState *s = ACPI_GED(adev);
@@ -318,6 +345,8 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
     dc->vmsd = &vmstate_acpi_ged;
 
     hc->plug = acpi_ged_device_plug_cb;
+    hc->unplug_request = acpi_ged_unplug_request_cb;
+    hc->unplug = acpi_ged_unplug_cb;
 
     adevc->send_event = acpi_ged_send_event;
 }
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 9afa6eee79..4a224a6351 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -59,7 +59,7 @@ config HIGHBANK
     select ARM_TIMER # sp804
     select ARM_V7M
     select PL011 # UART
-    select PL022 # Serial port
+    select PL022 # SPI
     select PL031 # RTC
     select PL061 # GPIO
     select PL310 # cache controller
@@ -222,7 +222,7 @@ config STELLARIS
     select CMSDK_APB_WATCHDOG
     select I2C
     select PL011 # UART
-    select PL022 # Serial port
+    select PL022 # SPI
     select PL061 # GPIO
     select SSD0303 # OLED display
     select SSD0323 # OLED display
@@ -401,10 +401,12 @@ config MPS2
     select MPS2_FPGAIO
     select MPS2_SCC
     select OR_IRQ
-    select PL022    # Serial port
+    select PL022    # SPI
     select PL080    # DMA controller
     select SPLIT_IRQ
     select UNIMP
+    select CMSDK_APB_WATCHDOG
+    select VERSATILE_I2C
 
 config FSL_IMX7
     bool
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 0ad08a2b4c..863757e1f0 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -215,8 +215,8 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
     g_free(storage);
 }
 
-static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
-                                      Error **errp)
+static void aspeed_board_init_flashes(AspeedSMCState *s,
+                                      const char *flashtype)
 {
     int i ;
 
@@ -227,8 +227,8 @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
 
         fl->flash = qdev_new(flashtype);
         if (dinfo) {
-            qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
-                                errp);
+            qdev_prop_set_drive(fl->flash, "drive",
+                                blk_by_legacy_dinfo(dinfo));
         }
         qdev_realize_and_unref(fl->flash, BUS(s->spi), &error_fatal);
 
@@ -243,8 +243,8 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
 
         card = qdev_new(TYPE_SD_CARD);
         if (dinfo) {
-            qdev_prop_set_drive(card, "drive", blk_by_legacy_dinfo(dinfo),
-                                &error_fatal);
+            qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+                                    &error_fatal);
         }
         qdev_realize_and_unref(card,
                                qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
@@ -314,8 +314,8 @@ static void aspeed_machine_init(MachineState *machine)
                           "max_ram", max_ram_size  - ram_size);
     memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram);
 
-    aspeed_board_init_flashes(&bmc->soc.fmc, amc->fmc_model, &error_abort);
-    aspeed_board_init_flashes(&bmc->soc.spi[0], amc->spi_model, &error_abort);
+    aspeed_board_init_flashes(&bmc->soc.fmc, amc->fmc_model);
+    aspeed_board_init_flashes(&bmc->soc.spi[0], amc->spi_model);
 
     /* Install first FMC flash content as a boot rom. */
     if (drive0) {
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index a96c860575..5cbd115c53 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -93,7 +93,7 @@ static void cubieboard_init(MachineState *machine)
 
     /* Plug in SD card */
     carddev = qdev_new(TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+    qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
     qdev_realize_and_unref(carddev, bus, &error_fatal);
 
     memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index b888a5c9ab..fa639806ec 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -434,7 +434,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
         di = drive_get(IF_SD, 0, n);
         blk = di ? blk_by_legacy_dinfo(di) : NULL;
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_abort);
+        qdev_prop_set_drive(carddev, "drive", blk);
         qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"),
                                &error_fatal);
     }
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
index af8f7f969c..1c201d0d8e 100644
--- a/hw/arm/imx25_pdk.c
+++ b/hw/arm/imx25_pdk.c
@@ -130,7 +130,7 @@ static void imx25_pdk_init(MachineState *machine)
         blk = di ? blk_by_legacy_dinfo(di) : NULL;
         bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
         qdev_realize_and_unref(carddev, bus, &error_fatal);
     }
 
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index 3d1d2e3c04..2f845cedfc 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -55,7 +55,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
         blk = di ? blk_by_legacy_dinfo(di) : NULL;
         bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
         qdev_realize_and_unref(carddev, bus, &error_fatal);
     }
 
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index 365f8183bc..e57d52b344 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -57,7 +57,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
         blk = di ? blk_by_legacy_dinfo(di) : NULL;
         bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
         qdev_realize_and_unref(carddev, bus, &error_fatal);
     }
 
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 8155c35418..a4fd5ddede 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -58,6 +58,7 @@
 #include "hw/arm/armsse.h"
 #include "hw/dma/pl080.h"
 #include "hw/ssi/pl022.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
 #include "hw/net/lan9118.h"
 #include "net/net.h"
 #include "hw/core/split-irq.h"
@@ -87,7 +88,7 @@ typedef struct {
     TZPPC ppc[5];
     TZMPC ssram_mpc[3];
     PL022State spi[5];
-    UnimplementedDeviceState i2c[4];
+    ArmSbconI2CState i2c[4];
     UnimplementedDeviceState i2s_audio;
     UnimplementedDeviceState gpio[4];
     UnimplementedDeviceState gfx;
@@ -365,6 +366,18 @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
     return sysbus_mmio_get_region(s, 0);
 }
 
+static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
+                              const char *name, hwaddr size)
+{
+    ArmSbconI2CState *i2c = opaque;
+    SysBusDevice *s;
+
+    object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
+    s = SYS_BUS_DEVICE(i2c);
+    sysbus_realize(s, &error_fatal);
+    return sysbus_mmio_get_region(s, 0);
+}
+
 static void mps2tz_common_init(MachineState *machine)
 {
     MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
@@ -499,10 +512,10 @@ static void mps2tz_common_init(MachineState *machine)
                 { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
                 { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
                 { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
-                { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
-                { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
-                { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
-                { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
+                { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
+                { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
+                { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
+                { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
             },
         }, {
             .name = "apb_ppcexp2",
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index daa55f730b..d1653a7e6e 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -38,8 +38,12 @@
 #include "hw/timer/cmsdk-apb-timer.h"
 #include "hw/timer/cmsdk-apb-dualtimer.h"
 #include "hw/misc/mps2-scc.h"
+#include "hw/misc/mps2-fpgaio.h"
+#include "hw/ssi/pl022.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
 #include "hw/net/lan9118.h"
 #include "net/net.h"
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
 
 typedef enum MPS2FPGAType {
     FPGA_AN385,
@@ -65,8 +69,12 @@ typedef struct {
     MemoryRegion blockram_m2;
     MemoryRegion blockram_m3;
     MemoryRegion sram;
+    /* FPGA APB subsystem */
     MPS2SCC scc;
+    MPS2FPGAIO fpgaio;
+    /* CMSDK APB subsystem */
     CMSDKAPBDualTimer dualtimer;
+    CMSDKAPBWatchdog watchdog;
 } MPS2MachineState;
 
 #define TYPE_MPS2_MACHINE "mps2"
@@ -111,6 +119,7 @@ static void mps2_common_init(MachineState *machine)
     MemoryRegion *system_memory = get_system_memory();
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     DeviceState *armv7m, *sccdev;
+    int i;
 
     if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
         error_report("This board can only be used with CPU %s",
@@ -210,10 +219,11 @@ static void mps2_common_init(MachineState *machine)
      */
     create_unimplemented_device("CMSDK APB peripheral region @0x40000000",
                                 0x40000000, 0x00010000);
-    create_unimplemented_device("CMSDK peripheral region @0x40010000",
+    create_unimplemented_device("CMSDK AHB peripheral region @0x40010000",
                                 0x40010000, 0x00010000);
     create_unimplemented_device("Extra peripheral region @0x40020000",
                                 0x40020000, 0x00010000);
+
     create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
     create_unimplemented_device("VGA", 0x41000000, 0x0200000);
 
@@ -225,7 +235,6 @@ static void mps2_common_init(MachineState *machine)
          */
         Object *orgate;
         DeviceState *orgate_dev;
-        int i;
 
         orgate = object_new(TYPE_OR_IRQ);
         object_property_set_int(orgate, 6, "num-lines", &error_fatal);
@@ -262,7 +271,6 @@ static void mps2_common_init(MachineState *machine)
          */
         Object *orgate;
         DeviceState *orgate_dev;
-        int i;
 
         orgate = object_new(TYPE_OR_IRQ);
         object_property_set_int(orgate, 10, "num-lines", &error_fatal);
@@ -298,10 +306,15 @@ static void mps2_common_init(MachineState *machine)
     default:
         g_assert_not_reached();
     }
+    for (i = 0; i < 4; i++) {
+        static const hwaddr gpiobase[] = {0x40010000, 0x40011000,
+                                          0x40012000, 0x40013000};
+        create_unimplemented_device("cmsdk-ahb-gpio", gpiobase[i], 0x1000);
+    }
 
+    /* CMSDK APB subsystem */
     cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
     cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
-
     object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
                             TYPE_CMSDK_APB_DUALTIMER);
     qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
@@ -309,7 +322,15 @@ static void mps2_common_init(MachineState *machine)
     sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
                        qdev_get_gpio_in(armv7m, 10));
     sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
-
+    object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
+                            TYPE_CMSDK_APB_WATCHDOG);
+    qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
+    sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
+                       qdev_get_gpio_in_named(armv7m, "NMI", 0));
+    sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0x40008000);
+
+    /* FPGA APB subsystem */
     object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
     sccdev = DEVICE(&mms->scc);
     qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
@@ -317,6 +338,42 @@ static void mps2_common_init(MachineState *machine)
     qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
     sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
     sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
+    object_initialize_child(OBJECT(mms), "fpgaio",
+                            &mms->fpgaio, TYPE_MPS2_FPGAIO);
+    qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", 25000000);
+    sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0x40028000);
+    sysbus_create_simple(TYPE_PL022, 0x40025000,        /* External ADC */
+                         qdev_get_gpio_in(armv7m, 22));
+    for (i = 0; i < 2; i++) {
+        static const int spi_irqno[] = {11, 24};
+        static const hwaddr spibase[] = {0x40020000,    /* APB */
+                                         0x40021000,    /* LCD */
+                                         0x40026000,    /* Shield0 */
+                                         0x40027000};   /* Shield1 */
+        DeviceState *orgate_dev;
+        Object *orgate;
+        int j;
+
+        orgate = object_new(TYPE_OR_IRQ);
+        object_property_set_int(orgate, 2, "num-lines", &error_fatal);
+        orgate_dev = DEVICE(orgate);
+        qdev_realize(orgate_dev, NULL, &error_fatal);
+        qdev_connect_gpio_out(orgate_dev, 0,
+                              qdev_get_gpio_in(armv7m, spi_irqno[i]));
+        for (j = 0; j < 2; j++) {
+            sysbus_create_simple(TYPE_PL022, spibase[2 * i + j],
+                                 qdev_get_gpio_in(orgate_dev, j));
+        }
+    }
+    for (i = 0; i < 4; i++) {
+        static const hwaddr i2cbase[] = {0x40022000,    /* Touch */
+                                         0x40023000,    /* Audio */
+                                         0x40029000,    /* Shield0 */
+                                         0x4002a000};   /* Shield1 */
+        sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
+    }
+    create_unimplemented_device("i2s", 0x40024000, 0x400);
 
     /* In hardware this is a LAN9220; the LAN9118 is software compatible
      * except that it doesn't support the checksum-offload feature.
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index 355966c073..f9b61c36dd 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -86,8 +86,8 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
     spi_flash = qdev_new("s25sl12801");
     qdev_prop_set_uint8(spi_flash, "spansion-cr2nv", 1);
     if (dinfo) {
-        qdev_prop_set_drive(spi_flash, "drive", blk_by_legacy_dinfo(dinfo),
-                                    &error_fatal);
+        qdev_prop_set_drive_err(spi_flash, "drive",
+                                blk_by_legacy_dinfo(dinfo), &error_fatal);
     }
     qdev_realize_and_unref(spi_flash, spi_bus, &error_fatal);
     cs_line = qdev_get_gpio_in_named(spi_flash, SSI_GPIO_CS, 0);
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 02678dda2d..428a2a2c5a 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -182,8 +182,8 @@ static void n8x0_nand_setup(struct n800_s *s)
     qdev_prop_set_int32(s->nand, "shift", 1);
     dinfo = drive_get(IF_MTD, 0, 0);
     if (dinfo) {
-        qdev_prop_set_drive(s->nand, "drive", blk_by_legacy_dinfo(dinfo),
-                            &error_fatal);
+        qdev_prop_set_drive_err(s->nand, "drive", blk_by_legacy_dinfo(dinfo),
+                                &error_fatal);
     }
     sysbus_realize_and_unref(SYS_BUS_DEVICE(s->nand), &error_fatal);
     sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
index 678c93033e..843dcbbd62 100644
--- a/hw/arm/orangepi.c
+++ b/hw/arm/orangepi.c
@@ -95,7 +95,7 @@ static void orangepi_init(MachineState *machine)
 
     /* Plug in SD card */
     carddev = qdev_new(TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+    qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
     qdev_realize_and_unref(carddev, bus, &error_fatal);
 
     /* SDRAM */
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 380978fc27..09bf02ec9c 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -298,7 +298,7 @@ static void raspi_machine_init(MachineState *machine)
         exit(1);
     }
     carddev = qdev_new(TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+    qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
     qdev_realize_and_unref(carddev, bus, &error_fatal);
 
     vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index f3c00fe00c..b6c0a1adb9 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -26,6 +26,7 @@
 #include "hw/cpu/a9mpcore.h"
 #include "hw/intc/realview_gic.h"
 #include "hw/irq.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
 #define SMP_BOOTREG_ADDR 0x10000030
@@ -282,7 +283,7 @@ static void realview_init(MachineState *machine,
         }
     }
 
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
     i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
     i2c_create_slave(i2c, "ds1338", 0x68);
 
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
index a27e5baf60..91d8c43a7e 100644
--- a/hw/arm/sabrelite.c
+++ b/hw/arm/sabrelite.c
@@ -77,9 +77,9 @@ static void sabrelite_init(MachineState *machine)
 
                 flash_dev = qdev_new("sst25vf016b");
                 if (dinfo) {
-                    qdev_prop_set_drive(flash_dev, "drive",
-                                        blk_by_legacy_dinfo(dinfo),
-                                        &error_fatal);
+                    qdev_prop_set_drive_err(flash_dev, "drive",
+                                            blk_by_legacy_dinfo(dinfo),
+                                            &error_fatal);
                 }
                 qdev_realize_and_unref(flash_dev, BUS(spi_bus), &error_fatal);
 
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 2ebdcbd8ac..e596b8170f 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -18,6 +18,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/pci/pci.h"
 #include "hw/i2c/i2c.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
 #include "hw/irq.h"
 #include "hw/boards.h"
 #include "exec/address-spaces.h"
@@ -314,7 +315,7 @@ static void versatile_init(MachineState *machine, int board_id)
     /* Add PL031 Real Time Clock. */
     sysbus_create_simple("pl031", 0x101e8000, pic[10]);
 
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
     i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
     i2c_create_slave(i2c, "ds1338", 0x68);
 
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 7ca5d523a4..5bf9cff8a8 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -42,6 +42,7 @@
 #include "hw/char/pl011.h"
 #include "hw/cpu/a9mpcore.h"
 #include "hw/cpu/a15mpcore.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
 
 #define VEXPRESS_BOARD_ID 0x8e0
 #define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
@@ -517,8 +518,7 @@ static PFlashCFI01 *ve_pflash_cfi01_register(hwaddr base, const char *name,
     DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
     if (di) {
-        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di),
-                            &error_abort);
+        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di));
     }
 
     qdev_prop_set_uint32(dev, "num-blocks",
@@ -640,7 +640,7 @@ static void vexpress_common_init(MachineState *machine)
     sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
     sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
 
-    dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL);
+    dev = sysbus_create_simple(TYPE_VERSATILE_I2C, map[VE_SERIALDVI], NULL);
     i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
     i2c_create_slave(i2c, "sii9022", 0x39);
 
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index caceb1e4a0..402c362c14 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2177,11 +2177,68 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
     }
 }
 
+static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
+                                     DeviceState *dev, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+    Error *local_err = NULL;
+
+    if (!vms->acpi_dev) {
+        error_setg(&local_err,
+                   "memory hotplug is not enabled: missing acpi-ged device");
+        goto out;
+    }
+
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
+        error_setg(&local_err,
+                   "nvdimm device hot unplug is not supported yet.");
+        goto out;
+    }
+
+    hotplug_handler_unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev,
+                                   &local_err);
+out:
+    error_propagate(errp, local_err);
+}
+
+static void virt_dimm_unplug(HotplugHandler *hotplug_dev,
+                             DeviceState *dev, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+    Error *local_err = NULL;
+
+    hotplug_handler_unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
+    if (local_err) {
+        goto out;
+    }
+
+    pc_dimm_unplug(PC_DIMM(dev), MACHINE(vms));
+    qdev_unrealize(dev);
+
+out:
+    error_propagate(errp, local_err);
+}
+
 static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                           DeviceState *dev, Error **errp)
 {
-    error_setg(errp, "device unplug request for unsupported device"
-               " type: %s", object_get_typename(OBJECT(dev)));
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        virt_dimm_unplug_request(hotplug_dev, dev, errp);
+    } else {
+        error_setg(errp, "device unplug request for unsupported device"
+                   " type: %s", object_get_typename(OBJECT(dev)));
+    }
+}
+
+static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                          DeviceState *dev, Error **errp)
+{
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        virt_dimm_unplug(hotplug_dev, dev, errp);
+    } else {
+        error_setg(errp, "virt: device unplug for unsupported device"
+                   " type: %s", object_get_typename(OBJECT(dev)));
+    }
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
@@ -2262,6 +2319,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     hc->pre_plug = virt_machine_device_pre_plug_cb;
     hc->plug = virt_machine_device_plug_cb;
     hc->unplug_request = virt_machine_device_unplug_request_cb;
+    hc->unplug = virt_machine_device_unplug_cb;
     mc->numa_mem_supported = true;
     mc->nvdimm_supported = true;
     mc->auto_enable_numa_with_memhp = true;
@@ -2375,6 +2433,7 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 1)
 static void virt_machine_5_0_options(MachineClass *mc)
 {
     virt_machine_5_1_options(mc);
+    compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
 }
 DEFINE_VIRT_MACHINE(5, 0)
 
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 4247c4dbd8..ed970273f3 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -159,8 +159,9 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
             DriveInfo *dinfo = drive_get_next(IF_MTD);
             flash_dev = qdev_new("n25q128");
             if (dinfo) {
-                qdev_prop_set_drive(flash_dev, "drive",
-                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
+                qdev_prop_set_drive_err(flash_dev, "drive",
+                                        blk_by_legacy_dinfo(dinfo),
+                                        &error_fatal);
             }
             qdev_realize_and_unref(flash_dev, BUS(spi), &error_fatal);
 
@@ -290,7 +291,7 @@ static void zynq_init(MachineState *machine)
         di = drive_get_next(IF_SD);
         blk = di ? blk_by_legacy_dinfo(di) : NULL;
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
         qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"),
                                &error_fatal);
     }
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 5bcca7f95b..a3b1ce9c7c 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -465,7 +465,7 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
 
     card = qdev_new(TYPE_SD_CARD);
     object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
-    qdev_prop_set_drive(card, "drive", blk, &error_fatal);
+    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
     qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"),
                            &error_fatal);
 }
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index b920bcee94..77449759c6 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -143,7 +143,7 @@ static void xlnx_zcu102_init(MachineState *machine)
             exit(1);
         }
         carddev = qdev_new(TYPE_SD_CARD);
-        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
         qdev_realize_and_unref(carddev, bus, &error_fatal);
     }
 
@@ -159,8 +159,8 @@ static void xlnx_zcu102_init(MachineState *machine)
 
         flash_dev = qdev_new("sst25wf080");
         if (dinfo) {
-            qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo),
-                                &error_fatal);
+            qdev_prop_set_drive_err(flash_dev, "drive",
+                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
         }
         qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
 
@@ -182,8 +182,8 @@ static void xlnx_zcu102_init(MachineState *machine)
 
         flash_dev = qdev_new("n25q512a11");
         if (dinfo) {
-            qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo),
-                                &error_fatal);
+            qdev_prop_set_drive_err(flash_dev, "drive",
+                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
         }
         qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
 
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index be0674e4aa..f4493d6afa 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -2497,6 +2497,29 @@ static void fdctrl_result_timer(void *opaque)
 }
 
 /* Init functions */
+
+static void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds)
+{
+    DeviceState *dev;
+    int i;
+
+    for (i = 0; i < MAX_FD; i++) {
+        if (fds[i]) {
+            dev = qdev_new("floppy");
+            qdev_prop_set_uint32(dev, "unit", i);
+            qdev_prop_set_enum(dev, "drive-type", FLOPPY_DRIVE_TYPE_AUTO);
+            qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(fds[i]),
+                                    &error_fatal);
+            qdev_realize_and_unref(dev, &bus->bus, &error_fatal);
+        }
+    }
+}
+
+void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds)
+{
+    fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds);
+}
+
 static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev,
                                   Error **errp)
 {
@@ -2505,6 +2528,7 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev,
     DeviceState *dev;
     BlockBackend *blk;
     Error *local_err = NULL;
+    const char *fdc_name, *drive_suffix;
 
     for (i = 0; i < MAX_FD; i++) {
         drive = &fdctrl->drives[i];
@@ -2519,14 +2543,30 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev,
             continue;
         }
 
+        fdc_name = object_get_typename(OBJECT(fdc_dev));
+        drive_suffix = !strcmp(fdc_name, "SUNW,fdtwo") ? "" : i ? "B" : "A";
+        warn_report("warning: property %s.drive%s is deprecated",
+                    fdc_name, drive_suffix);
+        error_printf("Use -device floppy,unit=%d,drive=... instead.\n", i);
+
         dev = qdev_new("floppy");
         qdev_prop_set_uint32(dev, "unit", i);
         qdev_prop_set_enum(dev, "drive-type", fdctrl->qdev_for_drives[i].type);
 
+        /*
+         * Hack alert: we move the backend from the floppy controller
+         * device to the floppy device.  We first need to detach the
+         * controller, or else floppy_create()'s qdev_prop_set_drive()
+         * will die when it attaches floppy device.  We also need to
+         * take another reference so that blk_detach_dev() doesn't
+         * free blk while we still need it.
+         *
+         * The hack is probably a bad idea.
+         */
         blk_ref(blk);
         blk_detach_dev(blk, fdc_dev);
         fdctrl->qdev_for_drives[i].blk = NULL;
-        qdev_prop_set_drive(dev, "drive", blk, &local_err);
+        qdev_prop_set_drive_err(dev, "drive", blk, &local_err);
         blk_unref(blk);
 
         if (local_err) {
@@ -2542,30 +2582,6 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev,
     }
 }
 
-ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
-{
-    DeviceState *dev;
-    ISADevice *isadev;
-
-    isadev = isa_try_new(TYPE_ISA_FDC);
-    if (!isadev) {
-        return NULL;
-    }
-    dev = DEVICE(isadev);
-
-    if (fds[0]) {
-        qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]),
-                            &error_fatal);
-    }
-    if (fds[1]) {
-        qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]),
-                            &error_fatal);
-    }
-    isa_realize_and_unref(isadev, bus, &error_fatal);
-
-    return isadev;
-}
-
 void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
                         hwaddr mmio_base, DriveInfo **fds)
 {
@@ -2578,18 +2594,12 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
     sys = SYSBUS_FDC(dev);
     fdctrl = &sys->state;
     fdctrl->dma_chann = dma_chann; /* FIXME */
-    if (fds[0]) {
-        qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]),
-                            &error_fatal);
-    }
-    if (fds[1]) {
-        qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]),
-                            &error_fatal);
-    }
     sbd = SYS_BUS_DEVICE(dev);
     sysbus_realize_and_unref(sbd, &error_fatal);
     sysbus_connect_irq(sbd, 0, irq);
     sysbus_mmio_map(sbd, 0, mmio_base);
+
+    fdctrl_init_drives(&sys->state.bus, fds);
 }
 
 void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
@@ -2599,15 +2609,13 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
     FDCtrlSysBus *sys;
 
     dev = qdev_new("SUNW,fdtwo");
-    if (fds[0]) {
-        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(fds[0]),
-                            &error_fatal);
-    }
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
     sys = SYSBUS_FDC(dev);
     sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
     sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
     *fdc_tc = qdev_get_gpio_in(dev, 0);
+
+    fdctrl_init_drives(&sys->state.bus, fds);
 }
 
 static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl,
diff --git a/hw/block/nand.c b/hw/block/nand.c
index 7e25681d59..654e0cb5d1 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -648,7 +648,7 @@ DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id)
     qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
     qdev_prop_set_uint8(dev, "chip_id", chip_id);
     if (blk) {
-        qdev_prop_set_drive(dev, "drive", blk, &error_fatal);
+        qdev_prop_set_drive_err(dev, "drive", blk, &error_fatal);
     }
 
     qdev_realize(dev, NULL, &error_fatal);
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 9f0c1d61ca..cddc3a5a0c 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -962,7 +962,7 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base,
     DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
     if (blk) {
-        qdev_prop_set_drive(dev, "drive", blk, &error_abort);
+        qdev_prop_set_drive(dev, "drive", blk);
     }
     assert(QEMU_IS_ALIGNED(size, sector_len));
     qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
@@ -1010,8 +1010,8 @@ void pflash_cfi01_legacy_drive(PFlashCFI01 *fl, DriveInfo *dinfo)
         error_report("clashes with -machine");
         exit(1);
     }
-    qdev_prop_set_drive(DEVICE(fl), "drive",
-                        blk_by_legacy_dinfo(dinfo), &error_fatal);
+    qdev_prop_set_drive_err(DEVICE(fl), "drive", blk_by_legacy_dinfo(dinfo),
+                            &error_fatal);
     loc_pop(&loc);
 }
 
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 6eb66e7bb0..b40ce2335a 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -1001,7 +1001,7 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base,
     DeviceState *dev = qdev_new(TYPE_PFLASH_CFI02);
 
     if (blk) {
-        qdev_prop_set_drive(dev, "drive", blk, &error_abort);
+        qdev_prop_set_drive(dev, "drive", blk);
     }
     assert(QEMU_IS_ALIGNED(size, sector_len));
     qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 70bfd4809b..38b0c9f09b 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -25,29 +25,67 @@
 #include "sysemu/iothread.h"
 #include "sysemu/tpm_backend.h"
 
-static void get_pointer(Object *obj, Visitor *v, Property *prop,
-                        char *(*print)(void *ptr),
-                        const char *name, Error **errp)
+static bool check_prop_still_unset(DeviceState *dev, const char *name,
+                                   const void *old_val, const char *new_val,
+                                   Error **errp)
+{
+    const GlobalProperty *prop = qdev_find_global_prop(dev, name);
+
+    if (!old_val) {
+        return true;
+    }
+
+    if (prop) {
+        error_setg(errp, "-global %s.%s=... conflicts with %s=%s",
+                   prop->driver, prop->property, name, new_val);
+    } else {
+        /* Error message is vague, but a better one would be hard */
+        error_setg(errp, "%s=%s conflicts, and override is not implemented",
+                   name, new_val);
+    }
+    return false;
+}
+
+
+/* --- drive --- */
+
+static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
+                      Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
     void **ptr = qdev_get_prop_ptr(dev, prop);
+    const char *value;
     char *p;
 
-    p = *ptr ? print(*ptr) : g_strdup("");
+    if (*ptr) {
+        value = blk_name(*ptr);
+        if (!*value) {
+            BlockDriverState *bs = blk_bs(*ptr);
+            if (bs) {
+                value = bdrv_get_node_name(bs);
+            }
+        }
+    } else {
+        value = "";
+    }
+
+    p = g_strdup(value);
     visit_type_str(v, name, &p, errp);
     g_free(p);
 }
 
-static void set_pointer(Object *obj, Visitor *v, Property *prop,
-                        void (*parse)(DeviceState *dev, const char *str,
-                                      void **ptr, const char *propname,
-                                      Error **errp),
-                        const char *name, Error **errp)
+static void set_drive_helper(Object *obj, Visitor *v, const char *name,
+                             void *opaque, bool iothread, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
     Error *local_err = NULL;
     void **ptr = qdev_get_prop_ptr(dev, prop);
     char *str;
+    BlockBackend *blk;
+    bool blk_created = false;
+    int ret;
 
     if (dev->realized) {
         qdev_prop_set_after_realize(dev, name, errp);
@@ -59,23 +97,20 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
         error_propagate(errp, local_err);
         return;
     }
+
+    /*
+     * TODO Should this really be an error?  If no, the old value
+     * needs to be released before we store the new one.
+     */
+    if (!check_prop_still_unset(dev, name, *ptr, str, errp)) {
+        return;
+    }
+
     if (!*str) {
         g_free(str);
         *ptr = NULL;
         return;
     }
-    parse(dev, str, ptr, prop->name, errp);
-    g_free(str);
-}
-
-/* --- drive --- */
-
-static void do_parse_drive(DeviceState *dev, const char *str, void **ptr,
-                           const char *propname, bool iothread, Error **errp)
-{
-    BlockBackend *blk;
-    bool blk_created = false;
-    int ret;
 
     blk = blk_by_name(str);
     if (!blk) {
@@ -101,7 +136,7 @@ static void do_parse_drive(DeviceState *dev, const char *str, void **ptr,
     }
     if (!blk) {
         error_setg(errp, "Property '%s.%s' can't find value '%s'",
-                   object_get_typename(OBJECT(dev)), propname, str);
+                   object_get_typename(OBJECT(dev)), prop->name, str);
         goto fail;
     }
     if (blk_attach_dev(blk, dev) < 0) {
@@ -126,18 +161,20 @@ fail:
         /* If we need to keep a reference, blk_attach_dev() took it */
         blk_unref(blk);
     }
+
+    g_free(str);
 }
 
-static void parse_drive(DeviceState *dev, const char *str, void **ptr,
-                        const char *propname, Error **errp)
+static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
+                      Error **errp)
 {
-    do_parse_drive(dev, str, ptr, propname, false, errp);
+    set_drive_helper(obj, v, name, opaque, false, errp);
 }
 
-static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr,
-                                 const char *propname, Error **errp)
+static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
+                               void *opaque, Error **errp)
 {
-    do_parse_drive(dev, str, ptr, propname, true, errp);
+    set_drive_helper(obj, v, name, opaque, true, errp);
 }
 
 static void release_drive(Object *obj, const char *name, void *opaque)
@@ -156,38 +193,6 @@ static void release_drive(Object *obj, const char *name, void *opaque)
     }
 }
 
-static char *print_drive(void *ptr)
-{
-    const char *name;
-
-    name = blk_name(ptr);
-    if (!*name) {
-        BlockDriverState *bs = blk_bs(ptr);
-        if (bs) {
-            name = bdrv_get_node_name(bs);
-        }
-    }
-    return g_strdup(name);
-}
-
-static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
-                      Error **errp)
-{
-    get_pointer(obj, v, opaque, print_drive, name, errp);
-}
-
-static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
-                      Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_drive, name, errp);
-}
-
-static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
-                               void *opaque, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_drive_iothread, name, errp);
-}
-
 const PropertyInfo qdev_prop_drive = {
     .name  = "str",
     .description = "Node name or ID of a block device to use as a backend",
@@ -239,6 +244,14 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
         return;
     }
 
+    /*
+     * TODO Should this really be an error?  If no, the old value
+     * needs to be released before we store the new one.
+     */
+    if (!check_prop_still_unset(dev, name, be->chr, str, errp)) {
+        return;
+    }
+
     if (!*str) {
         g_free(str);
         be->chr = NULL;
@@ -324,14 +337,16 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
     }
 
     for (i = 0; i < queues; i++) {
-
         if (peers[i]->peer) {
             err = -EEXIST;
             goto out;
         }
 
-        if (ncs[i]) {
-            err = -EINVAL;
+        /*
+         * TODO Should this really be an error?  If no, the old value
+         * needs to be released before we store the new one.
+         */
+        if (!check_prop_still_unset(dev, name, ncs[i], str, errp)) {
             goto out;
         }
 
@@ -410,8 +425,8 @@ const PropertyInfo qdev_prop_audiodev = {
     .set = set_audiodev,
 };
 
-void qdev_prop_set_drive(DeviceState *dev, const char *name,
-                         BlockBackend *value, Error **errp)
+void qdev_prop_set_drive_err(DeviceState *dev, const char *name,
+                             BlockBackend *value, Error **errp)
 {
     const char *ref = "";
 
@@ -428,6 +443,12 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name,
     object_property_set_str(OBJECT(dev), ref, name, errp);
 }
 
+void qdev_prop_set_drive(DeviceState *dev, const char *name,
+                         BlockBackend *value)
+{
+    qdev_prop_set_drive_err(dev, name, value, &error_abort);
+}
+
 void qdev_prop_set_chr(DeviceState *dev, const char *name,
                        Chardev *value)
 {
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index ead35d7ffd..71f8aca7c6 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1246,6 +1246,23 @@ void qdev_prop_register_global(GlobalProperty *prop)
     g_ptr_array_add(global_props(), prop);
 }
 
+const GlobalProperty *qdev_find_global_prop(DeviceState *dev,
+                                            const char *name)
+{
+    GPtrArray *props = global_props();
+    const GlobalProperty *p;
+    int i;
+
+    for (i = 0; i < props->len; i++) {
+        p = g_ptr_array_index(props, i);
+        if (object_dynamic_cast(OBJECT(dev), p->driver)
+            && !strcmp(p->property, name)) {
+            return p;
+        }
+    }
+    return NULL;
+}
+
 int qdev_prop_check_globals(void)
 {
     int i, ret = 0;
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index 1ac2a6f59a..da8cda2ec1 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -1,5 +1,6 @@
 /*
- * ARM Versatile I2C controller
+ * ARM SBCon two-wire serial bus interface (I2C bitbang)
+ * a.k.a. ARM Versatile I2C controller
  *
  * Copyright (c) 2006-2007 CodeSourcery.
  * Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
@@ -22,32 +23,33 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "hw/i2c/bitbang_i2c.h"
+#include "hw/i2c/arm_sbcon_i2c.h"
+#include "hw/registerfields.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
 
-#define TYPE_VERSATILE_I2C "versatile_i2c"
 #define VERSATILE_I2C(obj) \
     OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C)
 
-typedef struct VersatileI2CState {
-    SysBusDevice parent_obj;
+typedef ArmSbconI2CState VersatileI2CState;
 
-    MemoryRegion iomem;
-    bitbang_i2c_interface bitbang;
-    int out;
-    int in;
-} VersatileI2CState;
+
+REG32(CONTROL_GET, 0)
+REG32(CONTROL_SET, 0)
+REG32(CONTROL_CLR, 4)
+
+#define SCL BIT(0)
+#define SDA BIT(1)
 
 static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
                                    unsigned size)
 {
     VersatileI2CState *s = (VersatileI2CState *)opaque;
 
-    if (offset == 0) {
+    switch (offset) {
+    case A_CONTROL_SET:
         return (s->out & 1) | (s->in << 1);
-    } else {
+    default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Bad offset 0x%x\n", __func__, (int)offset);
         return -1;
@@ -60,18 +62,18 @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
     VersatileI2CState *s = (VersatileI2CState *)opaque;
 
     switch (offset) {
-    case 0:
+    case A_CONTROL_SET:
         s->out |= value & 3;
         break;
-    case 4:
+    case A_CONTROL_CLR:
         s->out &= ~value;
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Bad offset 0x%x\n", __func__, (int)offset);
     }
-    bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
-    s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
+    bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0);
+    s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
 }
 
 static const MemoryRegionOps versatile_i2c_ops = {
@@ -90,7 +92,7 @@ static void versatile_i2c_init(Object *obj)
     bus = i2c_init_bus(dev, "i2c");
     bitbang_i2c_init(&s->bitbang, bus);
     memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
-                          "versatile_i2c", 0x1000);
+                          "arm_sbcon_i2c", 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
 }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d103b8c0ab..f670bcd6e6 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1142,7 +1142,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport)
     int i;
     DriveInfo *fd[MAX_FD];
     qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse;
+    ISADevice *fdc, *i8042, *port92, *vmmouse;
 
     serial_hds_isa_init(isa_bus, 0, MAX_ISA_SERIAL_PORTS);
     parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
@@ -1152,7 +1152,11 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport)
         create_fdctrl |= !!fd[i];
     }
     if (create_fdctrl) {
-        fdctrl_init_isa(isa_bus, fd);
+        fdc = isa_new(TYPE_ISA_FDC);
+        if (fdc) {
+            isa_realize_and_unref(fdc, isa_bus, &error_fatal);
+            isa_fdc_init_drives(fdc, fd);
+        }
     }
 
     i8042 = isa_create_simple(isa_bus, "i8042");
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 3ccb5e2529..f68fbee93d 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -129,8 +129,8 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 
     dev = qdev_new(drive->media_cd ? "ide-cd" : "ide-hd");
     qdev_prop_set_uint32(dev, "unit", unit);
-    qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(drive),
-                        &error_fatal);
+    qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(drive),
+                            &error_fatal);
     qdev_realize_and_unref(dev, &bus->qbus, &error_fatal);
     return DO_UPCAST(IDEDevice, qdev, dev);
 }
diff --git a/hw/isa/isa-superio.c b/hw/isa/isa-superio.c
index d3d58f9f16..e2e47d8fd9 100644
--- a/hw/isa/isa-superio.c
+++ b/hw/isa/isa-superio.c
@@ -17,6 +17,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/blockdev.h"
 #include "chardev/char.h"
+#include "hw/block/fdc.h"
 #include "hw/isa/superio.h"
 #include "hw/qdev-properties.h"
 #include "hw/input/i8042.h"
@@ -31,7 +32,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp)
     ISADevice *isa;
     DeviceState *d;
     Chardev *chr;
-    DriveInfo *drive;
+    DriveInfo *fd[MAX_FD];
     char *name;
     int i;
 
@@ -115,7 +116,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp)
 
     /* Floppy disc */
     if (!k->floppy.is_enabled || k->floppy.is_enabled(sio, 0)) {
-        isa = isa_new("isa-fdc");
+        isa = isa_new(TYPE_ISA_FDC);
         d = DEVICE(isa);
         if (k->floppy.get_iobase) {
             qdev_prop_set_uint32(d, "iobase", k->floppy.get_iobase(sio, 0));
@@ -124,19 +125,12 @@ static void isa_superio_realize(DeviceState *dev, Error **errp)
             qdev_prop_set_uint32(d, "irq", k->floppy.get_irq(sio, 0));
         }
         /* FIXME use a qdev drive property instead of drive_get() */
-        drive = drive_get(IF_FLOPPY, 0, 0);
-        if (drive != NULL) {
-            qdev_prop_set_drive(d, "driveA", blk_by_legacy_dinfo(drive),
-                                &error_fatal);
-        }
-        /* FIXME use a qdev drive property instead of drive_get() */
-        drive = drive_get(IF_FLOPPY, 0, 1);
-        if (drive != NULL) {
-            qdev_prop_set_drive(d, "driveB", blk_by_legacy_dinfo(drive),
-                                &error_fatal);
+        for (i = 0; i < MAX_FD; i++) {
+            fd[i] = drive_get(IF_FLOPPY, 0, i);
         }
         object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa));
         isa_realize_and_unref(isa, bus, &error_fatal);
+        isa_fdc_init_drives(isa, fd);
         sio->floppy = isa;
         trace_superio_create_floppy(0,
                                     k->floppy.get_iobase ?
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 503ec54f5d..459d326af0 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -221,8 +221,7 @@ static void q800_init(MachineState *machine)
     via_dev = qdev_new(TYPE_MAC_VIA);
     dinfo = drive_get(IF_MTD, 0, 0);
     if (dinfo) {
-        qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo),
-                            &error_abort);
+        qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo));
     }
     sysbus = SYS_BUS_DEVICE(via_dev);
     sysbus_realize_and_unref(sysbus, &error_fatal);
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 23420028f5..fff2c578ef 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -188,8 +188,9 @@ petalogix_ml605_init(MachineState *machine)
 
             dev = qdev_new("n25q128");
             if (dinfo) {
-                qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
-                                    &error_fatal);
+                qdev_prop_set_drive_err(dev, "drive",
+                                        blk_by_legacy_dinfo(dinfo),
+                                        &error_fatal);
             }
             qdev_realize_and_unref(dev, BUS(spi), &error_fatal);
 
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 80b4afd211..8bd03f3b10 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -730,8 +730,7 @@ static void pnv_init(MachineState *machine)
      */
     dev = qdev_new(TYPE_PNV_PNOR);
     if (pnor) {
-        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
-                            &error_abort);
+        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
     }
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
     pnv->pnor = PNV_PNOR(dev);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 8d630baa5d..bd9345cdac 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1716,8 +1716,8 @@ static void spapr_create_nvram(SpaprMachineState *spapr)
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
 
     if (dinfo) {
-        qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
-                            &error_fatal);
+        qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo),
+                                &error_fatal);
     }
 
     qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal);
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 1a7320c0af..27843bb04b 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -277,7 +277,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
     if (serial && object_property_find(OBJECT(dev), "serial", NULL)) {
         qdev_prop_set_string(dev, "serial", serial);
     }
-    qdev_prop_set_drive(dev, "drive", blk, &err);
+    qdev_prop_set_drive_err(dev, "drive", blk, &err);
     if (err) {
         error_propagate(errp, err);
         object_unparent(OBJECT(dev));
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 4cfdf7b64c..482e97191e 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -279,7 +279,7 @@ static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
     dinfo = drive_get_next(IF_SD);
     blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
     carddev = qdev_new(TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &err);
+    qdev_prop_set_drive(carddev, "drive", blk);
     qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err);
     if (err) {
         error_setg(errp, "failed to init SD card: %s", error_get_pretty(err));
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 623be70b26..68bed24480 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -18,7 +18,6 @@
 #include "hw/arm/pxa.h"
 #include "hw/sd/sd.h"
 #include "hw/qdev-properties.h"
-#include "qemu/error-report.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
@@ -483,7 +482,6 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
     DeviceState *dev, *carddev;
     SysBusDevice *sbd;
     PXA2xxMMCIState *s;
-    Error *err = NULL;
 
     dev = qdev_new(TYPE_PXA2XX_MMCI);
     s = PXA2XX_MMCI(dev);
@@ -496,16 +494,9 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 
     /* Create and plug in the sd card */
     carddev = qdev_new(TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &err);
-    if (err) {
-        error_reportf_err(err, "failed to init SD card: ");
-        return NULL;
-    }
-    qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"), &err);
-    if (err) {
-        error_reportf_err(err, "failed to init SD card: ");
-        return NULL;
-    }
+    qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+    qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"),
+                           &error_fatal);
 
     return s;
 }
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7070a116ea..97a9d32964 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -706,7 +706,7 @@ SDState *sd_init(BlockBackend *blk, bool is_spi)
 
     obj = object_new(TYPE_SD_CARD);
     dev = DEVICE(obj);
-    qdev_prop_set_drive(dev, "drive", blk, &err);
+    qdev_prop_set_drive_err(dev, "drive", blk, &err);
     if (err) {
         error_reportf_err(err, "sd_init failed: ");
         return NULL;
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index f98a6f3ae1..25cec2ddea 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -254,7 +254,8 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
     dinfo = drive_get_next(IF_SD);
     carddev = qdev_new(TYPE_SD_CARD);
     if (dinfo) {
-        qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err);
+        qdev_prop_set_drive_err(carddev, "drive", blk_by_legacy_dinfo(dinfo),
+                                &err);
         if (err) {
             goto fail;
         }
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 97e6d3a025..9c8655cffc 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -341,16 +341,9 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
     }
     isa_dev = isa_new(TYPE_ISA_FDC);
     dev = DEVICE(isa_dev);
-    if (fd[0]) {
-        qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]),
-                            &error_abort);
-    }
-    if (fd[1]) {
-        qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]),
-                            &error_abort);
-    }
     qdev_prop_set_uint32(dev, "dma", -1);
     isa_realize_and_unref(isa_dev, s->isa_bus, &error_fatal);
+    isa_fdc_init_drives(isa_dev, fd);
 
     /* Power */
     dev = qdev_new(TYPE_SUN4U_POWER);
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 4794e7fe28..29e82f3c92 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -1,7 +1,3 @@
-config TPMDEV
-    bool
-    depends on TPM
-
 config TPM_TIS_ISA
     bool
     depends on TPM && ISA_BUS
@@ -15,26 +11,15 @@ config TPM_TIS_SYSBUS
 config TPM_TIS
     bool
     depends on TPM
-    select TPMDEV
+    select TPM_BACKEND
 
 config TPM_CRB
     bool
     depends on TPM && PC
-    select TPMDEV
-
-config TPM_PASSTHROUGH
-    bool
-    default y
-    # FIXME: should check for x86 host as well
-    depends on TPMDEV && LINUX
-
-config TPM_EMULATOR
-    bool
-    default y
-    depends on TPMDEV
+    select TPM_BACKEND
 
 config TPM_SPAPR
     bool
     default y
     depends on TPM && PSERIES
-    select TPMDEV
+    select TPM_BACKEND
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index f1ec4beb95..6fc05be67c 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,9 +1,6 @@
-common-obj-$(CONFIG_TPM) += tpm_util.o
 obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o
 common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o
 common-obj-$(CONFIG_TPM_TIS_SYSBUS) += tpm_tis_sysbus.o
 common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o
 common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
-common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
-common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
 obj-$(CONFIG_TPM_SPAPR) += tpm_spapr.o
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index cd004e7f8e..60247295d4 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -24,9 +24,9 @@
 #include "hw/acpi/tpm.h"
 #include "migration/vmstate.h"
 #include "sysemu/tpm_backend.h"
+#include "sysemu/tpm_util.h"
 #include "sysemu/reset.h"
-#include "tpm_int.h"
-#include "tpm_util.h"
+#include "tpm_prop.h"
 #include "tpm_ppi.h"
 #include "trace.h"
 
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
deleted file mode 100644
index 3a0fc442f3..0000000000
--- a/hw/tpm/tpm_emulator.c
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- *  Emulator TPM driver
- *
- *  Copyright (c) 2017 Intel Corporation
- *  Author: Amarnath Valluri <amarnath.valluri@intel.com>
- *
- *  Copyright (c) 2010 - 2013, 2018 IBM Corporation
- *  Authors:
- *    Stefan Berger <stefanb@us.ibm.com>
- *
- *  Copyright (C) 2011 IAIK, Graz University of Technology
- *    Author: Andreas Niederl
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/error-report.h"
-#include "qemu/module.h"
-#include "qemu/sockets.h"
-#include "io/channel-socket.h"
-#include "sysemu/tpm_backend.h"
-#include "tpm_int.h"
-#include "tpm_util.h"
-#include "tpm_ioctl.h"
-#include "migration/blocker.h"
-#include "migration/vmstate.h"
-#include "qapi/error.h"
-#include "qapi/clone-visitor.h"
-#include "qapi/qapi-visit-tpm.h"
-#include "chardev/char-fe.h"
-#include "trace.h"
-
-#define TYPE_TPM_EMULATOR "tpm-emulator"
-#define TPM_EMULATOR(obj) \
-    OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
-
-#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
-
-/* data structures */
-
-/* blobs from the TPM; part of VM state when migrating */
-typedef struct TPMBlobBuffers {
-    uint32_t permanent_flags;
-    TPMSizedBuffer permanent;
-
-    uint32_t volatil_flags;
-    TPMSizedBuffer volatil;
-
-    uint32_t savestate_flags;
-    TPMSizedBuffer savestate;
-} TPMBlobBuffers;
-
-typedef struct TPMEmulator {
-    TPMBackend parent;
-
-    TPMEmulatorOptions *options;
-    CharBackend ctrl_chr;
-    QIOChannel *data_ioc;
-    TPMVersion tpm_version;
-    ptm_cap caps; /* capabilities of the TPM */
-    uint8_t cur_locty_number; /* last set locality */
-    Error *migration_blocker;
-
-    QemuMutex mutex;
-
-    unsigned int established_flag:1;
-    unsigned int established_flag_cached:1;
-
-    TPMBlobBuffers state_blobs;
-} TPMEmulator;
-
-struct tpm_error {
-    uint32_t tpm_result;
-    const char *string;
-};
-
-static const struct tpm_error tpm_errors[] = {
-    /* TPM 1.2 error codes */
-    { TPM_BAD_PARAMETER   , "a parameter is bad" },
-    { TPM_FAIL            , "operation failed" },
-    { TPM_KEYNOTFOUND     , "key could not be found" },
-    { TPM_BAD_PARAM_SIZE  , "bad parameter size"},
-    { TPM_ENCRYPT_ERROR   , "encryption error" },
-    { TPM_DECRYPT_ERROR   , "decryption error" },
-    { TPM_BAD_KEY_PROPERTY, "bad key property" },
-    { TPM_BAD_MODE        , "bad (encryption) mode" },
-    { TPM_BAD_VERSION     , "bad version identifier" },
-    { TPM_BAD_LOCALITY    , "bad locality" },
-    /* TPM 2 error codes */
-    { TPM_RC_FAILURE     , "operation failed" },
-    { TPM_RC_LOCALITY    , "bad locality"     },
-    { TPM_RC_INSUFFICIENT, "insufficient amount of data" },
-};
-
-static const char *tpm_emulator_strerror(uint32_t tpm_result)
-{
-    size_t i;
-
-    for (i = 0; i < ARRAY_SIZE(tpm_errors); i++) {
-        if (tpm_errors[i].tpm_result == tpm_result) {
-            return tpm_errors[i].string;
-        }
-    }
-    return "";
-}
-
-static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
-                                size_t msg_len_in, size_t msg_len_out)
-{
-    CharBackend *dev = &tpm->ctrl_chr;
-    uint32_t cmd_no = cpu_to_be32(cmd);
-    ssize_t n = sizeof(uint32_t) + msg_len_in;
-    uint8_t *buf = NULL;
-    int ret = -1;
-
-    qemu_mutex_lock(&tpm->mutex);
-
-    buf = g_alloca(n);
-    memcpy(buf, &cmd_no, sizeof(cmd_no));
-    memcpy(buf + sizeof(cmd_no), msg, msg_len_in);
-
-    n = qemu_chr_fe_write_all(dev, buf, n);
-    if (n <= 0) {
-        goto end;
-    }
-
-    if (msg_len_out != 0) {
-        n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
-        if (n <= 0) {
-            goto end;
-        }
-    }
-
-    ret = 0;
-
-end:
-    qemu_mutex_unlock(&tpm->mutex);
-    return ret;
-}
-
-static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
-                                     const uint8_t *in, uint32_t in_len,
-                                     uint8_t *out, uint32_t out_len,
-                                     bool *selftest_done,
-                                     Error **errp)
-{
-    ssize_t ret;
-    bool is_selftest = false;
-
-    if (selftest_done) {
-        *selftest_done = false;
-        is_selftest = tpm_util_is_selftest(in, in_len);
-    }
-
-    ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, errp);
-    if (ret != 0) {
-        return -1;
-    }
-
-    ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out,
-              sizeof(struct tpm_resp_hdr), errp);
-    if (ret != 0) {
-        return -1;
-    }
-
-    ret = qio_channel_read_all(tpm_emu->data_ioc,
-              (char *)out + sizeof(struct tpm_resp_hdr),
-              tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), errp);
-    if (ret != 0) {
-        return -1;
-    }
-
-    if (is_selftest) {
-        *selftest_done = tpm_cmd_get_errcode(out) == 0;
-    }
-
-    return 0;
-}
-
-static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
-                                     Error **errp)
-{
-    ptm_loc loc;
-
-    if (tpm_emu->cur_locty_number == locty_number) {
-        return 0;
-    }
-
-    trace_tpm_emulator_set_locality(locty_number);
-
-    memset(&loc, 0, sizeof(loc));
-    loc.u.req.loc = locty_number;
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
-                             sizeof(loc), sizeof(loc)) < 0) {
-        error_setg(errp, "tpm-emulator: could not set locality : %s",
-                   strerror(errno));
-        return -1;
-    }
-
-    loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
-    if (loc.u.resp.tpm_result != 0) {
-        error_setg(errp, "tpm-emulator: TPM result for set locality : 0x%x",
-                   loc.u.resp.tpm_result);
-        return -1;
-    }
-
-    tpm_emu->cur_locty_number = locty_number;
-
-    return 0;
-}
-
-static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
-                                        Error **errp)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-
-    trace_tpm_emulator_handle_request();
-
-    if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
-        tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
-                                  cmd->out, cmd->out_len,
-                                  &cmd->selftest_done, errp) < 0) {
-        tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
-    }
-}
-
-static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
-{
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
-                             &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
-        error_report("tpm-emulator: probing failed : %s", strerror(errno));
-        return -1;
-    }
-
-    tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
-
-    trace_tpm_emulator_probe_caps(tpm_emu->caps);
-
-    return 0;
-}
-
-static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
-{
-    ptm_cap caps = 0;
-    const char *tpm = NULL;
-
-    /* check for min. required capabilities */
-    switch (tpm_emu->tpm_version) {
-    case TPM_VERSION_1_2:
-        caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
-               PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP |
-               PTM_CAP_SET_BUFFERSIZE;
-        tpm = "1.2";
-        break;
-    case TPM_VERSION_2_0:
-        caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
-               PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
-               PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE;
-        tpm = "2";
-        break;
-    case TPM_VERSION_UNSPEC:
-        error_report("tpm-emulator: TPM version has not been set");
-        return -1;
-    }
-
-    if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
-        error_report("tpm-emulator: TPM does not implement minimum set of "
-                     "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
-        return -1;
-    }
-
-    return 0;
-}
-
-static int tpm_emulator_stop_tpm(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_res res;
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
-        error_report("tpm-emulator: Could not stop TPM: %s",
-                     strerror(errno));
-        return -1;
-    }
-
-    res = be32_to_cpu(res);
-    if (res) {
-        error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x %s", res,
-                     tpm_emulator_strerror(res));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int tpm_emulator_set_buffer_size(TPMBackend *tb,
-                                        size_t wanted_size,
-                                        size_t *actual_size)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_setbuffersize psbs;
-
-    if (tpm_emulator_stop_tpm(tb) < 0) {
-        return -1;
-    }
-
-    psbs.u.req.buffersize = cpu_to_be32(wanted_size);
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
-                             sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
-        error_report("tpm-emulator: Could not set buffer size: %s",
-                     strerror(errno));
-        return -1;
-    }
-
-    psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
-    if (psbs.u.resp.tpm_result != 0) {
-        error_report("tpm-emulator: TPM result for set buffer size : 0x%x %s",
-                     psbs.u.resp.tpm_result,
-                     tpm_emulator_strerror(psbs.u.resp.tpm_result));
-        return -1;
-    }
-
-    if (actual_size) {
-        *actual_size = be32_to_cpu(psbs.u.resp.buffersize);
-    }
-
-    trace_tpm_emulator_set_buffer_size(
-            be32_to_cpu(psbs.u.resp.buffersize),
-            be32_to_cpu(psbs.u.resp.minsize),
-            be32_to_cpu(psbs.u.resp.maxsize));
-
-    return 0;
-}
-
-static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
-                                     bool is_resume)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_init init = {
-        .u.req.init_flags = 0,
-    };
-    ptm_res res;
-
-    trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize);
-
-    if (buffersize != 0 &&
-        tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
-        goto err_exit;
-    }
-
-    if (is_resume) {
-        init.u.req.init_flags |= cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATILE);
-    }
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
-                             sizeof(init)) < 0) {
-        error_report("tpm-emulator: could not send INIT: %s",
-                     strerror(errno));
-        goto err_exit;
-    }
-
-    res = be32_to_cpu(init.u.resp.tpm_result);
-    if (res) {
-        error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x %s", res,
-                     tpm_emulator_strerror(res));
-        goto err_exit;
-    }
-    return 0;
-
-err_exit:
-    return -1;
-}
-
-static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
-{
-    return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
-}
-
-static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_est est;
-
-    if (tpm_emu->established_flag_cached) {
-        return tpm_emu->established_flag;
-    }
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
-                             0, sizeof(est)) < 0) {
-        error_report("tpm-emulator: Could not get the TPM established flag: %s",
-                     strerror(errno));
-        return false;
-    }
-    trace_tpm_emulator_get_tpm_established_flag(est.u.resp.bit);
-
-    tpm_emu->established_flag_cached = 1;
-    tpm_emu->established_flag = (est.u.resp.bit != 0);
-
-    return tpm_emu->established_flag;
-}
-
-static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
-                                                   uint8_t locty)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_reset_est reset_est;
-    ptm_res res;
-
-    /* only a TPM 2.0 will support this */
-    if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
-        return 0;
-    }
-
-    reset_est.u.req.loc = tpm_emu->cur_locty_number;
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
-                             &reset_est, sizeof(reset_est),
-                             sizeof(reset_est)) < 0) {
-        error_report("tpm-emulator: Could not reset the establishment bit: %s",
-                     strerror(errno));
-        return -1;
-    }
-
-    res = be32_to_cpu(reset_est.u.resp.tpm_result);
-    if (res) {
-        error_report(
-            "tpm-emulator: TPM result for rest established flag: 0x%x %s",
-            res, tpm_emulator_strerror(res));
-        return -1;
-    }
-
-    tpm_emu->established_flag_cached = 0;
-
-    return 0;
-}
-
-static void tpm_emulator_cancel_cmd(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    ptm_res res;
-
-    if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
-        trace_tpm_emulator_cancel_cmd_not_supt();
-        return;
-    }
-
-    /* FIXME: make the function non-blocking, or it may block a VCPU */
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
-                             sizeof(res)) < 0) {
-        error_report("tpm-emulator: Could not cancel command: %s",
-                     strerror(errno));
-    } else if (res != 0) {
-        error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
-                     be32_to_cpu(res));
-    }
-}
-
-static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-
-    return tpm_emu->tpm_version;
-}
-
-static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
-{
-    size_t actual_size;
-
-    if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
-        return 4096;
-    }
-
-    return actual_size;
-}
-
-static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
-{
-    Error *err = NULL;
-    ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
-                   PTM_CAP_STOP;
-
-    if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
-        error_setg(&tpm_emu->migration_blocker,
-                   "Migration disabled: TPM emulator does not support "
-                   "migration");
-        migrate_add_blocker(tpm_emu->migration_blocker, &err);
-        if (err) {
-            error_report_err(err);
-            error_free(tpm_emu->migration_blocker);
-            tpm_emu->migration_blocker = NULL;
-
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
-{
-    ptm_res res;
-    Error *err = NULL;
-    int fds[2] = { -1, -1 };
-
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
-        error_report("tpm-emulator: Failed to create socketpair");
-        return -1;
-    }
-
-    qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
-                             sizeof(res)) < 0 || res != 0) {
-        error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
-                     strerror(errno));
-        goto err_exit;
-    }
-
-    tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
-    if (err) {
-        error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
-        error_report_err(err);
-        goto err_exit;
-    }
-
-    closesocket(fds[1]);
-
-    return 0;
-
-err_exit:
-    closesocket(fds[0]);
-    closesocket(fds[1]);
-    return -1;
-}
-
-static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
-{
-    const char *value;
-
-    value = qemu_opt_get(opts, "chardev");
-    if (value) {
-        Error *err = NULL;
-        Chardev *dev = qemu_chr_find(value);
-
-        if (!dev) {
-            error_report("tpm-emulator: tpm chardev '%s' not found.", value);
-            goto err;
-        }
-
-        if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
-            error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
-                          value);
-            error_report_err(err);
-            goto err;
-        }
-
-        tpm_emu->options->chardev = g_strdup(value);
-    }
-
-    if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
-        goto err;
-    }
-
-    /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
-     * by passthrough driver, which not yet using GIOChannel.
-     */
-    if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
-                             &tpm_emu->tpm_version)) {
-        error_report("'%s' is not emulating TPM device. Error: %s",
-                      tpm_emu->options->chardev, strerror(errno));
-        goto err;
-    }
-
-    switch (tpm_emu->tpm_version) {
-    case TPM_VERSION_1_2:
-        trace_tpm_emulator_handle_device_opts_tpm12();
-        break;
-    case TPM_VERSION_2_0:
-        trace_tpm_emulator_handle_device_opts_tpm2();
-        break;
-    default:
-        trace_tpm_emulator_handle_device_opts_unspec();
-    }
-
-    if (tpm_emulator_probe_caps(tpm_emu) ||
-        tpm_emulator_check_caps(tpm_emu)) {
-        goto err;
-    }
-
-    return tpm_emulator_block_migration(tpm_emu);
-
-err:
-    trace_tpm_emulator_handle_device_opts_startup_error();
-
-    return -1;
-}
-
-static TPMBackend *tpm_emulator_create(QemuOpts *opts)
-{
-    TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
-
-    if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
-        object_unref(OBJECT(tb));
-        return NULL;
-    }
-
-    return tb;
-}
-
-static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
-
-    options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
-    options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
-
-    return options;
-}
-
-static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
-    TPM_STANDARD_CMDLINE_OPTS,
-    {
-        .name = "chardev",
-        .type = QEMU_OPT_STRING,
-        .help = "Character device to use for out-of-band control messages",
-    },
-    { /* end of list */ },
-};
-
-/*
- * Transfer a TPM state blob from the TPM into a provided buffer.
- *
- * @tpm_emu: TPMEmulator
- * @type: the type of blob to transfer
- * @tsb: the TPMSizeBuffer to fill with the blob
- * @flags: the flags to return to the caller
- */
-static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
-                                       uint8_t type,
-                                       TPMSizedBuffer *tsb,
-                                       uint32_t *flags)
-{
-    ptm_getstate pgs;
-    ptm_res res;
-    ssize_t n;
-    uint32_t totlength, length;
-
-    tpm_sized_buffer_reset(tsb);
-
-    pgs.u.req.state_flags = cpu_to_be32(PTM_STATE_FLAG_DECRYPTED);
-    pgs.u.req.type = cpu_to_be32(type);
-    pgs.u.req.offset = 0;
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB,
-                             &pgs, sizeof(pgs.u.req),
-                             offsetof(ptm_getstate, u.resp.data)) < 0) {
-        error_report("tpm-emulator: could not get state blob type %d : %s",
-                     type, strerror(errno));
-        return -1;
-    }
-
-    res = be32_to_cpu(pgs.u.resp.tpm_result);
-    if (res != 0 && (res & 0x800) == 0) {
-        error_report("tpm-emulator: Getting the stateblob (type %d) failed "
-                     "with a TPM error 0x%x %s", type, res,
-                     tpm_emulator_strerror(res));
-        return -1;
-    }
-
-    totlength = be32_to_cpu(pgs.u.resp.totlength);
-    length = be32_to_cpu(pgs.u.resp.length);
-    if (totlength != length) {
-        error_report("tpm-emulator: Expecting to read %u bytes "
-                     "but would get %u", totlength, length);
-        return -1;
-    }
-
-    *flags = be32_to_cpu(pgs.u.resp.state_flags);
-
-    if (totlength > 0) {
-        tsb->buffer = g_try_malloc(totlength);
-        if (!tsb->buffer) {
-            error_report("tpm-emulator: Out of memory allocating %u bytes",
-                         totlength);
-            return -1;
-        }
-
-        n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, tsb->buffer, totlength);
-        if (n != totlength) {
-            error_report("tpm-emulator: Could not read stateblob (type %d); "
-                         "expected %u bytes, got %zd",
-                         type, totlength, n);
-            return -1;
-        }
-    }
-    tsb->size = totlength;
-
-    trace_tpm_emulator_get_state_blob(type, tsb->size, *flags);
-
-    return 0;
-}
-
-static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
-{
-    TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
-
-    if (tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
-                                    &state_blobs->permanent,
-                                    &state_blobs->permanent_flags) < 0 ||
-        tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
-                                    &state_blobs->volatil,
-                                    &state_blobs->volatil_flags) < 0 ||
-        tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
-                                    &state_blobs->savestate,
-                                    &state_blobs->savestate_flags) < 0) {
-        goto err_exit;
-    }
-
-    return 0;
-
- err_exit:
-    tpm_sized_buffer_reset(&state_blobs->volatil);
-    tpm_sized_buffer_reset(&state_blobs->permanent);
-    tpm_sized_buffer_reset(&state_blobs->savestate);
-
-    return -1;
-}
-
-/*
- * Transfer a TPM state blob to the TPM emulator.
- *
- * @tpm_emu: TPMEmulator
- * @type: the type of TPM state blob to transfer
- * @tsb: TPMSizedBuffer containing the TPM state blob
- * @flags: Flags describing the (encryption) state of the TPM state blob
- */
-static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
-                                       uint32_t type,
-                                       TPMSizedBuffer *tsb,
-                                       uint32_t flags)
-{
-    ssize_t n;
-    ptm_setstate pss;
-    ptm_res tpm_result;
-
-    if (tsb->size == 0) {
-        return 0;
-    }
-
-    pss = (ptm_setstate) {
-        .u.req.state_flags = cpu_to_be32(flags),
-        .u.req.type = cpu_to_be32(type),
-        .u.req.length = cpu_to_be32(tsb->size),
-    };
-
-    /* write the header only */
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
-                             offsetof(ptm_setstate, u.req.data), 0) < 0) {
-        error_report("tpm-emulator: could not set state blob type %d : %s",
-                     type, strerror(errno));
-        return -1;
-    }
-
-    /* now the body */
-    n = qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size);
-    if (n != tsb->size) {
-        error_report("tpm-emulator: Writing the stateblob (type %d) "
-                     "failed; could not write %u bytes, but only %zd",
-                     type, tsb->size, n);
-        return -1;
-    }
-
-    /* now get the result */
-    n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr,
-                             (uint8_t *)&pss, sizeof(pss.u.resp));
-    if (n != sizeof(pss.u.resp)) {
-        error_report("tpm-emulator: Reading response from writing stateblob "
-                     "(type %d) failed; expected %zu bytes, got %zd", type,
-                     sizeof(pss.u.resp), n);
-        return -1;
-    }
-
-    tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
-    if (tpm_result != 0) {
-        error_report("tpm-emulator: Setting the stateblob (type %d) failed "
-                     "with a TPM error 0x%x %s", type, tpm_result,
-                     tpm_emulator_strerror(tpm_result));
-        return -1;
-    }
-
-    trace_tpm_emulator_set_state_blob(type, tsb->size, flags);
-
-    return 0;
-}
-
-/*
- * Set all the TPM state blobs.
- *
- * Returns a negative errno code in case of error.
- */
-static int tpm_emulator_set_state_blobs(TPMBackend *tb)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
-
-    trace_tpm_emulator_set_state_blobs();
-
-    if (tpm_emulator_stop_tpm(tb) < 0) {
-        trace_tpm_emulator_set_state_blobs_error("Could not stop TPM");
-        return -EIO;
-    }
-
-    if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
-                                    &state_blobs->permanent,
-                                    state_blobs->permanent_flags) < 0 ||
-        tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
-                                    &state_blobs->volatil,
-                                    state_blobs->volatil_flags) < 0 ||
-        tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
-                                    &state_blobs->savestate,
-                                    state_blobs->savestate_flags) < 0) {
-        return -EIO;
-    }
-
-    trace_tpm_emulator_set_state_blobs_done();
-
-    return 0;
-}
-
-static int tpm_emulator_pre_save(void *opaque)
-{
-    TPMBackend *tb = opaque;
-    TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-
-    trace_tpm_emulator_pre_save();
-
-    tpm_backend_finish_sync(tb);
-
-    /* get the state blobs from the TPM */
-    return tpm_emulator_get_state_blobs(tpm_emu);
-}
-
-/*
- * Load the TPM state blobs into the TPM.
- *
- * Returns negative errno codes in case of error.
- */
-static int tpm_emulator_post_load(void *opaque, int version_id)
-{
-    TPMBackend *tb = opaque;
-    int ret;
-
-    ret = tpm_emulator_set_state_blobs(tb);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) {
-        return -EIO;
-    }
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_tpm_emulator = {
-    .name = "tpm-emulator",
-    .version_id = 0,
-    .pre_save = tpm_emulator_pre_save,
-    .post_load = tpm_emulator_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator),
-        VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator),
-        VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.permanent.buffer,
-                                     TPMEmulator, 0, 0,
-                                     state_blobs.permanent.size),
-
-        VMSTATE_UINT32(state_blobs.volatil_flags, TPMEmulator),
-        VMSTATE_UINT32(state_blobs.volatil.size, TPMEmulator),
-        VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.volatil.buffer,
-                                     TPMEmulator, 0, 0,
-                                     state_blobs.volatil.size),
-
-        VMSTATE_UINT32(state_blobs.savestate_flags, TPMEmulator),
-        VMSTATE_UINT32(state_blobs.savestate.size, TPMEmulator),
-        VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.savestate.buffer,
-                                     TPMEmulator, 0, 0,
-                                     state_blobs.savestate.size),
-
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void tpm_emulator_inst_init(Object *obj)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
-
-    trace_tpm_emulator_inst_init();
-
-    tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
-    tpm_emu->cur_locty_number = ~0;
-    qemu_mutex_init(&tpm_emu->mutex);
-
-    vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
-                     &vmstate_tpm_emulator, obj);
-}
-
-/*
- * Gracefully shut down the external TPM
- */
-static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
-{
-    ptm_res res;
-
-    if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
-        error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
-                     strerror(errno));
-    } else if (res != 0) {
-        error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
-                     be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
-    }
-}
-
-static void tpm_emulator_inst_finalize(Object *obj)
-{
-    TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
-    TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
-
-    tpm_emulator_shutdown(tpm_emu);
-
-    object_unref(OBJECT(tpm_emu->data_ioc));
-
-    qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
-
-    qapi_free_TPMEmulatorOptions(tpm_emu->options);
-
-    if (tpm_emu->migration_blocker) {
-        migrate_del_blocker(tpm_emu->migration_blocker);
-        error_free(tpm_emu->migration_blocker);
-    }
-
-    tpm_sized_buffer_reset(&state_blobs->volatil);
-    tpm_sized_buffer_reset(&state_blobs->permanent);
-    tpm_sized_buffer_reset(&state_blobs->savestate);
-
-    qemu_mutex_destroy(&tpm_emu->mutex);
-
-    vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
-}
-
-static void tpm_emulator_class_init(ObjectClass *klass, void *data)
-{
-    TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
-
-    tbc->type = TPM_TYPE_EMULATOR;
-    tbc->opts = tpm_emulator_cmdline_opts;
-    tbc->desc = "TPM emulator backend driver";
-    tbc->create = tpm_emulator_create;
-    tbc->startup_tpm = tpm_emulator_startup_tpm;
-    tbc->cancel_cmd = tpm_emulator_cancel_cmd;
-    tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
-    tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
-    tbc->get_tpm_version = tpm_emulator_get_tpm_version;
-    tbc->get_buffer_size = tpm_emulator_get_buffer_size;
-    tbc->get_tpm_options = tpm_emulator_get_tpm_options;
-
-    tbc->handle_request = tpm_emulator_handle_request;
-}
-
-static const TypeInfo tpm_emulator_info = {
-    .name = TYPE_TPM_EMULATOR,
-    .parent = TYPE_TPM_BACKEND,
-    .instance_size = sizeof(TPMEmulator),
-    .class_init = tpm_emulator_class_init,
-    .instance_init = tpm_emulator_inst_init,
-    .instance_finalize = tpm_emulator_inst_finalize,
-};
-
-static void tpm_emulator_register(void)
-{
-    type_register_static(&tpm_emulator_info);
-}
-
-type_init(tpm_emulator_register)
diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h
deleted file mode 100644
index 3fb28a9d6c..0000000000
--- a/hw/tpm/tpm_int.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * TPM configuration
- *
- * Copyright (C) 2011-2013 IBM Corporation
- *
- * Authors:
- *  Stefan Berger    <stefanb@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-#ifndef TPM_TPM_INT_H
-#define TPM_TPM_INT_H
-
-#define TPM_STANDARD_CMDLINE_OPTS \
-    { \
-        .name = "type", \
-        .type = QEMU_OPT_STRING, \
-        .help = "Type of TPM backend", \
-    }
-
-struct tpm_req_hdr {
-    uint16_t tag;
-    uint32_t len;
-    uint32_t ordinal;
-} QEMU_PACKED;
-
-struct tpm_resp_hdr {
-    uint16_t tag;
-    uint32_t len;
-    uint32_t errcode;
-} QEMU_PACKED;
-
-#define TPM_TAG_RQU_COMMAND       0xc1
-#define TPM_TAG_RQU_AUTH1_COMMAND 0xc2
-#define TPM_TAG_RQU_AUTH2_COMMAND 0xc3
-
-#define TPM_TAG_RSP_COMMAND       0xc4
-#define TPM_TAG_RSP_AUTH1_COMMAND 0xc5
-#define TPM_TAG_RSP_AUTH2_COMMAND 0xc6
-
-#define TPM_BAD_PARAMETER         3
-#define TPM_FAIL                  9
-#define TPM_KEYNOTFOUND           13
-#define TPM_BAD_PARAM_SIZE        25
-#define TPM_ENCRYPT_ERROR         32
-#define TPM_DECRYPT_ERROR         33
-#define TPM_BAD_KEY_PROPERTY      40
-#define TPM_BAD_MODE              44
-#define TPM_BAD_VERSION           46
-#define TPM_BAD_LOCALITY          61
-
-#define TPM_ORD_ContinueSelfTest  0x53
-#define TPM_ORD_GetTicks          0xf1
-#define TPM_ORD_GetCapability     0x65
-
-#define TPM_CAP_PROPERTY          0x05
-
-#define TPM_CAP_PROP_INPUT_BUFFER 0x124
-
-/* TPM2 defines */
-#define TPM2_ST_NO_SESSIONS       0x8001
-
-#define TPM2_CC_ReadClock         0x00000181
-#define TPM2_CC_GetCapability     0x0000017a
-
-#define TPM2_CAP_TPM_PROPERTIES   0x6
-
-#define TPM2_PT_MAX_COMMAND_SIZE  0x11e
-
-#define TPM_RC_INSUFFICIENT       0x9a
-#define TPM_RC_FAILURE            0x101
-#define TPM_RC_LOCALITY           0x907
-
-#endif /* TPM_TPM_INT_H */
diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
deleted file mode 100644
index f5f5c553a9..0000000000
--- a/hw/tpm/tpm_ioctl.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * tpm_ioctl.h
- *
- * (c) Copyright IBM Corporation 2014, 2015.
- *
- * This file is licensed under the terms of the 3-clause BSD license
- */
-
-#ifndef TPM_IOCTL_H
-#define TPM_IOCTL_H
-
-#include <sys/uio.h>
-#include <sys/ioctl.h>
-
-/*
- * Every response from a command involving a TPM command execution must hold
- * the ptm_res as the first element.
- * ptm_res corresponds to the error code of a command executed by the TPM.
- */
-
-typedef uint32_t ptm_res;
-
-/* PTM_GET_TPMESTABLISHED: get the establishment bit */
-struct ptm_est {
-    union {
-        struct {
-            ptm_res tpm_result;
-            unsigned char bit; /* TPM established bit */
-        } resp; /* response */
-    } u;
-};
-
-/* PTM_RESET_TPMESTABLISHED: reset establishment bit */
-struct ptm_reset_est {
-    union {
-        struct {
-            uint8_t loc; /* locality to use */
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-        } resp; /* response */
-    } u;
-};
-
-/* PTM_INIT */
-struct ptm_init {
-    union {
-        struct {
-            uint32_t init_flags; /* see definitions below */
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-        } resp; /* response */
-    } u;
-};
-
-/* above init_flags */
-#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0)
-    /* delete volatile state file after reading it */
-
-/* PTM_SET_LOCALITY */
-struct ptm_loc {
-    union {
-        struct {
-            uint8_t loc; /* locality to set */
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-        } resp; /* response */
-    } u;
-};
-
-/* PTM_HASH_DATA: hash given data */
-struct ptm_hdata {
-    union {
-        struct {
-            uint32_t length;
-            uint8_t data[4096];
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-        } resp; /* response */
-    } u;
-};
-
-/*
- * size of the TPM state blob to transfer; x86_64 can handle 8k,
- * ppc64le only ~7k; keep the response below a 4k page size
- */
-#define PTM_STATE_BLOB_SIZE (3 * 1024)
-
-/*
- * The following is the data structure to get state blobs from the TPM.
- * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads
- * with this ioctl and with adjusted offset are necessary. All bytes
- * must be transferred and the transfer is done once the last byte has been
- * returned.
- * It is possible to use the read() interface for reading the data; however, the
- * first bytes of the state blob will be part of the response to the ioctl(); a
- * subsequent read() is only necessary if the total length (totlength) exceeds
- * the number of received bytes. seek() is not supported.
- */
-struct ptm_getstate {
-    union {
-        struct {
-            uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
-            uint32_t type;        /* which blob to pull */
-            uint32_t offset;      /* offset from where to read */
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-            uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
-            uint32_t totlength;   /* total length that will be transferred */
-            uint32_t length;      /* number of bytes in following buffer */
-            uint8_t  data[PTM_STATE_BLOB_SIZE];
-        } resp; /* response */
-    } u;
-};
-
-/* TPM state blob types */
-#define PTM_BLOB_TYPE_PERMANENT  1
-#define PTM_BLOB_TYPE_VOLATILE   2
-#define PTM_BLOB_TYPE_SAVESTATE  3
-
-/* state_flags above : */
-#define PTM_STATE_FLAG_DECRYPTED     1 /* on input:  get decrypted state */
-#define PTM_STATE_FLAG_ENCRYPTED     2 /* on output: state is encrypted */
-
-/*
- * The following is the data structure to set state blobs in the TPM.
- * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple
- * 'writes' using this ioctl are necessary. The last packet is indicated
- * by the length being smaller than the PTM_STATE_BLOB_SIZE.
- * The very first packet may have a length indicator of '0' enabling
- * a write() with all the bytes from a buffer. If the write() interface
- * is used, a final ioctl with a non-full buffer must be made to indicate
- * that all data were transferred (a write with 0 bytes would not work).
- */
-struct ptm_setstate {
-    union {
-        struct {
-            uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
-            uint32_t type;        /* which blob to set */
-            uint32_t length;      /* length of the data;
-                                     use 0 on the first packet to
-                                     transfer using write() */
-            uint8_t data[PTM_STATE_BLOB_SIZE];
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-        } resp; /* response */
-    } u;
-};
-
-/*
- * PTM_GET_CONFIG: Data structure to get runtime configuration information
- * such as which keys are applied.
- */
-struct ptm_getconfig {
-    union {
-        struct {
-            ptm_res tpm_result;
-            uint32_t flags;
-        } resp; /* response */
-    } u;
-};
-
-#define PTM_CONFIG_FLAG_FILE_KEY        0x1
-#define PTM_CONFIG_FLAG_MIGRATION_KEY   0x2
-
-/*
- * PTM_SET_BUFFERSIZE: Set the buffer size to be used by the TPM.
- * A 0 on input queries for the current buffer size. Any other
- * number will try to set the buffer size. The returned number is
- * the buffer size that will be used, which can be larger than the
- * requested one, if it was below the minimum, or smaller than the
- * requested one, if it was above the maximum.
- */
-struct ptm_setbuffersize {
-    union {
-        struct {
-            uint32_t buffersize; /* 0 to query for current buffer size */
-        } req; /* request */
-        struct {
-            ptm_res tpm_result;
-            uint32_t buffersize; /* buffer size in use */
-            uint32_t minsize; /* min. supported buffer size */
-            uint32_t maxsize; /* max. supported buffer size */
-        } resp; /* response */
-    } u;
-};
-
-
-typedef uint64_t ptm_cap;
-typedef struct ptm_est ptm_est;
-typedef struct ptm_reset_est ptm_reset_est;
-typedef struct ptm_loc ptm_loc;
-typedef struct ptm_hdata ptm_hdata;
-typedef struct ptm_init ptm_init;
-typedef struct ptm_getstate ptm_getstate;
-typedef struct ptm_setstate ptm_setstate;
-typedef struct ptm_getconfig ptm_getconfig;
-typedef struct ptm_setbuffersize ptm_setbuffersize;
-
-/* capability flags returned by PTM_GET_CAPABILITY */
-#define PTM_CAP_INIT               (1)
-#define PTM_CAP_SHUTDOWN           (1 << 1)
-#define PTM_CAP_GET_TPMESTABLISHED (1 << 2)
-#define PTM_CAP_SET_LOCALITY       (1 << 3)
-#define PTM_CAP_HASHING            (1 << 4)
-#define PTM_CAP_CANCEL_TPM_CMD     (1 << 5)
-#define PTM_CAP_STORE_VOLATILE     (1 << 6)
-#define PTM_CAP_RESET_TPMESTABLISHED (1 << 7)
-#define PTM_CAP_GET_STATEBLOB      (1 << 8)
-#define PTM_CAP_SET_STATEBLOB      (1 << 9)
-#define PTM_CAP_STOP               (1 << 10)
-#define PTM_CAP_GET_CONFIG         (1 << 11)
-#define PTM_CAP_SET_DATAFD         (1 << 12)
-#define PTM_CAP_SET_BUFFERSIZE     (1 << 13)
-
-enum {
-    PTM_GET_CAPABILITY     = _IOR('P', 0, ptm_cap),
-    PTM_INIT               = _IOWR('P', 1, ptm_init),
-    PTM_SHUTDOWN           = _IOR('P', 2, ptm_res),
-    PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est),
-    PTM_SET_LOCALITY       = _IOWR('P', 4, ptm_loc),
-    PTM_HASH_START         = _IOR('P', 5, ptm_res),
-    PTM_HASH_DATA          = _IOWR('P', 6, ptm_hdata),
-    PTM_HASH_END           = _IOR('P', 7, ptm_res),
-    PTM_CANCEL_TPM_CMD     = _IOR('P', 8, ptm_res),
-    PTM_STORE_VOLATILE     = _IOR('P', 9, ptm_res),
-    PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est),
-    PTM_GET_STATEBLOB      = _IOWR('P', 11, ptm_getstate),
-    PTM_SET_STATEBLOB      = _IOWR('P', 12, ptm_setstate),
-    PTM_STOP               = _IOR('P', 13, ptm_res),
-    PTM_GET_CONFIG         = _IOR('P', 14, ptm_getconfig),
-    PTM_SET_DATAFD         = _IOR('P', 15, ptm_res),
-    PTM_SET_BUFFERSIZE     = _IOWR('P', 16, ptm_setbuffersize),
-};
-
-/*
- * Commands used by the non-CUSE TPMs
- *
- * All messages container big-endian data.
- *
- * The return messages only contain the 'resp' part of the unions
- * in the data structures above. Besides that the limits in the
- * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
- * and ptm_set_state:u.req.data) are 0xffffffff.
- */
-enum {
-    CMD_GET_CAPABILITY = 1,
-    CMD_INIT,
-    CMD_SHUTDOWN,
-    CMD_GET_TPMESTABLISHED,
-    CMD_SET_LOCALITY,
-    CMD_HASH_START,
-    CMD_HASH_DATA,
-    CMD_HASH_END,
-    CMD_CANCEL_TPM_CMD,
-    CMD_STORE_VOLATILE,
-    CMD_RESET_TPMESTABLISHED,
-    CMD_GET_STATEBLOB,
-    CMD_SET_STATEBLOB,
-    CMD_STOP,
-    CMD_GET_CONFIG,
-    CMD_SET_DATAFD,
-    CMD_SET_BUFFERSIZE,
-};
-
-#endif /* TPM_IOCTL_H */
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
deleted file mode 100644
index f67244b5d4..0000000000
--- a/hw/tpm/tpm_passthrough.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- *  passthrough TPM driver
- *
- *  Copyright (c) 2010 - 2013 IBM Corporation
- *  Authors:
- *    Stefan Berger <stefanb@us.ibm.com>
- *
- *  Copyright (C) 2011 IAIK, Graz University of Technology
- *    Author: Andreas Niederl
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-#include "qemu/module.h"
-#include "qemu/sockets.h"
-#include "sysemu/tpm_backend.h"
-#include "tpm_int.h"
-#include "qapi/clone-visitor.h"
-#include "qapi/qapi-visit-tpm.h"
-#include "tpm_util.h"
-#include "trace.h"
-
-#define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
-#define TPM_PASSTHROUGH(obj) \
-    OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
-
-/* data structures */
-struct TPMPassthruState {
-    TPMBackend parent;
-
-    TPMPassthroughOptions *options;
-    const char *tpm_dev;
-    int tpm_fd;
-    bool tpm_executing;
-    bool tpm_op_canceled;
-    int cancel_fd;
-
-    TPMVersion tpm_version;
-    size_t tpm_buffersize;
-};
-
-typedef struct TPMPassthruState TPMPassthruState;
-
-#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
-
-/* functions */
-
-static void tpm_passthrough_cancel_cmd(TPMBackend *tb);
-
-static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
-{
-    int ret;
- reread:
-    ret = read(fd, buf, len);
-    if (ret < 0) {
-        if (errno != EINTR && errno != EAGAIN) {
-            return -1;
-        }
-        goto reread;
-    }
-    return ret;
-}
-
-static void tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
-                                         const uint8_t *in, uint32_t in_len,
-                                         uint8_t *out, uint32_t out_len,
-                                         bool *selftest_done, Error **errp)
-{
-    ssize_t ret;
-    bool is_selftest;
-
-    /* FIXME: protect shared variables or use other sync mechanism */
-    tpm_pt->tpm_op_canceled = false;
-    tpm_pt->tpm_executing = true;
-    *selftest_done = false;
-
-    is_selftest = tpm_util_is_selftest(in, in_len);
-
-    ret = qemu_write_full(tpm_pt->tpm_fd, in, in_len);
-    if (ret != in_len) {
-        if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
-            error_setg_errno(errp, errno, "tpm_passthrough: error while "
-                             "transmitting data to TPM");
-        }
-        goto err_exit;
-    }
-
-    tpm_pt->tpm_executing = false;
-
-    ret = tpm_passthrough_unix_read(tpm_pt->tpm_fd, out, out_len);
-    if (ret < 0) {
-        if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
-            error_setg_errno(errp, errno, "tpm_passthrough: error while "
-                             "reading data from TPM");
-        }
-    } else if (ret < sizeof(struct tpm_resp_hdr) ||
-               tpm_cmd_get_size(out) != ret) {
-        ret = -1;
-        error_setg_errno(errp, errno, "tpm_passthrough: received invalid "
-                     "response packet from TPM");
-    }
-
-    if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
-        *selftest_done = tpm_cmd_get_errcode(out) == 0;
-    }
-
-err_exit:
-    if (ret < 0) {
-        tpm_util_write_fatal_error_response(out, out_len);
-    }
-
-    tpm_pt->tpm_executing = false;
-}
-
-static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
-                                           Error **errp)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
-    trace_tpm_passthrough_handle_request(cmd);
-
-    tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len,
-                                 cmd->out, cmd->out_len, &cmd->selftest_done,
-                                 errp);
-}
-
-static void tpm_passthrough_reset(TPMBackend *tb)
-{
-    trace_tpm_passthrough_reset();
-
-    tpm_passthrough_cancel_cmd(tb);
-}
-
-static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
-{
-    return false;
-}
-
-static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
-                                                      uint8_t locty)
-{
-    /* only a TPM 2.0 will support this */
-    return 0;
-}
-
-static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-    int n;
-
-    /*
-     * As of Linux 3.7 the tpm_tis driver does not properly cancel
-     * commands on all TPM manufacturers' TPMs.
-     * Only cancel if we're busy so we don't cancel someone else's
-     * command, e.g., a command executed on the host.
-     */
-    if (tpm_pt->tpm_executing) {
-        if (tpm_pt->cancel_fd >= 0) {
-            tpm_pt->tpm_op_canceled = true;
-            n = write(tpm_pt->cancel_fd, "-", 1);
-            if (n != 1) {
-                error_report("Canceling TPM command failed: %s",
-                             strerror(errno));
-            }
-        } else {
-            error_report("Cannot cancel TPM command due to missing "
-                         "TPM sysfs cancel entry");
-        }
-    }
-}
-
-static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
-    return tpm_pt->tpm_version;
-}
-
-static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-    int ret;
-
-    ret = tpm_util_get_buffer_size(tpm_pt->tpm_fd, tpm_pt->tpm_version,
-                                   &tpm_pt->tpm_buffersize);
-    if (ret < 0) {
-        tpm_pt->tpm_buffersize = 4096;
-    }
-    return tpm_pt->tpm_buffersize;
-}
-
-/*
- * Unless path or file descriptor set has been provided by user,
- * determine the sysfs cancel file following kernel documentation
- * in Documentation/ABI/stable/sysfs-class-tpm.
- * From /dev/tpm0 create /sys/class/tpm/tpm0/device/cancel
- * before 4.0: /sys/class/misc/tpm0/device/cancel
- */
-static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
-{
-    int fd = -1;
-    char *dev;
-    char path[PATH_MAX];
-
-    if (tpm_pt->options->cancel_path) {
-        fd = qemu_open(tpm_pt->options->cancel_path, O_WRONLY);
-        if (fd < 0) {
-            error_report("tpm_passthrough: Could not open TPM cancel path: %s",
-                         strerror(errno));
-        }
-        return fd;
-    }
-
-    dev = strrchr(tpm_pt->tpm_dev, '/');
-    if (!dev) {
-        error_report("tpm_passthrough: Bad TPM device path %s",
-                     tpm_pt->tpm_dev);
-        return -1;
-    }
-
-    dev++;
-    if (snprintf(path, sizeof(path), "/sys/class/tpm/%s/device/cancel",
-                 dev) < sizeof(path)) {
-        fd = qemu_open(path, O_WRONLY);
-        if (fd < 0) {
-            if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
-                         dev) < sizeof(path)) {
-                fd = qemu_open(path, O_WRONLY);
-            }
-        }
-    }
-
-    if (fd < 0) {
-        error_report("tpm_passthrough: Could not guess TPM cancel path");
-    } else {
-        tpm_pt->options->cancel_path = g_strdup(path);
-    }
-
-    return fd;
-}
-
-static int
-tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
-{
-    const char *value;
-
-    value = qemu_opt_get(opts, "cancel-path");
-    if (value) {
-        tpm_pt->options->cancel_path = g_strdup(value);
-        tpm_pt->options->has_cancel_path = true;
-    }
-
-    value = qemu_opt_get(opts, "path");
-    if (value) {
-        tpm_pt->options->has_path = true;
-        tpm_pt->options->path = g_strdup(value);
-    }
-
-    tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
-    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
-    if (tpm_pt->tpm_fd < 0) {
-        error_report("Cannot access TPM device using '%s': %s",
-                     tpm_pt->tpm_dev, strerror(errno));
-        return -1;
-    }
-
-    if (tpm_util_test_tpmdev(tpm_pt->tpm_fd, &tpm_pt->tpm_version)) {
-        error_report("'%s' is not a TPM device.",
-                     tpm_pt->tpm_dev);
-        return -1;
-    }
-
-    tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tpm_pt);
-    if (tpm_pt->cancel_fd < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static TPMBackend *tpm_passthrough_create(QemuOpts *opts)
-{
-    Object *obj = object_new(TYPE_TPM_PASSTHROUGH);
-
-    if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), opts)) {
-        object_unref(obj);
-        return NULL;
-    }
-
-    return TPM_BACKEND(obj);
-}
-
-static int tpm_passthrough_startup_tpm(TPMBackend *tb, size_t buffersize)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
-    if (buffersize && buffersize < tpm_pt->tpm_buffersize) {
-        error_report("Requested buffer size of %zu is smaller than host TPM's "
-                     "fixed buffer size of %zu",
-                     buffersize, tpm_pt->tpm_buffersize);
-        return -1;
-    }
-
-    return 0;
-}
-
-static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
-{
-    TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
-
-    options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
-    options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
-                                             TPM_PASSTHROUGH(tb)->options);
-
-    return options;
-}
-
-static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
-    TPM_STANDARD_CMDLINE_OPTS,
-    {
-        .name = "cancel-path",
-        .type = QEMU_OPT_STRING,
-        .help = "Sysfs file entry for canceling TPM commands",
-    },
-    {
-        .name = "path",
-        .type = QEMU_OPT_STRING,
-        .help = "Path to TPM device on the host",
-    },
-    { /* end of list */ },
-};
-
-static void tpm_passthrough_inst_init(Object *obj)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
-
-    tpm_pt->options = g_new0(TPMPassthroughOptions, 1);
-    tpm_pt->tpm_fd = -1;
-    tpm_pt->cancel_fd = -1;
-}
-
-static void tpm_passthrough_inst_finalize(Object *obj)
-{
-    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
-
-    tpm_passthrough_cancel_cmd(TPM_BACKEND(obj));
-
-    if (tpm_pt->tpm_fd >= 0) {
-        qemu_close(tpm_pt->tpm_fd);
-    }
-    if (tpm_pt->cancel_fd >= 0) {
-        qemu_close(tpm_pt->cancel_fd);
-    }
-    qapi_free_TPMPassthroughOptions(tpm_pt->options);
-}
-
-static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
-{
-    TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
-
-    tbc->type = TPM_TYPE_PASSTHROUGH;
-    tbc->opts = tpm_passthrough_cmdline_opts;
-    tbc->desc = "Passthrough TPM backend driver";
-    tbc->create = tpm_passthrough_create;
-    tbc->startup_tpm = tpm_passthrough_startup_tpm;
-    tbc->reset = tpm_passthrough_reset;
-    tbc->cancel_cmd = tpm_passthrough_cancel_cmd;
-    tbc->get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag;
-    tbc->reset_tpm_established_flag =
-        tpm_passthrough_reset_tpm_established_flag;
-    tbc->get_tpm_version = tpm_passthrough_get_tpm_version;
-    tbc->get_buffer_size = tpm_passthrough_get_buffer_size;
-    tbc->get_tpm_options = tpm_passthrough_get_tpm_options;
-    tbc->handle_request = tpm_passthrough_handle_request;
-}
-
-static const TypeInfo tpm_passthrough_info = {
-    .name = TYPE_TPM_PASSTHROUGH,
-    .parent = TYPE_TPM_BACKEND,
-    .instance_size = sizeof(TPMPassthruState),
-    .class_init = tpm_passthrough_class_init,
-    .instance_init = tpm_passthrough_inst_init,
-    .instance_finalize = tpm_passthrough_inst_finalize,
-};
-
-static void tpm_passthrough_register(void)
-{
-    type_register_static(&tpm_passthrough_info);
-}
-
-type_init(tpm_passthrough_register)
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 6d9c1a3e40..72d7a3d926 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -17,6 +17,7 @@
 #include "cpu.h"
 #include "sysemu/memory_mapping.h"
 #include "migration/vmstate.h"
+#include "hw/acpi/tpm.h"
 #include "tpm_ppi.h"
 #include "trace.h"
 
diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index d33ef27de6..6f773c25a0 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -12,7 +12,6 @@
 #ifndef TPM_TPM_PPI_H
 #define TPM_TPM_PPI_H
 
-#include "hw/acpi/tpm.h"
 #include "exec/address-spaces.h"
 
 typedef struct TPMPPI {
diff --git a/hw/tpm/tpm_prop.h b/hw/tpm/tpm_prop.h
new file mode 100644
index 0000000000..85e1ae5718
--- /dev/null
+++ b/hw/tpm/tpm_prop.h
@@ -0,0 +1,31 @@
+/*
+ * TPM utility functions
+ *
+ *  Copyright (c) 2010 - 2015 IBM Corporation
+ *  Authors:
+ *    Stefan Berger <stefanb@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef HW_TPM_PROP_H
+#define HW_TPM_PROP_H
+
+#include "sysemu/tpm_backend.h"
+#include "hw/qdev-properties.h"
+
+#define DEFINE_PROP_TPMBE(_n, _s, _f)                     \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *)
+
+#endif /* HW_TPM_PROP_H */
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
index ce65eb2e45..cb4dfd1e6a 100644
--- a/hw/tpm/tpm_spapr.c
+++ b/hw/tpm/tpm_spapr.c
@@ -20,8 +20,8 @@
 #include "migration/vmstate.h"
 
 #include "sysemu/tpm_backend.h"
-#include "tpm_int.h"
-#include "tpm_util.h"
+#include "sysemu/tpm_util.h"
+#include "tpm_prop.h"
 
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
index 5554989395..f6b5872ba6 100644
--- a/hw/tpm/tpm_tis.h
+++ b/hw/tpm/tpm_tis.h
@@ -24,7 +24,6 @@
 #ifndef TPM_TPM_TIS_H
 #define TPM_TPM_TIS_H
 
-#include "qemu/osdep.h"
 #include "sysemu/tpm_backend.h"
 #include "tpm_ppi.h"
 
diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 1af4bce139..e700d82181 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -33,8 +33,7 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "sysemu/tpm_backend.h"
-#include "tpm_int.h"
-#include "tpm_util.h"
+#include "sysemu/tpm_util.h"
 #include "tpm_ppi.h"
 #include "trace.h"
 
@@ -79,9 +78,7 @@ static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
  */
 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
 {
-    if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) {
-        tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
-    }
+    tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
 
     /*
      * rw_offset serves as length indicator for length of data;
@@ -247,9 +244,7 @@ void tpm_tis_request_completed(TPMState *s, int ret)
     s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
     s->rw_offset = 0;
 
-    if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) {
-        tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
-    }
+    tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
 
     if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
         tpm_tis_abort(s);
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 30ba37079d..5faf6231c0 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -26,7 +26,8 @@
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
-#include "tpm_util.h"
+#include "hw/acpi/tpm.h"
+#include "tpm_prop.h"
 #include "tpm_tis.h"
 
 typedef struct TPMStateISA {
diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
index eced1fc843..4a3bc70625 100644
--- a/hw/tpm/tpm_tis_sysbus.c
+++ b/hw/tpm/tpm_tis_sysbus.c
@@ -25,7 +25,8 @@
 #include "qemu/osdep.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
-#include "tpm_util.h"
+#include "hw/acpi/tpm.h"
+#include "tpm_prop.h"
 #include "hw/sysbus.h"
 #include "tpm_tis.h"
 
diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
deleted file mode 100644
index c0a0f3d71f..0000000000
--- a/hw/tpm/tpm_util.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * TPM utility functions
- *
- *  Copyright (c) 2010 - 2015 IBM Corporation
- *  Authors:
- *    Stefan Berger <stefanb@us.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-
-#include "qemu/osdep.h"
-#include "qemu/error-report.h"
-#include "qapi/error.h"
-#include "qapi/visitor.h"
-#include "tpm_util.h"
-#include "tpm_int.h"
-#include "exec/memory.h"
-#include "hw/qdev-properties.h"
-#include "sysemu/tpm_backend.h"
-#include "trace.h"
-
-/* tpm backend property */
-
-static void get_tpm(Object *obj, Visitor *v, const char *name, void *opaque,
-                    Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    TPMBackend **be = qdev_get_prop_ptr(dev, opaque);
-    char *p;
-
-    p = g_strdup(*be ? (*be)->id : "");
-    visit_type_str(v, name, &p, errp);
-    g_free(p);
-}
-
-static void set_tpm(Object *obj, Visitor *v, const char *name, void *opaque,
-                    Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    Error *local_err = NULL;
-    Property *prop = opaque;
-    TPMBackend *s, **be = qdev_get_prop_ptr(dev, prop);
-    char *str;
-
-    if (dev->realized) {
-        qdev_prop_set_after_realize(dev, name, errp);
-        return;
-    }
-
-    visit_type_str(v, name, &str, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    s = qemu_find_tpm_be(str);
-    if (s == NULL) {
-        error_setg(errp, "Property '%s.%s' can't find value '%s'",
-                   object_get_typename(obj), prop->name, str);
-    } else if (tpm_backend_init(s, TPM_IF(obj), errp) == 0) {
-        *be = s; /* weak reference, avoid cyclic ref */
-    }
-    g_free(str);
-}
-
-static void release_tpm(Object *obj, const char *name, void *opaque)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    TPMBackend **be = qdev_get_prop_ptr(dev, prop);
-
-    if (*be) {
-        tpm_backend_reset(*be);
-    }
-}
-
-const PropertyInfo qdev_prop_tpm = {
-    .name  = "str",
-    .description = "ID of a tpm to use as a backend",
-    .get   = get_tpm,
-    .set   = set_tpm,
-    .release = release_tpm,
-};
-
-/*
- * Write an error message in the given output buffer.
- */
-void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len)
-{
-    if (out_len >= sizeof(struct tpm_resp_hdr)) {
-        tpm_cmd_set_tag(out, TPM_TAG_RSP_COMMAND);
-        tpm_cmd_set_size(out, sizeof(struct tpm_resp_hdr));
-        tpm_cmd_set_error(out, TPM_FAIL);
-    }
-}
-
-bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len)
-{
-    if (in_len >= sizeof(struct tpm_req_hdr)) {
-        return tpm_cmd_get_ordinal(in) == TPM_ORD_ContinueSelfTest;
-    }
-
-    return false;
-}
-
-/*
- * Send request to a TPM device. We expect a response within one second.
- */
-static int tpm_util_request(int fd,
-                            const void *request,
-                            size_t requestlen,
-                            void *response,
-                            size_t responselen)
-{
-    fd_set readfds;
-    int n;
-    struct timeval tv = {
-        .tv_sec = 1,
-        .tv_usec = 0,
-    };
-
-    n = write(fd, request, requestlen);
-    if (n < 0) {
-        return -errno;
-    }
-    if (n != requestlen) {
-        return -EFAULT;
-    }
-
-    FD_ZERO(&readfds);
-    FD_SET(fd, &readfds);
-
-    /* wait for a second */
-    n = select(fd + 1, &readfds, NULL, NULL, &tv);
-    if (n != 1) {
-        return -errno;
-    }
-
-    n = read(fd, response, responselen);
-    if (n < sizeof(struct tpm_resp_hdr)) {
-        return -EFAULT;
-    }
-
-    /* check the header */
-    if (tpm_cmd_get_size(response) != n) {
-        return -EMSGSIZE;
-    }
-
-    return 0;
-}
-
-/*
- * A basic test of a TPM device. We expect a well formatted response header
- * (error response is fine).
- */
-static int tpm_util_test(int fd,
-                         const void *request,
-                         size_t requestlen,
-                         uint16_t *return_tag)
-{
-    char buf[1024];
-    ssize_t ret;
-
-    ret = tpm_util_request(fd, request, requestlen,
-                           buf, sizeof(buf));
-    if (ret < 0) {
-        return ret;
-    }
-
-    *return_tag = tpm_cmd_get_tag(buf);
-
-    return 0;
-}
-
-/*
- * Probe for the TPM device in the back
- * Returns 0 on success with the version of the probed TPM set, 1 on failure.
- */
-int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version)
-{
-    /*
-     * Sending a TPM1.2 command to a TPM2 should return a TPM1.2
-     * header (tag = 0xc4) and error code (TPM_BADTAG = 0x1e)
-     *
-     * Sending a TPM2 command to a TPM 2 will give a TPM 2 tag in the
-     * header.
-     * Sending a TPM2 command to a TPM 1.2 will give a TPM 1.2 tag
-     * in the header and an error code.
-     */
-    const struct tpm_req_hdr test_req = {
-        .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-        .len = cpu_to_be32(sizeof(test_req)),
-        .ordinal = cpu_to_be32(TPM_ORD_GetTicks),
-    };
-
-    const struct tpm_req_hdr test_req_tpm2 = {
-        .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-        .len = cpu_to_be32(sizeof(test_req_tpm2)),
-        .ordinal = cpu_to_be32(TPM2_CC_ReadClock),
-    };
-    uint16_t return_tag;
-    int ret;
-
-    /* Send TPM 2 command */
-    ret = tpm_util_test(tpm_fd, &test_req_tpm2,
-                        sizeof(test_req_tpm2), &return_tag);
-    /* TPM 2 would respond with a tag of TPM2_ST_NO_SESSIONS */
-    if (!ret && return_tag == TPM2_ST_NO_SESSIONS) {
-        *tpm_version = TPM_VERSION_2_0;
-        return 0;
-    }
-
-    /* Send TPM 1.2 command */
-    ret = tpm_util_test(tpm_fd, &test_req,
-                        sizeof(test_req), &return_tag);
-    if (!ret && return_tag == TPM_TAG_RSP_COMMAND) {
-        *tpm_version = TPM_VERSION_1_2;
-        /* this is a TPM 1.2 */
-        return 0;
-    }
-
-    *tpm_version = TPM_VERSION_UNSPEC;
-
-    return 1;
-}
-
-int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version,
-                             size_t *buffersize)
-{
-    int ret;
-
-    switch (tpm_version) {
-    case TPM_VERSION_1_2: {
-        const struct tpm_req_get_buffer_size {
-            struct tpm_req_hdr hdr;
-            uint32_t capability;
-            uint32_t len;
-            uint32_t subcap;
-        } QEMU_PACKED tpm_get_buffer_size = {
-            .hdr = {
-                .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-                .len = cpu_to_be32(sizeof(tpm_get_buffer_size)),
-                .ordinal = cpu_to_be32(TPM_ORD_GetCapability),
-            },
-            .capability = cpu_to_be32(TPM_CAP_PROPERTY),
-            .len = cpu_to_be32(sizeof(uint32_t)),
-            .subcap = cpu_to_be32(TPM_CAP_PROP_INPUT_BUFFER),
-        };
-        struct tpm_resp_get_buffer_size {
-            struct tpm_resp_hdr hdr;
-            uint32_t len;
-            uint32_t buffersize;
-        } QEMU_PACKED tpm_resp;
-
-        ret = tpm_util_request(tpm_fd, &tpm_get_buffer_size,
-                               sizeof(tpm_get_buffer_size),
-                               &tpm_resp, sizeof(tpm_resp));
-        if (ret < 0) {
-            return ret;
-        }
-
-        if (be32_to_cpu(tpm_resp.hdr.len) != sizeof(tpm_resp) ||
-            be32_to_cpu(tpm_resp.len) != sizeof(uint32_t)) {
-            trace_tpm_util_get_buffer_size_hdr_len(
-                be32_to_cpu(tpm_resp.hdr.len),
-                sizeof(tpm_resp));
-            trace_tpm_util_get_buffer_size_len(be32_to_cpu(tpm_resp.len),
-                                               sizeof(uint32_t));
-            error_report("tpm_util: Got unexpected response to "
-                         "TPM_GetCapability; errcode: 0x%x",
-                         be32_to_cpu(tpm_resp.hdr.errcode));
-            return -EFAULT;
-        }
-        *buffersize = be32_to_cpu(tpm_resp.buffersize);
-        break;
-    }
-    case TPM_VERSION_2_0: {
-        const struct tpm2_req_get_buffer_size {
-            struct tpm_req_hdr hdr;
-            uint32_t capability;
-            uint32_t property;
-            uint32_t count;
-        } QEMU_PACKED tpm2_get_buffer_size = {
-            .hdr = {
-                .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-                .len = cpu_to_be32(sizeof(tpm2_get_buffer_size)),
-                .ordinal = cpu_to_be32(TPM2_CC_GetCapability),
-            },
-            .capability = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES),
-            .property = cpu_to_be32(TPM2_PT_MAX_COMMAND_SIZE),
-            .count = cpu_to_be32(2), /* also get TPM2_PT_MAX_RESPONSE_SIZE */
-        };
-        struct tpm2_resp_get_buffer_size {
-            struct tpm_resp_hdr hdr;
-            uint8_t more;
-            uint32_t capability;
-            uint32_t count;
-            uint32_t property1;
-            uint32_t value1;
-            uint32_t property2;
-            uint32_t value2;
-        } QEMU_PACKED tpm2_resp;
-
-        ret = tpm_util_request(tpm_fd, &tpm2_get_buffer_size,
-                               sizeof(tpm2_get_buffer_size),
-                               &tpm2_resp, sizeof(tpm2_resp));
-        if (ret < 0) {
-            return ret;
-        }
-
-        if (be32_to_cpu(tpm2_resp.hdr.len) != sizeof(tpm2_resp) ||
-            be32_to_cpu(tpm2_resp.count) != 2) {
-            trace_tpm_util_get_buffer_size_hdr_len2(
-                be32_to_cpu(tpm2_resp.hdr.len),
-                sizeof(tpm2_resp));
-            trace_tpm_util_get_buffer_size_len2(
-                be32_to_cpu(tpm2_resp.count), 2);
-            error_report("tpm_util: Got unexpected response to "
-                         "TPM2_GetCapability; errcode: 0x%x",
-                         be32_to_cpu(tpm2_resp.hdr.errcode));
-            return -EFAULT;
-        }
-        *buffersize = MAX(be32_to_cpu(tpm2_resp.value1),
-                          be32_to_cpu(tpm2_resp.value2));
-        break;
-    }
-    case TPM_VERSION_UNSPEC:
-        return -EFAULT;
-    }
-
-    trace_tpm_util_get_buffer_size(*buffersize);
-
-    return 0;
-}
-
-void tpm_sized_buffer_reset(TPMSizedBuffer *tsb)
-{
-    g_free(tsb->buffer);
-    tsb->buffer = NULL;
-    tsb->size = 0;
-}
-
-void tpm_util_show_buffer(const unsigned char *buffer,
-                          size_t buffer_size, const char *string)
-{
-    size_t len, i;
-    char *line_buffer, *p;
-
-    len = MIN(tpm_cmd_get_size(buffer), buffer_size);
-
-    /*
-     * allocate enough room for 3 chars per buffer entry plus a
-     * newline after every 16 chars and a final null terminator.
-     */
-    line_buffer = g_malloc(len * 3 + (len / 16) + 1);
-
-    for (i = 0, p = line_buffer; i < len; i++) {
-        if (i && !(i % 16)) {
-            p += sprintf(p, "\n");
-        }
-        p += sprintf(p, "%.2X ", buffer[i]);
-    }
-    trace_tpm_util_show_buffer(string, len, line_buffer);
-
-    g_free(line_buffer);
-}
diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
deleted file mode 100644
index 7889081fba..0000000000
--- a/hw/tpm/tpm_util.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * TPM utility functions
- *
- *  Copyright (c) 2010 - 2015 IBM Corporation
- *  Authors:
- *    Stefan Berger <stefanb@us.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-
-#ifndef TPM_TPM_UTIL_H
-#define TPM_TPM_UTIL_H
-
-#include "sysemu/tpm.h"
-#include "qemu/bswap.h"
-
-void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len);
-
-bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len);
-
-int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
-
-static inline uint16_t tpm_cmd_get_tag(const void *b)
-{
-    return lduw_be_p(b);
-}
-
-static inline void tpm_cmd_set_tag(void *b, uint16_t tag)
-{
-    stw_be_p(b, tag);
-}
-
-static inline uint32_t tpm_cmd_get_size(const void *b)
-{
-    return ldl_be_p(b + 2);
-}
-
-static inline void tpm_cmd_set_size(void *b, uint32_t size)
-{
-    stl_be_p(b + 2, size);
-}
-
-static inline uint32_t tpm_cmd_get_ordinal(const void *b)
-{
-    return ldl_be_p(b + 6);
-}
-
-static inline uint32_t tpm_cmd_get_errcode(const void *b)
-{
-    return ldl_be_p(b + 6);
-}
-
-static inline void tpm_cmd_set_error(void *b, uint32_t error)
-{
-    stl_be_p(b + 6, error);
-}
-
-int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version,
-                             size_t *buffersize);
-
-#define DEFINE_PROP_TPMBE(_n, _s, _f)                     \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *)
-
-typedef struct TPMSizedBuffer {
-    uint32_t size;
-    uint8_t  *buffer;
-} TPMSizedBuffer;
-
-void tpm_sized_buffer_reset(TPMSizedBuffer *tsb);
-
-void tpm_util_show_buffer(const unsigned char *buffer,
-                          size_t buffer_size, const char *string);
-
-#endif /* TPM_TPM_UTIL_H */
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 439e514787..de9bf1e01b 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -4,38 +4,6 @@
 tpm_crb_mmio_read(uint64_t addr, unsigned size, uint32_t val) "CRB read 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 tpm_crb_mmio_write(uint64_t addr, unsigned size, uint32_t val) "CRB write 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 
-# tpm_passthrough.c
-tpm_passthrough_handle_request(void *cmd) "processing command %p"
-tpm_passthrough_reset(void) "reset"
-
-# tpm_util.c
-tpm_util_get_buffer_size_hdr_len(uint32_t len, size_t expected) "tpm_resp->hdr.len = %u, expected = %zu"
-tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u, expected = %zu"
-tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu"
-tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu"
-tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu"
-tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
-
-# tpm_emulator.c
-tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"
-tpm_emulator_handle_request(void) "processing TPM command"
-tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64
-tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t maxsize) "buffer size: %u, min: %u, max: %u"
-tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: %d, buffer size: %zu"
-tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d"
-tpm_emulator_cancel_cmd_not_supt(void) "Backend does not support CANCEL_TPM_CMD"
-tpm_emulator_handle_device_opts_tpm12(void) "TPM Version 1.2"
-tpm_emulator_handle_device_opts_tpm2(void) "TPM Version 2"
-tpm_emulator_handle_device_opts_unspec(void) "TPM Version Unspecified"
-tpm_emulator_handle_device_opts_startup_error(void) "Startup error"
-tpm_emulator_get_state_blob(uint8_t type, uint32_t size, uint32_t flags) "got state blob type %d, %u bytes, flags 0x%08x"
-tpm_emulator_set_state_blob(uint8_t type, uint32_t size, uint32_t flags) "set state blob type %d, %u bytes, flags 0x%08x"
-tpm_emulator_set_state_blobs(void) "setting state blobs"
-tpm_emulator_set_state_blobs_error(const char *msg) "error while setting state blobs: %s"
-tpm_emulator_set_state_blobs_done(void) "Done setting state blobs"
-tpm_emulator_pre_save(void) ""
-tpm_emulator_inst_init(void) ""
-
 # tpm_tis.c
 tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x"
 tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d"
@@ -56,7 +24,7 @@ tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u"
 # tpm_ppi.c
 tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu"
 
-# hw/tpm/tpm_spapr.c
+# tpm_spapr.c
 tpm_spapr_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
 tpm_spapr_do_crq(uint8_t raw1, uint8_t raw2) "1st 2 bytes in CRQ: 0x%02x 0x%02x"
 tpm_spapr_do_crq_crq_result(void) "SPAPR_VTPM_INIT_CRQ_RESULT"
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index 1541365914..5bbadadfa6 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -225,6 +225,7 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
         break;
     case A_WDOGLOCK:
         s->lock = (value != WDOG_UNLOCK_VALUE);
+        trace_cmsdk_apb_watchdog_lock(s->lock);
         break;
     case A_WDOGITCR:
         if (s->is_luminary) {
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index ab94d7df50..3124ca1f1b 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -4,3 +4,4 @@
 cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
+cmsdk_apb_watchdog_lock(uint32_t lock) "CMSDK APB watchdog: lock %" PRIu32
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 5d0834c1d9..10de15855a 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -173,8 +173,7 @@ static PFlashCFI01 *xtfpga_flash_init(MemoryRegion *address_space,
     SysBusDevice *s;
     DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
-    qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
-                        &error_abort);
+    qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo));
     qdev_prop_set_uint32(dev, "num-blocks",
                          board->flash->size / board->flash->sector_size);
     qdev_prop_set_uint64(dev, "sector-length", board->flash->sector_size);