[PATCH 2.5] R5000 secondary cache support (fwd)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




---------- Forwarded message ----------
Date: Mon, 26 Aug 2002 21:49:37 +0200 (CEST)
From: Vivien Chappelier <glaurung@melkor.maisel.enst-bretagne.fr>
To: Ralf Baechle <ralf@oss.sgi.com>
Cc: Brian Murphy <brm@murphy.dk>, linux-mips@oss.sgi.com
Subject: [PATCH 2.5] R5000 secondary cache support

Hi,

	I've tested and updated Brian Murphy's R5K SC patch to the 2.5
kernel. I've also changed a few comments, changed Page_Invalidate
operation to R5K_Page_Invalidate_S to be consistent with the naming of R4K
cache ops, and simplified the r5k_dma_cache_inv_sc routine (no need for
two 'while'). And I've also removed the extra crap for in config-shared.in
in Brian's latest diff (removing spaces/formating) :)

	I've also tested this patch at runtime, it runs fine (as far as
a 2.5.8 can run fine :)). This patch is for both 2.5.8/mips64 and
2.5.8/mips.

Please comment and/or apply,
Vivien.

diff -Naur linux/arch/mips/config-shared.in linux.patch/arch/mips/config-shared.in
--- linux/arch/mips/config-shared.in	2002-08-24 14:58:40.000000000 +0200
+++ linux.patch/arch/mips/config-shared.in	2002-08-24 16:44:34.000000000 +0200
@@ -388,6 +388,14 @@
 	 RM7000	CONFIG_CPU_RM7000 \
 	 SB1	CONFIG_CPU_SB1" R4x00
 
+if [ "$CONFIG_CPU_R5000" = "y" ]; then
+   define_bool CONFIG_BOARD_SCACHE y
+fi
+
+if [ "$CONFIG_CPU_NEVADA" = "y" ]; then
+   define_bool CONFIG_BOARD_SCACHE y
+fi
+ 
 if [ "$CONFIG_CPU_MIPS32" = "y" ]; then
    define_bool CONFIG_CPU_HAS_PREFETCH y
    bool '  Support for Virtual Tagged I-cache' CONFIG_VTAG_ICACHE
diff -Naur linux/arch/mips/mm/c-r4k.c linux.patch/arch/mips/mm/c-r4k.c
--- linux/arch/mips/mm/c-r4k.c	2002-08-09 08:04:58.000000000 +0200
+++ linux.patch/arch/mips/mm/c-r4k.c	2002-08-24 16:44:34.000000000 +0200
@@ -1436,7 +1436,9 @@
 	_dma_cache_inv = r4k_dma_cache_inv_sc;
 }
 
+
 typedef int (*probe_func_t)(unsigned long);
+extern void r5k_sc_init(void);
 
 static inline void __init setup_scache(unsigned int config)
 {
@@ -1447,12 +1449,24 @@
 	probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
 	sc_present = probe_scache_kseg1(config);
 
-	if (sc_present) {
-		setup_scache_funcs();
+	if (!sc_present) {
+		setup_noscache_funcs();
 		return;
 	}
 
-	setup_noscache_funcs();
+	switch(mips_cpu.cputype) {
+	case CPU_R5000:
+	case CPU_NEVADA:
+			setup_noscache_funcs();
+#if defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)
+			r5k_sc_init();
+#endif
+			break;
+	default:
+			setup_scache_funcs();
+	}
+
+
 }
 
 void __init ld_mmu_r4xx0(void)
diff -Naur linux/arch/mips/mm/Makefile linux.patch/arch/mips/mm/Makefile
--- linux/arch/mips/mm/Makefile	2002-06-25 18:11:44.000000000 +0200
+++ linux.patch/arch/mips/mm/Makefile	2002-08-24 16:44:34.000000000 +0200
@@ -20,8 +20,10 @@
 obj-$(CONFIG_CPU_R4300)		+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_R4X00)		+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_VR41XX)	+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R5000)		+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_NEVADA)	+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
+obj-$(CONFIG_CPU_R5000)		+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o \
+				   r5k-sc.o
+obj-$(CONFIG_CPU_NEVADA)	+= pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o \
+				   r5k-sc.o
 obj-$(CONFIG_CPU_R5432)		+= pg-r5432.o c-r5432.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_RM7000)	+= pg-rm7k.o c-rm7k.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_R10000)	+= pg-andes.o c-andes.o tlb-r4k.o tlbex-r4k.o
