aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-03-18 07:01:24 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-04-08 17:28:28 -0400
commitb594c6e20c7ff65e0f0775cb1866e97501c96846 (patch)
treed8f16e08f6611fd36c156156ec1160301f28c73d
parent567178077c369ae6a32f90926fb4172f7cf1f87f (diff)
irqchip: GICv3: 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-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/irqchip/irq-gic-v3.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index fd8850def1b8..4f2fb62e6f37 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -195,6 +195,19 @@ static void gic_enable_redist(bool enable)
195/* 195/*
196 * Routines to disable, enable, EOI and route interrupts 196 * Routines to disable, enable, EOI and route interrupts
197 */ 197 */
198static int gic_peek_irq(struct irq_data *d, u32 offset)
199{
200 u32 mask = 1 << (gic_irq(d) % 32);
201 void __iomem *base;
202
203 if (gic_irq_in_rdist(d))
204 base = gic_data_rdist_sgi_base();
205 else
206 base = gic_data.dist_base;
207
208 return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
209}
210
198static void gic_poke_irq(struct irq_data *d, u32 offset) 211static void gic_poke_irq(struct irq_data *d, u32 offset)
199{ 212{
200 u32 mask = 1 << (gic_irq(d) % 32); 213 u32 mask = 1 << (gic_irq(d) % 32);
@@ -223,6 +236,61 @@ static void gic_unmask_irq(struct irq_data *d)
223 gic_poke_irq(d, GICD_ISENABLER); 236 gic_poke_irq(d, GICD_ISENABLER);
224} 237}
225 238
239static int gic_irq_set_irqchip_state(struct irq_data *d,
240 enum irqchip_irq_state which, bool val)
241{
242 u32 reg;
243
244 if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
245 return -EINVAL;
246
247 switch (which) {
248 case IRQCHIP_STATE_PENDING:
249 reg = val ? GICD_ISPENDR : GICD_ICPENDR;
250 break;
251
252 case IRQCHIP_STATE_ACTIVE:
253 reg = val ? GICD_ISACTIVER : GICD_ICACTIVER;
254 break;
255
256 case IRQCHIP_STATE_MASKED:
257 reg = val ? GICD_ICENABLER : GICD_ISENABLER;
258 break;
259
260 default:
261 return -EINVAL;
262 }
263
264 gic_poke_irq(d, reg);
265 return 0;
266}
267
268static int gic_irq_get_irqchip_state(struct irq_data *d,
269 enum irqchip_irq_state which, bool *val)
270{
271 if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
272 return -EINVAL;
273
274 switch (which) {
275 case IRQCHIP_STATE_PENDING:
276 *val = gic_peek_irq(d, GICD_ISPENDR);
277 break;
278
279 case IRQCHIP_STATE_ACTIVE:
280 *val = gic_peek_irq(d, GICD_ISACTIVER);
281 break;
282
283 case IRQCHIP_STATE_MASKED:
284 *val = !gic_peek_irq(d, GICD_ISENABLER);
285 break;
286
287 default:
288 return -EINVAL;
289 }
290
291 return 0;
292}
293
226static void gic_eoi_irq(struct irq_data *d) 294static void gic_eoi_irq(struct irq_data *d)
227{ 295{
228 gic_write_eoir(gic_irq(d)); 296 gic_write_eoir(gic_irq(d));
@@ -418,19 +486,6 @@ static void gic_cpu_init(void)
418} 486}
419 487
420#ifdef CONFIG_SMP 488#ifdef CONFIG_SMP
421static int gic_peek_irq(struct irq_data *d, u32 offset)
422{
423 u32 mask = 1 << (gic_irq(d) % 32);
424 void __iomem *base;
425
426 if (gic_irq_in_rdist(d))
427 base = gic_data_rdist_sgi_base();
428 else
429 base = gic_data.dist_base;
430
431 return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
432}
433
434static int gic_secondary_init(struct notifier_block *nfb, 489static int gic_secondary_init(struct notifier_block *nfb,
435 unsigned long action, void *hcpu) 490 unsigned long action, void *hcpu)
436{ 491{
@@ -601,6 +656,8 @@ static struct irq_chip gic_chip = {
601 .irq_eoi = gic_eoi_irq, 656 .irq_eoi = gic_eoi_irq,
602 .irq_set_type = gic_set_type, 657 .irq_set_type = gic_set_type,
603 .irq_set_affinity = gic_set_affinity, 658 .irq_set_affinity = gic_set_affinity,
659 .irq_get_irqchip_state = gic_irq_get_irqchip_state,
660 .irq_set_irqchip_state = gic_irq_set_irqchip_state,
604}; 661};
605 662
606#define GIC_ID_NR (1U << gic_data.rdists.id_bits) 663#define GIC_ID_NR (1U << gic_data.rdists.id_bits)