2 * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
4 * Copyright (c) 2009 CodeSourcery.
5 * Copyright (c) 2011 Linaro Limited.
6 * Written by Paul Brook, Peter Maydell.
8 * This code is licensed under the GPL.
11 #include "hw/sysbus.h"
13 /* A9MP private memory region. */
15 typedef struct A9SCUState
{
23 #define TYPE_A9_SCU "a9-scu"
24 #define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
26 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
29 A9SCUState
*s
= (A9SCUState
*)opaque
;
31 case 0x00: /* Control */
33 case 0x04: /* Configuration */
34 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
35 case 0x08: /* CPU Power Status */
37 case 0x09: /* CPU status. */
38 return s
->status
>> 8;
39 case 0x0a: /* CPU status. */
40 return s
->status
>> 16;
41 case 0x0b: /* CPU status. */
42 return s
->status
>> 24;
43 case 0x0c: /* Invalidate All Registers In Secure State */
45 case 0x40: /* Filtering Start Address Register */
46 case 0x44: /* Filtering End Address Register */
47 /* RAZ/WI, like an implementation with only one AXI master */
49 case 0x50: /* SCU Access Control Register */
50 case 0x54: /* SCU Non-secure Access Control Register */
51 /* unimplemented, fall through */
57 static void a9_scu_write(void *opaque
, hwaddr offset
,
58 uint64_t value
, unsigned size
)
60 A9SCUState
*s
= (A9SCUState
*)opaque
;
74 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
75 size
, (unsigned)offset
);
80 case 0x00: /* Control */
81 s
->control
= value
& 1;
83 case 0x4: /* Configuration: RO */
85 case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
86 shift
= (offset
- 0x8) * 8;
87 s
->status
&= ~(mask
<< shift
);
88 s
->status
|= ((value
& mask
) << shift
);
90 case 0x0c: /* Invalidate All Registers In Secure State */
91 /* no-op as we do not implement caches */
93 case 0x40: /* Filtering Start Address Register */
94 case 0x44: /* Filtering End Address Register */
95 /* RAZ/WI, like an implementation with only one AXI master */
97 case 0x50: /* SCU Access Control Register */
98 case 0x54: /* SCU Non-secure Access Control Register */
99 /* unimplemented, fall through */
105 static const MemoryRegionOps a9_scu_ops
= {
107 .write
= a9_scu_write
,
108 .endianness
= DEVICE_NATIVE_ENDIAN
,
111 static void a9_scu_reset(DeviceState
*dev
)
113 A9SCUState
*s
= A9_SCU(dev
);
117 static void a9_scu_realize(DeviceState
*dev
, Error
** errp
)
119 A9SCUState
*s
= A9_SCU(dev
);
120 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
122 memory_region_init_io(&s
->iomem
, OBJECT(dev
), &a9_scu_ops
, s
,
124 sysbus_init_mmio(sbd
, &s
->iomem
);
127 static const VMStateDescription vmstate_a9_scu
= {
130 .minimum_version_id
= 1,
131 .fields
= (VMStateField
[]) {
132 VMSTATE_UINT32(control
, A9SCUState
),
133 VMSTATE_UINT32(status
, A9SCUState
),
134 VMSTATE_END_OF_LIST()
138 static Property a9_scu_properties
[] = {
139 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
140 DEFINE_PROP_END_OF_LIST(),
143 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
145 DeviceClass
*dc
= DEVICE_CLASS(klass
);
147 dc
->realize
= a9_scu_realize
;
148 dc
->props
= a9_scu_properties
;
149 dc
->vmsd
= &vmstate_a9_scu
;
150 dc
->reset
= a9_scu_reset
;
153 static const TypeInfo a9_scu_info
= {
155 .parent
= TYPE_SYS_BUS_DEVICE
,
156 .instance_size
= sizeof(A9SCUState
),
157 .class_init
= a9_scu_class_init
,
160 static void a9mp_register_types(void)
162 type_register_static(&a9_scu_info
);
165 type_init(a9mp_register_types
)