arm11mpcore: Split off SCU device
Inspired by a9scu. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Andreas Färber <afaerber@suse.de>
This commit is contained in:
parent
2c42c3a063
commit
53cb9a1c2f
@ -61,6 +61,7 @@ CONFIG_BITBANG_I2C=y
|
|||||||
CONFIG_FRAMEBUFFER=y
|
CONFIG_FRAMEBUFFER=y
|
||||||
CONFIG_XILINX_SPIPS=y
|
CONFIG_XILINX_SPIPS=y
|
||||||
|
|
||||||
|
CONFIG_ARM11SCU=y
|
||||||
CONFIG_A9SCU=y
|
CONFIG_A9SCU=y
|
||||||
CONFIG_MARVELL_88W8618=y
|
CONFIG_MARVELL_88W8618=y
|
||||||
CONFIG_OMAP=y
|
CONFIG_OMAP=y
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
#include "hw/misc/arm11scu.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
|
|
||||||
/* MPCore private memory region. */
|
/* MPCore private memory region. */
|
||||||
@ -19,64 +20,18 @@
|
|||||||
typedef struct ARM11MPCorePriveState {
|
typedef struct ARM11MPCorePriveState {
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
uint32_t scu_control;
|
|
||||||
uint32_t num_cpu;
|
uint32_t num_cpu;
|
||||||
MemoryRegion iomem;
|
|
||||||
MemoryRegion container;
|
MemoryRegion container;
|
||||||
DeviceState *mptimer;
|
DeviceState *mptimer;
|
||||||
DeviceState *wdtimer;
|
DeviceState *wdtimer;
|
||||||
DeviceState *gic;
|
DeviceState *gic;
|
||||||
uint32_t num_irq;
|
uint32_t num_irq;
|
||||||
|
|
||||||
|
ARM11SCUState scu;
|
||||||
} ARM11MPCorePriveState;
|
} ARM11MPCorePriveState;
|
||||||
|
|
||||||
/* Per-CPU private memory mapped IO. */
|
/* 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)
|
static void mpcore_priv_set_irq(void *opaque, int irq, int level)
|
||||||
{
|
{
|
||||||
@ -87,12 +42,13 @@ static void mpcore_priv_set_irq(void *opaque, int irq, int level)
|
|||||||
static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
|
static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
|
||||||
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
|
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
|
||||||
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
|
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
|
||||||
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
|
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,
|
||||||
memory_region_add_subregion(&s->container, 0, &s->iomem);
|
sysbus_mmio_get_region(scubusdev, 0));
|
||||||
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
|
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
|
||||||
* at 0x200, 0x300...
|
* at 0x200, 0x300...
|
||||||
*/
|
*/
|
||||||
@ -130,6 +86,10 @@ static int mpcore_priv_init(SysBusDevice *sbd)
|
|||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(sbd);
|
DeviceState *dev = DEVICE(sbd);
|
||||||
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
|
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");
|
s->gic = qdev_create(NULL, "arm_gic");
|
||||||
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
|
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
|
||||||
@ -164,6 +124,9 @@ static void mpcore_priv_initfn(Object *obj)
|
|||||||
memory_region_init(&s->container, OBJECT(s),
|
memory_region_init(&s->container, OBJECT(s),
|
||||||
"mpcore-priv-container", 0x2000);
|
"mpcore-priv-container", 0x2000);
|
||||||
sysbus_init_mmio(sbd, &s->container);
|
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"
|
#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
|
||||||
|
@ -12,6 +12,7 @@ obj-$(CONFIG_VMPORT) += vmport.o
|
|||||||
common-obj-$(CONFIG_PL310) += arm_l2x0.o
|
common-obj-$(CONFIG_PL310) += arm_l2x0.o
|
||||||
common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
|
common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
|
||||||
common-obj-$(CONFIG_A9SCU) += a9scu.o
|
common-obj-$(CONFIG_A9SCU) += a9scu.o
|
||||||
|
common-obj-$(CONFIG_ARM11SCU) += arm11scu.o
|
||||||
|
|
||||||
# PKUnity SoC devices
|
# PKUnity SoC devices
|
||||||
common-obj-$(CONFIG_PUV3) += puv3_pm.o
|
common-obj-$(CONFIG_PUV3) += puv3_pm.o
|
||||||
|
100
hw/misc/arm11scu.c
Normal file
100
hw/misc/arm11scu.c
Normal file
@ -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
include/hw/misc/arm11scu.h
Normal file
29
include/hw/misc/arm11scu.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user