Esempio n. 1
0
static int gic_set_type(unsigned int irq, unsigned int type)
{
	void __iomem *base = gic_dist_base(irq);
	unsigned int gicirq = gic_irq(irq);
	u32 enablemask = 1 << (gicirq % 32);
	u32 enableoff = (gicirq / 32) * 4;
	u32 confmask = 0x2 << ((gicirq % 16) * 2);
	u32 confoff = (gicirq / 16) * 4;
	bool enabled = false;
	u32 val;

	/* Interrupt configuration for SGIs can't be changed */
	if (gicirq < 16)
		return -EINVAL;

	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
		return -EINVAL;

	spin_lock(&irq_controller_lock);

	val = readl(base + GIC_DIST_CONFIG + confoff);
	if (type == IRQ_TYPE_LEVEL_HIGH)
		val &= ~confmask;
	else if (type == IRQ_TYPE_EDGE_RISING)
		val |= confmask;

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

	writel(val, base + GIC_DIST_CONFIG + confoff);

	if (enabled)
		writel(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);

	spin_unlock(&irq_controller_lock);

	if ((type & IRQ_TYPE_EDGE_RISING) && gicirq > 31)
		__set_irq_handler_unlocked(irq, handle_edge_irq);

#ifdef CONFIG_MSM_MPM
	msm_mpm_set_irq_type(irq, type);
#endif

	return 0;
}
Esempio n. 2
0
static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
{
    u32 ctrl_reg, type;
    int irq;
    int l2irq;
    void *handler = handle_level_irq;

    irq = irq_map[virq].hwirq;
    l2irq = irq & MPC52xx_IRQ_L2_MASK;

    pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);

    switch (flow_type) {
    case IRQF_TRIGGER_HIGH:
        type = 0;
        break;
    case IRQF_TRIGGER_RISING:
        type = 1;
        handler = handle_edge_irq;
        break;
    case IRQF_TRIGGER_FALLING:
        type = 2;
        handler = handle_edge_irq;
        break;
    case IRQF_TRIGGER_LOW:
        type = 3;
        break;
    default:
        type = 0;
    }

    ctrl_reg = in_be32(&intr->ctrl);
    ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
    ctrl_reg |= (type << (22 - (l2irq * 2)));
    out_be32(&intr->ctrl, ctrl_reg);

    __set_irq_handler_unlocked(virq, handler);

    return 0;
}