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 "qemu/osdep.h"
12 #include "hw/misc/a9scu.h"
13 #include "qemu/module.h"
15 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
18 A9SCUState
*s
= (A9SCUState
*)opaque
;
20 case 0x00: /* Control */
22 case 0x04: /* Configuration */
23 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
24 case 0x08: /* CPU Power Status */
26 case 0x09: /* CPU status. */
27 return s
->status
>> 8;
28 case 0x0a: /* CPU status. */
29 return s
->status
>> 16;
30 case 0x0b: /* CPU status. */
31 return s
->status
>> 24;
32 case 0x0c: /* Invalidate All Registers In Secure State */
34 case 0x40: /* Filtering Start Address Register */
35 case 0x44: /* Filtering End Address Register */
36 /* RAZ/WI, like an implementation with only one AXI master */
38 case 0x50: /* SCU Access Control Register */
39 case 0x54: /* SCU Non-secure Access Control Register */
40 /* unimplemented, fall through */
46 static void a9_scu_write(void *opaque
, hwaddr offset
,
47 uint64_t value
, unsigned size
)
49 A9SCUState
*s
= (A9SCUState
*)opaque
;
63 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
64 size
, (unsigned)offset
);
69 case 0x00: /* Control */
70 s
->control
= value
& 1;
72 case 0x4: /* Configuration: RO */
74 case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
75 shift
= (offset
- 0x8) * 8;
76 s
->status
&= ~(mask
<< shift
);
77 s
->status
|= ((value
& mask
) << shift
);
79 case 0x0c: /* Invalidate All Registers In Secure State */
80 /* no-op as we do not implement caches */
82 case 0x40: /* Filtering Start Address Register */
83 case 0x44: /* Filtering End Address Register */
84 /* RAZ/WI, like an implementation with only one AXI master */
86 case 0x50: /* SCU Access Control Register */
87 case 0x54: /* SCU Non-secure Access Control Register */
88 /* unimplemented, fall through */
94 static const MemoryRegionOps a9_scu_ops
= {
96 .write
= a9_scu_write
,
97 .endianness
= DEVICE_NATIVE_ENDIAN
,
100 static void a9_scu_reset(DeviceState
*dev
)
102 A9SCUState
*s
= A9_SCU(dev
);
106 static void a9_scu_init(Object
*obj
)
108 A9SCUState
*s
= A9_SCU(obj
);
109 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
111 memory_region_init_io(&s
->iomem
, obj
, &a9_scu_ops
, s
,
113 sysbus_init_mmio(sbd
, &s
->iomem
);
116 static const VMStateDescription vmstate_a9_scu
= {
119 .minimum_version_id
= 1,
120 .fields
= (VMStateField
[]) {
121 VMSTATE_UINT32(control
, A9SCUState
),
122 VMSTATE_UINT32(status
, A9SCUState
),
123 VMSTATE_END_OF_LIST()
127 static Property a9_scu_properties
[] = {
128 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
129 DEFINE_PROP_END_OF_LIST(),
132 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
134 DeviceClass
*dc
= DEVICE_CLASS(klass
);
136 dc
->props
= a9_scu_properties
;
137 dc
->vmsd
= &vmstate_a9_scu
;
138 dc
->reset
= a9_scu_reset
;
141 static const TypeInfo a9_scu_info
= {
143 .parent
= TYPE_SYS_BUS_DEVICE
,
144 .instance_size
= sizeof(A9SCUState
),
145 .instance_init
= a9_scu_init
,
146 .class_init
= a9_scu_class_init
,
149 static void a9mp_register_types(void)
151 type_register_static(&a9_scu_info
);
154 type_init(a9mp_register_types
)