qemu/hw/misc/a9scu.c
<<
>>
Prefs
   1/*
   2 * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
   3 *
   4 * Copyright (c) 2009 CodeSourcery.
   5 * Copyright (c) 2011 Linaro Limited.
   6 * Written by Paul Brook, Peter Maydell.
   7 *
   8 * This code is licensed under the GPL.
   9 */
  10
  11#include "qemu/osdep.h"
  12#include "hw/misc/a9scu.h"
  13
  14static uint64_t a9_scu_read(void *opaque, hwaddr offset,
  15                            unsigned size)
  16{
  17    A9SCUState *s = (A9SCUState *)opaque;
  18    switch (offset) {
  19    case 0x00: /* Control */
  20        return s->control;
  21    case 0x04: /* Configuration */
  22        return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
  23    case 0x08: /* CPU Power Status */
  24        return s->status;
  25    case 0x09: /* CPU status.  */
  26        return s->status >> 8;
  27    case 0x0a: /* CPU status.  */
  28        return s->status >> 16;
  29    case 0x0b: /* CPU status.  */
  30        return s->status >> 24;
  31    case 0x0c: /* Invalidate All Registers In Secure State */
  32        return 0;
  33    case 0x40: /* Filtering Start Address Register */
  34    case 0x44: /* Filtering End Address Register */
  35        /* RAZ/WI, like an implementation with only one AXI master */
  36        return 0;
  37    case 0x50: /* SCU Access Control Register */
  38    case 0x54: /* SCU Non-secure Access Control Register */
  39        /* unimplemented, fall through */
  40    default:
  41        return 0;
  42    }
  43}
  44
  45static void a9_scu_write(void *opaque, hwaddr offset,
  46                         uint64_t value, unsigned size)
  47{
  48    A9SCUState *s = (A9SCUState *)opaque;
  49    uint32_t mask;
  50    uint32_t shift;
  51    switch (size) {
  52    case 1:
  53        mask = 0xff;
  54        break;
  55    case 2:
  56        mask = 0xffff;
  57        break;
  58    case 4:
  59        mask = 0xffffffff;
  60        break;
  61    default:
  62        fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
  63                size, (unsigned)offset);
  64        return;
  65    }
  66
  67    switch (offset) {
  68    case 0x00: /* Control */
  69        s->control = value & 1;
  70        break;
  71    case 0x4: /* Configuration: RO */
  72        break;
  73    case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
  74        shift = (offset - 0x8) * 8;
  75        s->status &= ~(mask << shift);
  76        s->status |= ((value & mask) << shift);
  77        break;
  78    case 0x0c: /* Invalidate All Registers In Secure State */
  79        /* no-op as we do not implement caches */
  80        break;
  81    case 0x40: /* Filtering Start Address Register */
  82    case 0x44: /* Filtering End Address Register */
  83        /* RAZ/WI, like an implementation with only one AXI master */
  84        break;
  85    case 0x50: /* SCU Access Control Register */
  86    case 0x54: /* SCU Non-secure Access Control Register */
  87        /* unimplemented, fall through */
  88    default:
  89        break;
  90    }
  91}
  92
  93static const MemoryRegionOps a9_scu_ops = {
  94    .read = a9_scu_read,
  95    .write = a9_scu_write,
  96    .endianness = DEVICE_NATIVE_ENDIAN,
  97};
  98
  99static void a9_scu_reset(DeviceState *dev)
 100{
 101    A9SCUState *s = A9_SCU(dev);
 102    s->control = 0;
 103}
 104
 105static void a9_scu_init(Object *obj)
 106{
 107    A9SCUState *s = A9_SCU(obj);
 108    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 109
 110    memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
 111                          "a9-scu", 0x100);
 112    sysbus_init_mmio(sbd, &s->iomem);
 113}
 114
 115static const VMStateDescription vmstate_a9_scu = {
 116    .name = "a9-scu",
 117    .version_id = 1,
 118    .minimum_version_id = 1,
 119    .fields = (VMStateField[]) {
 120        VMSTATE_UINT32(control, A9SCUState),
 121        VMSTATE_UINT32(status, A9SCUState),
 122        VMSTATE_END_OF_LIST()
 123    }
 124};
 125
 126static Property a9_scu_properties[] = {
 127    DEFINE_PROP_UINT32("num-cpu", A9SCUState, num_cpu, 1),
 128    DEFINE_PROP_END_OF_LIST(),
 129};
 130
 131static void a9_scu_class_init(ObjectClass *klass, void *data)
 132{
 133    DeviceClass *dc = DEVICE_CLASS(klass);
 134
 135    dc->props = a9_scu_properties;
 136    dc->vmsd = &vmstate_a9_scu;
 137    dc->reset = a9_scu_reset;
 138}
 139
 140static const TypeInfo a9_scu_info = {
 141    .name          = TYPE_A9_SCU,
 142    .parent        = TYPE_SYS_BUS_DEVICE,
 143    .instance_size = sizeof(A9SCUState),
 144    .instance_init = a9_scu_init,
 145    .class_init    = a9_scu_class_init,
 146};
 147
 148static void a9mp_register_types(void)
 149{
 150    type_register_static(&a9_scu_info);
 151}
 152
 153type_init(a9mp_register_types)
 154