From patchwork Wed Feb 20 01:28:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Crosthwaite X-Patchwork-Id: 221937 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 612372C007C for ; Wed, 20 Feb 2013 12:29:24 +1100 (EST) Received: from localhost ([::1]:36487 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7yUs-0006ZF-GD for incoming@patchwork.ozlabs.org; Tue, 19 Feb 2013 20:29:22 -0500 Received: from eggs.gnu.org ([208.118.235.92]:38358) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7yUi-0006Z3-PY for qemu-devel@nongnu.org; Tue, 19 Feb 2013 20:29:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U7yUd-0008ON-4a for qemu-devel@nongnu.org; Tue, 19 Feb 2013 20:29:12 -0500 Received: from mail-pb0-f42.google.com ([209.85.160.42]:44795) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7yUc-0008NY-S0 for qemu-devel@nongnu.org; Tue, 19 Feb 2013 20:29:07 -0500 Received: by mail-pb0-f42.google.com with SMTP id xb4so2567385pbc.15 for ; Tue, 19 Feb 2013 17:29:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:in-reply-to:references:x-gm-message-state; bh=fyigbnpANbSOAFAIZdqT+7prgx/BnKsfQalhwL7RMxY=; b=dlNy0lypyn/nHDtb3vOUw2mErnu+oqwmXAkav2SAxo58kUXJ4zLQYoMC9EQ1RLyiy5 QBpsNaxwafAA4peCZnEBid04NadxmSUhpkyfOFLkaAQha+jl82gQL0J5E/p3MsgeTnv3 kxWeI6hOMm+VnCbL1NG5K/GMfq5A3gVGQUBvF1aJIAm9eGA9vuYnAvrV2gc3pJIMa22v lbn5DrAXIAy26g4kaN3FC5LmTSjXDw6LWJOm91TJ9x6bviDGQ3ZAUZ4BsJiEd9w3R4+x Q2+Q6rMCRuA0yrNjviZJuhe5agOKlp4RlstStN+2KHXV7QqBPX6z1ElxiHZg+6EOxDYS HLCA== X-Received: by 10.68.41.229 with SMTP id i5mr45607278pbl.62.1361323746078; Tue, 19 Feb 2013 17:29:06 -0800 (PST) Received: from localhost ([101.168.89.21]) by mx.google.com with ESMTPS id iu10sm19718217pbc.13.2013.02.19.17.29.00 (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Tue, 19 Feb 2013 17:29:05 -0800 (PST) From: Peter Crosthwaite To: qemu-devel@nongnu.org Date: Wed, 20 Feb 2013 11:28:09 +1000 Message-Id: <9478a00dc55cf051d61b590d7b5b9a8c19058007.1361323153.git.peter.crosthwaite@xilinx.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: References: In-Reply-To: References: X-Gm-Message-State: ALoCoQl/T4vxPEFiKHkfX6FP32FxrSC8KYTEXWOm4j0kidOIBMiqAEaH+oXFFzXxP8n0raXuNvg1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.160.42 Cc: Peter Crosthwaite , edgar.iglesias@gmail.com, aliguori@us.ibm.com, afaerber@suse.de Subject: [Qemu-devel] [PATCH v2 5/5] 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 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 --- changed from v1: added DeviceState pointer for SCU in APMPPrivState (PMM review) Deleted stale comment (PMM review) hyphenated strings (PMM review) Change Sysbus->init over to Device->realize (PMM Review) removed usages of FROM_SYSBUS constified TypeInfo (Andreas review) 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