Skip to content

Commit

Permalink
arm11mpcore: Split off SCU device
Browse files Browse the repository at this point in the history
Inspired by a9scu.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andreas Färber <afaerber@suse.de>
  • Loading branch information
afaerber committed Nov 5, 2013
1 parent 2c42c3a commit 53cb9a1
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 51 deletions.
1 change: 1 addition & 0 deletions default-configs/arm-softmmu.mak
Expand Up @@ -61,6 +61,7 @@ CONFIG_BITBANG_I2C=y
CONFIG_FRAMEBUFFER=y
CONFIG_XILINX_SPIPS=y

CONFIG_ARM11SCU=y
CONFIG_A9SCU=y
CONFIG_MARVELL_88W8618=y
CONFIG_OMAP=y
Expand Down
65 changes: 14 additions & 51 deletions hw/cpu/arm11mpcore.c
Expand Up @@ -8,6 +8,7 @@
*/

#include "hw/sysbus.h"
#include "hw/misc/arm11scu.h"
#include "qemu/timer.h"

/* MPCore private memory region. */
Expand All @@ -19,64 +20,18 @@
typedef struct ARM11MPCorePriveState {
SysBusDevice parent_obj;

uint32_t scu_control;
uint32_t num_cpu;
MemoryRegion iomem;
MemoryRegion container;
DeviceState *mptimer;
DeviceState *wdtimer;
DeviceState *gic;
uint32_t num_irq;

ARM11SCUState scu;
} ARM11MPCorePriveState;

/* Per-CPU private memory mapped IO. */

static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
unsigned size)
{
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
int id;
/* SCU */
switch (offset) {
case 0x00: /* Control. */
return s->scu_control;
case 0x04: /* Configuration. */
id = ((1 << s->num_cpu) - 1) << 4;
return id | (s->num_cpu - 1);
case 0x08: /* CPU status. */
return 0;
case 0x0c: /* Invalidate all. */
return 0;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
return 0;
}
}

static void mpcore_scu_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
/* SCU */
switch (offset) {
case 0: /* Control register. */
s->scu_control = value & 1;
break;
case 0x0c: /* Invalidate all. */
/* This is a no-op as cache is not emulated. */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
}
}

static const MemoryRegionOps mpcore_scu_ops = {
.read = mpcore_scu_read,
.write = mpcore_scu_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};

static void mpcore_priv_set_irq(void *opaque, int irq, int level)
{
Expand All @@ -87,12 +42,13 @@ static void mpcore_priv_set_irq(void *opaque, int irq, int level)
static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
{
int i;
SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
memory_region_init_io(&s->iomem, OBJECT(s),
&mpcore_scu_ops, s, "mpcore-scu", 0x100);
memory_region_add_subregion(&s->container, 0, &s->iomem);

memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(scubusdev, 0));
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
* at 0x200, 0x300...
*/
Expand Down Expand Up @@ -130,6 +86,10 @@ static int mpcore_priv_init(SysBusDevice *sbd)
{
DeviceState *dev = DEVICE(sbd);
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
DeviceState *scudev = DEVICE(&s->scu);

qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
qdev_init_nofail(scudev);

s->gic = qdev_create(NULL, "arm_gic");
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
Expand Down Expand Up @@ -164,6 +124,9 @@ static void mpcore_priv_initfn(Object *obj)
memory_region_init(&s->container, OBJECT(s),
"mpcore-priv-container", 0x2000);
sysbus_init_mmio(sbd, &s->container);

object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU);
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
}

#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
Expand Down
1 change: 1 addition & 0 deletions hw/misc/Makefile.objs
Expand Up @@ -12,6 +12,7 @@ obj-$(CONFIG_VMPORT) += vmport.o
common-obj-$(CONFIG_PL310) += arm_l2x0.o
common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
common-obj-$(CONFIG_A9SCU) += a9scu.o
common-obj-$(CONFIG_ARM11SCU) += arm11scu.o

# PKUnity SoC devices
common-obj-$(CONFIG_PUV3) += puv3_pm.o
Expand Down
100 changes: 100 additions & 0 deletions hw/misc/arm11scu.c
@@ -0,0 +1,100 @@
/*
* ARM11MPCore Snoop Control Unit (SCU) emulation
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2013 SUSE LINUX Products GmbH
* Written by Paul Brook and Andreas Färber
*
* This code is licensed under the GPL.
*/

#include "hw/misc/arm11scu.h"

static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
unsigned size)
{
ARM11SCUState *s = (ARM11SCUState *)opaque;
int id;
/* SCU */
switch (offset) {
case 0x00: /* Control. */
return s->control;
case 0x04: /* Configuration. */
id = ((1 << s->num_cpu) - 1) << 4;
return id | (s->num_cpu - 1);
case 0x08: /* CPU status. */
return 0;
case 0x0c: /* Invalidate all. */
return 0;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
return 0;
}
}

static void mpcore_scu_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
ARM11SCUState *s = (ARM11SCUState *)opaque;
/* SCU */
switch (offset) {
case 0: /* Control register. */
s->control = value & 1;
break;
case 0x0c: /* Invalidate all. */
/* This is a no-op as cache is not emulated. */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
}
}

static const MemoryRegionOps mpcore_scu_ops = {
.read = mpcore_scu_read,
.write = mpcore_scu_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};

static void arm11_scu_realize(DeviceState *dev, Error **errp)
{
}

static void arm11_scu_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ARM11SCUState *s = ARM11_SCU(obj);

memory_region_init_io(&s->iomem, OBJECT(s),
&mpcore_scu_ops, s, "mpcore-scu", 0x100);
sysbus_init_mmio(sbd, &s->iomem);
}

static Property arm11_scu_properties[] = {
DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1),
DEFINE_PROP_END_OF_LIST()
};

static void arm11_scu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);

dc->realize = arm11_scu_realize;
dc->props = arm11_scu_properties;
}

static const TypeInfo arm11_scu_type_info = {
.name = TYPE_ARM11_SCU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARM11SCUState),
.instance_init = arm11_scu_init,
.class_init = arm11_scu_class_init,
};

static void arm11_scu_register_types(void)
{
type_register_static(&arm11_scu_type_info);
}

type_init(arm11_scu_register_types)
29 changes: 29 additions & 0 deletions include/hw/misc/arm11scu.h
@@ -0,0 +1,29 @@
/*
* ARM11MPCore Snoop Control Unit (SCU) emulation
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2013 SUSE LINUX Products GmbH
* Written by Paul Brook and Andreas Färber
*
* This code is licensed under the GPL.
*/

#ifndef HW_MISC_ARM11SCU_H
#define HW_MISC_ARM11SCU_H

#include "hw/sysbus.h"

#define TYPE_ARM11_SCU "arm11-scu"
#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)

typedef struct ARM11SCUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/

uint32_t control;
uint32_t num_cpu;
MemoryRegion iomem;
} ARM11SCUState;

#endif

0 comments on commit 53cb9a1

Please sign in to comment.