summaryrefslogtreecommitdiff
path: root/arch/mips/mips-boards/generic
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mips-boards/generic')
-rw-r--r--arch/mips/mips-boards/generic/Makefile4
-rw-r--r--arch/mips/mips-boards/generic/gdb_hook.c2
-rw-r--r--arch/mips/mips-boards/generic/init.c1
-rw-r--r--arch/mips/mips-boards/generic/memory.c9
-rw-r--r--arch/mips/mips-boards/generic/mipsIRQ.S155
-rw-r--r--arch/mips/mips-boards/generic/time.c68
6 files changed, 68 insertions, 171 deletions
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
index b21bc6887fa8..be47c1c2bc80 100644
--- a/arch/mips/mips-boards/generic/Makefile
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -18,8 +18,8 @@
# Makefile for the MIPS boards generic routines under Linux.
#
-obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
- printf.o cmdline.o time.o
+obj-y := reset.o display.o init.o memory.o printf.o \
+ cmdline.o time.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
index 91a2ccbe3730..6a1854de4579 100644
--- a/arch/mips/mips-boards/generic/gdb_hook.c
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -25,7 +25,7 @@
#include <asm/serial.h>
#include <asm/io.h>
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
+static struct serial_state rs_table[] = {
SERIAL_PORT_DFNS /* Defined in serial.h */
};
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index eab5a705e989..17dfe6a8cab9 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -220,7 +220,6 @@ void __init kgdb_config (void)
generic_putDebugChar (*s++);
}
- kgdb_enabled = 1;
/* Breakpoint is invoked after interrupts are initialised */
}
}
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index 32c9210373ac..bc4d093685bb 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,10 +22,12 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/mips-boards/prom.h>
@@ -46,9 +48,6 @@ static char *mtypes[3] = {
};
#endif
-/* References to section boundaries */
-extern char _end;
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
char *memsize_str;
@@ -106,10 +105,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[3].type = yamon_dontuse;
mdesc[3].base = 0x00100000;
- mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
+ mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base;
mdesc[4].type = yamon_free;
- mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
+ mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
mdesc[4].size = memsize - mdesc[4].base;
return &mdesc[0];
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
deleted file mode 100644
index ddd5c73a2971..000000000000
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlasint.h>
-#define CASCADE_IRQ MIPSCPU_INT_ATLAS
-#define CASCADE_DISPATCH atlas_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/maltaint.h>
-#define CASCADE_IRQ MIPSCPU_INT_I8259A
-#define CASCADE_DISPATCH malta_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/seadint.h>
-#endif
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Combined hardware interrupt (hw0)
- * 3 Hardware (ignored)
- * 4 Hardware (ignored)
- * 5 Hardware (ignored)
- * 6 Hardware (ignored)
- * 7 R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- * wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Lowest ---- Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(mipsIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 s0, CP0_CAUSE # get irq bits
- mfc0 s1, CP0_STATUS # get irq mask
- andi s0, ST0_IM # CAUSE.CE may be non-zero!
- and s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
- .set mips32
- clz a0, s0
- .set mips0
- negu a0
- addu a0, 31-CAUSEB_IP
- bltz a0, spurious
-#else
- beqz s0, spurious
- li a0, 7
-
- and t0, s0, 0xf000
- sltiu t0, t0, 1
- sll t0, 2
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0xc000
- sltiu t0, t0, 1
- sll t0, 1
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0x8000
- sltiu t0, t0, 1
- # sll t0, 0
- subu a0, t0
- # sll s0, t0
-#endif
-
-#ifdef CASCADE_IRQ
- li a1, CASCADE_IRQ
- bne a0, a1, 1f
- addu a0, MIPSCPU_INT_BASE
-
- jal CASCADE_DISPATCH
- move a0, sp
-
- j ret_from_irq
- nop
-1:
-#else
- addu a0, MIPSCPU_INT_BASE
-#endif
-
- jal do_IRQ
- move a1, sp
-
- j ret_from_irq
- nop
-
-
-spurious:
- j spurious_interrupt
- nop
- END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 93f3bf2c2b22..a9f6124b3a22 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,6 +30,7 @@
#include <linux/mc146818rtc.h>
#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
#include <asm/ptrace.h>
#include <asm/hardirq.h>
#include <asm/irq.h>
@@ -50,16 +51,23 @@ unsigned long cpu_khz;
static char display_string[] = " LINUX ON ATLAS ";
#endif
#if defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MIPS_MT_SMTC)
+static char display_string[] = " SMTC LINUX ON MALTA ";
+#else
static char display_string[] = " LINUX ON MALTA ";
+#endif /* CONFIG_MIPS_MT_SMTC */
#endif
#if defined(CONFIG_MIPS_SEAD)
static char display_string[] = " LINUX ON SEAD ";
#endif
-static unsigned int display_count = 0;
+static unsigned int display_count;
#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-static unsigned int timer_tick_count=0;
+#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
+
+static unsigned int timer_tick_count;
static int mips_cpu_timer_irq;
+extern void smtc_timer_broadcast(int);
static inline void scroll_display_message(void)
{
@@ -75,15 +83,55 @@ static void mips_timer_dispatch (struct pt_regs *regs)
do_IRQ (mips_cpu_timer_irq, regs);
}
+/*
+ * Redeclare until I get around mopping the timer code insanity on MIPS.
+ */
extern int null_perf_irq(struct pt_regs *regs);
extern int (*perf_irq)(struct pt_regs *regs);
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int r2 = cpu_has_mips_r2;
int cpu = smp_processor_id();
+ int r2 = cpu_has_mips_r2;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * In an SMTC system, one Count/Compare set exists per VPE.
+ * Which TC within a VPE gets the interrupt is essentially
+ * random - we only know that it shouldn't be one with
+ * IXMT set. Whichever TC gets the interrupt needs to
+ * send special interprocessor interrupts to the other
+ * TCs to make sure that they schedule, etc.
+ *
+ * That code is specific to the SMTC kernel, not to
+ * the a particular platform, so it's invoked from
+ * the general MIPS timer_interrupt routine.
+ */
+
+ /*
+ * DVPE is necessary so long as cross-VPE interrupts
+ * are done via read-modify-write of Cause register.
+ */
+ int vpflags = dvpe();
+ write_c0_compare (read_c0_count() - 1);
+ clear_c0_cause(CPUCTR_IMASKBIT);
+ evpe(vpflags);
+
+ if (cpu_data[cpu].vpe_id == 0) {
+ timer_interrupt(irq, dev_id, regs);
+ scroll_display_message();
+ } else
+ write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+ if (cpu != 0)
+ /*
+ * Other CPUs should do profiling and process accounting
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+#else /* CONFIG_MIPS_MT_SMTC */
if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* More support needs to be added to kernel/time for
* counter/timer interrupts on multiple CPU's
*/
- write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+ write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+
/*
- * other CPUs should do profiling and process accounting
+ * Other CPUs should do profiling and process accounting
*/
- local_timer_interrupt (irq, dev_id, regs);
+ local_timer_interrupt(irq, dev_id, regs);
}
+#endif /* CONFIG_MIPS_MT_SMTC */
out:
return IRQ_HANDLED;
@@ -126,7 +176,7 @@ static unsigned int __init estimate_cpu_frequency(void)
unsigned int prid = read_c0_prid() & 0xffff00;
unsigned int count;
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
/*
* The SEAD board doesn't have a real time clock, so we can't
* really calculate the timer frequency
@@ -211,7 +261,11 @@ void __init mips_timer_setup(struct irqaction *irq)
/* we are using the cpu counter for timer interrupts */
irq->handler = mips_timer_interrupt; /* we use our own handler */
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+#else
setup_irq(mips_cpu_timer_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_SMP
/* irq_desc(riptor) is a global resource, when the interrupt overlaps