static size_t probe_max_it(vaddr_t gicc_base, vaddr_t gicd_base) { int i; uint32_t old_ctlr; size_t ret = 0; const size_t max_regs = ((GIC_MAX_INTS + NUM_INTS_PER_REG - 1) / NUM_INTS_PER_REG) - 1; /* * Probe which interrupt number is the largest. */ old_ctlr = read32(gicc_base + GICC_CTLR); write32(0, gicc_base + GICC_CTLR); for (i = max_regs; i >= 0; i--) { uint32_t old_reg; uint32_t reg; int b; old_reg = read32(gicd_base + GICD_ISENABLER(i)); write32(0xffffffff, gicd_base + GICD_ISENABLER(i)); reg = read32(gicd_base + GICD_ISENABLER(i)); write32(old_reg, gicd_base + GICD_ICENABLER(i)); for (b = NUM_INTS_PER_REG - 1; b >= 0; b--) { if (BIT32(b) & reg) { ret = i * NUM_INTS_PER_REG + b; goto out; } } } out: write32(old_ctlr, gicc_base + GICC_CTLR); return ret; }
static size_t probe_max_it(void) { int i; uint32_t old_ctlr; size_t ret = 0; /* * Probe which interrupt number is the largest. */ old_ctlr = read32(gic.gicc_base + GICC_CTLR); write32(0, gic.gicc_base + GICC_CTLR); for (i = GIC_MAX_INTS / 32; i > 0; i--) { uint32_t old_reg; uint32_t reg; int b; old_reg = read32(gic.gicd_base + GICD_ISENABLER(i)); write32(0xffffffff, gic.gicd_base + GICD_ISENABLER(i)); reg = read32(gic.gicd_base + GICD_ISENABLER(i)); write32(old_reg, gic.gicd_base + GICD_ICENABLER(i)); for (b = 31; b > 0; b--) { if ((1 << b) & reg) { ret = i * 32 + b; goto out; } } } out: write32(old_ctlr, gic.gicc_base + GICC_CTLR); return ret; }
static void gic_it_enable(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); /* Assigned to group0 */ assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); /* Not enabled yet */ assert(!(read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask)); /* Enable the interrupt */ write32(mask, gd->gicd_base + GICD_ISENABLER(idx)); }
void gic_it_enable(size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); assert(it <= gic.max_it); /* Not too large */ /* Assigned to group0 */ assert(!(read32(gic.gicd_base + GICD_IGROUPR(idx)) & mask)); /* Not enabled yet */ assert(!(read32(gic.gicd_base + GICD_ISENABLER(idx)) & mask)); /* Enable the interrupt */ write32(mask, gic.gicd_base + GICD_ISENABLER(idx)); }
/** * \fn init_gic_cpu * * Initialise GIC CPU interface */ void init_gic_cpu() { unsigned int i; GICD[GICD_ICENABLER(0)] = 0xFFFF0000; GICD[GICD_ISENABLER(0)] = 0x0000FFFF; for (i = 0; i < 128; i += 4) GICD[GICD_IPRIORITYR(i / 4)] = 0xa0a0a0a0; GICC[GICC_PMR] = 0xff; GICC[GICC_BPR] = 0; GICC[GICC_CTLR] = 0x201; }
void irqctrl_enable(unsigned int irq) { int n = irq / BITS_PER_REGISTER; int m = irq % BITS_PER_REGISTER; uint32_t tmp; /* Writing zeroes to this register has no * effect, so we just write single "1" */ REG_STORE(GICD_ISENABLER(n), 1 << m); /* N-N irq model: all CPUs receive this IRQ */ REG_STORE(GICD_ICFGR(n), 1 << m); /* All CPUs do listen to this IRQ */ n = irq / 4; m = irq % 4; tmp = REG_LOAD(GICD_ITARGETSR(n)); tmp |= 0xFF << (8 * m); REG_STORE(GICD_ITARGETSR(n), tmp); }
static bool gic_it_is_enabled(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); return !!(read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask); }
bool gic_it_is_enabled(size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); return !!(read32(gic.gicd_base + GICD_ISENABLER(idx)) & mask); }
/** * \fn enable_irq(unsigned int irqn) * * Enable IRQ in GICD, setting target CPU to cpu0 and priority to 0xa0 */ void enable_irq(unsigned int irqn) { GICD[GICD_ISENABLER(irqn / 32)] = 1 << (irqn % 32); GICD[GICD_ITARGETSR(irqn / 4)] |= (0x01 << ((irqn % 4) * 8)); GICD[GICD_IPRIORITYR(irqn / 4)] |= (0xa0 << ((irqn % 4) * 8)); }