Skip to content

Commit

Permalink
m68knommu: general interrupt controller for ColdFire many 52xx parts
Browse files Browse the repository at this point in the history
Create general interrupt controller code for the many ColdFire version 2
cores that use the two region INTC interrupt controller. This includes the
523x family, 5270, 5271, 5274, 5275, and the 528x families.

This code does proper masking and unmasking of interrupts. With this in
place some of the driver hacks in place to support ColdFire interrupts
can finally go away.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
  • Loading branch information
Greg Ungerer committed Sep 15, 2009
1 parent d0d77c2 commit 2fba4f0
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 4 deletions.
3 changes: 2 additions & 1 deletion arch/m68knommu/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
set_irq_regs(oldregs);
}

#if !defined(CONFIG_M520x)
#if !defined(CONFIG_M520x) && !defined(CONFIG_M523x) && \
!defined(CONFIG_M527x) && !defined(CONFIG_M528x)

static struct irq_chip m_irq_chip = {
.name = "M68K-INTC",
Expand Down
6 changes: 3 additions & 3 deletions arch/m68knommu/platform/coldfire/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ obj-$(CONFIG_COLDFIRE) += clk.o dma.o entry.o vectors.o
obj-$(CONFIG_M5206) += timers.o
obj-$(CONFIG_M5206e) += timers.o
obj-$(CONFIG_M520x) += pit.o intc-simr.o
obj-$(CONFIG_M523x) += pit.o dma_timer.o
obj-$(CONFIG_M523x) += pit.o dma_timer.o intc-2.o
obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
obj-$(CONFIG_M527x) += pit.o intc-2.o
obj-$(CONFIG_M5272) += timers.o
obj-$(CONFIG_M528x) += pit.o
obj-$(CONFIG_M528x) += pit.o intc-2.o
obj-$(CONFIG_M5307) += timers.o
obj-$(CONFIG_M532x) += timers.o
obj-$(CONFIG_M5407) += timers.o
Expand Down
93 changes: 93 additions & 0 deletions arch/m68knommu/platform/coldfire/intc-2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* intc-1.c
*
* (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/

#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/traps.h>

/*
* Each vector needs a unique priority and level asscoiated with it.
* We don't really care so much what they are, we don't rely on the
* tranditional priority interrupt scheme of the m68k/ColdFire.
*/
static u8 intc_intpri = 0x36;

static void intc_irq_mask(unsigned int irq)
{
if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
unsigned long imraddr;
u32 val, imrbit;

irq -= MCFINT_VECBASE;
imraddr = MCF_IPSBAR;
imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
imrbit = 0x1 << (irq & 0x1f);

val = __raw_readl(imraddr);
__raw_writel(val | imrbit, imraddr);
}
}

static void intc_irq_unmask(unsigned int irq)
{
if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
unsigned long intaddr, imraddr, icraddr;
u32 val, imrbit;

irq -= MCFINT_VECBASE;
intaddr = MCF_IPSBAR;
intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
imrbit = 0x1 << (irq & 0x1f);

/* Don't set the "maskall" bit! */
if ((irq & 0x20) == 0)
imrbit |= 0x1;

if (__raw_readb(icraddr) == 0)
__raw_writeb(intc_intpri--, icraddr);

val = __raw_readl(imraddr);
__raw_writel(val & ~imrbit, imraddr);
}
}

static struct irq_chip intc_irq_chip = {
.name = "CF-INTC",
.mask = intc_irq_mask,
.unmask = intc_irq_unmask,
};

void __init init_IRQ(void)
{
int irq;

init_vectors();

/* Mask all interrupt sources */
__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);

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 = &intc_irq_chip;
}
}

0 comments on commit 2fba4f0

Please sign in to comment.