summaryrefslogtreecommitdiffstats
path: root/hw/arm/iotkit.c
diff options
context:
space:
mode:
authorPeter Maydell2018-06-22 17:03:31 +0200
committerPeter Maydell2018-06-22 17:03:31 +0200
commit5fce31220003bbe1b4c7faa0dbf92d131b0a413b (patch)
tree2a7aff159e9ce1f120b691a17d8a9f8a25ab1441 /hw/arm/iotkit.c
parentMerge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180622' into... (diff)
parentxen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_opti... (diff)
downloadqemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.tar.gz
qemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.tar.xz
qemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180622' into staging
target-arm queue: * hw/intc/arm_gicv3: fix wrong values when reading IPRIORITYR * target/arm: fix read of freed memory in kvm_arm_machine_init_done() * virt: support up to 512 CPUs * virt: support 256MB ECAM PCI region (for more PCI devices) * xlnx-zynqmp: Use Cortex-R5F, not Cortex-R5 * mps2-tz: Implement and use the TrustZone Memory Protection Controller * target/arm: enforce alignment checking for v6M cores * xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() * vl.c: Don't zero-initialize statics for serial_hds # gpg: Signature made Fri 22 Jun 2018 13:56:00 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180622: (28 commits) xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() vl.c: Don't zero-initialize statics for serial_hds target/arm: Strict alignment for ARMv6-M and ARMv8-M Baseline target/arm: Introduce ARM_FEATURE_M_MAIN hw/arm/mps2-tz.c: Instantiate MPCs hw/arm/iotkit: Wire up MPC interrupt lines hw/arm/iotkit: Instantiate MPC hw/misc/iotkit-secctl.c: Implement SECMPCINTSTATUS hw/misc/tz_mpc.c: Honour the BLK_LUT settings in translate hw/misc/tz-mpc.c: Implement correct blocked-access behaviour hw/misc/tz-mpc.c: Implement registers hw/misc/tz-mpc.c: Implement the Arm TrustZone Memory Protection Controller xlnx-zynqmp: Swap Cortex-R5 for Cortex-R5F target-arm: Add the Cortex-R5F hw/arm/virt: Increase max_cpus to 512 hw/arm/virt: Use 256MB ECAM region by default hw/arm/virt: Add virt-3.0 machine type hw/arm/virt: Add a new 256MB ECAM region hw/arm/virt: Register two redistributor regions when necessary hw/arm/virt-acpi-build: Advertise one or two GICR structures ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/iotkit.c')
-rw-r--r--hw/arm/iotkit.c112
1 files changed, 101 insertions, 11 deletions
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
index 234185e8f7..133d5bb34f 100644
--- a/hw/arm/iotkit.c
+++ b/hw/arm/iotkit.c
@@ -130,6 +130,19 @@ static void iotkit_init(Object *obj)
TYPE_TZ_PPC);
init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
TYPE_TZ_PPC);
+ init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
+ object_initialize(&s->mpc_irq_orgate, sizeof(s->mpc_irq_orgate),
+ TYPE_OR_IRQ);
+ object_property_add_child(obj, "mpc-irq-orgate",
+ OBJECT(&s->mpc_irq_orgate), &error_abort);
+ for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
+ char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
+
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
+ g_free(name);
+ }
init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
TYPE_CMSDK_APB_TIMER);
init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
@@ -162,6 +175,12 @@ static void iotkit_exp_irq(void *opaque, int n, int level)
qemu_set_irq(s->exp_irqs[n], level);
}
+static void iotkit_mpcexp_status(void *opaque, int n, int level)
+{
+ IoTKit *s = IOTKIT(opaque);
+ qemu_set_irq(s->mpcexp_status_in[n], level);
+}
+
static void iotkit_realize(DeviceState *dev, Error **errp)
{
IoTKit *s = IOTKIT(dev);
@@ -266,15 +285,6 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
*/
make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
- /* This RAM should be behind a Memory Protection Controller, but we
- * don't implement that yet.
- */
- memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
/* Security controller */
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
@@ -310,6 +320,48 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
qdev_get_gpio_in(dev_splitter, 0));
+ /* This RAM lives behind the Memory Protection Controller */
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
+ "downstream", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ /* Map the upstream end of the MPC into the right place... */
+ memory_region_add_subregion(&s->container, 0x20000000,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
+ 1));
+ /* ...and its register interface */
+ memory_region_add_subregion(&s->container, 0x50083000,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
+ 0));
+
+ /* We must OR together lines from the MPC splitters to go to the NVIC */
+ object_property_set_int(OBJECT(&s->mpc_irq_orgate),
+ IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
+ "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
+
/* Devices behind APB PPC0:
* 0x40000000: timer0
* 0x40001000: timer1
@@ -473,8 +525,6 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
- create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
-
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
@@ -520,6 +570,46 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
g_free(gpioname);
}
+ /* Wire up the splitters for the MPC IRQs */
+ for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
+ DeviceState *dev_splitter = DEVICE(splitter);
+
+ object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ object_property_set_bool(OBJECT(splitter), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ if (i < IOTS_NUM_EXP_MPC) {
+ /* Splitter input is from GPIO input line */
+ s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
+ qdev_connect_gpio_out(dev_splitter, 0,
+ qdev_get_gpio_in_named(dev_secctl,
+ "mpcexp_status", i));
+ } else {
+ /* Splitter input is from our own MPC */
+ qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
+ qdev_get_gpio_in(dev_splitter, 0));
+ qdev_connect_gpio_out(dev_splitter, 0,
+ qdev_get_gpio_in_named(dev_secctl,
+ "mpc_status", 0));
+ }
+
+ qdev_connect_gpio_out(dev_splitter, 1,
+ qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
+ }
+ /* Create GPIO inputs which will pass the line state for our
+ * mpcexp_irq inputs to the correct splitter devices.
+ */
+ qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
+ IOTS_NUM_EXP_MPC);
+
iotkit_forward_sec_resp_cfg(s);
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;