Merge branch 'master' into raspi
[qemu/ar7.git] / hw / intc / bcm2835_ic.c.orig
blobbc8a370c7f8deb67b6d7311db0882af0270b8e88
1 /*
2  * Raspberry Pi emulation (c) 2012 Gregory Estrade
3 <<<<<<< HEAD
4 =======
5  * Refactoring for Pi2 Copyright (c) 2015, Microsoft. Written by Andrew Baumann.
6 >>>>>>> upstreaming-raspi
7  * This code is licensed under the GNU GPLv2 and later.
8  * Heavily based on pl190.c, copyright terms below:
9  *
10  * Arm PrimeCell PL190 Vector Interrupt Controller
11  *
12  * Copyright (c) 2006 CodeSourcery.
13  * Written by Paul Brook
14  *
15  * This code is licensed under the GPL.
16  */
18 #include "hw/intc/bcm2835_ic.h"
20 #define GPU_IRQS 64
21 #define ARM_IRQS 8
23 #define IRQ_PENDING_BASIC       0x00 /* IRQ basic pending */
24 #define IRQ_PENDING_1           0x04 /* IRQ pending 1 */
25 #define IRQ_PENDING_2           0x08 /* IRQ pending 2 */
26 #define FIQ_CONTROL             0x0C /* FIQ register */
27 #define IRQ_ENABLE_1            0x10 /* Interrupt enable register 1 */
28 #define IRQ_ENABLE_2            0x14 /* Interrupt enable register 2 */
29 #define IRQ_ENABLE_BASIC        0x18 /* Base interrupt enable register */
30 #define IRQ_DISABLE_1           0x1C /* Interrupt disable register 1 */
31 #define IRQ_DISABLE_2           0x20 /* Interrupt disable register 2 */
32 #define IRQ_DISABLE_BASIC       0x24 /* Base interrupt disable register */
34 /* Update interrupts.  */
35 static void bcm2835_ic_update(BCM2835ICState *s)
37     bool set = false;
39     if (s->fiq_enable) {
40         if (s->fiq_select >= GPU_IRQS) {
41             /* ARM IRQ */
42             set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
43         } else {
44             set = extract64(s->gpu_irq_level, s->fiq_select, 1);
45         }
46     }
47     qemu_set_irq(s->fiq, set);
49     set = (s->gpu_irq_level & s->gpu_irq_enable)
50         || (s->arm_irq_level & s->arm_irq_enable);
51     qemu_set_irq(s->irq, set);
55 static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
57     BCM2835ICState *s = opaque;
58 <<<<<<< HEAD
59 =======
61 >>>>>>> upstreaming-raspi
62     assert(irq >= 0 && irq < 64);
63     s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
64     bcm2835_ic_update(s);
67 static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
69     BCM2835ICState *s = opaque;
70 <<<<<<< HEAD
71 =======
73 >>>>>>> upstreaming-raspi
74     assert(irq >= 0 && irq < 8);
75     s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
76     bcm2835_ic_update(s);
79 static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };
81 static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset, unsigned size)
83     BCM2835ICState *s = opaque;
84     uint32_t res = 0;
85     uint64_t gpu_pending = s->gpu_irq_level & s->gpu_irq_enable;
86     int i;
88     switch (offset) {
89     case IRQ_PENDING_BASIC:
90         /* bits 0-7: ARM irqs */
91         res = s->arm_irq_level & s->arm_irq_enable;
93         /* bits 8 & 9: pending registers 1 & 2 */
94         res |= (((uint32_t)gpu_pending) != 0) << 8;
95         res |= ((gpu_pending >> 32) != 0) << 9;
97         /* bits 10-20: selected GPU IRQs */
98         for (i = 0; i < ARRAY_SIZE(irq_dups); i++) {
99             res |= extract64(gpu_pending, irq_dups[i], 1) << (i + 10);
100         }
101         break;
102 <<<<<<< HEAD
103     case IRQ_PENDING_1:  /* IRQ pending 1 */
104         res = gpu_pending;
105         break;
106     case IRQ_PENDING_2:  /* IRQ pending 2 */
107         res = gpu_pending >> 32;
108         break;
109     case FIQ_CONTROL:  /* FIQ register */
110         res = (s->fiq_enable << 7) | s->fiq_select;
111         break;
112     case IRQ_ENABLE_1:  /* Interrupt enable register 1 */
113         res = s->gpu_irq_enable;
114         break;
115     case IRQ_ENABLE_2:  /* Interrupt enable register 2 */
116         res = s->gpu_irq_enable >> 32;
117         break;
118     case IRQ_ENABLE_BASIC:  /* Base interrupt enable register */
119         res = s->arm_irq_enable;
120         break;
121     case IRQ_DISABLE_1:  /* Interrupt disable register 1 */
122         res = ~s->gpu_irq_enable;
123         break;
124     case IRQ_DISABLE_2:  /* Interrupt disable register 2 */
125         res = ~s->gpu_irq_enable >> 32;
126         break;
127     case IRQ_DISABLE_BASIC:  /* Base interrupt disable register */
128 =======
129     case IRQ_PENDING_1:
130         res = gpu_pending;
131         break;
132     case IRQ_PENDING_2:
133         res = gpu_pending >> 32;
134         break;
135     case FIQ_CONTROL:
136         res = (s->fiq_enable << 7) | s->fiq_select;
137         break;
138     case IRQ_ENABLE_1:
139         res = s->gpu_irq_enable;
140         break;
141     case IRQ_ENABLE_2:
142         res = s->gpu_irq_enable >> 32;
143         break;
144     case IRQ_ENABLE_BASIC:
145         res = s->arm_irq_enable;
146         break;
147     case IRQ_DISABLE_1:
148         res = ~s->gpu_irq_enable;
149         break;
150     case IRQ_DISABLE_2:
151         res = ~s->gpu_irq_enable >> 32;
152         break;
153     case IRQ_DISABLE_BASIC:
154 >>>>>>> upstreaming-raspi
155         res = ~s->arm_irq_enable;
156         break;
157     default:
158         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
159                       __func__, offset);
160         return 0;
161     }
163     return res;
166 static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
167                              unsigned size)
169     BCM2835ICState *s = opaque;
171     switch (offset) {
172     case FIQ_CONTROL:
173 <<<<<<< HEAD
174         s->fiq_select = (val & 0x7f);
175         s->fiq_enable = (val >> 7) & 0x1;
176 =======
177         s->fiq_select = extract32(val, 0, 7);
178         s->fiq_enable = extract32(val, 7, 1);
179 >>>>>>> upstreaming-raspi
180         break;
181     case IRQ_ENABLE_1:
182         s->gpu_irq_enable |= val;
183         break;
184     case IRQ_ENABLE_2:
185         s->gpu_irq_enable |= val << 32;
186         break;
187     case IRQ_ENABLE_BASIC:
188         s->arm_irq_enable |= val & 0xff;
189         break;
190     case IRQ_DISABLE_1:
191         s->gpu_irq_enable &= ~val;
192         break;
193     case IRQ_DISABLE_2:
194         s->gpu_irq_enable &= ~(val << 32);
195         break;
196     case IRQ_DISABLE_BASIC:
197         s->arm_irq_enable &= ~val & 0xff;
198         break;
199     default:
200         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
201                       __func__, offset);
202         return;
203     }
204     bcm2835_ic_update(s);
207 static const MemoryRegionOps bcm2835_ic_ops = {
208     .read = bcm2835_ic_read,
209     .write = bcm2835_ic_write,
210     .endianness = DEVICE_NATIVE_ENDIAN,
211     .valid.min_access_size = 4,
212     .valid.max_access_size = 4,
215 static void bcm2835_ic_reset(DeviceState *d)
217     BCM2835ICState *s = BCM2835_IC(d);
219     s->gpu_irq_enable = 0;
220     s->arm_irq_enable = 0;
221     s->fiq_enable = false;
222     s->fiq_select = 0;
225 static void bcm2835_ic_init(Object *obj)
227     BCM2835ICState *s = BCM2835_IC(obj);
229     memory_region_init_io(&s->iomem, obj, &bcm2835_ic_ops, s, TYPE_BCM2835_IC,
230                           0x200);
231     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
233     qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_gpu_irq,
234                             BCM2835_IC_GPU_IRQ, GPU_IRQS);
235     qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_arm_irq,
236                             BCM2835_IC_ARM_IRQ, ARM_IRQS);
238     sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
239     sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
242 static const VMStateDescription vmstate_bcm2835_ic = {
243     .name = TYPE_BCM2835_IC,
244     .version_id = 1,
245     .minimum_version_id = 1,
246     .fields = (VMStateField[]) {
247         VMSTATE_UINT64(gpu_irq_level, BCM2835ICState),
248         VMSTATE_UINT64(gpu_irq_enable, BCM2835ICState),
249         VMSTATE_UINT8(arm_irq_level, BCM2835ICState),
250         VMSTATE_UINT8(arm_irq_enable, BCM2835ICState),
251         VMSTATE_BOOL(fiq_enable, BCM2835ICState),
252         VMSTATE_UINT8(fiq_select, BCM2835ICState),
253         VMSTATE_END_OF_LIST()
254     }
257 static void bcm2835_ic_class_init(ObjectClass *klass, void *data)
259     DeviceClass *dc = DEVICE_CLASS(klass);
261     dc->reset = bcm2835_ic_reset;
262     dc->vmsd = &vmstate_bcm2835_ic;
265 static TypeInfo bcm2835_ic_info = {
266     .name          = TYPE_BCM2835_IC,
267     .parent        = TYPE_SYS_BUS_DEVICE,
268     .instance_size = sizeof(BCM2835ICState),
269     .class_init    = bcm2835_ic_class_init,
270     .instance_init = bcm2835_ic_init,
273 static void bcm2835_ic_register_types(void)
275     type_register_static(&bcm2835_ic_info);
278 type_init(bcm2835_ic_register_types)