diff options
Diffstat (limited to 'arch/mips/sgi-ip32')
| -rw-r--r-- | arch/mips/sgi-ip32/Makefile | 4 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/Platform | 11 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/crime.c | 13 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-berr.c | 2 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-irq.c | 543 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-memory.c | 9 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-platform.c | 111 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-reset.c | 19 | ||||
| -rw-r--r-- | arch/mips/sgi-ip32/ip32-setup.c | 51 |
9 files changed, 368 insertions, 395 deletions
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile index 530bf848c3d..60f0227425e 100644 --- a/arch/mips/sgi-ip32/Makefile +++ b/arch/mips/sgi-ip32/Makefile @@ -3,7 +3,5 @@ # under Linux. # -obj-y += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \ +obj-y += ip32-berr.o ip32-irq.o ip32-platform.o ip32-setup.o ip32-reset.o \ crime.o ip32-memory.o - -EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/sgi-ip32/Platform b/arch/mips/sgi-ip32/Platform new file mode 100644 index 00000000000..0fea556f364 --- /dev/null +++ b/arch/mips/sgi-ip32/Platform @@ -0,0 +1,11 @@ +# +# SGI-IP32 (O2) +# +# Set the load address to >= 80069000 if you want to leave space for symmon, +# 0xffffffff80004000 for production kernels. Note that the value must be aligned to +# a multiple of the kernel stack size or the handling of the current variable +# will break. +# +platform-$(CONFIG_SGI_IP32) += sgi-ip32/ +cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 +load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 diff --git a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c index 41b5eca1148..563c614ad02 100644 --- a/arch/mips/sgi-ip32/crime.c +++ b/arch/mips/sgi-ip32/crime.c @@ -14,7 +14,6 @@ #include <asm/bootinfo.h> #include <asm/io.h> #include <asm/mipsregs.h> -#include <asm/ptrace.h> #include <asm/page.h> #include <asm/ip32/crime.h> #include <asm/ip32/mace.h> @@ -36,12 +35,11 @@ void __init crime_init(void) id = crime->id; rev = id & CRIME_ID_REV; id = (id & CRIME_ID_IDBITS) >> 4; - printk (KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n", - id, rev, field, (unsigned long) CRIME_BASE); + printk(KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n", + id, rev, field, (unsigned long) CRIME_BASE); } -irqreturn_t -crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t crime_memerr_intr(unsigned int irq, void *dev_id) { unsigned long stat, addr; int fatal = 0; @@ -92,14 +90,13 @@ crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -irqreturn_t -crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t crime_cpuerr_intr(unsigned int irq, void *dev_id) { unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK; unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK; addr <<= 2; - printk ("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat); + printk("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat); crime->cpu_error_stat = 0; return IRQ_HANDLED; diff --git a/arch/mips/sgi-ip32/ip32-berr.c b/arch/mips/sgi-ip32/ip32-berr.c index a278e918a01..afc1cadbba3 100644 --- a/arch/mips/sgi-ip32/ip32-berr.c +++ b/arch/mips/sgi-ip32/ip32-berr.c @@ -16,7 +16,7 @@ #include <asm/ptrace.h> #include <asm/tlbdebug.h> -int ip32_be_handler(struct pt_regs *regs, int is_fixup) +static int ip32_be_handler(struct pt_regs *regs, int is_fixup) { int data = regs->cp0_cause & 4; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index c64a820373d..e0c7d9e142f 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -15,14 +15,13 @@ #include <linux/irq.h> #include <linux/bitops.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/mm.h> #include <linux/random.h> #include <linux/sched.h> +#include <asm/irq_cpu.h> #include <asm/mipsregs.h> #include <asm/signal.h> -#include <asm/system.h> #include <asm/time.h> #include <asm/ip32/crime.h> #include <asm/ip32/mace.h> @@ -39,14 +38,8 @@ static void inline flush_mace_bus(void) mace->perif.ctrl.misc; } -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* O2 irq map +/* + * O2 irq map * * IP0 -> software (ignored) * IP1 -> software (ignored) @@ -55,119 +48,76 @@ static void inline flush_mace_bus(void) * IP4 -> (irq2) X unknown * IP5 -> (irq3) X unknown * IP6 -> (irq4) X unknown - * IP7 -> (irq5) 0 CPU count/compare timer (system timer) + * IP7 -> (irq5) 7 CPU count/compare timer (system timer) * * crime: (C) * * CRIME_INT_STAT 31:0: * - * 0 -> 1 Video in 1 - * 1 -> 2 Video in 2 - * 2 -> 3 Video out - * 3 -> 4 Mace ethernet + * 0 -> 8 Video in 1 + * 1 -> 9 Video in 2 + * 2 -> 10 Video out + * 3 -> 11 Mace ethernet * 4 -> S SuperIO sub-interrupt * 5 -> M Miscellaneous sub-interrupt * 6 -> A Audio sub-interrupt - * 7 -> 8 PCI bridge errors - * 8 -> 9 PCI SCSI aic7xxx 0 - * 9 -> 10 PCI SCSI aic7xxx 1 - * 10 -> 11 PCI slot 0 - * 11 -> 12 unused (PCI slot 1) - * 12 -> 13 unused (PCI slot 2) - * 13 -> 14 unused (PCI shared 0) - * 14 -> 15 unused (PCI shared 1) - * 15 -> 16 unused (PCI shared 2) - * 16 -> 17 GBE0 (E) - * 17 -> 18 GBE1 (E) - * 18 -> 19 GBE2 (E) - * 19 -> 20 GBE3 (E) - * 20 -> 21 CPU errors - * 21 -> 22 Memory errors - * 22 -> 23 RE empty edge (E) - * 23 -> 24 RE full edge (E) - * 24 -> 25 RE idle edge (E) - * 25 -> 26 RE empty level - * 26 -> 27 RE full level - * 27 -> 28 RE idle level - * 28 -> 29 unused (software 0) (E) - * 29 -> 30 unused (software 1) (E) - * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) - * 31 -> 32 VICE + * 7 -> 15 PCI bridge errors + * 8 -> 16 PCI SCSI aic7xxx 0 + * 9 -> 17 PCI SCSI aic7xxx 1 + * 10 -> 18 PCI slot 0 + * 11 -> 19 unused (PCI slot 1) + * 12 -> 20 unused (PCI slot 2) + * 13 -> 21 unused (PCI shared 0) + * 14 -> 22 unused (PCI shared 1) + * 15 -> 23 unused (PCI shared 2) + * 16 -> 24 GBE0 (E) + * 17 -> 25 GBE1 (E) + * 18 -> 26 GBE2 (E) + * 19 -> 27 GBE3 (E) + * 20 -> 28 CPU errors + * 21 -> 29 Memory errors + * 22 -> 30 RE empty edge (E) + * 23 -> 31 RE full edge (E) + * 24 -> 32 RE idle edge (E) + * 25 -> 33 RE empty level + * 26 -> 34 RE full level + * 27 -> 35 RE idle level + * 28 -> 36 unused (software 0) (E) + * 29 -> 37 unused (software 1) (E) + * 30 -> 38 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 31 -> 39 VICE * * S, M, A: Use the MACE ISA interrupt register * MACE_ISA_INT_STAT 31:0 * - * 0-7 -> 33-40 Audio - * 8 -> 41 RTC - * 9 -> 42 Keyboard + * 0-7 -> 40-47 Audio + * 8 -> 48 RTC + * 9 -> 49 Keyboard * 10 -> X Keyboard polled - * 11 -> 44 Mouse + * 11 -> 51 Mouse * 12 -> X Mouse polled - * 13-15 -> 46-48 Count/compare timers - * 16-19 -> 49-52 Parallel (16 E) - * 20-25 -> 53-58 Serial 1 (22 E) - * 26-31 -> 59-64 Serial 2 (28 E) + * 13-15 -> 53-55 Count/compare timers + * 16-19 -> 56-59 Parallel (16 E) + * 20-25 -> 60-62 Serial 1 (22 E) + * 26-31 -> 66-71 Serial 2 (28 E) * - * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a + * Note that this means IRQs 12-14, 50, and 52 do not exist. This is a * different IRQ map than IRIX uses, but that's OK as Linux irq handling * is quite different anyway. */ -/* - * IRQ spinlock - Ralf says not to disable CPU interrupts, - * and I think he knows better. - */ -static DEFINE_SPINLOCK(ip32_irq_lock); - /* Some initial interrupts to set up */ -extern irqreturn_t crime_memerr_intr (int irq, void *dev_id, - struct pt_regs *regs); -extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id, - struct pt_regs *regs); - -struct irqaction memerr_irq = { crime_memerr_intr, IRQF_DISABLED, - CPU_MASK_NONE, "CRIME memory error", NULL, NULL }; -struct irqaction cpuerr_irq = { crime_cpuerr_intr, IRQF_DISABLED, - CPU_MASK_NONE, "CRIME CPU error", NULL, NULL }; - -/* - * For interrupts wired from a single device to the CPU. Only the clock - * uses this it seems, which is IRQ 0 and IP7. - */ - -static void enable_cpu_irq(unsigned int irq) -{ - set_c0_status(STATUSF_IP7); -} - -static unsigned int startup_cpu_irq(unsigned int irq) -{ - enable_cpu_irq(irq); - return 0; -} +extern irqreturn_t crime_memerr_intr(int irq, void *dev_id); +extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id); -static void disable_cpu_irq(unsigned int irq) -{ - clear_c0_status(STATUSF_IP7); -} - -static void end_cpu_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_cpu_irq (irq); -} +static struct irqaction memerr_irq = { + .handler = crime_memerr_intr, + .name = "CRIME memory error", +}; -#define shutdown_cpu_irq disable_cpu_irq -#define mask_and_ack_cpu_irq disable_cpu_irq - -static struct irq_chip ip32_cpu_interrupt = { - .typename = "IP32 CPU", - .startup = startup_cpu_irq, - .shutdown = shutdown_cpu_irq, - .enable = enable_cpu_irq, - .disable = disable_cpu_irq, - .ack = mask_and_ack_cpu_irq, - .end = end_cpu_irq, +static struct irqaction cpuerr_irq = { + .handler = crime_cpuerr_intr, + .name = "CRIME CPU error", }; /* @@ -177,126 +127,80 @@ static struct irq_chip ip32_cpu_interrupt = { static uint64_t crime_mask; -static void enable_crime_irq(unsigned int irq) +static inline void crime_enable_irq(struct irq_data *d) { - unsigned long flags; + unsigned int bit = d->irq - CRIME_IRQ_BASE; - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_mask |= 1 << (irq - 1); + crime_mask |= 1 << bit; crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static unsigned int startup_crime_irq(unsigned int irq) +static inline void crime_disable_irq(struct irq_data *d) { - enable_crime_irq(irq); - return 0; /* This is probably not right; we could have pending irqs */ -} + unsigned int bit = d->irq - CRIME_IRQ_BASE; -static void disable_crime_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_mask &= ~(1 << (irq - 1)); + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static void mask_and_ack_crime_irq(unsigned int irq) +static struct irq_chip crime_level_interrupt = { + .name = "IP32 CRIME", + .irq_mask = crime_disable_irq, + .irq_unmask = crime_enable_irq, +}; + +static void crime_edge_mask_and_ack_irq(struct irq_data *d) { - unsigned long flags; + unsigned int bit = d->irq - CRIME_IRQ_BASE; + uint64_t crime_int; /* Edge triggered interrupts must be cleared. */ - if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) - || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) - || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { - uint64_t crime_int; - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_int = crime->hard_int; - crime_int &= ~(1 << (irq - 1)); - crime->hard_int = crime_int; - spin_unlock_irqrestore(&ip32_irq_lock, flags); - } - disable_crime_irq(irq); -} + crime_int = crime->hard_int; + crime_int &= ~(1 << bit); + crime->hard_int = crime_int; -static void end_crime_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_crime_irq(irq); + crime_disable_irq(d); } -#define shutdown_crime_irq disable_crime_irq - -static struct irq_chip ip32_crime_interrupt = { - .typename = "IP32 CRIME", - .startup = startup_crime_irq, - .shutdown = shutdown_crime_irq, - .enable = enable_crime_irq, - .disable = disable_crime_irq, - .ack = mask_and_ack_crime_irq, - .end = end_crime_irq, +static struct irq_chip crime_edge_interrupt = { + .name = "IP32 CRIME", + .irq_ack = crime_edge_mask_and_ack_irq, + .irq_mask = crime_disable_irq, + .irq_mask_ack = crime_edge_mask_and_ack_irq, + .irq_unmask = crime_enable_irq, }; /* * This is for MACE PCI interrupts. We can decrease bus traffic by masking - * as close to the source as possible. This also means we can take the + * as close to the source as possible. This also means we can take the * next chunk of the CRIME register in one piece. */ static unsigned long macepci_mask; -static void enable_macepci_irq(unsigned int irq) +static void enable_macepci_irq(struct irq_data *d) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); - macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); + macepci_mask |= MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; - crime_mask |= 1 << (irq - 1); + crime_mask |= 1 << (d->irq - CRIME_IRQ_BASE); crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); -} - -static unsigned int startup_macepci_irq(unsigned int irq) -{ - enable_macepci_irq (irq); - return 0; } -static void disable_macepci_irq(unsigned int irq) +static void disable_macepci_irq(struct irq_data *d) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_mask &= ~(1 << (irq - 1)); + crime_mask &= ~(1 << (d->irq - CRIME_IRQ_BASE)); crime->imask = crime_mask; flush_crime_bus(); - macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); + macepci_mask &= ~MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; flush_mace_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static void end_macepci_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_macepci_irq(irq); -} - -#define shutdown_macepci_irq disable_macepci_irq -#define mask_and_ack_macepci_irq disable_macepci_irq - static struct irq_chip ip32_macepci_interrupt = { - .typename = "IP32 MACE PCI", - .startup = startup_macepci_irq, - .shutdown = shutdown_macepci_irq, - .enable = enable_macepci_irq, - .disable = disable_macepci_irq, - .ack = mask_and_ack_macepci_irq, - .end = end_macepci_irq, + .name = "IP32 MACE PCI", + .irq_mask = disable_macepci_irq, + .irq_unmask = enable_macepci_irq, }; /* This is used for MACE ISA interrupts. That means bits 4-6 in the @@ -338,14 +242,13 @@ static struct irq_chip ip32_macepci_interrupt = { static unsigned long maceisa_mask; -static void enable_maceisa_irq (unsigned int irq) +static void enable_maceisa_irq(struct irq_data *d) { unsigned int crime_int = 0; - unsigned long flags; - DBG ("maceisa enable: %u\n", irq); + pr_debug("maceisa enable: %u\n", d->irq); - switch (irq) { + switch (d->irq) { case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: crime_int = MACE_AUDIO_INT; break; @@ -356,143 +259,98 @@ static void enable_maceisa_irq (unsigned int irq) crime_int = MACE_SUPERIO_INT; break; } - DBG ("crime_int %08x enabled\n", crime_int); - spin_lock_irqsave(&ip32_irq_lock, flags); + pr_debug("crime_int %08x enabled\n", crime_int); crime_mask |= crime_int; crime->imask = crime_mask; - maceisa_mask |= 1 << (irq - 33); + maceisa_mask |= 1 << (d->irq - MACEISA_AUDIO_SW_IRQ); mace->perif.ctrl.imask = maceisa_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static unsigned int startup_maceisa_irq(unsigned int irq) -{ - enable_maceisa_irq(irq); - return 0; -} - -static void disable_maceisa_irq(unsigned int irq) +static void disable_maceisa_irq(struct irq_data *d) { unsigned int crime_int = 0; - unsigned long flags; - spin_lock_irqsave(&ip32_irq_lock, flags); - maceisa_mask &= ~(1 << (irq - 33)); - if(!(maceisa_mask & MACEISA_AUDIO_INT)) + maceisa_mask &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ)); + if (!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; - if(!(maceisa_mask & MACEISA_MISC_INT)) + if (!(maceisa_mask & MACEISA_MISC_INT)) crime_int |= MACE_MISC_INT; - if(!(maceisa_mask & MACEISA_SUPERIO_INT)) + if (!(maceisa_mask & MACEISA_SUPERIO_INT)) crime_int |= MACE_SUPERIO_INT; crime_mask &= ~crime_int; crime->imask = crime_mask; flush_crime_bus(); mace->perif.ctrl.imask = maceisa_mask; flush_mace_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static void mask_and_ack_maceisa_irq(unsigned int irq) +static void mask_and_ack_maceisa_irq(struct irq_data *d) { - unsigned long mace_int, flags; - - switch (irq) { - case MACEISA_PARALLEL_IRQ: - case MACEISA_SERIAL1_TDMAPR_IRQ: - case MACEISA_SERIAL2_TDMAPR_IRQ: - /* edge triggered */ - spin_lock_irqsave(&ip32_irq_lock, flags); - mace_int = mace->perif.ctrl.istat; - mace_int &= ~(1 << (irq - 33)); - mace->perif.ctrl.istat = mace_int; - spin_unlock_irqrestore(&ip32_irq_lock, flags); - break; - } - disable_maceisa_irq(irq); -} + unsigned long mace_int; -static void end_maceisa_irq(unsigned irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_maceisa_irq(irq); + /* edge triggered */ + mace_int = mace->perif.ctrl.istat; + mace_int &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ)); + mace->perif.ctrl.istat = mace_int; + + disable_maceisa_irq(d); } -#define shutdown_maceisa_irq disable_maceisa_irq +static struct irq_chip ip32_maceisa_level_interrupt = { + .name = "IP32 MACE ISA", + .irq_mask = disable_maceisa_irq, + .irq_unmask = enable_maceisa_irq, +}; -static struct irq_chip ip32_maceisa_interrupt = { - .typename = "IP32 MACE ISA", - .startup = startup_maceisa_irq, - .shutdown = shutdown_maceisa_irq, - .enable = enable_maceisa_irq, - .disable = disable_maceisa_irq, - .ack = mask_and_ack_maceisa_irq, - .end = end_maceisa_irq, +static struct irq_chip ip32_maceisa_edge_interrupt = { + .name = "IP32 MACE ISA", + .irq_ack = mask_and_ack_maceisa_irq, + .irq_mask = disable_maceisa_irq, + .irq_mask_ack = mask_and_ack_maceisa_irq, + .irq_unmask = enable_maceisa_irq, }; /* This is used for regular non-ISA, non-PCI MACE interrupts. That means * bits 0-3 and 7 in the CRIME register. */ -static void enable_mace_irq(unsigned int irq) +static void enable_mace_irq(struct irq_data *d) { - unsigned long flags; + unsigned int bit = d->irq - CRIME_IRQ_BASE; - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_mask |= 1 << (irq - 1); + crime_mask |= (1 << bit); crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static unsigned int startup_mace_irq(unsigned int irq) +static void disable_mace_irq(struct irq_data *d) { - enable_mace_irq(irq); - return 0; -} - -static void disable_mace_irq(unsigned int irq) -{ - unsigned long flags; + unsigned int bit = d->irq - CRIME_IRQ_BASE; - spin_lock_irqsave(&ip32_irq_lock, flags); - crime_mask &= ~(1 << (irq - 1)); + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static void end_mace_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_mace_irq(irq); -} - -#define shutdown_mace_irq disable_mace_irq -#define mask_and_ack_mace_irq disable_mace_irq - static struct irq_chip ip32_mace_interrupt = { - .typename = "IP32 MACE", - .startup = startup_mace_irq, - .shutdown = shutdown_mace_irq, - .enable = enable_mace_irq, - .disable = disable_mace_irq, - .ack = mask_and_ack_mace_irq, - .end = end_mace_irq, + .name = "IP32 MACE", + .irq_mask = disable_mace_irq, + .irq_unmask = enable_mace_irq, }; -static void ip32_unknown_interrupt(struct pt_regs *regs) +static void ip32_unknown_interrupt(void) { - printk ("Unknown interrupt occurred!\n"); - printk ("cp0_status: %08x\n", read_c0_status()); - printk ("cp0_cause: %08x\n", read_c0_cause()); - printk ("CRIME intr mask: %016lx\n", crime->imask); - printk ("CRIME intr status: %016lx\n", crime->istat); - printk ("CRIME hardware intr register: %016lx\n", crime->hard_int); - printk ("MACE ISA intr mask: %08lx\n", mace->perif.ctrl.imask); - printk ("MACE ISA intr status: %08lx\n", mace->perif.ctrl.istat); - printk ("MACE PCI control register: %08x\n", mace->pci.control); + printk("Unknown interrupt occurred!\n"); + printk("cp0_status: %08x\n", read_c0_status()); + printk("cp0_cause: %08x\n", read_c0_cause()); + printk("CRIME intr mask: %016lx\n", crime->imask); + printk("CRIME intr status: %016lx\n", crime->istat); + printk("CRIME hardware intr register: %016lx\n", crime->hard_int); + printk("MACE ISA intr mask: %08lx\n", mace->perif.ctrl.imask); + printk("MACE ISA intr status: %08lx\n", mace->perif.ctrl.istat); + printk("MACE PCI control register: %08x\n", mace->pci.control); printk("Register dump:\n"); - show_regs(regs); + show_regs(get_irq_regs()); printk("Please mail this report to linux-mips@linux-mips.org\n"); printk("Spinning..."); @@ -501,65 +359,77 @@ static void ip32_unknown_interrupt(struct pt_regs *regs) /* CRIME 1.1 appears to deliver all interrupts to this one pin. */ /* change this to loop over all edge-triggered irqs, exception masked out ones */ -static void ip32_irq0(struct pt_regs *regs) +static void ip32_irq0(void) { uint64_t crime_int; int irq = 0; + /* + * Sanity check interrupt numbering enum. + * MACE got 32 interrupts and there are 32 MACE ISA interrupts daisy + * chained. + */ + BUILD_BUG_ON(CRIME_VICE_IRQ - MACE_VID_IN1_IRQ != 31); + BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31); + crime_int = crime->istat & crime_mask; - irq = __ffs(crime_int); - crime_int = 1 << irq; + + /* crime sometime delivers spurious interrupts, ignore them */ + if (unlikely(crime_int == 0)) + return; + + irq = MACE_VID_IN1_IRQ + __ffs(crime_int); if (crime_int & CRIME_MACEISA_INT_MASK) { unsigned long mace_int = mace->perif.ctrl.istat; - irq = __ffs(mace_int & maceisa_mask) + 32; + irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ; } - irq++; - DBG("*irq %u*\n", irq); - do_IRQ(irq, regs); + + pr_debug("*irq %u*\n", irq); + do_IRQ(irq); } -static void ip32_irq1(struct pt_regs *regs) +static void ip32_irq1(void) { - ip32_unknown_interrupt(regs); + ip32_unknown_interrupt(); } -static void ip32_irq2(struct pt_regs *regs) +static void ip32_irq2(void) { - ip32_unknown_interrupt(regs); + ip32_unknown_interrupt(); } -static void ip32_irq3(struct pt_regs *regs) +static void ip32_irq3(void) { - ip32_unknown_interrupt(regs); + ip32_unknown_interrupt(); } -static void ip32_irq4(struct pt_regs *regs) +static void ip32_irq4(void) { - ip32_unknown_interrupt(regs); + ip32_unknown_interrupt(); } -static void ip32_irq5(struct pt_regs *regs) +static void ip32_irq5(void) { - ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); } -asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +asmlinkage void plat_irq_dispatch(void) { - unsigned int pending = read_c0_cause(); + unsigned int pending = read_c0_status() & read_c0_cause(); if (likely(pending & IE_IRQ0)) - ip32_irq0(regs); + ip32_irq0(); else if (unlikely(pending & IE_IRQ1)) - ip32_irq1(regs); + ip32_irq1(); else if (unlikely(pending & IE_IRQ2)) - ip32_irq2(regs); + ip32_irq2(); else if (unlikely(pending & IE_IRQ3)) - ip32_irq3(regs); + ip32_irq3(); else if (unlikely(pending & IE_IRQ4)) - ip32_irq4(regs); + ip32_irq4(); else if (likely(pending & IE_IRQ5)) - ip32_irq5(regs); + ip32_irq5(); } void __init arch_init_irq(void) @@ -574,24 +444,57 @@ void __init arch_init_irq(void) mace->perif.ctrl.istat = 0; mace->perif.ctrl.imask = 0; - for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { - struct irq_chip *controller; - - if (irq == IP32_R4K_TIMER_IRQ) - controller = &ip32_cpu_interrupt; - else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) - controller = &ip32_mace_interrupt; - else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) - controller = &ip32_macepci_interrupt; - else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) - controller = &ip32_crime_interrupt; - else - controller = &ip32_maceisa_interrupt; - - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 0; - irq_desc[irq].chip = controller; + mips_cpu_irq_init(); + for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) { + switch (irq) { + case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: + irq_set_chip_and_handler_name(irq, + &ip32_mace_interrupt, + handle_level_irq, + "level"); + break; + + case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ: + irq_set_chip_and_handler_name(irq, + &ip32_macepci_interrupt, + handle_level_irq, + "level"); + break; + + case CRIME_CPUERR_IRQ: + case CRIME_MEMERR_IRQ: + irq_set_chip_and_handler_name(irq, + &crime_level_interrupt, + handle_level_irq, + "level"); + break; + + case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ: + case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ: + case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ: + case CRIME_VICE_IRQ: + irq_set_chip_and_handler_name(irq, + &crime_edge_interrupt, + handle_edge_irq, + "edge"); + break; + + case MACEISA_PARALLEL_IRQ: + case MACEISA_SERIAL1_TDMAPR_IRQ: + case MACEISA_SERIAL2_TDMAPR_IRQ: + irq_set_chip_and_handler_name(irq, + &ip32_maceisa_edge_interrupt, + handle_edge_irq, + "edge"); + break; + + default: + irq_set_chip_and_handler_name(irq, + &ip32_maceisa_level_interrupt, + handle_level_irq, + "level"); + break; + } } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/arch/mips/sgi-ip32/ip32-memory.c b/arch/mips/sgi-ip32/ip32-memory.c index d37d40a3cda..828ce131c22 100644 --- a/arch/mips/sgi-ip32/ip32-memory.c +++ b/arch/mips/sgi-ip32/ip32-memory.c @@ -19,7 +19,7 @@ extern void crime_init(void); -void __init prom_meminit (void) +void __init prom_meminit(void) { u64 base, size; int bank; @@ -36,14 +36,13 @@ void __init prom_meminit (void) if (base + size > (256 << 20)) base += CRIME_HI_MEM_BASE; - printk("CRIME MC: bank %u base 0x%016lx size %luMiB\n", + printk("CRIME MC: bank %u base 0x%016Lx size %LuMiB\n", bank, base, size >> 20); - add_memory_region (base, size, BOOT_MEM_RAM); + add_memory_region(base, size, BOOT_MEM_RAM); } } -unsigned long __init prom_free_prom_memory (void) +void __init prom_free_prom_memory(void) { - return 0; } diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c new file mode 100644 index 00000000000..511e9ff2acf --- /dev/null +++ b/arch/mips/sgi-ip32/ip32-platform.c @@ -0,0 +1,111 @@ +/* + * 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. + * + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> + +#include <asm/ip32/mace.h> +#include <asm/ip32/ip32_ints.h> + +#define MACEISA_SERIAL1_OFFS offsetof(struct sgi_mace, isa.serial1) +#define MACEISA_SERIAL2_OFFS offsetof(struct sgi_mace, isa.serial2) + +#define MACE_PORT(offset,_irq) \ +{ \ + .mapbase = MACE_BASE + offset, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_MEM, \ + .flags = UPF_SKIP_TEST|UPF_IOREMAP, \ + .regshift = 8, \ +} + +static struct plat_serial8250_port uart8250_data[] = { + MACE_PORT(MACEISA_SERIAL1_OFFS, MACEISA_SERIAL1_IRQ), + MACE_PORT(MACEISA_SERIAL2_OFFS, MACEISA_SERIAL2_IRQ), + { }, +}; + +static struct platform_device uart8250_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = uart8250_data, + }, +}; + +static int __init uart8250_init(void) +{ + return platform_device_register(&uart8250_device); +} + +device_initcall(uart8250_init); + +static __init int meth_devinit(void) +{ + struct platform_device *pd; + int ret; + + pd = platform_device_alloc("meth", -1); + if (!pd) + return -ENOMEM; + + ret = platform_device_add(pd); + if (ret) + platform_device_put(pd); + + return ret; +} + +device_initcall(meth_devinit); + +static __init int sgio2audio_devinit(void) +{ + struct platform_device *pd; + int ret; + + pd = platform_device_alloc("sgio2audio", -1); + if (!pd) + return -ENOMEM; + + ret = platform_device_add(pd); + if (ret) + platform_device_put(pd); + + return ret; +} + +device_initcall(sgio2audio_devinit); + +static __init int sgio2btns_devinit(void) +{ + return IS_ERR(platform_device_register_simple("sgibtns", -1, NULL, 0)); +} + +device_initcall(sgio2btns_devinit); + +static struct resource sgio2_cmos_rsrc[] = { + { + .start = 0x70, + .end = 0x71, + .flags = IORESOURCE_IO + } +}; + +static __init int sgio2_cmos_devinit(void) +{ + return IS_ERR(platform_device_register_simple("rtc_cmos", -1, + sgio2_cmos_rsrc, 1)); +} + +device_initcall(sgio2_cmos_devinit); + +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2"); diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 79ddb460565..1f823da4c77 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -20,7 +20,6 @@ #include <asm/addrspace.h> #include <asm/irq.h> #include <asm/reboot.h> -#include <asm/system.h> #include <asm/wbflush.h> #include <asm/ip32/mace.h> #include <asm/ip32/crime.h> @@ -53,7 +52,7 @@ static inline void ip32_machine_halt(void) static void ip32_machine_power_off(void) { - volatile unsigned char reg_a, xctrl_a, xctrl_b; + unsigned char reg_a, xctrl_a, xctrl_b; disable_irq(MACEISA_RTC_IRQ); reg_a = CMOS_READ(RTC_REG_A); @@ -91,9 +90,10 @@ static void blink_timeout(unsigned long data) static void debounce(unsigned long data) { - volatile unsigned char reg_a, reg_c, xctrl_a; + unsigned char reg_a, reg_c, xctrl_a; reg_c = CMOS_READ(RTC_INTR_FLAGS); + reg_a = CMOS_READ(RTC_REG_A); CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); wbflush(); xctrl_a = CMOS_READ(DS_B1_XCTRL4A); @@ -120,7 +120,7 @@ static inline void ip32_power_button(void) if (has_panicked) return; - if (shuting_down || kill_proc(1, SIGINT, 1)) { + if (shuting_down || kill_cad_pid(SIGINT, 1)) { /* No init process or button pressed twice. */ ip32_machine_power_off(); } @@ -135,17 +135,17 @@ static inline void ip32_power_button(void) add_timer(&power_timer); } -static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ip32_rtc_int(int irq, void *dev_id) { - volatile unsigned char reg_c; + unsigned char reg_c; reg_c = CMOS_READ(RTC_INTR_FLAGS); if (!(reg_c & RTC_IRQF)) { printk(KERN_WARNING - "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__); + "%s: RTC IRQ without RTC_IRQF\n", __func__); } /* Wait until interrupt goes away */ - disable_irq(MACEISA_RTC_IRQ); + disable_irq_nosync(MACEISA_RTC_IRQ); init_timer(&debounce_timer); debounce_timer.function = debounce; debounce_timer.expires = jiffies + 50; @@ -195,7 +195,8 @@ static __init int ip32_reboot_setup(void) blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL); + if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) + panic("Can't allocate MACEISA RTC IRQ"); return 0; } diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index 57708fe28bd..3abd1465ec0 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -62,16 +62,10 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str) } #endif -#ifdef CONFIG_SERIAL_8250 -#include <linux/tty.h> -#include <linux/serial.h> -#include <linux/serial_core.h> -#endif /* CONFIG_SERIAL_8250 */ - /* An arbitrary time; this can be decreased if reliability looks good */ #define WAIT_MS 10 -void __init ip32_time_init(void) +void __init plat_time_init(void) { printk(KERN_INFO "Calibrating system timer... "); write_c0_count(0); @@ -81,51 +75,10 @@ void __init ip32_time_init(void) printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000); } -void __init plat_timer_setup(struct irqaction *irq) -{ - irq->handler = no_action; - setup_irq(IP32_R4K_TIMER_IRQ, irq); -} - void __init plat_mem_setup(void) { board_be_init = ip32_be_init; - rtc_mips_get_time = mc146818_get_cmos_time; - rtc_mips_set_mmss = mc146818_set_rtc_mmss; - - board_time_init = ip32_time_init; - -#ifdef CONFIG_SERIAL_8250 - { - static struct uart_port o2_serial[2]; - - memset(o2_serial, 0, sizeof(o2_serial)); - o2_serial[0].type = PORT_16550A; - o2_serial[0].line = 0; - o2_serial[0].irq = MACEISA_SERIAL1_IRQ; - o2_serial[0].flags = UPF_SKIP_TEST; - o2_serial[0].uartclk = 1843200; - o2_serial[0].iotype = UPIO_MEM; - o2_serial[0].membase = (char *)&mace->isa.serial1; - o2_serial[0].fifosize = 14; - /* How much to shift register offset by. Each UART register - * is replicated over 256 byte space */ - o2_serial[0].regshift = 8; - o2_serial[1].type = PORT_16550A; - o2_serial[1].line = 1; - o2_serial[1].irq = MACEISA_SERIAL2_IRQ; - o2_serial[1].flags = UPF_SKIP_TEST; - o2_serial[1].uartclk = 1843200; - o2_serial[1].iotype = UPIO_MEM; - o2_serial[1].membase = (char *)&mace->isa.serial2; - o2_serial[1].fifosize = 14; - o2_serial[1].regshift = 8; - - early_serial_setup(&o2_serial[0]); - early_serial_setup(&o2_serial[1]); - } -#endif #ifdef CONFIG_SGI_O2MACE_ETH { char *mac = ArcGetEnvironmentVariable("eaddr"); @@ -137,7 +90,7 @@ void __init plat_mem_setup(void) { char* con = ArcGetEnvironmentVariable("console"); if (con && *con == 'd') { - static char options[8]; + static char options[8] __initdata; char *baud = ArcGetEnvironmentVariable("dbaud"); if (baud) strcpy(options, baud); |
