1
0
Fork 0

ARM: 6150/1: gic: implement set_type

Implement set_type() to allow configuration of the trigger type.

Cc: Abhijeet Dharmapurikar <adharmap@quicinc.com>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
wifi-calibration
Rabin Vincent 2010-05-28 04:37:38 +01:00 committed by Russell King
parent 7e27d6e778
commit 5c0c1f08ab
1 changed files with 46 additions and 0 deletions

View File

@ -108,6 +108,51 @@ static void gic_unmask_irq(unsigned int irq)
spin_unlock(&irq_controller_lock);
}
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);
return 0;
}
#ifdef CONFIG_SMP
static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
{
@ -161,6 +206,7 @@ static struct irq_chip gic_chip = {
.ack = gic_ack_irq,
.mask = gic_mask_irq,
.unmask = gic_unmask_irq,
.set_type = gic_set_type,
#ifdef CONFIG_SMP
.set_affinity = gic_set_cpu,
#endif