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
{
17 SysBusDevice parent_obj
;
26 #define TYPE_A9_SCU "a9-scu"
27 #define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
29 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
32 A9SCUState
*s
= (A9SCUState
*)opaque
;
34 case 0x00: /* Control */
36 case 0x04: /* Configuration */
37 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
38 case 0x08: /* CPU Power Status */
40 case 0x09: /* CPU status. */
41 return s
->status
>> 8;
42 case 0x0a: /* CPU status. */
43 return s
->status
>> 16;
44 case 0x0b: /* CPU status. */
45 return s
->status
>> 24;
46 case 0x0c: /* Invalidate All Registers In Secure State */
48 case 0x40: /* Filtering Start Address Register */
49 case 0x44: /* Filtering End Address Register */
50 /* RAZ/WI, like an implementation with only one AXI master */
52 case 0x50: /* SCU Access Control Register */
53 case 0x54: /* SCU Non-secure Access Control Register */
54 /* unimplemented, fall through */
60 static void a9_scu_write(void *opaque
, hwaddr offset
,
61 uint64_t value
, unsigned size
)
63 A9SCUState
*s
= (A9SCUState
*)opaque
;
77 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
78 size
, (unsigned)offset
);
83 case 0x00: /* Control */
84 s
->control
= value
& 1;
86 case 0x4: /* Configuration: RO */
88 case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
89 shift
= (offset
- 0x8) * 8;
90 s
->status
&= ~(mask
<< shift
);
91 s
->status
|= ((value
& mask
) << shift
);
93 case 0x0c: /* Invalidate All Registers In Secure State */
94 /* no-op as we do not implement caches */
96 case 0x40: /* Filtering Start Address Register */
97 case 0x44: /* Filtering End Address Register */
98 /* RAZ/WI, like an implementation with only one AXI master */
100 case 0x50: /* SCU Access Control Register */
101 case 0x54: /* SCU Non-secure Access Control Register */
102 /* unimplemented, fall through */
108 static const MemoryRegionOps a9_scu_ops
= {
110 .write
= a9_scu_write
,
111 .endianness
= DEVICE_NATIVE_ENDIAN
,
114 static void a9_scu_reset(DeviceState
*dev
)
116 A9SCUState
*s
= A9_SCU(dev
);
120 static void a9_scu_init(Object
*obj
)
122 A9SCUState
*s
= A9_SCU(obj
);
123 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
125 memory_region_init_io(&s
->iomem
, obj
, &a9_scu_ops
, s
,
127 sysbus_init_mmio(sbd
, &s
->iomem
);
130 static const VMStateDescription vmstate_a9_scu
= {
133 .minimum_version_id
= 1,
134 .fields
= (VMStateField
[]) {
135 VMSTATE_UINT32(control
, A9SCUState
),
136 VMSTATE_UINT32(status
, A9SCUState
),
137 VMSTATE_END_OF_LIST()
141 static Property a9_scu_properties
[] = {
142 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
143 DEFINE_PROP_END_OF_LIST(),
146 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
148 DeviceClass
*dc
= DEVICE_CLASS(klass
);
150 dc
->props
= a9_scu_properties
;
151 dc
->vmsd
= &vmstate_a9_scu
;
152 dc
->reset
= a9_scu_reset
;
155 static const TypeInfo a9_scu_info
= {
157 .parent
= TYPE_SYS_BUS_DEVICE
,
158 .instance_size
= sizeof(A9SCUState
),
159 .instance_init
= a9_scu_init
,
160 .class_init
= a9_scu_class_init
,
163 static void a9mp_register_types(void)
165 type_register_static(&a9_scu_info
);
168 type_init(a9mp_register_types
)