|
|
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
1.1.1.10! root 11: * controller, MPCore distributed interrupt controller and ARMv7-M
! 12: * Nested Vectored Interrupt Controller.
! 13: * It is compiled in two ways:
! 14: * (1) as a standalone file to produce a sysbus device which is a GIC
! 15: * that can be used on the realview board and as one of the builtin
! 16: * private peripherals for the ARM MP CPUs (11MPCore, A9, etc)
! 17: * (2) by being directly #included into armv7m_nvic.c to produce the
! 18: * armv7m_nvic device.
! 19: */
! 20:
! 21: #include "sysbus.h"
! 22:
! 23: /* Maximum number of possible interrupts, determined by the GIC architecture */
! 24: #define GIC_MAXIRQ 1020
! 25: /* First 32 are private to each CPU (SGIs and PPIs). */
! 26: #define GIC_INTERNAL 32
! 27: /* Maximum number of possible CPU interfaces, determined by GIC architecture */
! 28: #ifdef NVIC
! 29: #define NCPU 1
! 30: #else
! 31: #define NCPU 8
! 32: #endif
1.1 root 33:
34: //#define DEBUG_GIC
35:
36: #ifdef DEBUG_GIC
1.1.1.4 root 37: #define DPRINTF(fmt, ...) \
38: do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
1.1 root 39: #else
1.1.1.4 root 40: #define DPRINTF(fmt, ...) do {} while(0)
1.1 root 41: #endif
42:
1.1.1.2 root 43: #ifdef NVIC
44: static const uint8_t gic_id[] =
45: { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
46: /* The NVIC has 16 internal vectors. However these are not exposed
47: through the normal GIC interface. */
48: #define GIC_BASE_IRQ 32
49: #else
1.1 root 50: static const uint8_t gic_id[] =
51: { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
1.1.1.2 root 52: #define GIC_BASE_IRQ 0
53: #endif
1.1 root 54:
1.1.1.4 root 55: #define FROM_SYSBUSGIC(type, dev) \
56: DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
57:
1.1 root 58: typedef struct gic_irq_state
59: {
1.1.1.9 root 60: /* The enable bits are only banked for per-cpu interrupts. */
61: unsigned enabled:NCPU;
1.1.1.2 root 62: unsigned pending:NCPU;
63: unsigned active:NCPU;
1.1.1.4 root 64: unsigned level:NCPU;
1.1.1.2 root 65: unsigned model:1; /* 0 = N:N, 1 = 1:N */
1.1 root 66: unsigned trigger:1; /* nonzero = edge triggered. */
67: } gic_irq_state;
68:
1.1.1.10! root 69: #define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
1.1.1.5 root 70: #if NCPU > 1
71: #define NUM_CPU(s) ((s)->num_cpu)
72: #else
73: #define NUM_CPU(s) 1
74: #endif
1.1.1.2 root 75:
1.1.1.9 root 76: #define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
77: #define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
78: #define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
1.1.1.2 root 79: #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
80: #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
81: #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
82: #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
83: #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
84: #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
1.1 root 85: #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
86: #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
87: #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
1.1.1.2 root 88: #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
89: #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
1.1.1.3 root 90: #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
1.1 root 91: #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
92: #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
93: #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
1.1.1.10! root 94: #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
! 95: s->priority1[irq][cpu] : \
! 96: s->priority2[(irq) - GIC_INTERNAL])
1.1.1.2 root 97: #ifdef NVIC
98: #define GIC_TARGET(irq) 1
99: #else
100: #define GIC_TARGET(irq) s->irq_target[irq]
101: #endif
1.1 root 102:
103: typedef struct gic_state
104: {
1.1.1.4 root 105: SysBusDevice busdev;
1.1.1.2 root 106: qemu_irq parent_irq[NCPU];
1.1 root 107: int enabled;
1.1.1.2 root 108: int cpu_enabled[NCPU];
1.1 root 109:
1.1.1.10! root 110: gic_irq_state irq_state[GIC_MAXIRQ];
1.1.1.2 root 111: #ifndef NVIC
1.1.1.10! root 112: int irq_target[GIC_MAXIRQ];
1.1.1.2 root 113: #endif
1.1.1.10! root 114: int priority1[GIC_INTERNAL][NCPU];
! 115: int priority2[GIC_MAXIRQ - GIC_INTERNAL];
! 116: int last_active[GIC_MAXIRQ][NCPU];
1.1.1.2 root 117:
118: int priority_mask[NCPU];
119: int running_irq[NCPU];
120: int running_priority[NCPU];
121: int current_pending[NCPU];
122:
1.1.1.5 root 123: #if NCPU > 1
1.1.1.10! root 124: uint32_t num_cpu;
1.1.1.5 root 125: #endif
126:
1.1.1.10! root 127: MemoryRegion iomem; /* Distributor */
! 128: #ifndef NVIC
! 129: /* This is just so we can have an opaque pointer which identifies
! 130: * both this GIC and which CPU interface we should be accessing.
! 131: */
! 132: struct gic_state *backref[NCPU];
! 133: MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
! 134: #endif
! 135: uint32_t num_irq;
1.1 root 136: } gic_state;
137:
1.1.1.10! root 138: static inline int gic_get_current_cpu(gic_state *s)
! 139: {
! 140: #if NCPU > 1
! 141: if (s->num_cpu > 1) {
! 142: return cpu_single_env->cpu_index;
! 143: }
! 144: #endif
! 145: return 0;
! 146: }
! 147:
1.1 root 148: /* TODO: Many places that call this routine could be optimized. */
149: /* Update interrupt status after enabled or pending bits have been changed. */
150: static void gic_update(gic_state *s)
151: {
152: int best_irq;
153: int best_prio;
154: int irq;
1.1.1.2 root 155: int level;
156: int cpu;
157: int cm;
1.1 root 158:
1.1.1.5 root 159: for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
1.1.1.2 root 160: cm = 1 << cpu;
161: s->current_pending[cpu] = 1023;
162: if (!s->enabled || !s->cpu_enabled[cpu]) {
1.1.1.10! root 163: qemu_irq_lower(s->parent_irq[cpu]);
1.1.1.2 root 164: return;
165: }
166: best_prio = 0x100;
167: best_irq = 1023;
1.1.1.10! root 168: for (irq = 0; irq < s->num_irq; irq++) {
1.1.1.9 root 169: if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
1.1.1.2 root 170: if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
171: best_prio = GIC_GET_PRIORITY(irq, cpu);
172: best_irq = irq;
173: }
1.1 root 174: }
175: }
1.1.1.2 root 176: level = 0;
177: if (best_prio <= s->priority_mask[cpu]) {
178: s->current_pending[cpu] = best_irq;
179: if (best_prio < s->running_priority[cpu]) {
180: DPRINTF("Raised pending IRQ %d\n", best_irq);
181: level = 1;
182: }
1.1 root 183: }
1.1.1.2 root 184: qemu_set_irq(s->parent_irq[cpu], level);
1.1 root 185: }
186: }
187:
1.1.1.10! root 188: #ifdef NVIC
! 189: static void gic_set_pending_private(gic_state *s, int cpu, int irq)
1.1.1.2 root 190: {
191: int cm = 1 << cpu;
192:
193: if (GIC_TEST_PENDING(irq, cm))
194: return;
195:
196: DPRINTF("Set %d pending cpu %d\n", irq, cpu);
197: GIC_SET_PENDING(irq, cm);
198: gic_update(s);
199: }
1.1.1.10! root 200: #endif
1.1.1.2 root 201:
202: /* Process a change in an external IRQ input. */
1.1 root 203: static void gic_set_irq(void *opaque, int irq, int level)
204: {
1.1.1.10! root 205: /* Meaning of the 'irq' parameter:
! 206: * [0..N-1] : external interrupts
! 207: * [N..N+31] : PPI (internal) interrupts for CPU 0
! 208: * [N+32..N+63] : PPI (internal interrupts for CPU 1
! 209: * ...
! 210: */
1.1 root 211: gic_state *s = (gic_state *)opaque;
1.1.1.10! root 212: int cm, target;
! 213: if (irq < (s->num_irq - GIC_INTERNAL)) {
! 214: /* The first external input line is internal interrupt 32. */
! 215: cm = ALL_CPU_MASK;
! 216: irq += GIC_INTERNAL;
! 217: target = GIC_TARGET(irq);
! 218: } else {
! 219: int cpu;
! 220: irq -= (s->num_irq - GIC_INTERNAL);
! 221: cpu = irq / GIC_INTERNAL;
! 222: irq %= GIC_INTERNAL;
! 223: cm = 1 << cpu;
! 224: target = cm;
! 225: }
! 226:
! 227: if (level == GIC_TEST_LEVEL(irq, cm)) {
1.1 root 228: return;
1.1.1.10! root 229: }
1.1 root 230:
231: if (level) {
1.1.1.10! root 232: GIC_SET_LEVEL(irq, cm);
! 233: if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
! 234: DPRINTF("Set %d pending mask %x\n", irq, target);
! 235: GIC_SET_PENDING(irq, target);
1.1 root 236: }
237: } else {
1.1.1.10! root 238: GIC_CLEAR_LEVEL(irq, cm);
1.1 root 239: }
240: gic_update(s);
241: }
242:
1.1.1.2 root 243: static void gic_set_running_irq(gic_state *s, int cpu, int irq)
1.1 root 244: {
1.1.1.2 root 245: s->running_irq[cpu] = irq;
246: if (irq == 1023) {
247: s->running_priority[cpu] = 0x100;
248: } else {
249: s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
250: }
1.1 root 251: gic_update(s);
252: }
253:
1.1.1.2 root 254: static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
1.1 root 255: {
256: int new_irq;
1.1.1.2 root 257: int cm = 1 << cpu;
258: new_irq = s->current_pending[cpu];
259: if (new_irq == 1023
260: || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
1.1 root 261: DPRINTF("ACK no pending IRQ\n");
262: return 1023;
263: }
1.1.1.2 root 264: s->last_active[new_irq][cpu] = s->running_irq[cpu];
265: /* Clear pending flags for both level and edge triggered interrupts.
266: Level triggered IRQs will be reasserted once they become inactive. */
267: GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
268: gic_set_running_irq(s, cpu, new_irq);
1.1 root 269: DPRINTF("ACK %d\n", new_irq);
270: return new_irq;
271: }
272:
1.1.1.2 root 273: static void gic_complete_irq(gic_state * s, int cpu, int irq)
1.1 root 274: {
275: int update = 0;
1.1.1.2 root 276: int cm = 1 << cpu;
1.1 root 277: DPRINTF("EOI %d\n", irq);
1.1.1.10! root 278: if (irq >= s->num_irq) {
! 279: /* This handles two cases:
! 280: * 1. If software writes the ID of a spurious interrupt [ie 1023]
! 281: * to the GICC_EOIR, the GIC ignores that write.
! 282: * 2. If software writes the number of a non-existent interrupt
! 283: * this must be a subcase of "value written does not match the last
! 284: * valid interrupt value read from the Interrupt Acknowledge
! 285: * register" and so this is UNPREDICTABLE. We choose to ignore it.
! 286: */
! 287: return;
! 288: }
1.1.1.2 root 289: if (s->running_irq[cpu] == 1023)
1.1 root 290: return; /* No active IRQ. */
1.1.1.10! root 291: /* Mark level triggered interrupts as pending if they are still
! 292: raised. */
! 293: if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
! 294: && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
! 295: DPRINTF("Set %d pending mask %x\n", irq, cm);
! 296: GIC_SET_PENDING(irq, cm);
! 297: update = 1;
1.1 root 298: }
1.1.1.2 root 299: if (irq != s->running_irq[cpu]) {
1.1 root 300: /* Complete an IRQ that is not currently running. */
1.1.1.2 root 301: int tmp = s->running_irq[cpu];
302: while (s->last_active[tmp][cpu] != 1023) {
303: if (s->last_active[tmp][cpu] == irq) {
304: s->last_active[tmp][cpu] = s->last_active[irq][cpu];
1.1 root 305: break;
306: }
1.1.1.2 root 307: tmp = s->last_active[tmp][cpu];
1.1 root 308: }
309: if (update) {
310: gic_update(s);
311: }
312: } else {
313: /* Complete the current running IRQ. */
1.1.1.2 root 314: gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
1.1 root 315: }
316: }
317:
318: static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
319: {
320: gic_state *s = (gic_state *)opaque;
321: uint32_t res;
322: int irq;
323: int i;
1.1.1.2 root 324: int cpu;
325: int cm;
326: int mask;
327:
1.1.1.10! root 328: cpu = gic_get_current_cpu(s);
1.1.1.2 root 329: cm = 1 << cpu;
1.1 root 330: if (offset < 0x100) {
1.1.1.2 root 331: #ifndef NVIC
1.1 root 332: if (offset == 0)
333: return s->enabled;
334: if (offset == 4)
1.1.1.10! root 335: return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
1.1 root 336: if (offset < 0x08)
337: return 0;
1.1.1.10! root 338: if (offset >= 0x80) {
! 339: /* Interrupt Security , RAZ/WI */
! 340: return 0;
! 341: }
1.1.1.2 root 342: #endif
1.1 root 343: goto bad_reg;
344: } else if (offset < 0x200) {
345: /* Interrupt Set/Clear Enable. */
346: if (offset < 0x180)
347: irq = (offset - 0x100) * 8;
348: else
349: irq = (offset - 0x180) * 8;
1.1.1.2 root 350: irq += GIC_BASE_IRQ;
1.1.1.10! root 351: if (irq >= s->num_irq)
1.1 root 352: goto bad_reg;
353: res = 0;
354: for (i = 0; i < 8; i++) {
1.1.1.9 root 355: if (GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 356: res |= (1 << i);
357: }
358: }
359: } else if (offset < 0x300) {
360: /* Interrupt Set/Clear Pending. */
361: if (offset < 0x280)
362: irq = (offset - 0x200) * 8;
363: else
364: irq = (offset - 0x280) * 8;
1.1.1.2 root 365: irq += GIC_BASE_IRQ;
1.1.1.10! root 366: if (irq >= s->num_irq)
1.1 root 367: goto bad_reg;
368: res = 0;
1.1.1.10! root 369: mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
1.1 root 370: for (i = 0; i < 8; i++) {
1.1.1.2 root 371: if (GIC_TEST_PENDING(irq + i, mask)) {
1.1 root 372: res |= (1 << i);
373: }
374: }
375: } else if (offset < 0x400) {
376: /* Interrupt Active. */
1.1.1.2 root 377: irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
1.1.1.10! root 378: if (irq >= s->num_irq)
1.1 root 379: goto bad_reg;
380: res = 0;
1.1.1.10! root 381: mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
1.1 root 382: for (i = 0; i < 8; i++) {
1.1.1.2 root 383: if (GIC_TEST_ACTIVE(irq + i, mask)) {
1.1 root 384: res |= (1 << i);
385: }
386: }
387: } else if (offset < 0x800) {
388: /* Interrupt Priority. */
1.1.1.2 root 389: irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1.1.10! root 390: if (irq >= s->num_irq)
1.1 root 391: goto bad_reg;
1.1.1.2 root 392: res = GIC_GET_PRIORITY(irq, cpu);
393: #ifndef NVIC
1.1 root 394: } else if (offset < 0xc00) {
395: /* Interrupt CPU Target. */
1.1.1.2 root 396: irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1.1.10! root 397: if (irq >= s->num_irq)
1.1 root 398: goto bad_reg;
1.1.1.2 root 399: if (irq >= 29 && irq <= 31) {
400: res = cm;
401: } else {
402: res = GIC_TARGET(irq);
403: }
1.1 root 404: } else if (offset < 0xf00) {
405: /* Interrupt Configuration. */
1.1.1.2 root 406: irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
1.1.1.10! root 407: if (irq >= s->num_irq)
1.1 root 408: goto bad_reg;
409: res = 0;
410: for (i = 0; i < 4; i++) {
411: if (GIC_TEST_MODEL(irq + i))
412: res |= (1 << (i * 2));
413: if (GIC_TEST_TRIGGER(irq + i))
414: res |= (2 << (i * 2));
415: }
1.1.1.2 root 416: #endif
1.1 root 417: } else if (offset < 0xfe0) {
418: goto bad_reg;
419: } else /* offset >= 0xfe0 */ {
420: if (offset & 3) {
421: res = 0;
422: } else {
423: res = gic_id[(offset - 0xfe0) >> 2];
424: }
425: }
426: return res;
427: bad_reg:
1.1.1.4 root 428: hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
1.1 root 429: return 0;
430: }
431:
432: static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
433: {
434: uint32_t val;
435: val = gic_dist_readb(opaque, offset);
436: val |= gic_dist_readb(opaque, offset + 1) << 8;
437: return val;
438: }
439:
440: static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
441: {
442: uint32_t val;
1.1.1.2 root 443: #ifdef NVIC
444: gic_state *s = (gic_state *)opaque;
445: uint32_t addr;
1.1.1.3 root 446: addr = offset;
1.1.1.2 root 447: if (addr < 0x100 || addr > 0xd00)
1.1.1.4 root 448: return nvic_readl(s, addr);
1.1.1.2 root 449: #endif
1.1 root 450: val = gic_dist_readw(opaque, offset);
451: val |= gic_dist_readw(opaque, offset + 2) << 16;
452: return val;
453: }
454:
455: static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
456: uint32_t value)
457: {
458: gic_state *s = (gic_state *)opaque;
459: int irq;
460: int i;
1.1.1.2 root 461: int cpu;
1.1 root 462:
1.1.1.10! root 463: cpu = gic_get_current_cpu(s);
1.1 root 464: if (offset < 0x100) {
1.1.1.2 root 465: #ifdef NVIC
466: goto bad_reg;
467: #else
1.1 root 468: if (offset == 0) {
469: s->enabled = (value & 1);
470: DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
471: } else if (offset < 4) {
472: /* ignored. */
1.1.1.10! root 473: } else if (offset >= 0x80) {
! 474: /* Interrupt Security Registers, RAZ/WI */
1.1 root 475: } else {
476: goto bad_reg;
477: }
1.1.1.2 root 478: #endif
1.1 root 479: } else if (offset < 0x180) {
480: /* Interrupt Set Enable. */
1.1.1.2 root 481: irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
1.1.1.10! root 482: if (irq >= s->num_irq)
1.1 root 483: goto bad_reg;
1.1.1.2 root 484: if (irq < 16)
485: value = 0xff;
1.1 root 486: for (i = 0; i < 8; i++) {
487: if (value & (1 << i)) {
1.1.1.10! root 488: int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
! 489: int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
1.1.1.9 root 490:
491: if (!GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 492: DPRINTF("Enabled IRQ %d\n", irq + i);
1.1.1.9 root 493: }
494: GIC_SET_ENABLED(irq + i, cm);
1.1 root 495: /* If a raised level triggered IRQ enabled then mark
496: is as pending. */
1.1.1.2 root 497: if (GIC_TEST_LEVEL(irq + i, mask)
498: && !GIC_TEST_TRIGGER(irq + i)) {
499: DPRINTF("Set %d pending mask %x\n", irq + i, mask);
500: GIC_SET_PENDING(irq + i, mask);
501: }
1.1 root 502: }
503: }
504: } else if (offset < 0x200) {
505: /* Interrupt Clear Enable. */
1.1.1.2 root 506: irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
1.1.1.10! root 507: if (irq >= s->num_irq)
1.1 root 508: goto bad_reg;
1.1.1.2 root 509: if (irq < 16)
510: value = 0;
1.1 root 511: for (i = 0; i < 8; i++) {
512: if (value & (1 << i)) {
1.1.1.10! root 513: int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
1.1.1.9 root 514:
515: if (GIC_TEST_ENABLED(irq + i, cm)) {
1.1 root 516: DPRINTF("Disabled IRQ %d\n", irq + i);
1.1.1.9 root 517: }
518: GIC_CLEAR_ENABLED(irq + i, cm);
1.1 root 519: }
520: }
521: } else if (offset < 0x280) {
522: /* Interrupt Set Pending. */
1.1.1.2 root 523: irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
1.1.1.10! root 524: if (irq >= s->num_irq)
1.1 root 525: goto bad_reg;
1.1.1.2 root 526: if (irq < 16)
527: irq = 0;
528:
1.1 root 529: for (i = 0; i < 8; i++) {
530: if (value & (1 << i)) {
1.1.1.2 root 531: GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
1.1 root 532: }
533: }
534: } else if (offset < 0x300) {
535: /* Interrupt Clear Pending. */
1.1.1.2 root 536: irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
1.1.1.10! root 537: if (irq >= s->num_irq)
1.1 root 538: goto bad_reg;
539: for (i = 0; i < 8; i++) {
1.1.1.2 root 540: /* ??? This currently clears the pending bit for all CPUs, even
541: for per-CPU interrupts. It's unclear whether this is the
542: corect behavior. */
1.1 root 543: if (value & (1 << i)) {
1.1.1.2 root 544: GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
1.1 root 545: }
546: }
547: } else if (offset < 0x400) {
548: /* Interrupt Active. */
549: goto bad_reg;
550: } else if (offset < 0x800) {
551: /* Interrupt Priority. */
1.1.1.2 root 552: irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1.1.10! root 553: if (irq >= s->num_irq)
1.1 root 554: goto bad_reg;
1.1.1.10! root 555: if (irq < GIC_INTERNAL) {
1.1.1.2 root 556: s->priority1[irq][cpu] = value;
557: } else {
1.1.1.10! root 558: s->priority2[irq - GIC_INTERNAL] = value;
1.1.1.2 root 559: }
560: #ifndef NVIC
1.1 root 561: } else if (offset < 0xc00) {
562: /* Interrupt CPU Target. */
1.1.1.2 root 563: irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1.1.10! root 564: if (irq >= s->num_irq)
1.1 root 565: goto bad_reg;
1.1.1.2 root 566: if (irq < 29)
567: value = 0;
1.1.1.10! root 568: else if (irq < GIC_INTERNAL)
1.1.1.2 root 569: value = ALL_CPU_MASK;
570: s->irq_target[irq] = value & ALL_CPU_MASK;
1.1 root 571: } else if (offset < 0xf00) {
572: /* Interrupt Configuration. */
1.1.1.2 root 573: irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
1.1.1.10! root 574: if (irq >= s->num_irq)
1.1 root 575: goto bad_reg;
1.1.1.10! root 576: if (irq < GIC_INTERNAL)
1.1.1.2 root 577: value |= 0xaa;
1.1 root 578: for (i = 0; i < 4; i++) {
579: if (value & (1 << (i * 2))) {
580: GIC_SET_MODEL(irq + i);
581: } else {
582: GIC_CLEAR_MODEL(irq + i);
583: }
584: if (value & (2 << (i * 2))) {
585: GIC_SET_TRIGGER(irq + i);
586: } else {
587: GIC_CLEAR_TRIGGER(irq + i);
588: }
589: }
1.1.1.2 root 590: #endif
1.1 root 591: } else {
1.1.1.2 root 592: /* 0xf00 is only handled for 32-bit writes. */
1.1 root 593: goto bad_reg;
594: }
595: gic_update(s);
596: return;
597: bad_reg:
1.1.1.4 root 598: hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
1.1 root 599: }
600:
601: static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
602: uint32_t value)
603: {
604: gic_dist_writeb(opaque, offset, value & 0xff);
605: gic_dist_writeb(opaque, offset + 1, value >> 8);
606: }
607:
608: static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
609: uint32_t value)
610: {
1.1.1.2 root 611: gic_state *s = (gic_state *)opaque;
612: #ifdef NVIC
613: uint32_t addr;
1.1.1.3 root 614: addr = offset;
1.1.1.2 root 615: if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
1.1.1.4 root 616: nvic_writel(s, addr, value);
1.1.1.2 root 617: return;
618: }
619: #endif
1.1.1.3 root 620: if (offset == 0xf00) {
1.1.1.2 root 621: int cpu;
622: int irq;
623: int mask;
624:
1.1.1.10! root 625: cpu = gic_get_current_cpu(s);
1.1.1.2 root 626: irq = value & 0x3ff;
627: switch ((value >> 24) & 3) {
628: case 0:
629: mask = (value >> 16) & ALL_CPU_MASK;
630: break;
631: case 1:
1.1.1.8 root 632: mask = ALL_CPU_MASK ^ (1 << cpu);
1.1.1.2 root 633: break;
634: case 2:
1.1.1.8 root 635: mask = 1 << cpu;
1.1.1.2 root 636: break;
637: default:
638: DPRINTF("Bad Soft Int target filter\n");
639: mask = ALL_CPU_MASK;
640: break;
641: }
642: GIC_SET_PENDING(irq, mask);
643: gic_update(s);
644: return;
645: }
1.1 root 646: gic_dist_writew(opaque, offset, value & 0xffff);
647: gic_dist_writew(opaque, offset + 2, value >> 16);
648: }
649:
1.1.1.9 root 650: static const MemoryRegionOps gic_dist_ops = {
651: .old_mmio = {
652: .read = { gic_dist_readb, gic_dist_readw, gic_dist_readl, },
653: .write = { gic_dist_writeb, gic_dist_writew, gic_dist_writel, },
654: },
655: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 656: };
657:
1.1.1.2 root 658: #ifndef NVIC
659: static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
1.1 root 660: {
661: switch (offset) {
662: case 0x00: /* Control */
1.1.1.2 root 663: return s->cpu_enabled[cpu];
1.1 root 664: case 0x04: /* Priority mask */
1.1.1.2 root 665: return s->priority_mask[cpu];
1.1 root 666: case 0x08: /* Binary Point */
667: /* ??? Not implemented. */
668: return 0;
669: case 0x0c: /* Acknowledge */
1.1.1.2 root 670: return gic_acknowledge_irq(s, cpu);
1.1.1.10! root 671: case 0x14: /* Running Priority */
1.1.1.2 root 672: return s->running_priority[cpu];
1.1 root 673: case 0x18: /* Highest Pending Interrupt */
1.1.1.2 root 674: return s->current_pending[cpu];
1.1 root 675: default:
1.1.1.4 root 676: hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
1.1 root 677: return 0;
678: }
679: }
680:
1.1.1.2 root 681: static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
1.1 root 682: {
683: switch (offset) {
684: case 0x00: /* Control */
1.1.1.2 root 685: s->cpu_enabled[cpu] = (value & 1);
1.1.1.5 root 686: DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
1.1 root 687: break;
688: case 0x04: /* Priority mask */
1.1.1.2 root 689: s->priority_mask[cpu] = (value & 0xff);
1.1 root 690: break;
691: case 0x08: /* Binary Point */
692: /* ??? Not implemented. */
693: break;
694: case 0x10: /* End Of Interrupt */
1.1.1.2 root 695: return gic_complete_irq(s, cpu, value & 0x3ff);
1.1 root 696: default:
1.1.1.4 root 697: hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
1.1 root 698: return;
699: }
700: gic_update(s);
701: }
1.1.1.10! root 702:
! 703: /* Wrappers to read/write the GIC CPU interface for the current CPU */
! 704: static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
! 705: unsigned size)
! 706: {
! 707: gic_state *s = (gic_state *)opaque;
! 708: return gic_cpu_read(s, gic_get_current_cpu(s), addr);
! 709: }
! 710:
! 711: static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
! 712: uint64_t value, unsigned size)
! 713: {
! 714: gic_state *s = (gic_state *)opaque;
! 715: gic_cpu_write(s, gic_get_current_cpu(s), addr, value);
! 716: }
! 717:
! 718: /* Wrappers to read/write the GIC CPU interface for a specific CPU.
! 719: * These just decode the opaque pointer into gic_state* + cpu id.
! 720: */
! 721: static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
! 722: unsigned size)
! 723: {
! 724: gic_state **backref = (gic_state **)opaque;
! 725: gic_state *s = *backref;
! 726: int id = (backref - s->backref);
! 727: return gic_cpu_read(s, id, addr);
! 728: }
! 729:
! 730: static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
! 731: uint64_t value, unsigned size)
! 732: {
! 733: gic_state **backref = (gic_state **)opaque;
! 734: gic_state *s = *backref;
! 735: int id = (backref - s->backref);
! 736: gic_cpu_write(s, id, addr, value);
! 737: }
! 738:
! 739: static const MemoryRegionOps gic_thiscpu_ops = {
! 740: .read = gic_thiscpu_read,
! 741: .write = gic_thiscpu_write,
! 742: .endianness = DEVICE_NATIVE_ENDIAN,
! 743: };
! 744:
! 745: static const MemoryRegionOps gic_cpu_ops = {
! 746: .read = gic_do_cpu_read,
! 747: .write = gic_do_cpu_write,
! 748: .endianness = DEVICE_NATIVE_ENDIAN,
! 749: };
1.1.1.2 root 750: #endif
1.1 root 751:
1.1.1.10! root 752: static void gic_reset(DeviceState *dev)
1.1 root 753: {
1.1.1.10! root 754: gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev));
1.1 root 755: int i;
1.1.1.10! root 756: memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
1.1.1.5 root 757: for (i = 0 ; i < NUM_CPU(s); i++) {
1.1.1.2 root 758: s->priority_mask[i] = 0xf0;
759: s->current_pending[i] = 1023;
760: s->running_irq[i] = 1023;
761: s->running_priority[i] = 0x100;
762: #ifdef NVIC
763: /* The NVIC doesn't have per-cpu interfaces, so enable by default. */
764: s->cpu_enabled[i] = 1;
765: #else
766: s->cpu_enabled[i] = 0;
767: #endif
768: }
769: for (i = 0; i < 16; i++) {
1.1.1.9 root 770: GIC_SET_ENABLED(i, ALL_CPU_MASK);
1.1 root 771: GIC_SET_TRIGGER(i);
772: }
1.1.1.2 root 773: #ifdef NVIC
774: /* The NVIC is always enabled. */
775: s->enabled = 1;
776: #else
1.1 root 777: s->enabled = 0;
1.1.1.2 root 778: #endif
1.1 root 779: }
780:
1.1.1.3 root 781: static void gic_save(QEMUFile *f, void *opaque)
782: {
783: gic_state *s = (gic_state *)opaque;
784: int i;
785: int j;
786:
787: qemu_put_be32(f, s->enabled);
1.1.1.5 root 788: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3 root 789: qemu_put_be32(f, s->cpu_enabled[i]);
1.1.1.10! root 790: for (j = 0; j < GIC_INTERNAL; j++)
1.1.1.3 root 791: qemu_put_be32(f, s->priority1[j][i]);
1.1.1.10! root 792: for (j = 0; j < s->num_irq; j++)
1.1.1.3 root 793: qemu_put_be32(f, s->last_active[j][i]);
794: qemu_put_be32(f, s->priority_mask[i]);
795: qemu_put_be32(f, s->running_irq[i]);
796: qemu_put_be32(f, s->running_priority[i]);
797: qemu_put_be32(f, s->current_pending[i]);
798: }
1.1.1.10! root 799: for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
1.1.1.3 root 800: qemu_put_be32(f, s->priority2[i]);
801: }
1.1.1.10! root 802: for (i = 0; i < s->num_irq; i++) {
1.1.1.9 root 803: #ifndef NVIC
804: qemu_put_be32(f, s->irq_target[i]);
805: #endif
1.1.1.3 root 806: qemu_put_byte(f, s->irq_state[i].enabled);
807: qemu_put_byte(f, s->irq_state[i].pending);
808: qemu_put_byte(f, s->irq_state[i].active);
809: qemu_put_byte(f, s->irq_state[i].level);
810: qemu_put_byte(f, s->irq_state[i].model);
811: qemu_put_byte(f, s->irq_state[i].trigger);
812: }
813: }
814:
815: static int gic_load(QEMUFile *f, void *opaque, int version_id)
816: {
817: gic_state *s = (gic_state *)opaque;
818: int i;
819: int j;
820:
1.1.1.9 root 821: if (version_id != 2)
1.1.1.3 root 822: return -EINVAL;
823:
824: s->enabled = qemu_get_be32(f);
1.1.1.5 root 825: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3 root 826: s->cpu_enabled[i] = qemu_get_be32(f);
1.1.1.10! root 827: for (j = 0; j < GIC_INTERNAL; j++)
1.1.1.3 root 828: s->priority1[j][i] = qemu_get_be32(f);
1.1.1.10! root 829: for (j = 0; j < s->num_irq; j++)
1.1.1.3 root 830: s->last_active[j][i] = qemu_get_be32(f);
831: s->priority_mask[i] = qemu_get_be32(f);
832: s->running_irq[i] = qemu_get_be32(f);
833: s->running_priority[i] = qemu_get_be32(f);
834: s->current_pending[i] = qemu_get_be32(f);
835: }
1.1.1.10! root 836: for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
1.1.1.3 root 837: s->priority2[i] = qemu_get_be32(f);
838: }
1.1.1.10! root 839: for (i = 0; i < s->num_irq; i++) {
1.1.1.9 root 840: #ifndef NVIC
841: s->irq_target[i] = qemu_get_be32(f);
842: #endif
1.1.1.3 root 843: s->irq_state[i].enabled = qemu_get_byte(f);
844: s->irq_state[i].pending = qemu_get_byte(f);
845: s->irq_state[i].active = qemu_get_byte(f);
846: s->irq_state[i].level = qemu_get_byte(f);
847: s->irq_state[i].model = qemu_get_byte(f);
848: s->irq_state[i].trigger = qemu_get_byte(f);
849: }
850:
851: return 0;
852: }
853:
1.1.1.5 root 854: #if NCPU > 1
1.1.1.10! root 855: static void gic_init(gic_state *s, int num_cpu, int num_irq)
1.1.1.5 root 856: #else
1.1.1.10! root 857: static void gic_init(gic_state *s, int num_irq)
1.1.1.5 root 858: #endif
1.1 root 859: {
1.1.1.2 root 860: int i;
1.1 root 861:
1.1.1.5 root 862: #if NCPU > 1
863: s->num_cpu = num_cpu;
1.1.1.10! root 864: if (s->num_cpu > NCPU) {
! 865: hw_error("requested %u CPUs exceeds GIC maximum %d\n",
! 866: num_cpu, NCPU);
! 867: }
! 868: #endif
! 869: s->num_irq = num_irq + GIC_BASE_IRQ;
! 870: if (s->num_irq > GIC_MAXIRQ) {
! 871: hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
! 872: num_irq, GIC_MAXIRQ);
! 873: }
! 874: /* ITLinesNumber is represented as (N / 32) - 1 (see
! 875: * gic_dist_readb) so this is an implementation imposed
! 876: * restriction, not an architectural one:
! 877: */
! 878: if (s->num_irq < 32 || (s->num_irq % 32)) {
! 879: hw_error("%d interrupt lines unsupported: not divisible by 32\n",
! 880: num_irq);
! 881: }
! 882:
! 883: i = s->num_irq - GIC_INTERNAL;
! 884: #ifndef NVIC
! 885: /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
! 886: * GPIO array layout is thus:
! 887: * [0..N-1] SPIs
! 888: * [N..N+31] PPIs for CPU 0
! 889: * [N+32..N+63] PPIs for CPU 1
! 890: * ...
! 891: */
! 892: i += (GIC_INTERNAL * num_cpu);
1.1.1.5 root 893: #endif
1.1.1.10! root 894: qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, i);
1.1.1.5 root 895: for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.4 root 896: sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
1.1.1.2 root 897: }
1.1.1.9 root 898: memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
1.1.1.10! root 899: #ifndef NVIC
! 900: /* Memory regions for the CPU interfaces (NVIC doesn't have these):
! 901: * a region for "CPU interface for this core", then a region for
! 902: * "CPU interface for core 0", "for core 1", ...
! 903: * NB that the memory region size of 0x100 applies for the 11MPCore
! 904: * and also cores following the GIC v1 spec (ie A9).
! 905: * GIC v2 defines a larger memory region (0x1000) so this will need
! 906: * to be extended when we implement A15.
! 907: */
! 908: memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s,
! 909: "gic_cpu", 0x100);
! 910: for (i = 0; i < NUM_CPU(s); i++) {
! 911: s->backref[i] = s;
! 912: memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i],
! 913: "gic_cpu", 0x100);
! 914: }
! 915: #endif
! 916:
1.1.1.9 root 917: register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
1.1 root 918: }
1.1.1.10! root 919:
! 920: #ifndef NVIC
! 921:
! 922: static int arm_gic_init(SysBusDevice *dev)
! 923: {
! 924: /* Device instance init function for the GIC sysbus device */
! 925: int i;
! 926: gic_state *s = FROM_SYSBUS(gic_state, dev);
! 927: gic_init(s, s->num_cpu, s->num_irq);
! 928: /* Distributor */
! 929: sysbus_init_mmio(dev, &s->iomem);
! 930: /* cpu interfaces (one for "current cpu" plus one per cpu) */
! 931: for (i = 0; i <= NUM_CPU(s); i++) {
! 932: sysbus_init_mmio(dev, &s->cpuiomem[i]);
! 933: }
! 934: return 0;
! 935: }
! 936:
! 937: static Property arm_gic_properties[] = {
! 938: DEFINE_PROP_UINT32("num-cpu", gic_state, num_cpu, 1),
! 939: DEFINE_PROP_UINT32("num-irq", gic_state, num_irq, 32),
! 940: DEFINE_PROP_END_OF_LIST(),
! 941: };
! 942:
! 943: static void arm_gic_class_init(ObjectClass *klass, void *data)
! 944: {
! 945: DeviceClass *dc = DEVICE_CLASS(klass);
! 946: SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
! 947: sbc->init = arm_gic_init;
! 948: dc->props = arm_gic_properties;
! 949: dc->reset = gic_reset;
! 950: dc->no_user = 1;
! 951: }
! 952:
! 953: static TypeInfo arm_gic_info = {
! 954: .name = "arm_gic",
! 955: .parent = TYPE_SYS_BUS_DEVICE,
! 956: .instance_size = sizeof(gic_state),
! 957: .class_init = arm_gic_class_init,
! 958: };
! 959:
! 960: static void arm_gic_register_types(void)
! 961: {
! 962: type_register_static(&arm_gic_info);
! 963: }
! 964:
! 965: type_init(arm_gic_register_types)
! 966:
! 967: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.