patch-2.3.23 linux/include/asm-arm/arch-sa1100/irq.h

Next file: linux/include/asm-arm/arch-sa1100/irqs.h
Previous file: linux/include/asm-arm/arch-sa1100/io.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.22/linux/include/asm-arm/arch-sa1100/irq.h linux/include/asm-arm/arch-sa1100/irq.h
@@ -0,0 +1,183 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/irq.h
+ *
+ * Copyright (C) 1996-1999 Russell king
+ * Copyright (C) 1999 Hugo Fiennes
+ *
+ * Changelog:
+ *   22-08-1998	RMK	Restructured IRQ routines
+ *   06-01-1999	HBF	SA1100 twiddles
+ *   12-02-1999	NP	added ICCR
+ *   17-02-1999	NP	empeg henry ugly hacks now in a separate file ;)
+ *   11-08-1999	PD	SA1101 support added
+ *   25-09-1999	RMK	Merged into main ARM tree, cleaned up
+ */
+static inline unsigned int fixup_irq(unsigned int irq)
+{
+#ifdef CONFIG_SA1101
+	if (irq == SA1101_IRQ) {
+		unsigned long mask;
+		mask = INTSTATCLR0 & INTENABLE0;
+		irq  = 32;
+		if (!mask) {
+			mask = IRQSTATCLR1 & INTENABLE1;
+			irq  = 64;
+		}
+		if (mask)
+			while ((mask & 1) == 0) {
+				mask >>= 1;
+				irq += 1;
+			}
+	}
+#endif
+	return irq;
+}
+
+/* We don't need to ACK IRQs on the SA1100 unless they're <= 10,
+ * ie, an edge-detect.
+ */
+static void sa1100_mask_and_ack_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << irq);
+	if (irq <= 10)
+		GEDR = 1 << irq;
+}
+
+static void sa1100_mask_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << irq);
+}
+
+static void sa1100_unmask_irq(unsigned int irq)
+{
+	ICMR |= 1 << irq;
+}
+
+#ifdef CONFIG_SA1101
+
+static void sa1101_mask_and_ack_lowirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE0 &= ~mask;
+	GEDR = 1 << SA1101_IRQ;
+	INTSTATCLR0 = mask;
+}
+
+static void sa1101_mask_and_ack_highirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE1 &= ~mask;
+	GEDR = 1 << SA1101_IRQ;
+	INTSTATCLR1 = mask;
+}
+
+static void sa1101_mask_lowirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE0 &= ~mask;
+}
+
+static void sa1101_mask_highirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE1 &= ~mask;
+}
+
+/*
+ * unmasking an IRq with the wrong polarity can be
+ * fatal, but there is no need to check this in the
+ * interrupt code - it will be spotted anyway ;-)
+ */
+static void sa1101_unmask_lowirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE0 |= mask;
+	ICMR |= 1 << SA1101_IRQ;
+}
+
+static void sa1101_unmask_highirq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 31);
+
+	INTENABLE1 |= mask;
+	ICMR |= 1 << SA1101_IRQ;
+}
+#endif
+
+static __inline__ void irq_init_irq(void)
+{
+	int irq;
+
+	/* disable all IRQs */
+	ICMR = 0;
+
+	/* all IRQs are IRQ, not FIQ */
+	ICLR = 0;
+
+	/* clear all GPIO edge detects */
+	GEDR = -1;
+
+#ifdef CONFIG_SA1101
+	/* turn on interrupt controller */
+	SKPCR |= 4;
+
+	/* disable all IRQs */
+	INTENABLE0 = 0;
+	INTENABLE1 = 0;
+
+	/* detect on rising edge */
+	INTPOL0 = 0;
+	INTPOL1 = 0;
+
+	/* clear all IRQs */
+	INTSTATCLR0 = -1;
+	INTSTATCLR1 = -1;
+
+	/* SA1101 generates a rising edge */
+	GRER |= 1 << SA1101_IRQ;
+	GPER &= ~(1 << SA1101_IRQ);
+#endif
+
+	/*
+	 * Whatever the doc says, this has to be set for the wait-on-irq
+	 * instruction to work... on a SA1100 rev 9 at least.
+	 */
+	ICCR = 1;
+
+#ifndef CONFIG_SA1101
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= sa1100_mask_and_ack_irq;
+		irq_desc[irq].mask	= sa1100_mask_irq;
+		irq_desc[irq].unmask	= sa1100_unmask_irq;
+	}
+#else
+	for (irq = 0; irq < 31; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= sa1100_mask_and_ack_irq;
+		irq_desc[irq].mask	= sa1100_mask_irq;
+		irq_desc[irq].unmask	= sa1100_unmask_irq;
+	}
+	for (irq = 32; irq < 63; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= sa1101_mask_and_ack_lowirq;
+		irq_desc[irq].mask	= sa1101_mask_lowirq;
+		irq_desc[irq].unmask	= sa1101_unmask_lowirq;
+	}
+	for (irq = 64; irq < NR_IRQS; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= sa1101_mask_and_ack_highirq;
+		irq_desc[irq].mask	= sa1101_mask_highirq;
+		irq_desc[irq].unmask	= sa1101_unmask_highirq;
+	}
+#endif
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)