~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/microblaze/kernel/cpu/cache.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Cache control for MicroBlaze cache memories
  3  *
  4  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  5  * Copyright (C) 2007-2009 PetaLogix
  6  * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com>
  7  *
  8  * This file is subject to the terms and conditions of the GNU General
  9  * Public License. See the file COPYING in the main directory of this
 10  * archive for more details.
 11  */
 12 
 13 #include <asm/cacheflush.h>
 14 #include <linux/cache.h>
 15 #include <asm/cpuinfo.h>
 16 #include <asm/pvr.h>
 17 
 18 static inline void __enable_icache_msr(void)
 19 {
 20         __asm__ __volatile__ ("  msrset r0, %0;"        \
 21                                 "nop;"                  \
 22                         : : "i" (MSR_ICE) : "memory");
 23 }
 24 
 25 static inline void __disable_icache_msr(void)
 26 {
 27         __asm__ __volatile__ ("  msrclr r0, %0;"        \
 28                                 "nop;"                  \
 29                         : : "i" (MSR_ICE) : "memory");
 30 }
 31 
 32 static inline void __enable_dcache_msr(void)
 33 {
 34         __asm__ __volatile__ ("  msrset r0, %0;"        \
 35                                 "nop;"                  \
 36                         : : "i" (MSR_DCE) : "memory");
 37 }
 38 
 39 static inline void __disable_dcache_msr(void)
 40 {
 41         __asm__ __volatile__ ("  msrclr r0, %0;"        \
 42                                 "nop; "                 \
 43                         : : "i" (MSR_DCE) : "memory");
 44 }
 45 
 46 static inline void __enable_icache_nomsr(void)
 47 {
 48         __asm__ __volatile__ ("  mfs    r12, rmsr;"     \
 49                                 "nop;"                  \
 50                                 "ori    r12, r12, %0;"  \
 51                                 "mts    rmsr, r12;"     \
 52                                 "nop;"                  \
 53                         : : "i" (MSR_ICE) : "memory", "r12");
 54 }
 55 
 56 static inline void __disable_icache_nomsr(void)
 57 {
 58         __asm__ __volatile__ ("  mfs    r12, rmsr;"     \
 59                                 "nop;"                  \
 60                                 "andi   r12, r12, ~%0;" \
 61                                 "mts    rmsr, r12;"     \
 62                                 "nop;"                  \
 63                         : : "i" (MSR_ICE) : "memory", "r12");
 64 }
 65 
 66 static inline void __enable_dcache_nomsr(void)
 67 {
 68         __asm__ __volatile__ ("  mfs    r12, rmsr;"     \
 69                                 "nop;"                  \
 70                                 "ori    r12, r12, %0;"  \
 71                                 "mts    rmsr, r12;"     \
 72                                 "nop;"                  \
 73                         : : "i" (MSR_DCE) : "memory", "r12");
 74 }
 75 
 76 static inline void __disable_dcache_nomsr(void)
 77 {
 78         __asm__ __volatile__ ("  mfs    r12, rmsr;"     \
 79                                 "nop;"                  \
 80                                 "andi   r12, r12, ~%0;" \
 81                                 "mts    rmsr, r12;"     \
 82                                 "nop;"                  \
 83                         : : "i" (MSR_DCE) : "memory", "r12");
 84 }
 85 
 86 
 87 /* Helper macro for computing the limits of cache range loops
 88  *
 89  * End address can be unaligned which is OK for C implementation.
 90  * ASM implementation align it in ASM macros
 91  */
 92 #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size)    \
 93 do {                                                                    \
 94         int align = ~(cache_line_length - 1);                           \
 95         if (start <  UINT_MAX - cache_size)                             \
 96                 end = min(start + cache_size, end);                     \
 97         start &= align;                                                 \
 98 } while (0)
 99 
