diff options
Diffstat (limited to 'arch/sparc/kernel/sun4m_irq.c')
-rw-r--r-- | arch/sparc/kernel/sun4m_irq.c | 182 |
1 files changed, 93 insertions, 89 deletions
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 7f3b97ff62c1..3c6657a4caec 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -1,5 +1,5 @@ -/* sun4m_irq.c - * arch/sparc/kernel/sun4m_irq.c: +/* + * sun4m irq support * * djhr: Hacked out of irq.c into a CPU dependent version. * @@ -9,36 +9,92 @@ * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) */ -#include <linux/errno.h> -#include <linux/linkage.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/smp.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/of.h> -#include <linux/of_device.h> - -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/system.h> -#include <asm/psr.h> -#include <asm/vaddrs.h> #include <asm/timer.h> -#include <asm/openprom.h> -#include <asm/oplib.h> #include <asm/traps.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> -#include <asm/smp.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/cacheflush.h> #include "irq.h" +#include "kernel.h" + +/* Sample sun4m IRQ layout: + * + * 0x22 - Power + * 0x24 - ESP SCSI + * 0x26 - Lance ethernet + * 0x2b - Floppy + * 0x2c - Zilog uart + * 0x32 - SBUS level 0 + * 0x33 - Parallel port, SBUS level 1 + * 0x35 - SBUS level 2 + * 0x37 - SBUS level 3 + * 0x39 - Audio, Graphics card, SBUS level 4 + * 0x3b - SBUS level 5 + * 0x3d - SBUS level 6 + * + * Each interrupt source has a mask bit in the interrupt registers. + * When the mask bit is set, this blocks interrupt deliver. So you + * clear the bit to enable the interrupt. + * + * Interrupts numbered less than 0x10 are software triggered interrupts + * and unused by Linux. + * + * Interrupt level assignment on sun4m: + * + * level source + * ------------------------------------------------------------ + * 1 softint-1 + * 2 softint-2, VME/SBUS level 1 + * 3 softint-3, VME/SBUS level 2 + * 4 softint-4, onboard SCSI + * 5 softint-5, VME/SBUS level 3 + * 6 softint-6, onboard ETHERNET + * 7 softint-7, VME/SBUS level 4 + * 8 softint-8, onboard VIDEO + * 9 softint-9, VME/SBUS level 5, Module Interrupt + * 10 softint-10, system counter/timer + * 11 softint-11, VME/SBUS level 6, Floppy + * 12 softint-12, Keyboard/Mouse, Serial + * 13 softint-13, VME/SBUS level 7, ISDN Audio + * 14 softint-14, per-processor counter/timer + * 15 softint-15, Asynchronous Errors (broadcast) + * + * Each interrupt source is masked distinctly in the sun4m interrupt + * registers. The PIL level alone is therefore ambiguous, since multiple + * interrupt sources map to a single PIL. + * + * This ambiguity is resolved in the 'intr' property for device nodes + * in the OF device tree. Each 'intr' property entry is composed of + * two 32-bit words. The first word is the IRQ priority value, which + * is what we're intersted in. The second word is the IRQ vector, which + * is unused. + * + * The low 4 bits of the IRQ priority indicate the PIL, and the upper + * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20 + * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled. + * + * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI + * whereas a value of 0x33 is SBUS level 2. Here are some sample + * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and + * Tadpole S3 GX systems. + * + * esp: 0x24 onboard ESP SCSI + * le: 0x26 onboard Lance ETHERNET + * p9100: 0x32 SBUS level 1 P9100 video + * bpp: 0x33 SBUS level 2 BPP parallel port device + * DBRI: 0x39 SBUS level 5 DBRI ISDN audio + * SUNW,leo: 0x39 SBUS level 5 LEO video + * pcmcia: 0x3b SBUS level 6 PCMCIA controller + * uctrl: 0x3b SBUS level 6 UCTRL device + * modem: 0x3d SBUS level 7 MODEM + * zs: 0x2c onboard keyboard/mouse/serial + * floppy: 0x2b onboard Floppy + * power: 0x22 onboard power device (XXX unknown mask bit XXX) + */ + struct sun4m_irq_percpu { u32 pending; @@ -61,9 +117,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; /* Dave Redman (djhr@tadpole.co.uk) * The sun4m interrupt registers. */ -#define SUN4M_INT_ENABLE 0x80000000 -#define SUN4M_INT_E14 0x00000080 -#define SUN4M_INT_E10 0x00080000 +#define SUN4M_INT_ENABLE 0x80000000 +#define SUN4M_INT_E14 0x00000080 +#define SUN4M_INT_E10 0x00080000 #define SUN4M_HARD_INT(x) (0x000000001 << (x)) #define SUN4M_SOFT_INT(x) (0x000010000 << (x)) @@ -99,59 +155,6 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; #define OBP_INT_LEVEL_SBUS 0x30 #define OBP_INT_LEVEL_VME 0x40 -/* Interrupt level assignment on sun4m: - * - * level source - * ------------------------------------------------------------ - * 1 softint-1 - * 2 softint-2, VME/SBUS level 1 - * 3 softint-3, VME/SBUS level 2 - * 4 softint-4, onboard SCSI - * 5 softint-5, VME/SBUS level 3 - * 6 softint-6, onboard ETHERNET - * 7 softint-7, VME/SBUS level 4 - * 8 softint-8, onboard VIDEO - * 9 softint-9, VME/SBUS level 5, Module Interrupt - * 10 softint-10, system counter/timer - * 11 softint-11, VME/SBUS level 6, Floppy - * 12 softint-12, Keyboard/Mouse, Serial - * 13 softint-13, VME/SBUS level 7, ISDN Audio - * 14 softint-14, per-processor counter/timer - * 15 softint-15, Asynchronous Errors (broadcast) - * - * Each interrupt source is masked distinctly in the sun4m interrupt - * registers. The PIL level alone is therefore ambiguous, since multiple - * interrupt sources map to a single PIL. - * - * This ambiguity is resolved in the 'intr' property for device nodes - * in the OF device tree. Each 'intr' property entry is composed of - * two 32-bit words. The first word is the IRQ priority value, which - * is what we're intersted in. The second word is the IRQ vector, which - * is unused. - * - * The low 4 bits of the IRQ priority indicate the PIL, and the upper - * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20 - * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled. - * - * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI - * whereas a value of 0x33 is SBUS level 2. Here are some sample - * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and - * Tadpole S3 GX systems. - * - * esp: 0x24 onboard ESP SCSI - * le: 0x26 onboard Lance ETHERNET - * p9100: 0x32 SBUS level 1 P9100 video - * bpp: 0x33 SBUS level 2 BPP parallel port device - * DBRI: 0x39 SBUS level 5 DBRI ISDN audio - * SUNW,leo: 0x39 SBUS level 5 LEO video - * pcmcia: 0x3b SBUS level 6 PCMCIA controller - * uctrl: 0x3b SBUS level 6 UCTRL device - * modem: 0x3d SBUS level 7 MODEM - * zs: 0x2c onboard keyboard/mouse/serial - * floppy: 0x2b onboard Floppy - * power: 0x22 onboard power device (XXX unknown mask bit XXX) - */ - static unsigned long irq_mask[0x50] = { /* SMP */ 0, SUN4M_SOFT_INT(1), @@ -193,7 +196,7 @@ static unsigned long irq_mask[0x50] = { static unsigned long sun4m_get_irqmask(unsigned int irq) { unsigned long mask; - + if (irq < 0x50) mask = irq_mask[irq]; else @@ -217,7 +220,7 @@ static void sun4m_disable_irq(unsigned int irq_nr) sbus_writel(mask, &sun4m_irq_global->mask_set); else sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); - local_irq_restore(flags); + local_irq_restore(flags); } static void sun4m_enable_irq(unsigned int irq_nr) @@ -226,17 +229,17 @@ static void sun4m_enable_irq(unsigned int irq_nr) int cpu = smp_processor_id(); /* Dreadful floppy hack. When we use 0x2b instead of - * 0x0b the system blows (it starts to whistle!). - * So we continue to use 0x0b. Fixme ASAP. --P3 - */ - if (irq_nr != 0x0b) { + * 0x0b the system blows (it starts to whistle!). + * So we continue to use 0x0b. Fixme ASAP. --P3 + */ + if (irq_nr != 0x0b) { mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) sbus_writel(mask, &sun4m_irq_global->mask_clear); else sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); - local_irq_restore(flags); + local_irq_restore(flags); } else { local_irq_save(flags); sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); @@ -260,7 +263,7 @@ static unsigned long cpu_pil_to_imask[16] = { /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, /*14*/ SUN4M_INT_E14, -/*15*/ SUN4M_INT_ERROR +/*15*/ SUN4M_INT_ERROR, }; /* We assume the caller has disabled local interrupts when these are called, @@ -280,12 +283,14 @@ static void sun4m_enable_pil_irq(unsigned int pil) static void sun4m_send_ipi(int cpu, int level) { unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); } static void sun4m_clear_ipi(int cpu, int level) { unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); } @@ -314,7 +319,7 @@ struct sun4m_timer_global { static struct sun4m_timer_global __iomem *timers_global; -#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) +#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); @@ -407,7 +412,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) #ifdef CONFIG_SMP { unsigned long flags; - extern unsigned long lvl14_save[4]; struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; /* For SMP we use the level 14 ticker, however the bootup code |