From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933047AbaIOXwa (ORCPT ); Mon, 15 Sep 2014 19:52:30 -0400 Received: from mail-ig0-f202.google.com ([209.85.213.202]:61342 "EHLO mail-ig0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757235AbaIOXvm (ORCPT ); Mon, 15 Sep 2014 19:51:42 -0400 From: Andrew Bresticker To: Ralf Baechle , Thomas Gleixner , Jason Cooper Cc: Andrew Bresticker , Jeffrey Deans , Markos Chandras , Paul Burton , Qais Yousef , Jonas Gorski , John Crispin , David Daney , linux-mips@linux-mips.org, linux-kernel@vger.kernel.org Subject: [PATCH 15/24] irqchip: mips-gic: Implement irq_set_type callback Date: Mon, 15 Sep 2014 16:51:18 -0700 Message-Id: <1410825087-5497-16-git-send-email-abrestic@chromium.org> X-Mailer: git-send-email 2.1.0.rc2.206.gedb03e5 In-Reply-To: <1410825087-5497-1-git-send-email-abrestic@chromium.org> References: <1410825087-5497-1-git-send-email-abrestic@chromium.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement an irq_set_type callback for the GIC which is used to set the polarity and trigger type of GIC interrupts. Signed-off-by: Andrew Bresticker --- arch/mips/include/asm/gic.h | 9 ++++++++ drivers/irqchip/irq-mips-gic.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 1bf7985..662b567 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -23,6 +23,8 @@ #define GIC_POL_NEG 0 #define GIC_TRIG_EDGE 1 #define GIC_TRIG_LEVEL 0 +#define GIC_TRIG_DUAL_ENABLE 1 +#define GIC_TRIG_DUAL_DISABLE 0 #define MSK(n) ((1 << (n)) - 1) #define REG32(addr) (*(volatile unsigned int *) (addr)) @@ -179,6 +181,13 @@ GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ (trig) << GIC_INTR_BIT(intr)) +/* Dual edge triggering : Reset Value is always 0 */ +#define GIC_SH_SET_DUAL_OFS 0x0200 +#define GIC_SET_DUAL(intr, dual) \ + GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_DUAL_OFS + \ + GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ + (dual) << GIC_INTR_BIT(intr)) + /* Mask manipulation */ #define GIC_SH_SMASK_OFS 0x0380 #define GIC_SET_INTR_MASK(intr) \ diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 0dc2972..cde743c 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -246,6 +246,56 @@ static void gic_ack_irq(struct irq_data *d) GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base); } +static int gic_set_type(struct irq_data *d, unsigned int type) +{ + unsigned int irq = d->irq - gic_irq_base; + bool is_edge; + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_FALLING: + GIC_SET_POLARITY(irq, GIC_POL_NEG); + GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); + GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); + is_edge = true; + break; + case IRQ_TYPE_EDGE_RISING: + GIC_SET_POLARITY(irq, GIC_POL_POS); + GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); + GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); + is_edge = true; + break; + case IRQ_TYPE_EDGE_BOTH: + /* polarity is irrelevant in this case */ + GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); + GIC_SET_DUAL(irq, GIC_TRIG_DUAL_ENABLE); + is_edge = true; + break; + case IRQ_TYPE_LEVEL_LOW: + GIC_SET_POLARITY(irq, GIC_POL_NEG); + GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL); + GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); + is_edge = false; + break; + case IRQ_TYPE_LEVEL_HIGH: + default: + GIC_SET_POLARITY(irq, GIC_POL_POS); + GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL); + GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); + is_edge = false; + break; + } + + if (is_edge) { + gic_irq_flags[irq] |= GIC_TRIG_EDGE; + __irq_set_handler_locked(d->irq, handle_edge_irq); + } else { + gic_irq_flags[irq] &= ~GIC_TRIG_EDGE; + __irq_set_handler_locked(d->irq, handle_level_irq); + } + + return 0; +} + #ifdef CONFIG_SMP static DEFINE_SPINLOCK(gic_lock); @@ -286,6 +336,7 @@ static struct irq_chip gic_irq_controller = { .irq_mask_ack = gic_ack_irq, .irq_unmask = gic_unmask_irq, .irq_eoi = gic_unmask_irq, + .irq_set_type = gic_set_type, #ifdef CONFIG_SMP .irq_set_affinity = gic_set_affinity, #endif -- 2.1.0.rc2.206.gedb03e5