summaryrefslogtreecommitdiff
path: root/arch/mips/loongson32/common/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/loongson32/common/irq.c')
-rw-r--r--arch/mips/loongson32/common/irq.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/arch/mips/loongson32/common/irq.c b/arch/mips/loongson32/common/irq.c
index 455a7704a90f..635a4abe1f48 100644
--- a/arch/mips/loongson32/common/irq.c
+++ b/arch/mips/loongson32/common/irq.c
@@ -62,12 +62,58 @@ static void ls1x_irq_unmask(struct irq_data *d)
| (1 << bit), LS1X_INTC_INTIEN(n));
}
+static int ls1x_irq_settype(struct irq_data *d, unsigned int type)
+{
+ unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
+ | (1 << bit), LS1X_INTC_INTPOL(n));
+ __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
+ & ~(1 << bit), LS1X_INTC_INTEDGE(n));
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
+ & ~(1 << bit), LS1X_INTC_INTPOL(n));
+ __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
+ & ~(1 << bit), LS1X_INTC_INTEDGE(n));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
+ | (1 << bit), LS1X_INTC_INTPOL(n));
+ __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
+ | (1 << bit), LS1X_INTC_INTEDGE(n));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
+ & ~(1 << bit), LS1X_INTC_INTPOL(n));
+ __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
+ | (1 << bit), LS1X_INTC_INTEDGE(n));
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
+ & ~(1 << bit), LS1X_INTC_INTPOL(n));
+ __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
+ | (1 << bit), LS1X_INTC_INTEDGE(n));
+ break;
+ case IRQ_TYPE_NONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
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_settype,
};
static void ls1x_irq_dispatch(int n)
@@ -107,7 +153,7 @@ asmlinkage void plat_irq_dispatch(void)
}
-struct irqaction cascade_irqaction = {
+static struct irqaction cascade_irqaction = {
.handler = no_action,
.name = "cascade",
.flags = IRQF_NO_THREAD,
@@ -120,7 +166,7 @@ static void __init ls1x_irq_init(int base)
/* Disable interrupts and clear pending,
* setup all IRQs as high level triggered
*/
- for (n = 0; n < 4; n++) {
+ for (n = 0; n < INTN; n++) {
__raw_writel(0x0, LS1X_INTC_INTIEN(n));
__raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
__raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
@@ -129,7 +175,7 @@ static void __init ls1x_irq_init(int base)
}
- for (n = base; n < LS1X_IRQS; n++) {
+ for (n = base; n < NR_IRQS; n++) {
irq_set_chip_and_handler(n, &ls1x_irq_chip,
handle_level_irq);
}
@@ -138,6 +184,9 @@ 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);
+#if defined(CONFIG_LOONGSON1_LS1C)
+ setup_irq(INT4_IRQ, &cascade_irqaction);
+#endif
}
void __init arch_init_irq(void)