diff -Naur linux/arch/mips/mm/r5k-sc.c linux.patch/arch/mips/mm/r5k-sc.c
--- linux/arch/mips/mm/r5k-sc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux.patch/arch/mips/mm/r5k-sc.c	2002-08-24 17:06:25.000000000 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/bcache.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheops.h>
+
+/* Secondary cache size in bytes, if present.  */
+static unsigned long scache_size;
+
+#define SC_LINE 32
+#define SC_PAGE (128*SC_LINE)
+
+#define cache_op(base,op)                   \
+__asm__ __volatile__("				\
+		.set noreorder;                 \
+		.set mips3;                     \
+		cache %1, (%0);                 \
+		.set mips0;                     \
+		.set reorder"                   \
+		:                               \
+		: "r" (base),                   \
+		  "i" (op));
+
+static inline void blast_r5000_scache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		cache_op(start, R5K_Page_Invalidate_S);
+		start += SC_PAGE;
+	}
+}
+
+static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= scache_size) {
+		blast_r5000_scache();
+		return;
+	}
+
+	/* On the R5000 secondary cache we cannot
+	 * invalidate less than a page at a time.
+	 * The secondary cache is physically indexed, write-through.
+	 */
+	a = addr & ~(SC_PAGE - 1);
+	end = (addr + size - 1) & ~(SC_PAGE - 1);
+	while (a <= end) {
+		cache_op(a, R5K_Page_Invalidate_S);
+		a += SC_PAGE;
+	}
+}
+
+static void r5k_sc_enable(void)
+{
+        unsigned long flags;
+
+	__save_and_cli(flags);
+	change_cp0_config(CONF_SE, CONF_SE);
+	blast_r5000_scache();
+	__restore_flags(flags);
+}
+
+static void r5k_sc_disable(void)
+{
+        unsigned long flags;
+
+	__save_and_cli(flags);
+	blast_r5000_scache();
+	change_cp0_config(CONF_SE, 0);
+	__restore_flags(flags);
+}
+
+static inline int __init r5k_sc_probe(void)
+{
+	unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
+
+	if(config & CONF_SC)
+		return(0);
+
+	scache_size = (512*1024) << ((config >> 20)&3);
+
+	printk("R5000 SCACHE size %ldK, linesize 32 bytes.\n",
+			scache_size >> 10);
+
+	return 1;
+}
+
+struct bcache_ops r5k_sc_ops = {
+	r5k_sc_enable,
+	r5k_sc_disable,
+	r5k_dma_cache_inv_sc,
+	r5k_dma_cache_inv_sc
+};
+
+void __init r5k_sc_init(void)
+{
+	if (r5k_sc_probe()) {
+		r5k_sc_enable();
+		bcops = &r5k_sc_ops;
+	}
+}
diff -Naur linux/arch/mips64/mm/Makefile linux.patch/arch/mips64/mm/Makefile
--- linux/arch/mips64/mm/Makefile	2002-07-24 18:12:02.000000000 +0200
+++ linux.patch/arch/mips64/mm/Makefile	2002-08-24 16:46:55.000000000 +0200
@@ -11,8 +11,10 @@
 
 obj-$(CONFIG_CPU_R4300)		+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
 obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_R5000)		+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_NEVADA)	+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R5000)		+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o \
+				   r5k-sc.o
+obj-$(CONFIG_CPU_NEVADA)	+= r4xx0.o tlbex-r4k.o tlb-glue-r4k.o \
+				   r5k-sc.o
 obj-$(CONFIG_CPU_R10000)	+= andes.o tlbex-r4k.o tlb-glue-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= pg-sb1.o c-sb1.o tlb-sb1.o tlbex-r4k.o \
 				   tlb-glue-r4k.o
diff -Naur linux/arch/mips64/mm/r4xx0.c linux.patch/arch/mips64/mm/r4xx0.c
--- linux/arch/mips64/mm/r4xx0.c	2002-08-20 01:23:54.000000000 +0200
+++ linux.patch/arch/mips64/mm/r4xx0.c	2002-08-24 16:51:47.000000000 +0200
@@ -2274,6 +2274,7 @@
 }
 
 typedef int (*probe_func_t)(unsigned long);
