18
#include "qemu/osdep.h"
20
#include "qemu/module.h"
22
#include "qapi/error.h"
24
#include "migration/vmstate.h"
25
#include "hw/registerfields.h"
27
#include "hw/misc/armsse-mhu.h"
29
REG32(CPU0INTR_STAT, 0x0)
30
REG32(CPU0INTR_SET, 0x4)
31
REG32(CPU0INTR_CLR, 0x8)
32
REG32(CPU1INTR_STAT, 0x10)
33
REG32(CPU1INTR_SET, 0x14)
34
REG32(CPU1INTR_CLR, 0x18)
52
static const int armsse_mhu_id[] = {
53
0x04, 0x00, 0x00, 0x00,
54
0x56, 0xb8, 0x0b, 0x00,
55
0x0d, 0xf0, 0x05, 0xb1,
58
static void armsse_mhu_update(ARMSSEMHU *s)
60
qemu_set_irq(s->cpu0irq, s->cpu0intr != 0);
61
qemu_set_irq(s->cpu1irq, s->cpu1intr != 0);
64
static uint64_t armsse_mhu_read(void *opaque, hwaddr offset, unsigned size)
66
ARMSSEMHU *s = ARMSSE_MHU(opaque);
78
case A_PID4 ... A_CID3:
79
r = armsse_mhu_id[(offset - A_PID4) / 4];
86
qemu_log_mask(LOG_GUEST_ERROR,
87
"SSE MHU: read of write-only register at offset 0x%x\n",
93
qemu_log_mask(LOG_GUEST_ERROR,
94
"SSE MHU read: bad offset 0x%x\n", (int)offset);
98
trace_armsse_mhu_read(offset, r, size);
102
static void armsse_mhu_write(void *opaque, hwaddr offset,
103
uint64_t value, unsigned size)
105
ARMSSEMHU *s = ARMSSE_MHU(opaque);
107
trace_armsse_mhu_write(offset, value, size);
111
s->cpu0intr |= (value & INTR_MASK);
114
s->cpu0intr &= ~(value & INTR_MASK);
117
s->cpu1intr |= (value & INTR_MASK);
120
s->cpu1intr &= ~(value & INTR_MASK);
123
case A_CPU0INTR_STAT:
124
case A_CPU1INTR_STAT:
125
case A_PID4 ... A_CID3:
126
qemu_log_mask(LOG_GUEST_ERROR,
127
"SSE MHU: write to read-only register at offset 0x%x\n",
132
qemu_log_mask(LOG_GUEST_ERROR,
133
"SSE MHU write: bad offset 0x%x\n", (int)offset);
137
armsse_mhu_update(s);
140
static const MemoryRegionOps armsse_mhu_ops = {
141
.read = armsse_mhu_read,
142
.write = armsse_mhu_write,
143
.endianness = DEVICE_LITTLE_ENDIAN,
144
.valid.min_access_size = 4,
145
.valid.max_access_size = 4,
148
static void armsse_mhu_reset(DeviceState *dev)
150
ARMSSEMHU *s = ARMSSE_MHU(dev);
156
static const VMStateDescription armsse_mhu_vmstate = {
157
.name = "armsse-mhu",
159
.minimum_version_id = 1,
160
.fields = (const VMStateField[]) {
161
VMSTATE_UINT32(cpu0intr, ARMSSEMHU),
162
VMSTATE_UINT32(cpu1intr, ARMSSEMHU),
163
VMSTATE_END_OF_LIST()
167
static void armsse_mhu_init(Object *obj)
169
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
170
ARMSSEMHU *s = ARMSSE_MHU(obj);
172
memory_region_init_io(&s->iomem, obj, &armsse_mhu_ops,
173
s, "armsse-mhu", 0x1000);
174
sysbus_init_mmio(sbd, &s->iomem);
175
sysbus_init_irq(sbd, &s->cpu0irq);
176
sysbus_init_irq(sbd, &s->cpu1irq);
179
static void armsse_mhu_class_init(ObjectClass *klass, void *data)
181
DeviceClass *dc = DEVICE_CLASS(klass);
183
dc->reset = armsse_mhu_reset;
184
dc->vmsd = &armsse_mhu_vmstate;
187
static const TypeInfo armsse_mhu_info = {
188
.name = TYPE_ARMSSE_MHU,
189
.parent = TYPE_SYS_BUS_DEVICE,
190
.instance_size = sizeof(ARMSSEMHU),
191
.instance_init = armsse_mhu_init,
192
.class_init = armsse_mhu_class_init,
195
static void armsse_mhu_register_types(void)
197
type_register_static(&armsse_mhu_info);
200
type_init(armsse_mhu_register_types);