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 "hw/qdev-properties.h"
14 #include "migration/vmstate.h"
15 #include "qemu/module.h"
17 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
20 A9SCUState
*s
= (A9SCUState
*)opaque
;
22 case 0x00: /* Control */
24 case 0x04: /* Configuration */
25 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
26 case 0x08: /* CPU Power Status */
28 case 0x09: /* CPU status. */
29 return s
->status
>> 8;
30 case 0x0a: /* CPU status. */
31 return s
->status
>> 16;
32 case 0x0b: /* CPU status. */
33 return s
->status
>> 24;
34 case 0x0c: /* Invalidate All Registers In Secure State */
36 case 0x40: /* Filtering Start Address Register */
37 case 0x44: /* Filtering End Address Register */
38 /* RAZ/WI, like an implementation with only one AXI master */
40 case 0x50: /* SCU Access Control Register */
41 case 0x54: /* SCU Non-secure Access Control Register */
42 /* unimplemented, fall through */
48 static void a9_scu_write(void *opaque
, hwaddr offset
,
49 uint64_t value
, unsigned size
)
51 A9SCUState
*s
= (A9SCUState
*)opaque
;
65 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
66 size
, (unsigned)offset
);
71 case 0x00: /* Control */
72 s
->control
= value
& 1;
74 case 0x4: /* Configuration: RO */
76 case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
77 shift
= (offset
- 0x8) * 8;
78 s
->status
&= ~(mask
<< shift
);
79 s
->status
|= ((value
& mask
) << shift
);
81 case 0x0c: /* Invalidate All Registers In Secure State */
82 /* no-op as we do not implement caches */
84 case 0x40: /* Filtering Start Address Register */
85 case 0x44: /* Filtering End Address Register */
86 /* RAZ/WI, like an implementation with only one AXI master */
88 case 0x50: /* SCU Access Control Register */
89 case 0x54: /* SCU Non-secure Access Control Register */
90 /* unimplemented, fall through */
96 static const MemoryRegionOps a9_scu_ops
= {
98 .write
= a9_scu_write
,
99 .endianness
= DEVICE_NATIVE_ENDIAN
,
102 static void a9_scu_reset(DeviceState
*dev
)
104 A9SCUState
*s
= A9_SCU(dev
);
108 static void a9_scu_init(Object
*obj
)
110 A9SCUState
*s
= A9_SCU(obj
);
111 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
113 memory_region_init_io(&s
->iomem
, obj
, &a9_scu_ops
, s
,
115 sysbus_init_mmio(sbd
, &s
->iomem
);
118 static const VMStateDescription vmstate_a9_scu
= {
121 .minimum_version_id
= 1,
122 .fields
= (VMStateField
[]) {
123 VMSTATE_UINT32(control
, A9SCUState
),
124 VMSTATE_UINT32(status
, A9SCUState
),
125 VMSTATE_END_OF_LIST()
129 static Property a9_scu_properties
[] = {
130 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
131 DEFINE_PROP_END_OF_LIST(),
134 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
136 DeviceClass
*dc
= DEVICE_CLASS(klass
);
138 dc
->props
= a9_scu_properties
;
139 dc
->vmsd
= &vmstate_a9_scu
;
140 dc
->reset
= a9_scu_reset
;
143 static const TypeInfo a9_scu_info
= {
145 .parent
= TYPE_SYS_BUS_DEVICE
,
146 .instance_size
= sizeof(A9SCUState
),
147 .instance_init
= a9_scu_init
,
148 .class_init
= a9_scu_class_init
,
151 static void a9mp_register_types(void)
153 type_register_static(&a9_scu_info
);
156 type_init(a9mp_register_types
)