|
|
1.1.1.2 root 1: /*
2: * ARM Generic/Distributed Interrupt Controller
1.1 root 3: *
1.1.1.2 root 4: * Copyright (c) 2006-2007 CodeSourcery.
1.1 root 5: * Written by Paul Brook
6: *
1.1.1.8 root 7: * This code is licensed under the GPL.
1.1 root 8: */
9:
1.1.1.2 root 10: /* This file contains implementation code for the RealView EB interrupt
11: controller, MPCore distributed interrupt controller and ARMv7-M
12: Nested Vectored Interrupt Controller. */
1.1 root 13:
14: //#define DEBUG_GIC
15:
16: #ifdef DEBUG_GIC
1.1.1.4 root 17: #define DPRINTF(fmt, ...) \
18: do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
1.1 root 19: #else
1.1.1.4 root 20: #define DPRINTF(fmt, ...) do {} while(0)
1.1 root 21: #endif
22:
1.1.1.2 root 23: #ifdef NVIC
24: static const uint8_t gic_id[] =
25: { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
26: /* The NVIC has 16 internal vectors. However these are not exposed
27: through the normal GIC interface. */
28: #define GIC_BASE_IRQ 32
29: #else
1.1 root 30: static const uint8_t gic_id[] =
31: { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
1.1.1.2 root 32: #define GIC_BASE_IRQ 0
33: #endif
1.1 root 34:
1.1.1.4 root 35: #define FROM_SYSBUSGIC(type, dev) \
36: DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
37:
1.1 root 38: typedef struct gic_irq_state
39: {
1.1.1.9 ! root 40: /* The enable bits are only banked for per-cpu interrupts. */
! 41: unsigned enabled:NCPU;
1.1.1.2 root 42: unsigned pending:NCPU;
43: unsigned active:NCPU;
1.1.1.4 root 44: unsigned level:NCPU;
1.1.1.2 root 45: unsigned model:1; /* 0 = N:N, 1 = 1:N */
1.1 root 46: unsigned trigger:1; /* nonzero = edge triggered. */
47: } gic_irq_state;
48:
1.1.1.2 root 49: #define ALL_CPU_MASK ((1 << NCPU) - 1)
1.1.1.5 root 50: #if NCPU > 1
51: #define NUM_CPU(s) ((s)->num_cpu)
52: #else
53: #define NUM_CPU(s) 1
54: #endif
1.1.1.2 root 55:
1.1.1.9 ! root 56: #define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
! 57: #define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
! 58: #define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
1.1.1.2 root 59: #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
60: #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
61: #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
62: #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
63: #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
64: #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
1.1 root 65: #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
66: #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
67: #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
1.1.1.2 root 68: #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
69: #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
1.1.1.3 root 70: #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
1.1 root 71: #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
72: #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
73: #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
1.1.1.2 root 74: #define GIC_GET_PRIORITY(irq, cpu) \
75: (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
76: #ifdef NVIC
77: #define GIC_TARGET(irq) 1
78: #else
79: #define GIC_TARGET(irq) s->irq_target[irq]
80: #endif
1.1 root 81:
82: typedef struct gic_state
83: {
1.1.1.4 root 84: SysBusDevice busdev;
1.1.1.2 root 85: qemu_irq parent_irq[NCPU];
1.1 root 86: int enabled;
1.1.1.2 root 87: int cpu_enabled[NCPU];
1.1 root 88:
89: gic_irq_state irq_state[GIC_NIRQ];
1.1.1.2 root 90: #ifndef NVIC
1.1 root 91: int irq_target[GIC_NIRQ];
1.1.1.2 root 92: #endif
93: int priority1[32][NCPU];
94: int priority2[GIC_NIRQ - 32];
95: int last_active[GIC_NIRQ][NCPU];
96:
97: int priority_mask[NCPU];
98: int running_irq[NCPU];
99: int running_priority[NCPU];
100: int current_pending[NCPU];
101:
1.1.1.5 root 102: #if NCPU > 1
103: int num_cpu;
104: #endif
105:
1.1.1.9 ! root 106: MemoryRegion iomem;
1.1 root 107: } gic_state;
108:
109: /* TODO: Many places that call this routine could be optimized. */
110: /* Update interrupt status after enabled or pending bits have been changed. */
111: static void gic_update(gic_state *s)
112: {
113: int best_irq;
114: int best_prio;
115: int irq;
1.1.1.2 root 116: int level;
117: int cpu;
118: int cm;
1.1 root 119:
1.1.1.5 root 120: for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
1.1.1.2 root 121: cm = 1 << cpu;
122: s->current_pending[cpu] = 1023;
123: if (!s->enabled || !s->cpu_enabled[cpu]) {
124: qemu_irq_lower(s->parent_irq[cpu]);
125: return;
126: }
127: best_prio = 0x100;
128: best_irq = 1023;
129: for (irq = 0; irq < GIC_NIRQ; irq++) {
1.1.1.9 ! root 130: if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
1.1.1.2 root 131: if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
132: best_prio = GIC_GET_PRIORITY(irq, cpu);
133: best_irq = irq;
134: }
1.1 root 135: }
136: }
1.1.1.2 root 137: level = 0;
138: if (best_prio <= s->priority_mask[cpu]) {
139: s->current_pending[cpu] = best_irq;
140: if (best_prio < s->running_priority[cpu]) {
141: DPRINTF("Raised pending IRQ %d\n", best_irq);
142: level = 1;
143: }
1.1 root 144: }
1.1.1.2 root 145: qemu_set_irq(s->parent_irq[cpu], level);
1.1 root 146: }
147: }
148:
1.1.1.2 root 149: static void __attribute__((unused))
150: gic_set_pending_private(gic_state *s, int cpu, int irq)
151: {
152: int cm = 1 << cpu;
153:
154: if (GIC_TEST_PENDING(irq, cm))
155: return;
156:
157: DPRINTF("Set %d pending cpu %d\n", irq, cpu);
158: GIC_SET_PENDING(irq, cm);
159: gic_update(s);
160: }
161:
162: /* Process a change in an external IRQ input. */
1.1 root 163: static void gic_set_irq(void *opaque, int irq, int level)
164: {
165: gic_state *s = (gic_state *)opaque;
166: /* The first external input line is internal interrupt 32. */
167: irq += 32;
1.1.1.2 root 168: if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
1.1 root 169: return;
170:
171: if (level) {
1.1.1.2 root 172: GIC_SET_LEVEL(irq, ALL_CPU_MASK);
1.1.1.9 ! root 173: if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
1.1.1.2 root 174: DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
175: GIC_SET_PENDING(irq, GIC_TARGET(irq));
1.1 root 176: }
177: } else {
1.1.1.2 root 178: GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
1.1 root 179: }
180: gic_update(s);
181: }
182:
1.1.1.2 root 183: static void gic_set_running_irq(gic_state *s, int cpu, int irq)
1.1 root 184: {
1.1.1.2 root 185: s->running_irq[cpu] = irq;
186: if (irq == 1023) {
187: s->running_priority[cpu] = 0x100;
188: } else {
189: s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
190: }
1.1 root 191: gic_update(s);
192: }
193:
1.1.1.2 root 194: static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
1.1 root 195: {
196: int new_irq;
1.1.1.2 root 197: int cm = 1 << cpu;
198: new_irq = s->current_pending[cpu];
199: if (new_irq == 1023
200: || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
1.1 root 201: DPRINTF("ACK no pending IRQ\n");
202: return 1023;
203: }
1.1.1.2 root 204: s->last_active[new_irq][cpu] = s->running_irq[cpu];
205: /* Clear pending flags for both level and edge triggered interrupts.
206: Level triggered IRQs will be reasserted once they become inactive. */
207: GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
208: gic_set_running_irq(s, cpu, new_irq);
1.1 root 209: DPRINTF("ACK %d\n", new_irq);
210: return new_irq;
211: }
212:
1.1.1.2 root 213: static void gic_complete_irq(gic_state * s, int cpu, int irq)
1.1 root 214: {
215: int update = 0;
1.1.1.2 root 216: int cm = 1 << cpu;
1.1 root 217: DPRINTF("EOI %d\n", irq);
1.1.1.2 root 218: if (s->running_irq[cpu] == 1023)
1.1 root 219: return; /* No active IRQ. */
220: if (irq != 1023) {
221: /* Mark level triggered interrupts as pending if they are still
222: raised. */
1.1.1.9 ! root 223: if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
1.1.1.2 root 224: && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
225: DPRINTF("Set %d pending mask %x\n", irq, cm);
226: GIC_SET_PENDING(irq, cm);
1.1 root 227: update = 1;
228: }
229: }
1.1.1.2 root 230: if (irq != s->running_irq[cpu]) {
1.1 root 231: /* Complete an IRQ that is not currently running. */
1.1.1.2 root 232: int tmp = s->running_irq[cpu];
233: while (s->last_active[tmp][cpu] != 1023) {
234: if (s->last_active[tmp][cpu] == irq) {
235: s->last_active[tmp][cpu] = s->last_active[irq][cpu];
1.1 root 236: break;
237: }
1.1.1.2 root 238: tmp = s->last_active[tmp][cpu];
1.1 root 239: }
240: if (update) {
241: gic_update(s);
242: }
243: } else {
244: /* Complete the current running IRQ. */
1.1.1.2 root 245: gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
1.1 root 246: }
247: }
248:
249: static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
250: {
251: gic_state *s = (gic_state *)opaque;
252: uint32_t res;
253: int irq;
254: int i;
1.1.1.2 root 255: int cpu;
256: int cm;
257: int mask;
258:
259: cpu = gic_get_current_cpu();
260: cm = 1 << cpu;
1.1 root 261: if (offset < 0x100) {
1.1.1.2 root 262: #ifndef NVIC
1.1 root 263: if (offset == 0)
264: return s->enabled;
265: if (offset == 4)
1.1.1.5 root 266: return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
1.1 root 267: if (offset < 0x08)
268: return 0;
1.1.1.2 root 269: #endif
1.1 root 270: goto bad_reg;
271: } else if (offset < 0x200) {
272: /* Interrupt Set/Clear Enable. */
273: if (offset < 0x180)
274: irq = (offset - 0x100) * 8;
275: else
276: irq = (offset - 0x180) * 8;
1.1.1.2 root 277: irq += GIC_BASE_IRQ;
1.1 root 278: if (irq >= GIC_NIRQ)
279: goto bad_reg;
280: res = 0;
281: for (i = 0; i < 8; i++) {
1.1.1.9 ! root 282: if (GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 283: res |= (1 << i);
284: }
285: }
286: } else if (offset < 0x300) {
287: /* Interrupt Set/Clear Pending. */
288: if (offset < 0x280)
289: irq = (offset - 0x200) * 8;
290: else
291: irq = (offset - 0x280) * 8;
1.1.1.2 root 292: irq += GIC_BASE_IRQ;
1.1 root 293: if (irq >= GIC_NIRQ)
294: goto bad_reg;
295: res = 0;
1.1.1.2 root 296: mask = (irq < 32) ? cm : ALL_CPU_MASK;
1.1 root 297: for (i = 0; i < 8; i++) {
1.1.1.2 root 298: if (GIC_TEST_PENDING(irq + i, mask)) {
1.1 root 299: res |= (1 << i);
300: }
301: }
302: } else if (offset < 0x400) {
303: /* Interrupt Active. */
1.1.1.2 root 304: irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
1.1 root 305: if (irq >= GIC_NIRQ)
306: goto bad_reg;
307: res = 0;
1.1.1.2 root 308: mask = (irq < 32) ? cm : ALL_CPU_MASK;
1.1 root 309: for (i = 0; i < 8; i++) {
1.1.1.2 root 310: if (GIC_TEST_ACTIVE(irq + i, mask)) {
1.1 root 311: res |= (1 << i);
312: }
313: }
314: } else if (offset < 0x800) {
315: /* Interrupt Priority. */
1.1.1.2 root 316: irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1 root 317: if (irq >= GIC_NIRQ)
318: goto bad_reg;
1.1.1.2 root 319: res = GIC_GET_PRIORITY(irq, cpu);
320: #ifndef NVIC
1.1 root 321: } else if (offset < 0xc00) {
322: /* Interrupt CPU Target. */
1.1.1.2 root 323: irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1 root 324: if (irq >= GIC_NIRQ)
325: goto bad_reg;
1.1.1.2 root 326: if (irq >= 29 && irq <= 31) {
327: res = cm;
328: } else {
329: res = GIC_TARGET(irq);
330: }
1.1 root 331: } else if (offset < 0xf00) {
332: /* Interrupt Configuration. */
1.1.1.2 root 333: irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
1.1 root 334: if (irq >= GIC_NIRQ)
335: goto bad_reg;
336: res = 0;
337: for (i = 0; i < 4; i++) {
338: if (GIC_TEST_MODEL(irq + i))
339: res |= (1 << (i * 2));
340: if (GIC_TEST_TRIGGER(irq + i))
341: res |= (2 << (i * 2));
342: }
1.1.1.2 root 343: #endif
1.1 root 344: } else if (offset < 0xfe0) {
345: goto bad_reg;
346: } else /* offset >= 0xfe0 */ {
347: if (offset & 3) {
348: res = 0;
349: } else {
350: res = gic_id[(offset - 0xfe0) >> 2];
351: }
352: }
353: return res;
354: bad_reg:
1.1.1.4 root 355: hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
1.1 root 356: return 0;
357: }
358:
359: static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
360: {
361: uint32_t val;
362: val = gic_dist_readb(opaque, offset);
363: val |= gic_dist_readb(opaque, offset + 1) << 8;
364: return val;
365: }
366:
367: static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
368: {
369: uint32_t val;
1.1.1.2 root 370: #ifdef NVIC
371: gic_state *s = (gic_state *)opaque;
372: uint32_t addr;
1.1.1.3 root 373: addr = offset;
1.1.1.2 root 374: if (addr < 0x100 || addr > 0xd00)
1.1.1.4 root 375: return nvic_readl(s, addr);
1.1.1.2 root 376: #endif
1.1 root 377: val = gic_dist_readw(opaque, offset);
378: val |= gic_dist_readw(opaque, offset + 2) << 16;
379: return val;
380: }
381:
382: static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
383: uint32_t value)
384: {
385: gic_state *s = (gic_state *)opaque;
386: int irq;
387: int i;
1.1.1.2 root 388: int cpu;
1.1 root 389:
1.1.1.2 root 390: cpu = gic_get_current_cpu();
1.1 root 391: if (offset < 0x100) {
1.1.1.2 root 392: #ifdef NVIC
393: goto bad_reg;
394: #else
1.1 root 395: if (offset == 0) {
396: s->enabled = (value & 1);
397: DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
398: } else if (offset < 4) {
399: /* ignored. */
400: } else {
401: goto bad_reg;
402: }
1.1.1.2 root 403: #endif
1.1 root 404: } else if (offset < 0x180) {
405: /* Interrupt Set Enable. */
1.1.1.2 root 406: irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
1.1 root 407: if (irq >= GIC_NIRQ)
408: goto bad_reg;
1.1.1.2 root 409: if (irq < 16)
410: value = 0xff;
1.1 root 411: for (i = 0; i < 8; i++) {
412: if (value & (1 << i)) {
1.1.1.2 root 413: int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
1.1.1.9 ! root 414: int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
! 415:
! 416: if (!GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 417: DPRINTF("Enabled IRQ %d\n", irq + i);
1.1.1.9 ! root 418: }
! 419: GIC_SET_ENABLED(irq + i, cm);
1.1 root 420: /* If a raised level triggered IRQ enabled then mark
421: is as pending. */
1.1.1.2 root 422: if (GIC_TEST_LEVEL(irq + i, mask)
423: && !GIC_TEST_TRIGGER(irq + i)) {
424: DPRINTF("Set %d pending mask %x\n", irq + i, mask);
425: GIC_SET_PENDING(irq + i, mask);
426: }
1.1 root 427: }
428: }
429: } else if (offset < 0x200) {
430: /* Interrupt Clear Enable. */
1.1.1.2 root 431: irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
1.1 root 432: if (irq >= GIC_NIRQ)
433: goto bad_reg;
1.1.1.2 root 434: if (irq < 16)
435: value = 0;
1.1 root 436: for (i = 0; i < 8; i++) {
437: if (value & (1 << i)) {
1.1.1.9 ! root 438: int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
! 439:
! 440: if (GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 441: DPRINTF("Disabled IRQ %d\n", irq + i);
1.1.1.9 ! root 442: }
! 443: GIC_CLEAR_ENABLED(irq + i, cm);
1.1 root 444: }
445: }
446: } else if (offset < 0x280) {
447: /* Interrupt Set Pending. */
1.1.1.2 root 448: irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
1.1 root 449: if (irq >= GIC_NIRQ)
450: goto bad_reg;
1.1.1.2 root 451: if (irq < 16)
452: irq = 0;
453:
1.1 root 454: for (i = 0; i < 8; i++) {
455: if (value & (1 << i)) {
1.1.1.2 root 456: GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
1.1 root 457: }
458: }
459: } else if (offset < 0x300) {
460: /* Interrupt Clear Pending. */
1.1.1.2 root 461: irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
1.1 root 462: if (irq >= GIC_NIRQ)
463: goto bad_reg;
464: for (i = 0; i < 8; i++) {
1.1.1.2 root 465: /* ??? This currently clears the pending bit for all CPUs, even
466: for per-CPU interrupts. It's unclear whether this is the
467: corect behavior. */
1.1 root 468: if (value & (1 << i)) {
1.1.1.2 root 469: GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
1.1 root 470: }
471: }
472: } else if (offset < 0x400) {
473: /* Interrupt Active. */
474: goto bad_reg;
475: } else if (offset < 0x800) {
476: /* Interrupt Priority. */
1.1.1.2 root 477: irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1 root 478: if (irq >= GIC_NIRQ)
479: goto bad_reg;
1.1.1.2 root 480: if (irq < 32) {
481: s->priority1[irq][cpu] = value;
482: } else {
483: s->priority2[irq - 32] = value;
484: }
485: #ifndef NVIC
1.1 root 486: } else if (offset < 0xc00) {
487: /* Interrupt CPU Target. */
1.1.1.2 root 488: irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1 root 489: if (irq >= GIC_NIRQ)
490: goto bad_reg;
1.1.1.2 root 491: if (irq < 29)
492: value = 0;
493: else if (irq < 32)
494: value = ALL_CPU_MASK;
495: s->irq_target[irq] = value & ALL_CPU_MASK;
1.1 root 496: } else if (offset < 0xf00) {
497: /* Interrupt Configuration. */
1.1.1.2 root 498: irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
1.1 root 499: if (irq >= GIC_NIRQ)
500: goto bad_reg;
1.1.1.2 root 501: if (irq < 32)
502: value |= 0xaa;
1.1 root 503: for (i = 0; i < 4; i++) {
504: if (value & (1 << (i * 2))) {
505: GIC_SET_MODEL(irq + i);
506: } else {
507: GIC_CLEAR_MODEL(irq + i);
508: }
509: if (value & (2 << (i * 2))) {
510: GIC_SET_TRIGGER(irq + i);
511: } else {
512: GIC_CLEAR_TRIGGER(irq + i);
513: }
514: }
1.1.1.2 root 515: #endif
1.1 root 516: } else {
1.1.1.2 root 517: /* 0xf00 is only handled for 32-bit writes. */
1.1 root 518: goto bad_reg;
519: }
520: gic_update(s);
521: return;
522: bad_reg:
1.1.1.4 root 523: hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
1.1 root 524: }
525:
526: static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
527: uint32_t value)
528: {
529: gic_dist_writeb(opaque, offset, value & 0xff);
530: gic_dist_writeb(opaque, offset + 1, value >> 8);
531: }
532:
533: static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
534: uint32_t value)
535: {
1.1.1.2 root 536: gic_state *s = (gic_state *)opaque;
537: #ifdef NVIC
538: uint32_t addr;
1.1.1.3 root 539: addr = offset;
1.1.1.2 root 540: if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
1.1.1.4 root 541: nvic_writel(s, addr, value);
1.1.1.2 root 542: return;
543: }
544: #endif
1.1.1.3 root 545: if (offset == 0xf00) {
1.1.1.2 root 546: int cpu;
547: int irq;
548: int mask;
549:
550: cpu = gic_get_current_cpu();
551: irq = value & 0x3ff;
552: switch ((value >> 24) & 3) {
553: case 0:
554: mask = (value >> 16) & ALL_CPU_MASK;
555: break;
556: case 1:
1.1.1.8 root 557: mask = ALL_CPU_MASK ^ (1 << cpu);
1.1.1.2 root 558: break;
559: case 2:
1.1.1.8 root 560: mask = 1 << cpu;
1.1.1.2 root 561: break;
562: default:
563: DPRINTF("Bad Soft Int target filter\n");
564: mask = ALL_CPU_MASK;
565: break;
566: }
567: GIC_SET_PENDING(irq, mask);
568: gic_update(s);
569: return;
570: }
1.1 root 571: gic_dist_writew(opaque, offset, value & 0xffff);
572: gic_dist_writew(opaque, offset + 2, value >> 16);
573: }
574:
1.1.1.9 ! root 575: static const MemoryRegionOps gic_dist_ops = {
! 576: .old_mmio = {
! 577: .read = { gic_dist_readb, gic_dist_readw, gic_dist_readl, },
! 578: .write = { gic_dist_writeb, gic_dist_writew, gic_dist_writel, },
! 579: },
! 580: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 581: };
582:
1.1.1.2 root 583: #ifndef NVIC
584: static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
1.1 root 585: {
586: switch (offset) {
587: case 0x00: /* Control */
1.1.1.2 root 588: return s->cpu_enabled[cpu];
1.1 root 589: case 0x04: /* Priority mask */
1.1.1.2 root 590: return s->priority_mask[cpu];
1.1 root 591: case 0x08: /* Binary Point */
592: /* ??? Not implemented. */
593: return 0;
594: case 0x0c: /* Acknowledge */
1.1.1.2 root 595: return gic_acknowledge_irq(s, cpu);
1.1 root 596: case 0x14: /* Runing Priority */
1.1.1.2 root 597: return s->running_priority[cpu];
1.1 root 598: case 0x18: /* Highest Pending Interrupt */
1.1.1.2 root 599: return s->current_pending[cpu];
1.1 root 600: default:
1.1.1.4 root 601: hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
1.1 root 602: return 0;
603: }
604: }
605:
1.1.1.2 root 606: static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
1.1 root 607: {
608: switch (offset) {
609: case 0x00: /* Control */
1.1.1.2 root 610: s->cpu_enabled[cpu] = (value & 1);
1.1.1.5 root 611: DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
1.1 root 612: break;
613: case 0x04: /* Priority mask */
1.1.1.2 root 614: s->priority_mask[cpu] = (value & 0xff);
1.1 root 615: break;
616: case 0x08: /* Binary Point */
617: /* ??? Not implemented. */
618: break;
619: case 0x10: /* End Of Interrupt */
1.1.1.2 root 620: return gic_complete_irq(s, cpu, value & 0x3ff);
1.1 root 621: default:
1.1.1.4 root 622: hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
1.1 root 623: return;
624: }
625: gic_update(s);
626: }
1.1.1.2 root 627: #endif
1.1 root 628:
629: static void gic_reset(gic_state *s)
630: {
631: int i;
632: memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
1.1.1.5 root 633: for (i = 0 ; i < NUM_CPU(s); i++) {
1.1.1.2 root 634: s->priority_mask[i] = 0xf0;
635: s->current_pending[i] = 1023;
636: s->running_irq[i] = 1023;
637: s->running_priority[i] = 0x100;
638: #ifdef NVIC
639: /* The NVIC doesn't have per-cpu interfaces, so enable by default. */
640: s->cpu_enabled[i] = 1;
641: #else
642: s->cpu_enabled[i] = 0;
643: #endif
644: }
645: for (i = 0; i < 16; i++) {
1.1.1.9 ! root 646: GIC_SET_ENABLED(i, ALL_CPU_MASK);
1.1 root 647: GIC_SET_TRIGGER(i);
648: }
1.1.1.2 root 649: #ifdef NVIC
650: /* The NVIC is always enabled. */
651: s->enabled = 1;
652: #else
1.1 root 653: s->enabled = 0;
1.1.1.2 root 654: #endif
1.1 root 655: }
656:
1.1.1.3 root 657: static void gic_save(QEMUFile *f, void *opaque)
658: {
659: gic_state *s = (gic_state *)opaque;
660: int i;
661: int j;
662:
663: qemu_put_be32(f, s->enabled);
1.1.1.5 root 664: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3 root 665: qemu_put_be32(f, s->cpu_enabled[i]);
666: for (j = 0; j < 32; j++)
667: qemu_put_be32(f, s->priority1[j][i]);
668: for (j = 0; j < GIC_NIRQ; j++)
669: qemu_put_be32(f, s->last_active[j][i]);
670: qemu_put_be32(f, s->priority_mask[i]);
671: qemu_put_be32(f, s->running_irq[i]);
672: qemu_put_be32(f, s->running_priority[i]);
673: qemu_put_be32(f, s->current_pending[i]);
674: }
675: for (i = 0; i < GIC_NIRQ - 32; i++) {
676: qemu_put_be32(f, s->priority2[i]);
677: }
678: for (i = 0; i < GIC_NIRQ; i++) {
1.1.1.9 ! root 679: #ifndef NVIC
! 680: qemu_put_be32(f, s->irq_target[i]);
! 681: #endif
1.1.1.3 root 682: qemu_put_byte(f, s->irq_state[i].enabled);
683: qemu_put_byte(f, s->irq_state[i].pending);
684: qemu_put_byte(f, s->irq_state[i].active);
685: qemu_put_byte(f, s->irq_state[i].level);
686: qemu_put_byte(f, s->irq_state[i].model);
687: qemu_put_byte(f, s->irq_state[i].trigger);
688: }
689: }
690:
691: static int gic_load(QEMUFile *f, void *opaque, int version_id)
692: {
693: gic_state *s = (gic_state *)opaque;
694: int i;
695: int j;
696:
1.1.1.9 ! root 697: if (version_id != 2)
1.1.1.3 root 698: return -EINVAL;
699:
700: s->enabled = qemu_get_be32(f);
1.1.1.5 root 701: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3 root 702: s->cpu_enabled[i] = qemu_get_be32(f);
703: for (j = 0; j < 32; j++)
704: s->priority1[j][i] = qemu_get_be32(f);
705: for (j = 0; j < GIC_NIRQ; j++)
706: s->last_active[j][i] = qemu_get_be32(f);
707: s->priority_mask[i] = qemu_get_be32(f);
708: s->running_irq[i] = qemu_get_be32(f);
709: s->running_priority[i] = qemu_get_be32(f);
710: s->current_pending[i] = qemu_get_be32(f);
711: }
712: for (i = 0; i < GIC_NIRQ - 32; i++) {
713: s->priority2[i] = qemu_get_be32(f);
714: }
715: for (i = 0; i < GIC_NIRQ; i++) {
1.1.1.9 ! root 716: #ifndef NVIC
! 717: s->irq_target[i] = qemu_get_be32(f);
! 718: #endif
1.1.1.3 root 719: s->irq_state[i].enabled = qemu_get_byte(f);
720: s->irq_state[i].pending = qemu_get_byte(f);
721: s->irq_state[i].active = qemu_get_byte(f);
722: s->irq_state[i].level = qemu_get_byte(f);
723: s->irq_state[i].model = qemu_get_byte(f);
724: s->irq_state[i].trigger = qemu_get_byte(f);
725: }
726:
727: return 0;
728: }
729:
1.1.1.5 root 730: #if NCPU > 1
731: static void gic_init(gic_state *s, int num_cpu)
732: #else
1.1.1.4 root 733: static void gic_init(gic_state *s)
1.1.1.5 root 734: #endif
1.1 root 735: {
1.1.1.2 root 736: int i;
1.1 root 737:
1.1.1.5 root 738: #if NCPU > 1
739: s->num_cpu = num_cpu;
740: #endif
1.1.1.4 root 741: qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
1.1.1.5 root 742: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.4 root 743: sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
1.1.1.2 root 744: }
1.1.1.9 ! root 745: memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
1.1 root 746: gic_reset(s);
1.1.1.9 ! root 747: register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
1.1 root 748: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.