예제 #1
0
static void fpga_irq_unmask(struct vmm_host_irq *irq)
{
    struct fpga_irq_data *f = vmm_host_irq_get_chip_data(irq);
    u32 mask = 1 << fpga_irq(irq);

    vmm_writel(mask, f->base + IRQ_ENABLE_SET);
}
예제 #2
0
static void gic_eoi_irq(struct vmm_host_irq *d)
{
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(d);

	gic_write(d->hwirq, gic->cpu_base + GICC_EOI);
	if (gic->eoimode && !vmm_host_irq_is_routed(d)) {
		gic_write(d->hwirq, gic->cpu2_base + GICC2_DIR);
	}
}
예제 #3
0
static void gic_eoi_irq(struct vmm_host_irq *irq)
{
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(irq);
	u32 irq_no = gic_irq(gic, irq);

	gic_write(irq_no, gic->cpu_base + GIC_CPU_EOI);
	if (gic->eoimode && !vmm_host_irq_is_routed(irq)) {
		gic_write(irq_no, gic->cpu2_base + GIC_CPU2_DIR);
	}
}
예제 #4
0
static void gic_irq_set_routed_state(struct vmm_host_irq *d,
				     u32 val, u32 mask)
{
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(d);

	if (mask & VMM_ROUTED_IRQ_STATE_PENDING)
		gic_poke_irq(gic, d, (val & VMM_ROUTED_IRQ_STATE_PENDING) ?
				GICD_ENABLE_SET : GICD_ENABLE_CLEAR);
	if (mask & VMM_ROUTED_IRQ_STATE_ACTIVE)
		gic_poke_irq(gic, d, (val & VMM_ROUTED_IRQ_STATE_ACTIVE) ?
				GICD_ACTIVE_SET : GICD_ACTIVE_CLEAR);
	if (mask & VMM_ROUTED_IRQ_STATE_MASKED)
		gic_poke_irq(gic, d, (val & VMM_ROUTED_IRQ_STATE_MASKED) ?
				GICD_ENABLE_CLEAR : GICD_ENABLE_SET);
}
예제 #5
0
static u32 gic_irq_get_routed_state(struct vmm_host_irq *d, u32 mask)
{
	u32 val = 0;
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(d);

	if ((mask & VMM_ROUTED_IRQ_STATE_PENDING) &&
	    gic_peek_irq(gic, d, GICD_ENABLE_SET))
		val |= VMM_ROUTED_IRQ_STATE_PENDING;
	if ((mask & VMM_ROUTED_IRQ_STATE_ACTIVE) &&
	    gic_peek_irq(gic, d, GICD_ACTIVE_SET))
		val |= VMM_ROUTED_IRQ_STATE_ACTIVE;
	if ((mask & VMM_ROUTED_IRQ_STATE_MASKED) &&
	    !gic_peek_irq(gic, d, GICD_ENABLE_SET))
		val |= VMM_ROUTED_IRQ_STATE_MASKED;

	return val;
}
예제 #6
0
static int gic_set_type(struct vmm_host_irq *irq, u32 type)
{
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(irq);
	virtual_addr_t base = gic->dist_base;
	u32 irq_no = gic_irq(gic, irq);
	u32 enablemask = 1 << (irq_no % 32);
	u32 enableoff = (irq_no / 32) * 4;
	u32 confmask = 0x2 << ((irq_no % 16) * 2);
	u32 confoff = (irq_no / 16) * 4;
	bool enabled = FALSE;
	u32 val;

	/* Interrupt configuration for SGIs can't be changed */
	if (irq_no < 16) {
		return VMM_EINVALID;
	}

	if (type != VMM_IRQ_TYPE_LEVEL_HIGH && 
	    type != VMM_IRQ_TYPE_EDGE_RISING) {
		return VMM_EINVALID;
	}

	val = gic_read(base + GIC_DIST_CONFIG + confoff);
	if (type == VMM_IRQ_TYPE_LEVEL_HIGH) {
		val &= ~confmask;
	} else if (type == VMM_IRQ_TYPE_EDGE_RISING) {
		val |= confmask;
	}

	/*
	 * As recommended by the spec, disable the interrupt before changing
	 * the configuration
	 */
	if (gic_read(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
		gic_write(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
		enabled = TRUE;
	}

	gic_write(val, base + GIC_DIST_CONFIG + confoff);

	if (enabled) {
		gic_write(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
	}

	return 0;
}
예제 #7
0
static int gic_set_affinity(struct vmm_host_irq *d,
			    const struct vmm_cpumask *mask_val,
			    bool force)
{
	virtual_addr_t reg;
	u32 shift = (d->hwirq % 4) * 8;
	u32 cpu = vmm_cpumask_first(mask_val);
	u32 val, mask, bit;
	struct gic_chip_data *gic = vmm_host_irq_get_chip_data(d);

	if (cpu >= 8)
		return VMM_EINVALID;

	reg = gic->dist_base + GICD_TARGET + (d->hwirq & ~3);
	mask = 0xff << shift;
	bit = 1 << (cpu + shift);

	val = gic_read(reg) & ~mask;
	gic_write(val | bit, reg);

	return 0;
}
예제 #8
0
static void gic_unmask_irq(struct vmm_host_irq *d)
{
	gic_poke_irq(vmm_host_irq_get_chip_data(d), d, GICD_ENABLE_SET);
}
예제 #9
0
static inline u32 gic_irq(struct vmm_host_irq *irq)
{
	struct gic_chip_data *gic_data = vmm_host_irq_get_chip_data(irq);
	return irq->num - gic_data->irq_offset;
}
예제 #10
0
static inline virtual_addr_t gic_cpu_base(struct vmm_host_irq *irq)
{
	struct gic_chip_data *gic_data = vmm_host_irq_get_chip_data(irq);
	return gic_data->cpu_base;
}
예제 #11
0
static inline u32 fpga_irq(struct vmm_host_irq *irq)
{
    struct fpga_irq_data *f = vmm_host_irq_get_chip_data(irq);

    return irq->num - f->irq_start;
}
예제 #12
0
static void gic_unmask_irq(struct vmm_host_irq *irq)
{
	gic_poke_irq(vmm_host_irq_get_chip_data(irq),
		     irq, GIC_DIST_ENABLE_SET);
}
예제 #13
0
static void gic_mask_irq(struct vmm_host_irq *d)
{
	gic_poke_irq(vmm_host_irq_get_chip_data(d), d, GIC_DIST_ENABLE_CLEAR);
}