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"
14 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
17 A9SCUState
*s
= (A9SCUState
*)opaque
;
19 case 0x00: /* Control */
21 case 0x04: /* Configuration */
22 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
23 case 0x08: /* CPU Power 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 */
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 */
37 case 0x50: /* SCU Access Control Register */
38 case 0x54: /* SCU Non-secure Access Control Register */
39 /* unimplemented, fall through */
45 static void a9_scu_write(void *opaque
, hwaddr offset
,
46 uint64_t value
, unsigned size
)
48 A9SCUState
*s
= (A9SCUState
*)opaque
;
62 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
63 size
, (unsigned)offset
);
68 case 0x00: /* Control */
69 s
->control
= value
& 1;
71 case 0x4: /* Configuration: RO */
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
);
78 case 0x0c: /* Invalidate All Registers In Secure State */
79 /* no-op as we do not implement caches */
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 */
85 case 0x50: /* SCU Access Control Register */
86 case 0x54: /* SCU Non-secure Access Control Register */
87 /* unimplemented, fall through */
93 static const MemoryRegionOps a9_scu_ops
= {
95 .write
= a9_scu_write
,
96 .endianness
= DEVICE_NATIVE_ENDIAN
,
99 static void a9_scu_reset(DeviceState
*dev
)
101 A9SCUState
*s
= A9_SCU(dev
);
105 static void a9_scu_init(Object
*obj
)
107 A9SCUState
*s
= A9_SCU(obj
);
108 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
110 memory_region_init_io(&s
->iomem
, obj
, &a9_scu_ops
, s
,
112 sysbus_init_mmio(sbd
, &s
->iomem
);
115 static const VMStateDescription vmstate_a9_scu
= {
118 .minimum_version_id
= 1,
119 .fields
= (VMStateField
[]) {
120 VMSTATE_UINT32(control
, A9SCUState
),
121 VMSTATE_UINT32(status
, A9SCUState
),
122 VMSTATE_END_OF_LIST()
126 static Property a9_scu_properties
[] = {
127 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
128 DEFINE_PROP_END_OF_LIST(),
131 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
133 DeviceClass
*dc
= DEVICE_CLASS(klass
);
135 dc
->props
= a9_scu_properties
;
136 dc
->vmsd
= &vmstate_a9_scu
;
137 dc
->reset
= a9_scu_reset
;
140 static const TypeInfo a9_scu_info
= {
142 .parent
= TYPE_SYS_BUS_DEVICE
,
143 .instance_size
= sizeof(A9SCUState
),
144 .instance_init
= a9_scu_init
,
145 .class_init
= a9_scu_class_init
,
148 static void a9mp_register_types(void)
150 type_register_static(&a9_scu_info
);
153 type_init(a9mp_register_types
)