Sebastian Siewior
Tue, 08 Apr 2008 10:50:27 -0700
This patch implements a basic irq_chip which supports mask / unmask of interrupt sources. The plan is move more and more drivers to this approach and setting the IRQ source by them self. This is only enabled M523x. Other platforms work as usual.
Signed-off-by: Sebastian Siewior <[EMAIL PROTECTED]>
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -119,6 +119,7 @@ config M520x
config M523x
bool "MCF523x"
select GENERIC_CLOCKEVENTS
+ select GENERIC_HARDIRQS_NO__DO_IRQ
help
Freescale Coldfire 5230/1/2/4/5 processor support
@@ -674,6 +675,9 @@ config ROMKERNEL
endchoice
+config GENERIC_HARDIRQS_NO__DO_IRQ
+ bool "Force generic IRQ implementation"
+
source "kernel/time/Kconfig"
if COLDFIRE
source "kernel/Kconfig.preempt"
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68knommu/kernel/irq.c
@@ -23,7 +23,7 @@ asmlinkage void do_IRQ(int irq, struct p
struct pt_regs *oldregs = set_irq_regs(regs);
irq_enter();
- __do_IRQ(irq);
+ generic_handle_irq(irq);
irq_exit();
set_irq_regs(oldregs);
@@ -34,12 +34,16 @@ void ack_bad_irq(unsigned int irq)
printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
}
+#ifndef CONFIG_M523x
static struct irq_chip m_irq_chip = {
.name = "M68K-INTC",
.enable = enable_vector,
.disable = disable_vector,
.ack = ack_vector,
};
+#else
+void coldfire_init_irq_chip(void);
+#endif
void __init init_IRQ(void)
{
@@ -47,12 +51,16 @@ void __init init_IRQ(void)
init_vectors();
+#ifndef CONFIG_M523x
for (irq = 0; (irq < NR_IRQS); irq++) {
irq_desc[irq].status = IRQ_DISABLED;
irq_desc[irq].action = NULL;
irq_desc[irq].depth = 1;
irq_desc[irq].chip = &m_irq_chip;
}
+#else
+ coldfire_init_irq_chip();
+#endif
}
int show_interrupts(struct seq_file *p, void *v)
@@ -79,4 +87,3 @@ int show_interrupts(struct seq_file *p,
return 0;
}
-
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_COLDFIRE) += dma.o entry.o
obj-$(CONFIG_M5206) += timers.o
obj-$(CONFIG_M5206e) += timers.o
obj-$(CONFIG_M520x) += pit.o
-obj-$(CONFIG_M523x) += pit.o dma_timer.o
+obj-$(CONFIG_M523x) += pit.o dma_timer.o irq_chip.o
obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
obj-$(CONFIG_M5272) += timers.o
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/irq_chip.c
@@ -0,0 +1,110 @@
+/*
+ * IRQ-Chip implementation for Coldfire
+ *
+ * Author: Sebastian Siewior <[EMAIL PROTECTED]>
+ */
+
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+static void *coldfire_irqnum_to_mem(unsigned int irq)
+{
+ u32 imrp;
+
+ imrp = MCF_IPSBAR;
+#if defined(MCFINT_INTC1_VECBASE)
+ if (irq > MCFINT_INTC1_VECBASE) {
+ imrp += MCFICM_INTC1;
+ irq -= MCFINT_PER_INTC;
+ } else
+#endif
+ imrp += MCFICM_INTC0;
+
+ irq -= MCFINT_VECBASE;
+
+ if (irq > 32)
+ imrp += MCFINTC_IMRH;
+ else
+ imrp += MCFINTC_IMRL;
+
+ return (void *)imrp;
+}
+
+static unsigned int coldfire_irqnum_to_bit(unsigned int irq)
+{
+ irq -= MCFINT_VECBASE;
+
+ if (irq > 32)
+ irq -= 32;
+
+ return irq;
+}
+
+static void coldfire_mask(unsigned int irq)
+{
+ volatile unsigned long *imrp;
+ u32 mask;
+ u32 irq_bit;
+
+ imrp = coldfire_irqnum_to_mem(irq);
+ irq_bit = coldfire_irqnum_to_bit(irq);
+
+ mask = 1 << irq_bit;
+ *imrp |= mask;
+}
+
+static void coldfire_unmask(unsigned int irq)
+{
+ volatile unsigned long *imrp;
+ u32 mask;
+ u32 irq_bit;
+
+ imrp = coldfire_irqnum_to_mem(irq);
+ irq_bit = coldfire_irqnum_to_bit(irq);
+
+ mask = 1 << irq_bit;
+ *imrp &= ~mask;
+}
+
+static void coldfire_nop(unsigned int irq)
+{
+}
+
+static struct irq_chip m_irq_chip = {
+ .name = "M68K-INTC",
+ .ack = coldfire_nop,
+ .mask = coldfire_mask,
+ .unmask = coldfire_unmask,
+};
+
+void __init coldfire_init_irq_chip(void)
+{
+ volatile u32 *imrp;
+ volatile u8 *icrp;
+ u32 irq;
+ u32 i;
+
+ for (irq = 0; irq < NR_IRQS; irq++)
+ set_irq_chip_and_handler_name(irq, &m_irq_chip,
+ handle_level_irq, m_irq_chip.name);
+
+ /* setup prios for interrupt sources (first field is reserved) */
+ icrp = (u8 *)MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0;
+ for (i = 1; i <= 63; i++)
+ icrp[i] = i;
+
+ /* remove the disable all flag, disable all interrupt sources */
+ imrp = coldfire_irqnum_to_mem(MCFINT_VECBASE);
+ *imrp = 0xfffffffe;
+
+#if defined(MCFINT_INTC1_VECBASE)
+ icrp = (u8 *)MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_ICR0;
+ for (i = 1; i <= 63; i++)
+ icrp[i] = i;
+
+ imrp = coldfire_irqnum_to_mem(MCFINT_INTC1_VECBASE);
+ *imrp = 0xfffffffe;
+#endif
+}
--
_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev