diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2010-05-27 23:37:38 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-06-16 17:26:08 -0400 |
commit | 5c0c1f08abf094273f40a6d6fd4519fcacc6c58d (patch) | |
tree | d3d992cc81441b60fa919b0ec2b2f970ae3eaa3f /arch/arm/common/gic.c | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) |
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>
Diffstat (limited to 'arch/arm/common/gic.c')
-rw-r--r-- | arch/arm/common/gic.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 337741f734ac..7dfa9a85bc0c 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -108,6 +108,51 @@ static void gic_unmask_irq(unsigned int irq) | |||
108 | spin_unlock(&irq_controller_lock); | 108 | spin_unlock(&irq_controller_lock); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int gic_set_type(unsigned int irq, unsigned int type) | ||
112 | { | ||
113 | void __iomem *base = gic_dist_base(irq); | ||
114 | unsigned int gicirq = gic_irq(irq); | ||
115 | u32 enablemask = 1 << (gicirq % 32); | ||
116 | u32 enableoff = (gicirq / 32) * 4; | ||
117 | u32 confmask = 0x2 << ((gicirq % 16) * 2); | ||
118 | u32 confoff = (gicirq / 16) * 4; | ||
119 | bool enabled = false; | ||
120 | u32 val; | ||
121 | |||
122 | /* Interrupt configuration for SGIs can't be changed */ | ||
123 | if (gicirq < 16) | ||
124 | return -EINVAL; | ||
125 | |||
126 | if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) | ||
127 | return -EINVAL; | ||
128 | |||
129 | spin_lock(&irq_controller_lock); | ||
130 | |||
131 | val = readl(base + GIC_DIST_CONFIG + confoff); | ||
132 | if (type == IRQ_TYPE_LEVEL_HIGH) | ||
133 | val &= ~confmask; | ||
134 | else if (type == IRQ_TYPE_EDGE_RISING) | ||
135 | val |= confmask; | ||
136 | |||
137 | /* | ||
138 | * As recommended by the spec, disable the interrupt before changing | ||
139 | * the configuration | ||
140 | */ | ||
141 | if (readl(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) { | ||
142 | writel(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff); | ||
143 | enabled = true; | ||
144 | } | ||
145 | |||
146 | writel(val, base + GIC_DIST_CONFIG + confoff); | ||
147 | |||
148 | if (enabled) | ||
149 | writel(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); | ||
150 | |||
151 | spin_unlock(&irq_controller_lock); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
111 | #ifdef CONFIG_SMP | 156 | #ifdef CONFIG_SMP |
112 | static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val) | 157 | static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val) |
113 | { | 158 | { |
@@ -161,6 +206,7 @@ static struct irq_chip gic_chip = { | |||
161 | .ack = gic_ack_irq, | 206 | .ack = gic_ack_irq, |
162 | .mask = gic_mask_irq, | 207 | .mask = gic_mask_irq, |
163 | .unmask = gic_unmask_irq, | 208 | .unmask = gic_unmask_irq, |
209 | .set_type = gic_set_type, | ||
164 | #ifdef CONFIG_SMP | 210 | #ifdef CONFIG_SMP |
165 | .set_affinity = gic_set_cpu, | 211 | .set_affinity = gic_set_cpu, |
166 | #endif | 212 | #endif |