summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-04 08:29:09 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-04 08:29:09 +0000
commit664937a3d90d3e11b486b2c019041dc901d2893f (patch)
treef0ce25de8b0e71c8b8aa5607f8bb6484c642158c
parent4e36f47c962150bc140d858803f57ea47fb6e455 (diff)
- Some small cleanups
- The core of the new second level cache handling for Indy style l2 caches was missing ...
-rw-r--r--arch/mips/jazz/hw-access.c4
-rw-r--r--arch/mips/jazz/reset.c2
-rw-r--r--arch/mips/jazz/setup.c8
-rw-r--r--arch/mips/sgi/kernel/Makefile6
-rw-r--r--arch/mips/sgi/kernel/indy_sc.c248
5 files changed, 259 insertions, 9 deletions
diff --git a/arch/mips/jazz/hw-access.c b/arch/mips/jazz/hw-access.c
index 73122bcc7..8765be1a7 100644
--- a/arch/mips/jazz/hw-access.c
+++ b/arch/mips/jazz/hw-access.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*
- * $Id: hw-access.c,v 1.4 1997/12/01 17:57:23 ralf Exp $
+ * $Id: hw-access.c,v 1.5 1997/12/29 00:06:49 tsbogend Exp $
*/
#include <linux/delay.h>
#include <linux/linkage.h>
@@ -180,5 +180,5 @@ void jazz_keyboard_setup(void)
kbd_write_command = jazz_write_command;
kbd_read_status = jazz_read_status;
request_region(0x60, 16, "keyboard");
- r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD);
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD);
}
diff --git a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c
index d26e44034..f1aac5388 100644
--- a/arch/mips/jazz/reset.c
+++ b/arch/mips/jazz/reset.c
@@ -2,6 +2,8 @@
* linux/arch/mips/jazz/process.c
*
* Reset a Jazz machine.
+ *
+ * $Id:$
*/
#include <linux/sched.h>
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index d6ca9c516..d088a302c 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 1996, 1997 by Ralf Baechle
*
- * $Id: setup.c,v 1.6 1997/12/02 03:43:43 ralf Exp $
+ * $Id: setup.c,v 1.7 1997/12/29 00:06:49 tsbogend Exp $
*/
#include <linux/init.h>
#include <linux/ioport.h>
@@ -100,9 +100,9 @@ __initfunc(void jazz_setup(void))
}
}
- add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
- add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M);
- add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M);
+ add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
+ add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M);
+ add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M);
irq_setup = jazz_irq_setup;
fd_cacheflush = jazz_fd_cacheflush;
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
index c79023b23..43758c5f7 100644
--- a/arch/mips/sgi/kernel/Makefile
+++ b/arch/mips/sgi/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.5 1996/06/08 12:08:38 dm Exp $
+# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
# Makefile for the SGI specific kernel interface routines
# under Linux.
#
@@ -13,8 +13,8 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-OBJS = indy_mc.o indy_hpc.o indy_int.o system.o indy_timer.o indyIRQ.o \
- reset.o setup.o time.o
+OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o system.o indy_timer.o \
+ indyIRQ.o reset.o setup.o time.o
all: sgikern.a
diff --git a/arch/mips/sgi/kernel/indy_sc.c b/arch/mips/sgi/kernel/indy_sc.c
new file mode 100644
index 000000000..462723a7e
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_sc.c
@@ -0,0 +1,248 @@
+/*
+ * indy_sc.c: Indy cache managment functions.
+ *
+ * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ *
+ * $Id: indy_sc.c,v 1.4 1998/01/13 04:39:38 ralf Exp $
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/autoconf.h>
+
+#include <asm/bcache.h>
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+ "nop; nop; nop; nop; nop; nop;\n\t" \
+ ".set reorder\n\t")
+
+/* Primary cache parameters. */
+static int icache_size, dcache_size; /* Size in bytes */
+static int ic_lsize, dc_lsize; /* LineSize in bytes */
+
+/* Secondary cache (if present) parameters. */
+static scache_size, sc_lsize; /* Again, in bytes */
+
+#include <asm/cacheops.h>
+#include <asm/r4kcache.h>
+
+#undef DEBUG_CACHE
+
+
+static void indy_sc_wback_invalidate(unsigned long page, unsigned long size)
+{
+ unsigned long tmp1, tmp2, flags;
+
+ page &= PAGE_MASK;
+
+#ifdef DEBUG_CACHE
+ printk("indy_sc_flush_page_to_ram[%08lx]", page);
+#endif
+ if (size == 0)
+ return;
+
+ save_and_cli(flags);
+
+ __asm__ __volatile__("
+ .set noreorder
+ .set mips3
+ li %0, 0x1
+ dsll %0, 31
+ or %0, %0, %2
+ lui %1, 0x9000
+ dsll32 %1, 0
+ or %0, %0, %1
+ daddu %1, %0, %4
+ li %2, 0x80
+ mtc0 %2, $12
+ nop; nop; nop; nop;
+1: sw $0, 0(%0)
+ bltu %0, %1, 1b
+ daddu %0, 32
+ mtc0 $0, $12
+ nop; nop; nop; nop;
+ .set mips0
+ .set reorder"
+ : "=&r" (tmp1), "=&r" (tmp2),
+ "=&r" (page)
+ : "2" (page & 0x0007f000),
+ "r" (size - 32));
+ restore_flags(flags);
+}
+
+static void indy_sc_enable(void)
+{
+ unsigned long addr, tmp1, tmp2;
+
+ /* This is really cool... */
+ printk("Enabling R4600 SCACHE\n");
+ __asm__ __volatile__("
+ .set noreorder
+ .set mips3
+ mfc0 %2, $12
+ nop; nop; nop; nop;
+ li %1, 0x80
+ mtc0 %1, $12
+ nop; nop; nop; nop;
+ li %0, 0x1
+ dsll %0, 31
+ lui %1, 0x9000
+ dsll32 %1, 0
+ or %0, %1, %0
+ sb $0, 0(%0)
+ mtc0 $0, $12
+ nop; nop; nop; nop;
+ mtc0 %2, $12
+ nop; nop; nop; nop;
+ .set mips0
+ .set reorder"
+ : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
+}
+
+static void indy_sc_disable(void)
+{
+ unsigned long tmp1, tmp2, tmp3;
+
+ if(mips_cputype != CPU_R4600 &&
+ mips_cputype != CPU_R4640 &&
+ mips_cputype != CPU_R4700)
+ return;
+ printk("Disabling R4600 SCACHE\n");
+ __asm__ __volatile__("
+ .set noreorder
+ .set mips3
+ li %0, 0x1
+ dsll %0, 31
+ lui %1, 0x9000
+ dsll32 %1, 0
+ or %0, %1, %0
+ mfc0 %2, $12
+ nop; nop; nop; nop;
+ li %1, 0x80
+ mtc0 %1, $12
+ nop; nop; nop; nop;
+ sh $0, 0(%0)
+ mtc0 $0, $12
+ nop; nop; nop; nop;
+ mtc0 %2, $12
+ nop; nop; nop; nop;
+ .set mips2
+ .set reorder
+ " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+}
+
+static inline int indy_sc_probe(void)
+{
+ volatile unsigned int *cpu_control;
+ unsigned short cmd = 0xc220;
+ unsigned long data = 0;
+ unsigned long addr;
+ int i, n;
+
+#ifdef __MIPSEB__
+ cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
+#else
+ cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
+#endif
+#define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
+#define ASSERT(bit) (*(cpu_control) |= (bit))
+#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("")
+ DEASSERT(SGIMC_EEPROM_PRE);
+ DEASSERT(SGIMC_EEPROM_SDATAO);
+ DEASSERT(SGIMC_EEPROM_SECLOCK);
+ DEASSERT(SGIMC_EEPROM_PRE);
+ DELAY;
+ ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
+ for(i = 0; i < 11; i++) {
+ if(cmd & (1<<15))
+ ASSERT(SGIMC_EEPROM_SDATAO);
+ else
+ DEASSERT(SGIMC_EEPROM_SDATAO);
+ DEASSERT(SGIMC_EEPROM_SECLOCK);
+ ASSERT(SGIMC_EEPROM_SECLOCK);
+ cmd <<= 1;
+ }
+ DEASSERT(SGIMC_EEPROM_SDATAO);
+ for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
+ unsigned int tmp;
+
+ DEASSERT(SGIMC_EEPROM_SECLOCK);
+ DELAY;
+ ASSERT(SGIMC_EEPROM_SECLOCK);
+ DELAY;
+ data <<= 1;
+ tmp = *cpu_control;
+ if(tmp & SGIMC_EEPROM_SDATAI)
+ data |= 1;
+ }
+ DEASSERT(SGIMC_EEPROM_SECLOCK);
+ DEASSERT(SGIMC_EEPROM_CSEL);
+ ASSERT(SGIMC_EEPROM_PRE);
+ ASSERT(SGIMC_EEPROM_SECLOCK);
+ data <<= PAGE_SHIFT;
+ printk("R4600/R5000 SCACHE size %dK ", (int) (data >> 10));
+ switch(mips_cputype) {
+ case CPU_R4600:
+ case CPU_R4640:
+ sc_lsize = 32;
+ break;
+
+ default:
+ sc_lsize = 128;
+ break;
+ }
+ printk("linesize %d bytes\n", sc_lsize);
+ scache_size = data;
+ if (data == 0) {
+ if (mips_cputype == CPU_R5000)
+ return -1;
+ else
+ return 0;
+ }
+
+ /* Enable r4600/r5000 cache. But flush it first. */
+ for(addr = KSEG0; addr < (KSEG0 + dcache_size);
+ addr += dc_lsize)
+ flush_dcache_line_indexed(addr);
+ for(addr = KSEG0; addr < (KSEG0 + icache_size);
+ addr += ic_lsize)
+ flush_icache_line_indexed(addr);
+ for(addr = KSEG0; addr < (KSEG0 + scache_size);
+ addr += sc_lsize)
+ flush_scache_line_indexed(addr);
+
+ if (mips_cputype == CPU_R4600 ||
+ mips_cputype == CPU_R5000)
+ return 1;
+
+ return 0;
+}
+
+/* XXX Check with wje if the Indy caches can differenciate between
+ writeback + invalidate and just invalidate. */
+struct bcache_ops indy_sc_ops = {
+ indy_sc_enable,
+ indy_sc_disable,
+ indy_sc_wback_invalidate,
+ indy_sc_wback_invalidate
+};
+
+void indy_sc_init(void)
+{
+ if (indy_sc_probe()) {
+ indy_sc_enable();
+ bcops = &indy_sc_ops;
+ }
+}