100 /*
101  * Helper macro to loop over the specified cache_size/line_length and
102  * execute 'op' on that cacheline
103  */
104 #define CACHE_ALL_LOOP(cache_size, line_length, op)                     \
105 do {                                                                    \
106         unsigned int len = cache_size - line_length;                    \
107         int step = -line_length;                                        \
108         WARN_ON(step >= 0);                                             \
109                                                                         \
110         __asm__ __volatile__ (" 1:      " #op " %0, r0;"                \
111                                         "bgtid   %0, 1b;"               \
112                                         "addk    %0, %0, %1;"           \
113                                         : : "r" (len), "r" (step)       \
114                                         : "memory");                    \
115 } while (0)
116 
117 /* Used for wdc.flush/clear which can use rB for offset which is not possible
118  * to use for simple wdc or wic.
119  *
120  * start address is cache aligned
121  * end address is not aligned, if end is aligned then I have to subtract
122  * cacheline length because I can't flush/invalidate the next cacheline.
123  * If is not, I align it because I will flush/invalidate whole line.
124  */
125 #define CACHE_RANGE_LOOP_2(start, end, line_length, op)                 \
126 do {                                                                    \
127         int step = -line_length;                                        \
128         int align = ~(line_length - 1);                                 \
129         int count;                                                      \
130         end = ((end & align) == end) ? end - line_length : end & align; \
131         count = end - start;                                            \
132         WARN_ON(count < 0);                                             \
133                                                                         \
134         __asm__ __volatile__ (" 1:      " #op " %0, %1;"                \
135                                         "bgtid  %1, 1b;"                \
136                                         "addk   %1, %1, %2;"            \
137                                         : : "r" (start), "r" (count),   \
138                                         "r" (step) : "memory");         \
139 } while (0)
140 
141 /* It is used only first parameter for OP - for wic, wdc */
142 #define CACHE_RANGE_LOOP_1(start, end, line_length, op)                 \
143 do {                                                                    \
144         unsigned int volatile temp = 0;                                         \
145         unsigned int align = ~(line_length - 1);                                        \
146         end = ((end & align) == end) ? end - line_length : end & align; \
147         WARN_ON(end < start);                                   \
148                                                                         \
149         __asm__ __volatile__ (" 1:      " #op " %1, r0;"                \
150                                         "cmpu   %0, %1, %2;"            \
151                                         "bgtid  %0, 1b;"                \
152                                         "addk   %1, %1, %3;"            \
153                                 : : "r" (temp), "r" (start), "r" (end), \
154                                         "r" (line_length) : "memory");  \
155 } while (0)
156 
157 #define ASM_LOOP
158 
159 static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
160 {
161         unsigned long flags;
162 #ifndef ASM_LOOP
163         int i;
164 #endif
165         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
166                                 (unsigned int)start, (unsigned int) end);
167 
168         CACHE_LOOP_LIMITS(start, end,
169                         cpuinfo.icache_line_length, cpuinfo.icache_size);
170 
171         local_irq_save(flags);
172         __disable_icache_msr();
173 
174 #ifdef ASM_LOOP
175         CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
176 #else
177         for (i = start; i < end; i += cpuinfo.icache_line_length)
178                 __asm__ __volatile__ ("wic      %0, r0;"        \
179                                 : : "r" (i));
180 #endif
181         __enable_icache_msr();
182         local_irq_restore(flags);
183 }
184 
185 static void __flush_icache_range_nomsr_irq(unsigned long start,
186                                 unsigned long end)
187 {
188         unsigned long flags;
189 #ifndef ASM_LOOP
190         int i;
191 #endif
192         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
193                                 (unsigned int)start, (unsigned int) end);
194 
195         CACHE_LOOP_LIMITS(start, end,
196                         cpuinfo.icache_line_length, cpuinfo.icache_size);
197 
198         local_irq_save(flags);
199         __disable_icache_nomsr();
200 
201 #ifdef ASM_LOOP
202         CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
203 #else
204         for (i = start; i < end; i += cpuinfo.icache_line_length)
205                 __asm__ __volatile__ ("wic      %0, r0;"        \
206                                 : : "r" (i));
207 #endif
208 
209         __enable_icache_nomsr();
210         local_irq_restore(flags);
211 }
212 
213 static void __flush_icache_range_noirq(unsigned long start,
214                                 unsigned long end)
215 {
216 #ifndef ASM_LOOP
217         int i;
218 #endif
219         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
220                                 (unsigned int)start, (unsigned int) end);
221 
222         CACHE_LOOP_LIMITS(start, end,
223                         cpuinfo.icache_line_length, cpuinfo.icache_size);
224 #ifdef ASM_LOOP
225         CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
226 #else
227         for (i = start; i < end; i += cpuinfo.icache_line_length)
228                 __asm__ __volatile__ ("wic      %0, r0;"        \
229                                 : : "r" (i));
230 #endif
231 }
232 
233 static void __flush_icache_all_msr_irq(void)
234 {
235         unsigned long flags;
236 #ifndef ASM_LOOP
237         int i;
238 #endif
239         pr_debug("%s\n", __func__);
240 
241         local_irq_save(flags);
242         __disable_icache_msr();
243 #ifdef ASM_LOOP
244         CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
245 #else
246         for (i = 0; i < cpuinfo.icache_size;
247                  i += cpuinfo.icache_line_length)
248                         __asm__ __volatile__ ("wic      %0, r0;" \
249                                         : : "r" (i));
250 #endif
251         __enable_icache_msr();
252         local_irq_restore(flags);
253 }
254 
255 static void __flush_icache_all_nomsr_irq(void)
256 {
257         unsigned long flags;
258 #ifndef ASM_LOOP
259         int i;
260 #endif
261         pr_debug("%s\n", __func__);
262 
263         local_irq_save(flags);
264         __disable_icache_nomsr();
265 #ifdef ASM_LOOP
266         CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
267 #else
268         for (i = 0; i < cpuinfo.icache_size;
269                  i += cpuinfo.icache_line_length)
270                         __asm__ __volatile__ ("wic      %0, r0;" \
271                                         : : "r" (i));
272 #endif
273         __enable_icache_nomsr();
274         local_irq_restore(flags);
275 }
276 
277 static void __flush_icache_all_noirq(void)
278 {
279 #ifndef ASM_LOOP
280         int i;
281 #endif
282         pr_debug("%s\n", __func__);
283 #ifdef ASM_LOOP
284         CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
285 #else
286         for (i = 0; i < cpuinfo.icache_size;
287                  i += cpuinfo.icache_line_length)
288                         __asm__ __volatile__ ("wic      %0, r0;" \
289                                         : : "r" (i));
290 #endif
291 }
292 
293 static void __invalidate_dcache_all_msr_irq(void)
294 {
295         unsigned long flags;
296 #ifndef ASM_LOOP
297         int i;
298 #endif
299         pr_debug("%s\n", __func__);
300 
301         local_irq_save(flags);
302         __disable_dcache_msr();
303 #ifdef ASM_LOOP
304         CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
305 #else
306         for (i = 0; i < cpuinfo.dcache_size;
307                  i += cpuinfo.dcache_line_length)
308                         __asm__ __volatile__ ("wdc      %0, r0;" \
309                                         : : "r" (i));
310 #endif
311         __enable_dcache_msr();
312         local_irq_restore(flags);
313 }
314 
315 static void __invalidate_dcache_all_nomsr_irq(void)
316 {
317         unsigned long flags;
318 #ifndef ASM_LOOP
319         int i;
320 #endif
321         pr_debug("%s\n", __func__);
322 
323         local_irq_save(flags);
324         __disable_dcache_nomsr();
325 #ifdef ASM_LOOP
326         CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
327 #else
328         for (i = 0; i < cpuinfo.dcache_size;
329                  i += cpuinfo.dcache_line_length)
330                         __asm__ __volatile__ ("wdc      %0, r0;" \
331                                         : : "r" (i));
332 #endif
333         __enable_dcache_nomsr();
334         local_irq_restore(flags);
335 }
336 
337 static void __invalidate_dcache_all_noirq_wt(void)
338 {
339 #ifndef ASM_LOOP
340         int i;
341 #endif
342         pr_debug("%s\n", __func__);
343 #ifdef ASM_LOOP
344         CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
345 #else
346         for (i = 0; i < cpuinfo.dcache_size;
347                  i += cpuinfo.dcache_line_length)
348                         __asm__ __volatile__ ("wdc      %0, r0;" \
349                                         : : "r" (i));
350 #endif
351 }
352 
353 /*
354  * FIXME It is blindly invalidation as is expected
355  * but can't be called on noMMU in microblaze_cache_init below
356  *
357  * MS: noMMU kernel won't boot if simple wdc is used
358  * The reason should be that there are discared data which kernel needs
359  */
360 static void __invalidate_dcache_all_wb(void)
361 {
362 #ifndef ASM_LOOP
363         int i;
364 #endif
365         pr_debug("%s\n", __func__);
366 #ifdef ASM_LOOP
367         CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
368                                         wdc);
369 #else
370         for (i = 0; i < cpuinfo.dcache_size;
371                  i += cpuinfo.dcache_line_length)
372                         __asm__ __volatile__ ("wdc      %0, r0;" \
373                                         : : "r" (i));
374 #endif
375 }
376 
377 static void __invalidate_dcache_range_wb(unsigned long start,
378                                                 unsigned long end)
379 {
380 #ifndef ASM_LOOP
381         int i;
382 #endif
383         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
384                                 (unsigned int)start, (unsigned int) end);
385 
386         CACHE_LOOP_LIMITS(start, end,
387                         cpuinfo.dcache_line_length, cpuinfo.dcache_size);
388 #ifdef ASM_LOOP
389         CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
390 #else
391         for (i = start; i < end; i += cpuinfo.dcache_line_length)
392                 __asm__ __volatile__ ("wdc.clear        %0, r0;"        \
393                                 : : "r" (i));
394 #endif
395 }
396 
397 static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
398                                                         unsigned long end)
399 {
400 #ifndef ASM_LOOP
401         int i;
402 #endif
403         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
404                                 (unsigned int)start, (unsigned int) end);
405         CACHE_LOOP_LIMITS(start, end,
406                         cpuinfo.dcache_line_length, cpuinfo.dcache_size);
407 
408 #ifdef ASM_LOOP
409         CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
410 #else
411         for (i = start; i < end; i += cpuinfo.dcache_line_length)
412                 __asm__ __volatile__ ("wdc      %0, r0;"        \
413                                 : : "r" (i));
414 #endif
415 }
416 
417 static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
418                                                         unsigned long end)
419 {
420         unsigned long flags;
421 #ifndef ASM_LOOP
422         int i;
423 #endif
424         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
425                                 (unsigned int)start, (unsigned int) end);
426         CACHE_LOOP_LIMITS(start, end,
427                         cpuinfo.dcache_line_length, cpuinfo.dcache_size);
428 
429         local_irq_save(flags);
430         __disable_dcache_msr();
431 
432 #ifdef ASM_LOOP
433         CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
434 #else
435         for (i = start; i < end; i += cpuinfo.dcache_line_length)
436                 __asm__ __volatile__ ("wdc      %0, r0;"        \
437                                 : : "r" (i));
438 #endif
439 
440         __enable_dcache_msr();
441         local_irq_restore(flags);
442 }
443 
444 static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
445                                                         unsigned long end)
446 {
447         unsigned long flags;
448 #ifndef ASM_LOOP
449         int i;
450 #endif
451         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
452                                 (unsigned int)start, (unsigned int) end);
453 
454         CACHE_LOOP_LIMITS(start, end,
455                         cpuinfo.dcache_line_length, cpuinfo.dcache_size);
456 
457         local_irq_save(flags);
458         __disable_dcache_nomsr();
459 
460 #ifdef ASM_LOOP
461         CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
462 #else
463         for (i = start; i < end; i += cpuinfo.dcache_line_length)
464                 __asm__ __volatile__ ("wdc      %0, r0;"        \
465                                 : : "r" (i));
466 #endif
467 
468         __enable_dcache_nomsr();
469         local_irq_restore(flags);
470 }
471 
472 static void __flush_dcache_all_wb(void)
473 {
474 #ifndef ASM_LOOP
475         int i;
476 #endif
477         pr_debug("%s\n", __func__);
478 #ifdef ASM_LOOP
479         CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
480                                 wdc.flush);
481 #else
482         for (i = 0; i < cpuinfo.dcache_size;
483                  i += cpuinfo.dcache_line_length)
484                         __asm__ __volatile__ ("wdc.flush        %0, r0;" \
485                                         : : "r" (i));
486 #endif
487 }
488 
489 static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
490 {
491 #ifndef ASM_LOOP
492         int i;
493 #endif
494         pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
495                                 (unsigned int)start, (unsigned int) end);
496 
497         CACHE_LOOP_LIMITS(start, end,
498                         cpuinfo.dcache_line_length, cpuinfo.dcache_size);
499 #ifdef ASM_LOOP
500         CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
501 #else
502         for (i = start; i < end; i += cpuinfo.dcache_line_length)
503                 __asm__ __volatile__ ("wdc.flush        %0, r0;"        \
504                                 : : "r" (i));
505 #endif
506 }
507 
508 /* struct for wb caches and for wt caches */
509 struct scache *mbc;
510 
511 /* new wb cache model */
512 static const struct scache wb_msr = {
513         .ie = __enable_icache_msr,
514         .id = __disable_icache_msr,
515         .ifl = __flush_icache_all_noirq,
516         .iflr = __flush_icache_range_noirq,
517         .iin = __flush_icache_all_noirq,
518         .iinr = __flush_icache_range_noirq,
519         .de = __enable_dcache_msr,
520         .dd = __disable_dcache_msr,
521         .dfl = __flush_dcache_all_wb,
522         .dflr = __flush_dcache_range_wb,
523         .din = __invalidate_dcache_all_wb,
524         .dinr = __invalidate_dcache_range_wb,
525 };
526 
527 /* There is only difference in ie, id, de, dd functions */
528 static const struct scache wb_nomsr = {
529         .ie = __enable_icache_nomsr,
530         .id = __disable_icache_nomsr,
531         .ifl = __flush_icache_all_noirq,
532         .iflr = __flush_icache_range_noirq,
533         .iin = __flush_icache_all_noirq,
534         .iinr = __flush_icache_range_noirq,
535         .de = __enable_dcache_nomsr,
536         .dd = __disable_dcache_nomsr,
537         .dfl = __flush_dcache_all_wb,
538         .dflr = __flush_dcache_range_wb,
539         .din = __invalidate_dcache_all_wb,
540         .dinr = __invalidate_dcache_range_wb,
541 };
542 
543 /* Old wt cache model with disabling irq and turn off cache */
544 static const struct scache wt_msr = {
545         .ie = __enable_icache_msr,
546         .id = __disable_icache_msr,
547         .ifl = __flush_icache_all_msr_irq,
548         .iflr = __flush_icache_range_msr_irq,
549         .iin = __flush_icache_all_msr_irq,
550         .iinr = __flush_icache_range_msr_irq,
551         .de = __enable_dcache_msr,
552         .dd = __disable_dcache_msr,
553         .dfl = __invalidate_dcache_all_msr_irq,
554         .dflr = __invalidate_dcache_range_msr_irq_wt,
555         .din = __invalidate_dcache_all_msr_irq,
556         .dinr = __invalidate_dcache_range_msr_irq_wt,
557 };
558 
559 static const struct scache wt_nomsr = {
560         .ie = __enable_icache_nomsr,
561         .id = __disable_icache_nomsr,
562         .ifl = __flush_icache_all_nomsr_irq,
563         .iflr = __flush_icache_range_nomsr_irq,
564         .iin = __flush_icache_all_nomsr_irq,
565         .iinr = __flush_icache_range_nomsr_irq,
566         .de = __enable_dcache_nomsr,
567         .dd = __disable_dcache_nomsr,
568         .dfl = __invalidate_dcache_all_nomsr_irq,
569         .dflr = __invalidate_dcache_range_nomsr_irq,
570         .din = __invalidate_dcache_all_nomsr_irq,
571         .dinr = __invalidate_dcache_range_nomsr_irq,
572 };
573 
574 /* New wt cache model for newer Microblaze versions */
575 static const struct scache wt_msr_noirq = {
576         .ie = __enable_icache_msr,
577         .id = __disable_icache_msr,
578         .ifl = __flush_icache_all_noirq,
579         .iflr = __flush_icache_range_noirq,
580         .iin = __flush_icache_all_noirq,
581         .iinr = __flush_icache_range_noirq,
582         .de = __enable_dcache_msr,
583         .dd = __disable_dcache_msr,
584         .dfl = __invalidate_dcache_all_noirq_wt,
585         .dflr = __invalidate_dcache_range_nomsr_wt,
586         .din = __invalidate_dcache_all_noirq_wt,
587         .dinr = __invalidate_dcache_range_nomsr_wt,
588 };
589 
590 static const struct scache wt_nomsr_noirq = {
591         .ie = __enable_icache_nomsr,
592         .id = __disable_icache_nomsr,
593         .ifl = __flush_icache_all_noirq,
594         .iflr = __flush_icache_range_noirq,
595         .iin = __flush_icache_all_noirq,
596         .iinr = __flush_icache_range_noirq,
597         .de = __enable_dcache_nomsr,
598         .dd = __disable_dcache_nomsr,
599         .dfl = __invalidate_dcache_all_noirq_wt,
600         .dflr = __invalidate_dcache_range_nomsr_wt,
601         .din = __invalidate_dcache_all_noirq_wt,
602         .dinr = __invalidate_dcache_range_nomsr_wt,
603 };
604 
605 /* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
606 #define CPUVER_7_20_A   0x0c
607 #define CPUVER_7_20_D   0x0f
608 
609 void microblaze_cache_init(void)
610 {
611         if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
612                 if (cpuinfo.dcache_wb) {
613                         pr_info("wb_msr\n");
614                         mbc = (struct scache *)&wb_msr;
615                         if (cpuinfo.ver_code <= CPUVER_7_20_D) {
616                                 /* MS: problem with signal handling - hw bug */
617                                 pr_info("WB won't work properly\n");
618                         }
619                 } else {
620                         if (cpuinfo.ver_code >= CPUVER_7_20_A) {
621                                 pr_info("wt_msr_noirq\n");
622                                 mbc = (struct scache *)&wt_msr_noirq;
623                         } else {
624                                 pr_info("wt_msr\n");
625                                 mbc = (struct scache *)&wt_msr;
626                         }
627                 }
628         } else {
629                 if (cpuinfo.dcache_wb) {
630                         pr_info("wb_nomsr\n");
631                         mbc = (struct scache *)&wb_nomsr;
632                         if (cpuinfo.ver_code <= CPUVER_7_20_D) {
633                                 /* MS: problem with signal handling - hw bug */
634                                 pr_info("WB won't work properly\n");
635                         }
636                 } else {
637                         if (cpuinfo.ver_code >= CPUVER_7_20_A) {
638                                 pr_info("wt_nomsr_noirq\n");
639                                 mbc = (struct scache *)&wt_nomsr_noirq;
640                         } else {
641                                 pr_info("wt_nomsr\n");
642                                 mbc = (struct scache *)&wt_nomsr;
643                         }
644                 }
645         }
646         /*
647          * FIXME Invalidation is done in U-BOOT
648          * WT cache: Data is already written to main memory
649          * WB cache: Discard data on noMMU which caused that kernel doesn't boot
650          */
651         /* invalidate_dcache(); */
652         enable_dcache();
653 
654         invalidate_icache();
655         enable_icache();
656 }
657 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php