Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.14 193 lines 4.4 kB view raw
1/* 2 * sc-rm7k.c: RM7000 cache management functions. 3 * 4 * Copyright (C) 1997, 2001, 2003, 2004 Ralf Baechle (ralf@linux-mips.org) 5 */ 6 7#undef DEBUG 8 9#include <linux/init.h> 10#include <linux/kernel.h> 11#include <linux/mm.h> 12 13#include <asm/addrspace.h> 14#include <asm/bcache.h> 15#include <asm/cacheops.h> 16#include <asm/mipsregs.h> 17#include <asm/processor.h> 18 19/* Primary cache parameters. */ 20#define sc_lsize 32 21#define tc_pagesize (32*128) 22 23/* Secondary cache parameters. */ 24#define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ 25 26extern unsigned long icache_way_size, dcache_way_size; 27 28#include <asm/r4kcache.h> 29 30int rm7k_tcache_enabled; 31 32/* 33 * Writeback and invalidate the primary cache dcache before DMA. 34 * (XXX These need to be fixed ...) 35 */ 36static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) 37{ 38 unsigned long end, a; 39 40 pr_debug("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size); 41 42 /* Catch bad driver code */ 43 BUG_ON(size == 0); 44 45 a = addr & ~(sc_lsize - 1); 46 end = (addr + size - 1) & ~(sc_lsize - 1); 47 while (1) { 48 flush_scache_line(a); /* Hit_Writeback_Inv_SD */ 49 if (a == end) 50 break; 51 a += sc_lsize; 52 } 53 54 if (!rm7k_tcache_enabled) 55 return; 56 57 a = addr & ~(tc_pagesize - 1); 58 end = (addr + size - 1) & ~(tc_pagesize - 1); 59 while(1) { 60 invalidate_tcache_page(a); /* Page_Invalidate_T */ 61 if (a == end) 62 break; 63 a += tc_pagesize; 64 } 65} 66 67static void rm7k_sc_inv(unsigned long addr, unsigned long size) 68{ 69 unsigned long end, a; 70 71 pr_debug("rm7k_sc_inv[%08lx,%08lx]", addr, size); 72 73 /* Catch bad driver code */ 74 BUG_ON(size == 0); 75 76 a = addr & ~(sc_lsize - 1); 77 end = (addr + size - 1) & ~(sc_lsize - 1); 78 while (1) { 79 invalidate_scache_line(a); /* Hit_Invalidate_SD */ 80 if (a == end) 81 break; 82 a += sc_lsize; 83 } 84 85 if (!rm7k_tcache_enabled) 86 return; 87 88 a = addr & ~(tc_pagesize - 1); 89 end = (addr + size - 1) & ~(tc_pagesize - 1); 90 while(1) { 91 invalidate_tcache_page(a); /* Page_Invalidate_T */ 92 if (a == end) 93 break; 94 a += tc_pagesize; 95 } 96} 97 98/* 99 * This function is executed in the uncached segment CKSEG1. 100 * It must not touch the stack, because the stack pointer still points 101 * into CKSEG0. 102 * 103 * Three options: 104 * - Write it in assembly and guarantee that we don't use the stack. 105 * - Disable caching for CKSEG0 before calling it. 106 * - Pray that GCC doesn't randomly start using the stack. 107 * 108 * This being Linux, we obviously take the least sane of those options - 109 * following DaveM's lead in c-r4k.c 110 * 111 * It seems we get our kicks from relying on unguaranteed behaviour in GCC 112 */ 113static __init void __rm7k_sc_enable(void) 114{ 115 int i; 116 117 set_c0_config(1 << 3); /* CONF_SE */ 118 119 write_c0_taglo(0); 120 write_c0_taghi(0); 121 122 for (i = 0; i < scache_size; i += sc_lsize) { 123 __asm__ __volatile__ ( 124 ".set noreorder\n\t" 125 ".set mips3\n\t" 126 "cache %1, (%0)\n\t" 127 ".set mips0\n\t" 128 ".set reorder" 129 : 130 : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD)); 131 } 132} 133 134static __init void rm7k_sc_enable(void) 135{ 136 void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable); 137 138 if (read_c0_config() & 0x08) /* CONF_SE */ 139 return; 140 141 printk(KERN_INFO "Enabling secondary cache..."); 142 func(); 143} 144 145static void rm7k_sc_disable(void) 146{ 147 clear_c0_config(1<<3); /* CONF_SE */ 148} 149 150struct bcache_ops rm7k_sc_ops = { 151 .bc_enable = rm7k_sc_enable, 152 .bc_disable = rm7k_sc_disable, 153 .bc_wback_inv = rm7k_sc_wback_inv, 154 .bc_inv = rm7k_sc_inv 155}; 156 157void __init rm7k_sc_init(void) 158{ 159 unsigned int config = read_c0_config(); 160 161 if ((config >> 31) & 1) /* Bit 31 set -> no S-Cache */ 162 return; 163 164 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", 165 (scache_size >> 10), sc_lsize); 166 167 if (!((config >> 3) & 1)) /* CONF_SE */ 168 rm7k_sc_enable(); 169 170 /* 171 * While we're at it let's deal with the tertiary cache. 172 */ 173 if (!((config >> 17) & 1)) { 174 175 /* 176 * We can't enable the L3 cache yet. There may be board-specific 177 * magic necessary to turn it on, and blindly asking the CPU to 178 * start using it would may give cache errors. 179 * 180 * Also, board-specific knowledge may allow us to use the 181 * CACHE Flash_Invalidate_T instruction if the tag RAM supports 182 * it, and may specify the size of the L3 cache so we don't have 183 * to probe it. 184 */ 185 printk(KERN_INFO "Tertiary cache present, %s enabled\n", 186 config&(1<<12) ? "already" : "not (yet)"); 187 188 if ((config >> 12) & 1) 189 rm7k_tcache_enabled = 1; 190 } 191 192 bcops = &rm7k_sc_ops; 193}