Please consider moving this to drivers/irqchip/. Ralf On Tue, Mar 01, 2016 at 08:48:14AM +0800, Binbin Zhou wrote: > Date: Tue, 1 Mar 2016 08:48:14 +0800 > From: Binbin Zhou <zhoubb@xxxxxxxxxx> > To: Ralf Baechle <ralf@xxxxxxxxxxxxxx> > Cc: John Crispin <john@xxxxxxxxxxx>, "Steven J . Hill" > <Steven.Hill@xxxxxxxxxx>, linux-mips@xxxxxxxxxxxxxx, Fuxin Zhang > <zhangfx@xxxxxxxxxx>, Zhangjin Wu <wuzhangjin@xxxxxxxxx>, Kelvin Cheung > <keguang.zhang@xxxxxxxxx>, Binbin Zhou <zhoubb@xxxxxxxxxx>, Chunbo Cui > <cuicb@xxxxxxxxxx>, Huacai Chen <chenhc@xxxxxxxxxx> > Subject: [PATCH v3 6/8] MIPS: Loongson-1A: Add IRQ type setting support > > Loongson 1A's INT controller support two different interrupt trigger mode: > level trigger and edge trigger. > > Whether the INT controller stores the external interrupts is > the difference between them. > The edge trigger should do this, and operate INT_CLR register > to clear the CPU interrupt state. > > Signed-off-by: Chunbo Cui <cuicb@xxxxxxxxxx> > Signed-off-by: Binbin Zhou <zhoubb@xxxxxxxxxx> > Signed-off-by: Huacai Chen <chenhc@xxxxxxxxxx> > --- > arch/mips/loongson32/common/irq.c | 46 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 46 insertions(+) > > diff --git a/arch/mips/loongson32/common/irq.c b/arch/mips/loongson32/common/irq.c > index 455a770..01e8cb9 100644 > --- a/arch/mips/loongson32/common/irq.c > +++ b/arch/mips/loongson32/common/irq.c > @@ -62,12 +62,57 @@ static void ls1x_irq_unmask(struct irq_data *d) > | (1 << bit), LS1X_INTC_INTIEN(n)); > } > > +static int ls1x_irq_set_type(struct irq_data *data, unsigned int flow_type) > +{ > + unsigned int bit = (data->irq - LS1X_IRQ_BASE) & 0x1f; > + unsigned int n = (data->irq - LS1X_IRQ_BASE) >> 5; > + > + if (flow_type & IRQ_TYPE_EDGE_BOTH) { > + if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { > + pr_info("ls1x irq don't support both rising and falling\n"); > + return -1; > + } > + ls1x_writel(ls1x_readl(LS1X_INTC_INTCLR(n)) > + | (1 << bit), LS1X_INTC_INTCLR(n)); > + if (flow_type & IRQ_TYPE_EDGE_RISING) > + ls1x_writel(ls1x_readl(LS1X_INTC_INTPOL(n)) > + | (1 << bit), LS1X_INTC_INTPOL(n)); > + else > + ls1x_writel(ls1x_readl(LS1X_INTC_INTPOL(n)) > + & ~(1 << bit), LS1X_INTC_INTPOL(n)); > + > + ls1x_writel(ls1x_readl(LS1X_INTC_INTEDGE(n)) > + | (1 << bit), LS1X_INTC_INTEDGE(n)); > + ls1x_writel(ls1x_readl(LS1X_INTC_INTIEN(n)) > + | (1 << bit), LS1X_INTC_INTIEN(n)); > + irq_set_handler_locked(data, handle_edge_irq); > + } else if (flow_type && IRQ_TYPE_LEVEL_MASK) { > + ls1x_writel(ls1x_readl(LS1X_INTC_INTCLR(n)) > + | (1 << bit), LS1X_INTC_INTCLR(n)); > + if (flow_type & IRQ_TYPE_LEVEL_HIGH) > + ls1x_writel(ls1x_readl(LS1X_INTC_INTPOL(n)) > + | (1 << bit), LS1X_INTC_INTPOL(n)); > + else if (flow_type & IRQ_TYPE_LEVEL_LOW) > + ls1x_writel(ls1x_readl(LS1X_INTC_INTPOL(n)) > + & ~(1 << bit), LS1X_INTC_INTPOL(n)); > + > + ls1x_writel(ls1x_readl(LS1X_INTC_INTEDGE(n)) > + & ~(1 << bit), LS1X_INTC_INTEDGE(n)); > + ls1x_writel(ls1x_readl(LS1X_INTC_INTIEN(n)) > + | (1 << bit), LS1X_INTC_INTIEN(n)); > + irq_set_handler_locked(data, handle_level_irq); > + } > + > + return IRQ_SET_MASK_OK; > +} > + > static struct irq_chip ls1x_irq_chip = { > .name = "LS1X-INTC", > .irq_ack = ls1x_irq_ack, > .irq_mask = ls1x_irq_mask, > .irq_mask_ack = ls1x_irq_mask_ack, > .irq_unmask = ls1x_irq_unmask, > + .irq_set_type = ls1x_irq_set_type, > }; > > static void ls1x_irq_dispatch(int n) > @@ -138,6 +183,7 @@ static void __init ls1x_irq_init(int base) > setup_irq(INT1_IRQ, &cascade_irqaction); > setup_irq(INT2_IRQ, &cascade_irqaction); > setup_irq(INT3_IRQ, &cascade_irqaction); > + setup_irq(INT4_IRQ, &cascade_irqaction); > } > > void __init arch_init_irq(void) > -- > 1.9.1 > Ralf