Hello again, This patch adds support for the secondary cache on the O2. It works basically as the cache support for the ip22 (i.e. using the board_cache interface) Vivien Chappelier.
diff -Naur linux/arch/mips64/defconfig-ip32 linux.patch/arch/mips64/defconfig-ip32 --- linux/arch/mips64/defconfig-ip32 Tue Jan 1 21:51:11 2002 +++ linux.patch/arch/mips64/defconfig-ip32 Thu Jan 3 20:43:10 2002 @@ -27,6 +27,7 @@ CONFIG_MAPPED_PCI_IO=y CONFIG_NONCOHERENT_IO=y CONFIG_ARC_MEMORY=y +CONFIG_BOARD_SCACHE=y CONFIG_L1_CACHE_SHIFT=5 # CONFIG_ISA is not set # CONFIG_EISA is not set diff -Naur linux/arch/mips64/sgi-ip32/Makefile linux.patch/arch/mips64/sgi-ip32/Makefile --- linux/arch/mips64/sgi-ip32/Makefile Tue Jan 1 21:51:12 2002 +++ linux.patch/arch/mips64/sgi-ip32/Makefile Thu Jan 3 20:42:15 2002 @@ -18,7 +18,7 @@ all: ip32-kern.a ip32-irq-glue.o obj-y += ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o ip32-timer.o \ - crime.o ip32-reset.o + crime.o ip32-reset.o ip32-sc.o obj-$(CONFIG_PCI) += ip32-pci.o ip32-pci-dma.o diff -Naur linux/arch/mips64/sgi-ip32/ip32-sc.c linux.patch/arch/mips64/sgi-ip32/ip32-sc.c --- linux/arch/mips64/sgi-ip32/ip32-sc.c Thu Jan 1 01:00:00 1970 +++ linux.patch/arch/mips64/sgi-ip32/ip32-sc.c Thu Jan 3 20:42:30 2002 @@ -0,0 +1,154 @@ +/* + * ip32-sc.c: O2 cache management functions. + * + * 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> + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#undef DEBUG_CACHE + +#define SC_LINE 32 + +#define Clear_SD 0x03 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_SD 0x0B +#define Page_Writeback_Inv_SD 0x17 + +#if 0 /* This is supposed to flush the whole cache but doesn't seem to work */ +static inline void flush_scache_all(void) +{ + unsigned long addr = KSEG0; + + set_taglo(0); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + __asm__ __volatile__("\n\t.set noreorder\n\t" + "cache 0x03, (%0)\n\t" + ".set reorder\n\t" : : "r" (addr)); +} +#endif + +static inline void flush_scache_page(unsigned long page) +{ + __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ + __asm__ __volatile__("\n\t.set noreorder\n\t" + "cache 0x17, (%0)\n\t" + ".set reorder\n\t" : : "r" (page)); +} + +static inline void flush_scache_all(void) +{ + unsigned long start = KSEG0; /* unmapped */ + unsigned long end = (start + scache_size); + + set_taglo(0); + while(start < end) { + flush_scache_page(start); + start += PAGE_SIZE; + } +} + +static void ip32_sc_wback_invalidate(unsigned long addr, unsigned long size) +{ + unsigned long begin, end; + unsigned int flags; + +#ifdef DEBUG_CACHE + printk("ip32_sc_wback_invalidate[%08lx,%08lx]", addr, size); +#endif + + if (!size) + return; + + /* Which pages to flush? */ + begin = (addr & PAGE_MASK); + end = (addr+size+PAGE_SIZE-1) & PAGE_MASK; + /* Which lines to flush? */ + begin = KSEG0 + (begin & (scache_size - SC_LINE)); /* unmapped */ + end = KSEG0 + (end & (scache_size - SC_LINE)); + + set_taglo(0); /* invalidate flushed page */ + __save_and_cli(flags); + if(begin < end) { + for(addr = begin; addr < end; addr += PAGE_SIZE) + flush_scache_page(addr); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + } else { + for(addr = begin; addr < (KSEG0+scache_size); addr += PAGE_SIZE) + flush_scache_page(addr); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + for(addr = KSEG0; addr < end; addr += PAGE_SIZE) + flush_scache_page(addr); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + } + __restore_flags(flags); +} + +static void ip32_sc_enable(void) +{ + unsigned long flags; + + /* This is really cool... */ +#ifdef DEBUG_CACHE + printk("Enabling R5000 SCACHE\n"); +#endif + __save_and_cli(flags); + change_cp0_config(CONF_SE, CONF_SE); + flush_scache_all(); + __restore_flags(flags); +} + +static void ip32_sc_disable(void) +{ + unsigned long flags; +#ifdef DEBUG_CACHE + printk("Disabling R5000 SCACHE\n"); +#endif + __save_and_cli(flags); + flush_scache_all(); + change_cp0_config(CONF_SE, 0); + __restore_flags(flags); +} + +static inline int __init ip32_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 ip32_sc_ops = { + ip32_sc_enable, + ip32_sc_disable, + ip32_sc_wback_invalidate, + ip32_sc_wback_invalidate +}; + +void __init ip32_sc_init(void) +{ + if (ip32_sc_probe()) { + ip32_sc_enable(); + bcops = &ip32_sc_ops; + } +} diff -Naur linux/arch/mips64/sgi-ip32/ip32-setup.c linux.patch/arch/mips64/sgi-ip32/ip32-setup.c --- linux/arch/mips64/sgi-ip32/ip32-setup.c Wed Jan 2 23:49:19 2002 +++ linux.patch/arch/mips64/sgi-ip32/ip32-setup.c Thu Jan 3 20:42:06 2002 @@ -59,6 +59,7 @@ extern void ip32_time_init(void); extern void ip32_reboot_setup(void); +extern void ip32_sc_init(void); void __init bus_error_init(void) { @@ -94,6 +95,7 @@ conswitchp = &dummy_con; #endif ip32_reboot_setup(); + ip32_sc_init(); rtc_ops = &ip32_rtc_ops; board_time_init = ip32_time_init; --- linux/arch/mips64/config.in Tue Jan 1 21:51:10 2002 +++ linux.patch/arch/mips64/config.in Thu Jan 3 22:08:33 2002 @@ -91,7 +91,7 @@ define_bool CONFIG_ARC32 y define_bool CONFIG_PC_KEYB y define_bool CONFIG_PCI y - #define_bool CONFIG_BOARD_SCACHE y + define_bool CONFIG_BOARD_SCACHE y define_bool CONFIG_MAPPED_PCI_IO y define_bool CONFIG_NONCOHERENT_IO y define_bool CONFIG_ARC_MEMORY y