static void __init setup_intr(unsigned int intr, unsigned int cpu, unsigned int pin, unsigned int polarity, unsigned int trigtype) { /* Setup Intr to Pin mapping */ if (pin & GIC_MAP_TO_NMI_MSK) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); /* FIXME: hack to route NMI to all cpu's */ for (cpu = 0; cpu < NR_CPUS; cpu += 32) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), 0xffffffff); } } else { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), GIC_MAP_TO_PIN_MSK | pin); /* Setup Intr to CPU mapping */ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); } /* Setup Intr Polarity */ GIC_SET_POLARITY(intr, polarity); /* Setup Intr Trigger Type */ GIC_SET_TRIGGER(intr, trigtype); /* Init Intr Masks */ GIC_SET_INTR_MASK(intr, 0); }
static void __init gic_basic_init(void) { unsigned int i, cpu; /* Setup defaults */ for (i = 0; i < GIC_NUM_INTRS; i++) { GIC_SET_POLARITY(i, GIC_POL_POS); GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); GIC_SET_INTR_MASK(i, 0); } /* Setup specifics */ for (i = 0; i < _mapsize; i++) { cpu = _intrmap[i].cpunum; if (cpu == X) continue; setup_intr(_intrmap[i].intrnum, _intrmap[i].cpunum, _intrmap[i].pin, _intrmap[i].polarity, _intrmap[i].trigtype); /* Initialise per-cpu Interrupt software masks */ if (_intrmap[i].ipiflag) set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask); } vpe_local_setup(numvpes); for (i = _irqbase; i < (_irqbase + numintrs); i++) set_irq_chip(i, &gic_irq_controller); }
static void __init gic_basic_init(int numintrs, int numvpes, struct gic_intr_map *intrmap, int mapsize) { unsigned int i, cpu; /* Setup defaults */ for (i = 0; i < numintrs; i++) { GIC_SET_POLARITY(i, GIC_POL_POS); GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); GIC_CLR_INTR_MASK(i); if (i < GIC_NUM_INTRS) gic_irq_flags[i] = 0; } /* Setup specifics */ for (i = 0; i < mapsize; i++) { cpu = intrmap[i].cpunum; if (cpu == GIC_UNUSED) continue; if (cpu == 0 && i != 0 && intrmap[i].flags == 0) continue; gic_setup_intr(i, intrmap[i].cpunum, intrmap[i].pin, intrmap[i].polarity, intrmap[i].trigtype, intrmap[i].flags); } vpe_local_setup(numvpes); for (i = _irqbase; i < (_irqbase + numintrs); i++) irq_set_chip(i, &gic_irq_controller); }
static void gic_reset(gic_state *s) { int i; memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state)); s->priority_mask = 0xf0; s->current_pending = 1023; s->running_irq = 1023; s->running_priority = 0x100; for (i = 0; i < 15; i++) { GIC_SET_ENABLED(i); GIC_SET_TRIGGER(i); } s->enabled = 0; s->cpu_enabled = 0; }
static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, unsigned int pin, unsigned int polarity, unsigned int trigtype, unsigned int flags) { /* Setup Intr to Pin mapping */ if (pin & GIC_MAP_TO_NMI_MSK) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); /* FIXME: hack to route NMI to all cpu's */ for (cpu = 0; cpu < NR_CPUS; cpu += 32) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), 0xffffffff); } } else { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), GIC_MAP_TO_PIN_MSK | pin); /* Setup Intr to CPU mapping */ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); } /* Setup Intr Polarity */ GIC_SET_POLARITY(intr, polarity); /* Setup Intr Trigger Type */ GIC_SET_TRIGGER(intr, trigtype); /* Init Intr Masks */ GIC_CLR_INTR_MASK(intr); /* Initialise per-cpu Interrupt software masks */ if (flags & GIC_FLAG_IPI) set_bit(intr, pcpu_masks[cpu].pcpu_mask); #ifdef CONFIG_RALINK_SOC if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) #else if (flags & GIC_FLAG_TRANSPARENT) #endif GIC_SET_INTR_MASK(intr); if (trigtype == GIC_TRIG_EDGE) gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE; }
static void arm_gic_common_reset(DeviceState *dev) { gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev)); int i; memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state)); for (i = 0 ; i < s->num_cpu; i++) { s->priority_mask[i] = 0xf0; s->current_pending[i] = 1023; s->running_irq[i] = 1023; s->running_priority[i] = 0x100; s->cpu_enabled[i] = 0; } for (i = 0; i < 16; i++) { GIC_SET_ENABLED(i, ALL_CPU_MASK); GIC_SET_TRIGGER(i); } if (s->num_cpu == 1) { /* For uniprocessor GICs all interrupts always target the sole CPU */ for (i = 0; i < GIC_MAXIRQ; i++) { s->irq_target[i] = 1; } } s->enabled = 0; }
static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, uint32_t value) { gic_state *s = (gic_state *)opaque; int irq; int i; offset -= s->base + 0x1000; if (offset < 0x100) { if (offset == 0) { s->enabled = (value & 1); DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis"); } else if (offset < 4) { /* ignored. */ } else { goto bad_reg; } } else if (offset < 0x180) { /* Interrupt Set Enable. */ irq = (offset - 0x100) * 8; if (irq >= GIC_NIRQ) goto bad_reg; for (i = 0; i < 8; i++) { if (value & (1 << i)) { if (!GIC_TEST_ENABLED(irq + i)) DPRINTF("Enabled IRQ %d\n", irq + i); GIC_SET_ENABLED(irq + i); /* If a raised level triggered IRQ enabled then mark is as pending. */ if (GIC_TEST_LEVEL(irq + i) && !GIC_TEST_TRIGGER(irq + i)) GIC_SET_PENDING(irq + i); } } } else if (offset < 0x200) { /* Interrupt Clear Enable. */ irq = (offset - 0x180) * 8; if (irq >= GIC_NIRQ) goto bad_reg; for (i = 0; i < 8; i++) { if (value & (1 << i)) { if (GIC_TEST_ENABLED(irq + i)) DPRINTF("Disabled IRQ %d\n", irq + i); GIC_CLEAR_ENABLED(irq + i); } } } else if (offset < 0x280) { /* Interrupt Set Pending. */ irq = (offset - 0x200) * 8; if (irq >= GIC_NIRQ) goto bad_reg; for (i = 0; i < 8; i++) { if (value & (1 << i)) { GIC_SET_PENDING(irq + i); } } } else if (offset < 0x300) { /* Interrupt Clear Pending. */ irq = (offset - 0x280) * 8; if (irq >= GIC_NIRQ) goto bad_reg; for (i = 0; i < 8; i++) { if (value & (1 << i)) { GIC_CLEAR_PENDING(irq + i); } } } else if (offset < 0x400) { /* Interrupt Active. */ goto bad_reg; } else if (offset < 0x800) { /* Interrupt Priority. */ irq = offset - 0x400; if (irq >= GIC_NIRQ) goto bad_reg; s->priority[irq] = value; } else if (offset < 0xc00) { /* Interrupt CPU Target. */ irq = offset - 0x800; if (irq >= GIC_NIRQ) goto bad_reg; s->irq_target[irq] = value; } else if (offset < 0xf00) { /* Interrupt Configuration. */ irq = (offset - 0xc00) * 4; if (irq >= GIC_NIRQ) goto bad_reg; for (i = 0; i < 4; i++) { if (value & (1 << (i * 2))) { GIC_SET_MODEL(irq + i); } else { GIC_CLEAR_MODEL(irq + i); } if (value & (2 << (i * 2))) { GIC_SET_TRIGGER(irq + i); } else { GIC_CLEAR_TRIGGER(irq + i); } } } else { /* 0xf00 is only handled for word writes. */ goto bad_reg; } gic_update(s); return; bad_reg: cpu_abort (cpu_single_env, "gic_dist_writeb: Bad offset %x\n", offset); }