Merge tag 'v3.0.0-rc2'
[qemu/ar7.git] / hw / misc / bcm2835_mphi.c
blobaee62a172ff6620b8e830205beb22b74e48e1092
1 /*
2 * Raspberry Pi emulation (c) 2012 Gregory Estrade
3 * This code is licensed under the GNU GPLv2 and later.
4 */
6 #include "qemu/osdep.h"
7 #include "qemu/log.h"
8 #include "hw/misc/bcm2835_mphi.h"
10 static void bcm2835_mphi_update_irq(BCM2835MphiState *s)
12 if (s->mphi_intstat) {
13 qemu_set_irq(s->irq, 1);
14 } else {
15 qemu_set_irq(s->irq, 0);
19 static uint64_t bcm2835_mphi_read(void *opaque, hwaddr offset,
20 unsigned size)
22 BCM2835MphiState *s = (BCM2835MphiState *)opaque;
23 uint32_t res = 0;
25 assert(size == 4);
27 switch (offset) {
28 case 0x00: /* mphi_base */
29 res = s->mphi_base;
30 break;
31 case 0x28: /* mphi_outdda */
32 res = s->mphi_outdda;
33 break;
34 case 0x2c: /* mphi_outddb */
35 res = s->mphi_outddb;
36 break;
37 case 0x4c: /* mphi_ctrl */
38 res = s->mphi_ctrl;
39 break;
40 case 0x50: /* mphi_intstat */
41 res = s->mphi_intstat;
42 break;
44 default:
45 qemu_log_mask(LOG_GUEST_ERROR,
46 "bcm2835_mphi_read: Bad offset %x\n", (int)offset);
47 res = 0;
48 break;
51 return res;
54 static void bcm2835_mphi_write(void *opaque, hwaddr offset,
55 uint64_t value, unsigned size)
57 BCM2835MphiState *s = (BCM2835MphiState *)opaque;
58 int set_irq = 0;
60 assert(size == 4);
62 switch (offset) {
63 case 0x00: /* mphi_base */
64 s->mphi_base = value;
65 break;
66 case 0x28: /* mphi_outdda */
67 s->mphi_outdda = value;
68 break;
69 case 0x2c: /* mphi_outddb */
70 s->mphi_outddb = value;
71 if (value & (1 << 29)) {
72 /* Enable MPHI interrupt */
73 s->mphi_intstat |= (1 << 16);
74 set_irq = 1;
76 break;
77 case 0x4c: /* mphi_ctrl */
78 s->mphi_ctrl &= ~(1 << 31);
79 s->mphi_ctrl |= value & (1 << 31);
81 s->mphi_ctrl &= ~(3 << 16);
82 if (value & (1 << 16)) {
83 s->mphi_ctrl |= (3 << 16);
86 break;
87 case 0x50: /* mphi_intstat */
88 s->mphi_intstat &= ~value;
89 set_irq = 1;
90 break;
92 default:
93 qemu_log_mask(LOG_GUEST_ERROR,
94 "bcm2835_mphi_write: Bad offset %x\n", (int)offset);
95 break;
98 if (set_irq) {
99 bcm2835_mphi_update_irq(s);
103 static const MemoryRegionOps bcm2835_mphi_ops = {
104 .read = bcm2835_mphi_read,
105 .write = bcm2835_mphi_write,
106 .endianness = DEVICE_NATIVE_ENDIAN,
109 static const VMStateDescription vmstate_bcm2835_mphi = {
110 .name = TYPE_BCM2835_MPHI,
111 .version_id = 1,
112 .minimum_version_id = 1,
113 .minimum_version_id_old = 1,
114 .fields = (VMStateField[]) {
115 VMSTATE_END_OF_LIST()
119 static void bcm2835_mphi_init(Object *obj)
121 BCM2835MphiState *s = BCM2835_MPHI(obj);
123 memory_region_init_io(&s->iomem, obj, &bcm2835_mphi_ops, s,
124 TYPE_BCM2835_MPHI, 0x1000);
125 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
126 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
129 static void bcm2835_mphi_realize(DeviceState *dev, Error **errp)
131 BCM2835MphiState *s = BCM2835_MPHI(dev);
133 s->mphi_base = 0;
134 s->mphi_ctrl = 0;
135 s->mphi_outdda = 0;
136 s->mphi_outddb = 0;
137 s->mphi_intstat = 0;
140 static void bcm2835_mphi_class_init(ObjectClass *klass, void *data)
142 DeviceClass *dc = DEVICE_CLASS(klass);
144 dc->realize = bcm2835_mphi_realize;
145 dc->vmsd = &vmstate_bcm2835_mphi;
148 static TypeInfo bcm2835_mphi_info = {
149 .name = TYPE_BCM2835_MPHI,
150 .parent = TYPE_SYS_BUS_DEVICE,
151 .instance_size = sizeof(BCM2835MphiState),
152 .class_init = bcm2835_mphi_class_init,
153 .instance_init = bcm2835_mphi_init,
156 static void bcm2835_mphi_register_types(void)
158 type_register_static(&bcm2835_mphi_info);
161 type_init(bcm2835_mphi_register_types)