diff options
Diffstat (limited to 'hw/arm')
-rw-r--r-- | hw/arm/Kconfig | 8 | ||||
-rw-r--r-- | hw/arm/mps2-tz.c | 23 | ||||
-rw-r--r-- | hw/arm/mps2.c | 67 | ||||
-rw-r--r-- | hw/arm/realview.c | 3 | ||||
-rw-r--r-- | hw/arm/versatilepb.c | 3 | ||||
-rw-r--r-- | hw/arm/vexpress.c | 3 | ||||
-rw-r--r-- | hw/arm/virt.c | 63 |
7 files changed, 152 insertions, 18 deletions
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/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/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/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..24d656e653 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) @@ -640,7 +641,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) |