diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2015-03-18 07:01:23 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-04-08 17:28:28 -0400 |
commit | 567178077c369ae6a32f90926fb4172f7cf1f87f (patch) | |
tree | f466d3f7aaf24dee906acd02564e5238dbf0c178 /drivers/irqchip | |
parent | 1b7047edfcfb257f69e306c9afbab150cb987717 (diff) |
irqchip: GIC: Add support for irq_[get, set]_irqchip_state()
Add the required hooks for the internal state of an interrupt
to be exposed to other subsystems.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Phong Vo <pvo@apm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Tin Huynh <tnhuynh@apm.com>
Cc: Y Vo <yvo@apm.com>
Cc: Toan Le <toanle@apm.com>
Cc: Bjorn Andersson <bjorn@kryo.se>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Link: http://lkml.kernel.org/r/1426676484-21812-3-git-send-email-marc.zyngier@arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-gic.c | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 471e1cdc1933..0b4a4d0238e7 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -151,13 +151,24 @@ static inline unsigned int gic_irq(struct irq_data *d) | |||
151 | /* | 151 | /* |
152 | * Routines to acknowledge, disable and enable interrupts | 152 | * Routines to acknowledge, disable and enable interrupts |
153 | */ | 153 | */ |
154 | static void gic_mask_irq(struct irq_data *d) | 154 | static void gic_poke_irq(struct irq_data *d, u32 offset) |
155 | { | ||
156 | u32 mask = 1 << (gic_irq(d) % 32); | ||
157 | writel_relaxed(mask, gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4); | ||
158 | } | ||
159 | |||
160 | static int gic_peek_irq(struct irq_data *d, u32 offset) | ||
155 | { | 161 | { |
156 | u32 mask = 1 << (gic_irq(d) % 32); | 162 | u32 mask = 1 << (gic_irq(d) % 32); |
163 | return !!(readl_relaxed(gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4) & mask); | ||
164 | } | ||
165 | |||
166 | static void gic_mask_irq(struct irq_data *d) | ||
167 | { | ||
157 | unsigned long flags; | 168 | unsigned long flags; |
158 | 169 | ||
159 | raw_spin_lock_irqsave(&irq_controller_lock, flags); | 170 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
160 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); | 171 | gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR); |
161 | if (gic_arch_extn.irq_mask) | 172 | if (gic_arch_extn.irq_mask) |
162 | gic_arch_extn.irq_mask(d); | 173 | gic_arch_extn.irq_mask(d); |
163 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); | 174 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
@@ -165,13 +176,12 @@ static void gic_mask_irq(struct irq_data *d) | |||
165 | 176 | ||
166 | static void gic_unmask_irq(struct irq_data *d) | 177 | static void gic_unmask_irq(struct irq_data *d) |
167 | { | 178 | { |
168 | u32 mask = 1 << (gic_irq(d) % 32); | ||
169 | unsigned long flags; | 179 | unsigned long flags; |
170 | 180 | ||
171 | raw_spin_lock_irqsave(&irq_controller_lock, flags); | 181 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
172 | if (gic_arch_extn.irq_unmask) | 182 | if (gic_arch_extn.irq_unmask) |
173 | gic_arch_extn.irq_unmask(d); | 183 | gic_arch_extn.irq_unmask(d); |
174 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); | 184 | gic_poke_irq(d, GIC_DIST_ENABLE_SET); |
175 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); | 185 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
176 | } | 186 | } |
177 | 187 | ||
@@ -186,6 +196,55 @@ static void gic_eoi_irq(struct irq_data *d) | |||
186 | writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); | 196 | writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); |
187 | } | 197 | } |
188 | 198 | ||
199 | static int gic_irq_set_irqchip_state(struct irq_data *d, | ||
200 | enum irqchip_irq_state which, bool val) | ||
201 | { | ||
202 | u32 reg; | ||
203 | |||
204 | switch (which) { | ||
205 | case IRQCHIP_STATE_PENDING: | ||
206 | reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR; | ||
207 | break; | ||
208 | |||
209 | case IRQCHIP_STATE_ACTIVE: | ||
210 | reg = val ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR; | ||
211 | break; | ||
212 | |||
213 | case IRQCHIP_STATE_MASKED: | ||
214 | reg = val ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET; | ||
215 | break; | ||
216 | |||
217 | default: | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | gic_poke_irq(d, reg); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int gic_irq_get_irqchip_state(struct irq_data *d, | ||
226 | enum irqchip_irq_state which, bool *val) | ||
227 | { | ||
228 | switch (which) { | ||
229 | case IRQCHIP_STATE_PENDING: | ||
230 | *val = gic_peek_irq(d, GIC_DIST_PENDING_SET); | ||
231 | break; | ||
232 | |||
233 | case IRQCHIP_STATE_ACTIVE: | ||
234 | *val = gic_peek_irq(d, GIC_DIST_ACTIVE_SET); | ||
235 | break; | ||
236 | |||
237 | case IRQCHIP_STATE_MASKED: | ||
238 | *val = !gic_peek_irq(d, GIC_DIST_ENABLE_SET); | ||
239 | break; | ||
240 | |||
241 | default: | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
189 | static int gic_set_type(struct irq_data *d, unsigned int type) | 248 | static int gic_set_type(struct irq_data *d, unsigned int type) |
190 | { | 249 | { |
191 | void __iomem *base = gic_dist_base(d); | 250 | void __iomem *base = gic_dist_base(d); |
@@ -329,6 +388,8 @@ static struct irq_chip gic_chip = { | |||
329 | .irq_set_affinity = gic_set_affinity, | 388 | .irq_set_affinity = gic_set_affinity, |
330 | #endif | 389 | #endif |
331 | .irq_set_wake = gic_set_wake, | 390 | .irq_set_wake = gic_set_wake, |
391 | .irq_get_irqchip_state = gic_irq_get_irqchip_state, | ||
392 | .irq_set_irqchip_state = gic_irq_set_irqchip_state, | ||
332 | }; | 393 | }; |
333 | 394 | ||
334 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | 395 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) |