- Alan Cox: synch. PA-RISC arch and bitops cleanups
[davej-history.git] / arch / parisc / kernel / cache.c
blob713a8b39a526c54aaacb47c77ae765e45cc7d7c6
1 /* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
7 * Copyright (C) 1999 Helge Deller (07-13-1999)
8 * Copyright (C) 1999 SuSE GmbH Nuernberg
9 * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
11 * Cache and TLB management
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
19 #include <asm/pdc.h>
20 #include <asm/cache.h>
21 #include <asm/system.h>
22 #include <asm/page.h>
23 #include <asm/pgalloc.h>
25 struct pdc_cache_info cache_info;
26 #ifndef __LP64__
27 static struct pdc_btlb_info btlb_info;
28 #endif
31 void __flush_page_to_ram(unsigned long address)
33 __flush_dcache_range(address, PAGE_SIZE);
34 __flush_icache_range(address, PAGE_SIZE);
39 void flush_data_cache(void)
41 register unsigned long base = cache_info.dc_base;
42 register unsigned long count = cache_info.dc_count;
43 register unsigned long loop = cache_info.dc_loop;
44 register unsigned long stride = cache_info.dc_stride;
45 register unsigned long addr;
46 register long i, j;
48 for(i=0,addr=base; i<count; i++,addr+=stride)
49 for(j=0; j<loop; j++)
50 fdce(addr);
53 static inline void flush_data_tlb_space(void)
55 unsigned long base = cache_info.dt_off_base;
56 unsigned long count = cache_info.dt_off_count;
57 unsigned long stride = cache_info.dt_off_stride;
58 unsigned long loop = cache_info.dt_loop;
60 unsigned long addr;
61 long i,j;
63 for(i=0,addr=base; i<count; i++,addr+=stride)
64 for(j=0; j<loop; j++)
65 pdtlbe(addr);
70 void flush_data_tlb(void)
72 unsigned long base = cache_info.dt_sp_base;
73 unsigned long count = cache_info.dt_sp_count;
74 unsigned long stride = cache_info.dt_sp_stride;
75 unsigned long space;
76 unsigned long old_sr1;
77 long i;
79 old_sr1 = mfsp(1);
81 for(i=0,space=base; i<count; i++, space+=stride) {
82 mtsp(space,1);
83 flush_data_tlb_space();
86 mtsp(old_sr1, 1);
89 static inline void flush_instruction_tlb_space(void)
91 unsigned long base = cache_info.it_off_base;
92 unsigned long count = cache_info.it_off_count;
93 unsigned long stride = cache_info.it_off_stride;
94 unsigned long loop = cache_info.it_loop;
96 unsigned long addr;
97 long i,j;
99 for(i=0,addr=base; i<count; i++,addr+=stride)
100 for(j=0; j<loop; j++)
101 pitlbe(addr);
104 void flush_instruction_tlb(void)
106 unsigned long base = cache_info.it_sp_base;
107 unsigned long count = cache_info.it_sp_count;
108 unsigned long stride = cache_info.it_sp_stride;
109 unsigned long space;
110 unsigned long old_sr1;
111 unsigned int i;
113 old_sr1 = mfsp(1);
115 for(i=0,space=base; i<count; i++, space+=stride) {
116 mtsp(space,1);
117 flush_instruction_tlb_space();
120 mtsp(old_sr1, 1);
124 void __flush_tlb_space(unsigned long space)
126 unsigned long old_sr1;
128 old_sr1 = mfsp(1);
129 mtsp(space, 1);
131 flush_data_tlb_space();
132 flush_instruction_tlb_space();
134 mtsp(old_sr1, 1);
138 void flush_instruction_cache(void)
140 register unsigned long base = cache_info.ic_base;
141 register unsigned long count = cache_info.ic_count;
142 register unsigned long loop = cache_info.ic_loop;
143 register unsigned long stride = cache_info.ic_stride;
144 register unsigned long addr;
145 register long i, j;
146 unsigned long old_sr1;
148 old_sr1 = mfsp(1);
149 mtsp(0,1);
152 * Note: fice instruction has 3 bit space field, so one must
153 * be specified (otherwise you are justing using whatever
154 * happens to be in sr0).
157 for(i=0,addr=base; i<count; i++,addr+=stride)
158 for(j=0; j<loop; j++)
159 fice(addr);
161 mtsp(old_sr1, 1);
164 /* not yet ... fdc() needs to be implemented in cache.h !
165 void flush_datacache_range( unsigned int base, unsigned int end )
167 register long offset,offset_add;
168 offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) *
169 cache_info.dc_conf.cc_line ) << 4;
170 for (offset=base; offset<=end; offset+=offset_add)
171 fdc(space,offset);
172 fdc(space,end);
176 /* flushes code and data-cache */
177 void flush_all_caches(void)
179 flush_instruction_cache();
180 flush_data_cache();
182 flush_instruction_tlb();
183 flush_data_tlb();
185 asm volatile("sync");
186 asm volatile("syncdma");
187 asm volatile("sync");
190 int get_cache_info(char *buffer)
192 char *p = buffer;
194 p += sprintf(p, "I-cache\t\t: %ld KB\n",
195 cache_info.ic_size/1024 );
196 p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n",
197 cache_info.dc_size/1024,
198 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
199 (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
202 p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
203 cache_info.it_size,
204 cache_info.dt_size,
205 cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
208 #ifndef __LP64__
209 /* BTLB - Block TLB */
210 if (btlb_info.max_size==0) {
211 p += sprintf(p, "BTLB\t\t: not supported\n" );
212 } else {
213 p += sprintf(p,
214 "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
215 "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
216 "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
217 btlb_info.max_size, (int)4096,
218 btlb_info.max_size>>8,
219 btlb_info.fixed_range_info.num_i,
220 btlb_info.fixed_range_info.num_d,
221 btlb_info.fixed_range_info.num_comb,
222 btlb_info.variable_range_info.num_i,
223 btlb_info.variable_range_info.num_d,
224 btlb_info.variable_range_info.num_comb
227 #endif
229 return p - buffer;
233 void __init
234 cache_init(void)
236 if(pdc_cache_info(&cache_info)<0)
237 panic("cache_init: pdc_cache_info failed");
239 #if 0
240 printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
241 cache_info.ic_size,
242 cache_info.dc_size,
243 cache_info.it_size,
244 sizeof (struct pdc_cache_info) / sizeof (long),
245 sizeof (struct pdc_cache_cf)
247 #endif
248 #ifndef __LP64__
249 if(pdc_btlb_info(&btlb_info)<0) {
250 memset(&btlb_info, 0, sizeof btlb_info);
252 #endif