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; }
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; }