+extern int r5k_sc_init(void);
 
 static inline void __init setup_scache(unsigned int config)
 {
@@ -2284,12 +2285,23 @@
 	probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
 	sc_present = probe_scache_kseg1(config);
 
-	if (sc_present) {
-		setup_scache_funcs();
+	if (!sc_present) {
+		setup_noscache_funcs();
 		return;
 	}
 
-	setup_noscache_funcs();
+	switch(mips_cpu.cputype) {
+	case CPU_R5000:
+	case CPU_NEVADA:
+			setup_noscache_funcs();
+#if defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)
+			r5k_sc_init();
+#endif
+			break;
+	default:
+			setup_scache_funcs();
+	}
+
 }
 
 void __init ld_mmu_r4xx0(void)
diff -Naur linux/arch/mips64/mm/r5k-sc.c linux.patch/arch/mips64/mm/r5k-sc.c
--- linux/arch/mips64/mm/r5k-sc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux.patch/arch/mips64/mm/r5k-sc.c	2002-08-24 17:12:50.000000000 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/bcache.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/r4kcacheops.h>
+
+/* Secondary cache size in bytes, if present.  */
+static unsigned long scache_size;
+
+#define SC_LINE 32
+#define SC_PAGE (128*SC_LINE)
+
+#define cache_op(base,op)                   \
+__asm__ __volatile__("				\
+		.set noreorder;                 \
+		.set mips3;                     \
+		cache %1, (%0);                 \
+		.set mips0;                     \
+		.set reorder"                   \
+		:                               \
+		: "r" (base),                   \
+		  "i" (op));
+
+static inline void blast_r5000_scache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		cache_op(start, R5K_Page_Invalidate_S);
+		start += SC_PAGE;
+	}
+}
+
+static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
+{
+	unsigned long end, a;
+
+	if (size >= scache_size) {
+		blast_r5000_scache();
+		return;
+	}
+
+	/* On the R5000 secondary cache we cannot
+	 * invalidate less than a page at a time.
+	 * The secondary cache is physically indexed, write-through.
+	 */
+	a = addr & ~(SC_PAGE - 1);
+	end = (addr + size - 1) & ~(SC_PAGE - 1);
+	while (a <= end) {
+		cache_op(a, R5K_Page_Invalidate_S);
+		a += SC_PAGE;
+	}
+}
+
+static void r5k_sc_enable(void)
+{
+        unsigned long flags;
+
+	__save_and_cli(flags);
+	change_cp0_config(CONF_SE, CONF_SE);
+	blast_r5000_scache();
+	__restore_flags(flags);
+}
+
+static void r5k_sc_disable(void)
+{
+        unsigned long flags;
+
+	__save_and_cli(flags);
+	blast_r5000_scache();
+	change_cp0_config(CONF_SE, 0);
+	__restore_flags(flags);
+}
+
+static inline int __init r5k_sc_probe(void)
+{
+	unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
+
+	if(config & CONF_SC)
+		return(0);
+
+	scache_size = (512*1024) << ((config >> 20)&3);
+
+	printk("R5000 SCACHE size %ldK, linesize 32 bytes.\n",
+			scache_size >> 10);
+
+	return 1;
+}
+
+struct bcache_ops r5k_sc_ops = {
+	r5k_sc_enable,
+	r5k_sc_disable,
+	r5k_dma_cache_inv_sc,
+	r5k_dma_cache_inv_sc
+};
+
+void __init r5k_sc_init(void)
+{
+	if (r5k_sc_probe()) {
+		r5k_sc_enable();
+		bcops = &r5k_sc_ops;
+	}
+}
diff -Naur linux/include/asm-mips/cacheops.h linux.patch/include/asm-mips/cacheops.h
--- linux/include/asm-mips/cacheops.h	1997-06-01 05:17:12.000000000 +0200
+++ linux.patch/include/asm-mips/cacheops.h	2002-08-24 16:50:51.000000000 +0200
@@ -35,6 +35,7 @@
 #define Hit_Writeback_Inv_D	0x15
 					/* 0x16 is unused */
 #define Hit_Writeback_Inv_SD	0x17
+#define R5K_Page_Invalidate_S	0x17
 #define Hit_Writeback_I		0x18
 #define Hit_Writeback_D		0x19
 					/* 0x1a is unused */
diff -Naur linux/include/asm-mips/mipsregs.h linux.patch/include/asm-mips/mipsregs.h
--- linux/include/asm-mips/mipsregs.h	2002-08-06 02:08:58.000000000 +0200
+++ linux.patch/include/asm-mips/mipsregs.h	2002-08-24 16:44:34.000000000 +0200
@@ -377,6 +377,7 @@
 #define CONF_CU				(1 <<  3)
 #define CONF_DB				(1 <<  4)
 #define CONF_IB				(1 <<  5)
+#define CONF_SE 			(1 << 12)
 #define CONF_SC				(1 << 17)
 #define CONF_AC                         (1 << 23)
 #define CONF_HALT                       (1 << 25)
diff -Naur linux/include/asm-mips64/mipsregs.h linux.patch/include/asm-mips64/mipsregs.h
--- linux/include/asm-mips64/mipsregs.h	2002-08-06 02:09:00.000000000 +0200
+++ linux.patch/include/asm-mips64/mipsregs.h	2002-08-24 16:51:35.000000000 +0200
@@ -377,6 +377,7 @@
 #define CONF_CU				(1 <<  3)
 #define CONF_DB				(1 <<  4)
 #define CONF_IB				(1 <<  5)
+#define CONF_SE				(1 << 12)
 #define CONF_SC				(1 << 17)
 #define CONF_AC                         (1 << 23)
 #define CONF_HALT                       (1 << 25)
diff -Naur linux/include/asm-mips64/r4kcacheops.h linux.patch/include/asm-mips64/r4kcacheops.h
--- linux/include/asm-mips64/r4kcacheops.h	2001-07-09 02:25:38.000000000 +0200
+++ linux.patch/include/asm-mips64/r4kcacheops.h	2002-08-24 16:50:27.000000000 +0200
@@ -35,6 +35,7 @@
 #define Hit_Writeback_Inv_D	0x15
 					/* 0x16 is unused */
 #define Hit_Writeback_Inv_SD	0x17
+#define R5K_Page_Invalidate_S	0x17
 #define Hit_Writeback_I		0x18
 #define Hit_Writeback_D		0x19
 					/* 0x1a is unused */




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux