From patchwork Thu Feb 28 18:53:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 224138 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CDBEF2C02B9 for ; Fri, 1 Mar 2013 05:54:53 +1100 (EST) Received: from localhost ([::1]:54608 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UB8d2-0000tq-2W for incoming@patchwork.ozlabs.org; Thu, 28 Feb 2013 13:54:52 -0500 Received: from eggs.gnu.org ([208.118.235.92]:47307) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UB8cT-0000rW-EK for qemu-devel@nongnu.org; Thu, 28 Feb 2013 13:54:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UB8cQ-00040O-E1 for qemu-devel@nongnu.org; Thu, 28 Feb 2013 13:54:17 -0500 Received: from 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa ([2001:8b0:1d0::1]:60819 helo=mnementh.archaic.org.uk) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UB8cQ-0003yV-1A for qemu-devel@nongnu.org; Thu, 28 Feb 2013 13:54:14 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1UB8cG-0008Bq-9A; Thu, 28 Feb 2013 18:54:04 +0000 From: Peter Maydell To: Anthony Liguori , Blue Swirl Date: Thu, 28 Feb 2013 18:53:54 +0000 Message-Id: <1362077643-31443-9-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1362077643-31443-1-git-send-email-peter.maydell@linaro.org> References: <1362077643-31443-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Cc: qemu-devel@nongnu.org, Paul Brook Subject: [Qemu-devel] [PATCH 08/17] arm: a9mpcore: Coreify the SCU X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Peter Crosthwaite Split the SCU in a9mpcore out into its own object definition. mpcore is now just a container for the mpcore components. Signed-off-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/a9mpcore.c | 122 +++---------------------------------- hw/a9scu.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/arm/Makefile.objs | 1 + 3 files changed, 174 insertions(+), 113 deletions(-) create mode 100644 hw/a9scu.c diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c index 23630af..01aee02 100644 --- a/hw/a9mpcore.c +++ b/hw/a9mpcore.c @@ -10,113 +10,17 @@ #include "sysbus.h" -/* A9MP private memory region. */ - typedef struct A9MPPrivState { SysBusDevice busdev; - uint32_t scu_control; - uint32_t scu_status; uint32_t num_cpu; - MemoryRegion scu_iomem; MemoryRegion container; DeviceState *mptimer; DeviceState *wdt; DeviceState *gic; + DeviceState *scu; uint32_t num_irq; } A9MPPrivState; -static uint64_t a9_scu_read(void *opaque, hwaddr offset, - unsigned size) -{ - A9MPPrivState *s = (A9MPPrivState *)opaque; - switch (offset) { - case 0x00: /* Control */ - return s->scu_control; - case 0x04: /* Configuration */ - return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1); - case 0x08: /* CPU Power Status */ - return s->scu_status; - case 0x09: /* CPU status. */ - return s->scu_status >> 8; - case 0x0a: /* CPU status. */ - return s->scu_status >> 16; - case 0x0b: /* CPU status. */ - return s->scu_status >> 24; - case 0x0c: /* Invalidate All Registers In Secure State */ - return 0; - case 0x40: /* Filtering Start Address Register */ - case 0x44: /* Filtering End Address Register */ - /* RAZ/WI, like an implementation with only one AXI master */ - return 0; - case 0x50: /* SCU Access Control Register */ - case 0x54: /* SCU Non-secure Access Control Register */ - /* unimplemented, fall through */ - default: - return 0; - } -} - -static void a9_scu_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - A9MPPrivState *s = (A9MPPrivState *)opaque; - uint32_t mask; - uint32_t shift; - switch (size) { - case 1: - mask = 0xff; - break; - case 2: - mask = 0xffff; - break; - case 4: - mask = 0xffffffff; - break; - default: - fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n", - size, (unsigned)offset); - return; - } - - switch (offset) { - case 0x00: /* Control */ - s->scu_control = value & 1; - break; - case 0x4: /* Configuration: RO */ - break; - case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */ - shift = (offset - 0x8) * 8; - s->scu_status &= ~(mask << shift); - s->scu_status |= ((value & mask) << shift); - break; - case 0x0c: /* Invalidate All Registers In Secure State */ - /* no-op as we do not implement caches */ - break; - case 0x40: /* Filtering Start Address Register */ - case 0x44: /* Filtering End Address Register */ - /* RAZ/WI, like an implementation with only one AXI master */ - break; - case 0x50: /* SCU Access Control Register */ - case 0x54: /* SCU Non-secure Access Control Register */ - /* unimplemented, fall through */ - default: - break; - } -} - -static const MemoryRegionOps a9_scu_ops = { - .read = a9_scu_read, - .write = a9_scu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void a9mp_priv_reset(DeviceState *dev) -{ - A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, SYS_BUS_DEVICE(dev)); - - s->scu_control = 0; -} - static void a9mp_priv_set_irq(void *opaque, int irq, int level) { A9MPPrivState *s = (A9MPPrivState *)opaque; @@ -126,7 +30,7 @@ static void a9mp_priv_set_irq(void *opaque, int irq, int level) static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev); - SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev; + SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; int i; s->gic = qdev_create(NULL, "arm_gic"); @@ -141,6 +45,11 @@ static int a9mp_priv_init(SysBusDevice *dev) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(&s->busdev.qdev, a9mp_priv_set_irq, s->num_irq - 32); + s->scu = qdev_create(NULL, "a9-scu"); + qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu); + qdev_init_nofail(s->scu); + scubusdev = SYS_BUS_DEVICE(s->scu); + s->mptimer = qdev_create(NULL, "arm_mptimer"); qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); qdev_init_nofail(s->mptimer); @@ -163,8 +72,8 @@ static int a9mp_priv_init(SysBusDevice *dev) * We should implement the global timer but don't currently do so. */ memory_region_init(&s->container, "a9mp-priv-container", 0x2000); - memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100); - memory_region_add_subregion(&s->container, 0, &s->scu_iomem); + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interface */ memory_region_add_subregion(&s->container, 0x100, sysbus_mmio_get_region(gicbusdev, 1)); @@ -193,17 +102,6 @@ static int a9mp_priv_init(SysBusDevice *dev) return 0; } -static const VMStateDescription vmstate_a9mp_priv = { - .name = "a9mpcore_priv", - .version_id = 3, - .minimum_version_id = 3, - .fields = (VMStateField[]) { - VMSTATE_UINT32(scu_control, A9MPPrivState), - VMSTATE_UINT32_V(scu_status, A9MPPrivState, 2), - VMSTATE_END_OF_LIST() - } -}; - static Property a9mp_priv_properties[] = { DEFINE_PROP_UINT32("num-cpu", A9MPPrivState, num_cpu, 1), /* The Cortex-A9MP may have anything from 0 to 224 external interrupt @@ -223,8 +121,6 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data) k->init = a9mp_priv_init; dc->props = a9mp_priv_properties; - dc->vmsd = &vmstate_a9mp_priv; - dc->reset = a9mp_priv_reset; } static const TypeInfo a9mp_priv_info = { diff --git a/hw/a9scu.c b/hw/a9scu.c new file mode 100644 index 0000000..0e9e54d --- /dev/null +++ b/hw/a9scu.c @@ -0,0 +1,164 @@ +/* + * Cortex-A9MPCore Snoop Control Unit (SCU) emulation. + * + * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2011 Linaro Limited. + * Written by Paul Brook, Peter Maydell. + * + * This code is licensed under the GPL. + */ + +#include "sysbus.h" + +/* A9MP private memory region. */ + +typedef struct A9SCUState { + SysBusDevice busdev; + MemoryRegion iomem; + uint32_t control; + uint32_t status; + uint32_t num_cpu; +} A9SCUState; + +#define TYPE_A9_SCU "a9-scu" +#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) + +static uint64_t a9_scu_read(void *opaque, hwaddr offset, + unsigned size) +{ + A9SCUState *s = (A9SCUState *)opaque; + switch (offset) { + case 0x00: /* Control */ + return s->control; + case 0x04: /* Configuration */ + return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1); + case 0x08: /* CPU Power Status */ + return s->status; + case 0x09: /* CPU status. */ + return s->status >> 8; + case 0x0a: /* CPU status. */ + return s->status >> 16; + case 0x0b: /* CPU status. */ + return s->status >> 24; + case 0x0c: /* Invalidate All Registers In Secure State */ + return 0; + case 0x40: /* Filtering Start Address Register */ + case 0x44: /* Filtering End Address Register */ + /* RAZ/WI, like an implementation with only one AXI master */ + return 0; + case 0x50: /* SCU Access Control Register */ + case 0x54: /* SCU Non-secure Access Control Register */ + /* unimplemented, fall through */ + default: + return 0; + } +} + +static void a9_scu_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + A9SCUState *s = (A9SCUState *)opaque; + uint32_t mask; + uint32_t shift; + switch (size) { + case 1: + mask = 0xff; + break; + case 2: + mask = 0xffff; + break; + case 4: + mask = 0xffffffff; + break; + default: + fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n", + size, (unsigned)offset); + return; + } + + switch (offset) { + case 0x00: /* Control */ + s->control = value & 1; + break; + case 0x4: /* Configuration: RO */ + break; + case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */ + shift = (offset - 0x8) * 8; + s->status &= ~(mask << shift); + s->status |= ((value & mask) << shift); + break; + case 0x0c: /* Invalidate All Registers In Secure State */ + /* no-op as we do not implement caches */ + break; + case 0x40: /* Filtering Start Address Register */ + case 0x44: /* Filtering End Address Register */ + /* RAZ/WI, like an implementation with only one AXI master */ + break; + case 0x50: /* SCU Access Control Register */ + case 0x54: /* SCU Non-secure Access Control Register */ + /* unimplemented, fall through */ + default: + break; + } +} + +static const MemoryRegionOps a9_scu_ops = { + .read = a9_scu_read, + .write = a9_scu_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void a9_scu_reset(DeviceState *dev) +{ + A9SCUState *s = A9_SCU(dev); + s->control = 0; +} + +static void a9_scu_realize(DeviceState *dev, Error ** errp) +{ + A9SCUState *s = A9_SCU(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->iomem, &a9_scu_ops, s, "a9-scu", 0x100); + sysbus_init_mmio(sbd, &s->iomem); +} + +static const VMStateDescription vmstate_a9_scu = { + .name = "a9-scu", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(control, A9SCUState), + VMSTATE_UINT32(status, A9SCUState), + VMSTATE_END_OF_LIST() + } +}; + +static Property a9_scu_properties[] = { + DEFINE_PROP_UINT32("num-cpu", A9SCUState, num_cpu, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void a9_scu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = a9_scu_realize; + dc->props = a9_scu_properties; + dc->vmsd = &vmstate_a9_scu; + dc->reset = a9_scu_reset; +} + +static const TypeInfo a9_scu_info = { + .name = TYPE_A9_SCU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(A9SCUState), + .class_init = a9_scu_class_init, +}; + +static void a9mp_register_types(void) +{ + type_register_static(&a9_scu_info); +} + +type_init(a9mp_register_types) diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 6d049e7..4c10985 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -3,6 +3,7 @@ obj-y += arm_boot.o obj-y += xilinx_zynq.o zynq_slcr.o obj-y += xilinx_spips.o obj-y += arm_gic.o arm_gic_common.o +obj-y += a9scu.o obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o