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/misc/a9scu.h"
13 static uint64_t a9_scu_read(void *opaque
, hwaddr offset
,
16 A9SCUState
*s
= (A9SCUState
*)opaque
;
18 case 0x00: /* Control */
20 case 0x04: /* Configuration */
21 return (((1 << s
->num_cpu
) - 1) << 4) | (s
->num_cpu
- 1);
22 case 0x08: /* CPU Power Status */
24 case 0x09: /* CPU status. */
25 return s
->status
>> 8;
26 case 0x0a: /* CPU status. */
27 return s
->status
>> 16;
28 case 0x0b: /* CPU status. */
29 return s
->status
>> 24;
30 case 0x0c: /* Invalidate All Registers In Secure State */
32 case 0x40: /* Filtering Start Address Register */
33 case 0x44: /* Filtering End Address Register */
34 /* RAZ/WI, like an implementation with only one AXI master */
36 case 0x50: /* SCU Access Control Register */
37 case 0x54: /* SCU Non-secure Access Control Register */
38 /* unimplemented, fall through */
44 static void a9_scu_write(void *opaque
, hwaddr offset
,
45 uint64_t value
, unsigned size
)
47 A9SCUState
*s
= (A9SCUState
*)opaque
;
61 fprintf(stderr
, "Invalid size %u in write to a9 scu register %x\n",
62 size
, (unsigned)offset
);
67 case 0x00: /* Control */
68 s
->control
= value
& 1;
70 case 0x4: /* Configuration: RO */
72 case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
73 shift
= (offset
- 0x8) * 8;
74 s
->status
&= ~(mask
<< shift
);
75 s
->status
|= ((value
& mask
) << shift
);
77 case 0x0c: /* Invalidate All Registers In Secure State */
78 /* no-op as we do not implement caches */
80 case 0x40: /* Filtering Start Address Register */
81 case 0x44: /* Filtering End Address Register */
82 /* RAZ/WI, like an implementation with only one AXI master */
84 case 0x50: /* SCU Access Control Register */
85 case 0x54: /* SCU Non-secure Access Control Register */
86 /* unimplemented, fall through */
92 static const MemoryRegionOps a9_scu_ops
= {
94 .write
= a9_scu_write
,
95 .endianness
= DEVICE_NATIVE_ENDIAN
,
98 static void a9_scu_reset(DeviceState
*dev
)
100 A9SCUState
*s
= A9_SCU(dev
);
104 static void a9_scu_init(Object
*obj
)
106 A9SCUState
*s
= A9_SCU(obj
);
107 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
109 memory_region_init_io(&s
->iomem
, obj
, &a9_scu_ops
, s
,
111 sysbus_init_mmio(sbd
, &s
->iomem
);
114 static const VMStateDescription vmstate_a9_scu
= {
117 .minimum_version_id
= 1,
118 .fields
= (VMStateField
[]) {
119 VMSTATE_UINT32(control
, A9SCUState
),
120 VMSTATE_UINT32(status
, A9SCUState
),
121 VMSTATE_END_OF_LIST()
125 static Property a9_scu_properties
[] = {
126 DEFINE_PROP_UINT32("num-cpu", A9SCUState
, num_cpu
, 1),
127 DEFINE_PROP_END_OF_LIST(),
130 static void a9_scu_class_init(ObjectClass
*klass
, void *data
)
132 DeviceClass
*dc
= DEVICE_CLASS(klass
);
134 dc
->props
= a9_scu_properties
;
135 dc
->vmsd
= &vmstate_a9_scu
;
136 dc
->reset
= a9_scu_reset
;
139 static const TypeInfo a9_scu_info
= {
141 .parent
= TYPE_SYS_BUS_DEVICE
,
142 .instance_size
= sizeof(A9SCUState
),
143 .instance_init
= a9_scu_init
,
144 .class_init
= a9_scu_class_init
,
147 static void a9mp_register_types(void)
149 type_register_static(&a9_scu_info
);
152 type_init(a9mp_register_types
)