diff options
author | Peter Crosthwaite <peter.crosthwaite@xilinx.com> | 2013-02-28 18:23:14 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-02-28 18:23:14 +0000 |
commit | 353575f0959234e1680622f747e20308c94505b7 (patch) | |
tree | 34e150f5095027a56ab7e7c281c9de997589914e /hw/a9mpcore.c | |
parent | 9595978292e9a5b5f0ec77a9f6a0e724c10bf3b4 (diff) |
arm: a9mpcore: Coreify the SCU
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 <peter.crosthwaite@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/a9mpcore.c')
-rw-r--r-- | hw/a9mpcore.c | 122 |
1 files changed, 9 insertions, 113 deletions
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c index 23630af1fe..01aee0264d 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 = { |