]>
Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
ded963a4 | 2 | * Blackfin cache control code |
1394f032 | 3 | * |
ded963a4 | 4 | * Copyright 2004-2008 Analog Devices Inc. |
1394f032 | 5 | * |
ded963a4 | 6 | * Licensed under the GPL-2 or later. |
1394f032 BW |
7 | */ |
8 | ||
9 | #include <linux/linkage.h> | |
1394f032 BW |
10 | #include <asm/blackfin.h> |
11 | #include <asm/cache.h> | |
ded963a4 | 12 | #include <asm/page.h> |
1394f032 BW |
13 | |
14 | .text | |
1394f032 | 15 | |
78f28a0a MF |
16 | /* 05000443 - IFLUSH cannot be last instruction in hardware loop */ |
17 | #if ANOMALY_05000443 | |
18 | # define BROK_FLUSH_INST "IFLUSH" | |
19 | #else | |
20 | # define BROK_FLUSH_INST "no anomaly! yeah!" | |
21 | #endif | |
22 | ||
ded963a4 MF |
23 | /* Since all L1 caches work the same way, we use the same method for flushing |
24 | * them. Only the actual flush instruction differs. We write this in asm as | |
25 | * GCC can be hard to coax into writing nice hardware loops. | |
1394f032 | 26 | * |
ded963a4 MF |
27 | * Also, we assume the following register setup: |
28 | * R0 = start address | |
29 | * R1 = end address | |
1394f032 | 30 | */ |
78f28a0a | 31 | .macro do_flush flushins:req label |
ded963a4 | 32 | |
39e96c88 MF |
33 | R2 = -L1_CACHE_BYTES; |
34 | ||
35 | /* start = (start & -L1_CACHE_BYTES) */ | |
36 | R0 = R0 & R2; | |
37 | ||
ded963a4 MF |
38 | /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */ |
39 | R1 += -1; | |
ded963a4 MF |
40 | R1 = R1 & R2; |
41 | R1 += L1_CACHE_BYTES; | |
42 | ||
43 | /* count = (end - start) >> L1_CACHE_SHIFT */ | |
44 | R2 = R1 - R0; | |
45 | R2 >>= L1_CACHE_SHIFT; | |
46 | P1 = R2; | |
47 | ||
48 | .ifnb \label | |
49 | \label : | |
50 | .endif | |
51 | P0 = R0; | |
78f28a0a | 52 | |
ded963a4 | 53 | LSETUP (1f, 2f) LC1 = P1; |
1394f032 | 54 | 1: |
78f28a0a | 55 | .ifeqs "\flushins", BROK_FLUSH_INST |
ded963a4 | 56 | \flushins [P0++]; |
78f28a0a MF |
57 | 2: nop; |
58 | .else | |
2cf85113 | 59 | 2: \flushins [P0++]; |
78f28a0a | 60 | .endif |
ded963a4 | 61 | |
1394f032 | 62 | RTS; |
ded963a4 | 63 | .endm |
1394f032 | 64 | |
ded963a4 MF |
65 | /* Invalidate all instruction cache lines assocoiated with this memory area */ |
66 | ENTRY(_blackfin_icache_flush_range) | |
d7ff1a90 SZ |
67 | /* |
68 | * Walkaround to avoid loading wrong instruction after invalidating icache | |
69 | * and following sequence is met. | |
70 | * | |
71 | * 1) One instruction address is cached in the instruction cache. | |
72 | * 2) This instruction in SDRAM is changed. | |
73 | * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range(). | |
74 | * 4) This instruction is executed again, but the old one is loaded. | |
75 | */ | |
76 | P0 = R0; | |
77 | IFLUSH[P0]; | |
78f28a0a | 78 | do_flush IFLUSH |
ded963a4 | 79 | ENDPROC(_blackfin_icache_flush_range) |
1394f032 | 80 | |
1394f032 | 81 | /* Throw away all D-cached data in specified region without any obligation to |
ded963a4 MF |
82 | * write them back. Since the Blackfin ISA does not have an "invalidate" |
83 | * instruction, we use flush/invalidate. Perhaps as a speed optimization we | |
84 | * could bang on the DTEST MMRs ... | |
1394f032 | 85 | */ |
1394f032 | 86 | ENTRY(_blackfin_dcache_invalidate_range) |
ded963a4 | 87 | do_flush FLUSHINV |
51be24c3 | 88 | ENDPROC(_blackfin_dcache_invalidate_range) |
1394f032 | 89 | |
ded963a4 | 90 | /* Flush all data cache lines assocoiated with this memory area */ |
1394f032 | 91 | ENTRY(_blackfin_dcache_flush_range) |
78f28a0a | 92 | do_flush FLUSH, .Ldfr |
51be24c3 | 93 | ENDPROC(_blackfin_dcache_flush_range) |
1394f032 | 94 | |
ded963a4 MF |
95 | /* Our headers convert the page structure to an address, so just need to flush |
96 | * its contents like normal. We know the start address is page aligned (which | |
97 | * greater than our cache alignment), as is the end address. So just jump into | |
98 | * the middle of the dcache flush function. | |
99 | */ | |
1394f032 BW |
100 | ENTRY(_blackfin_dflush_page) |
101 | P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT); | |
ded963a4 | 102 | jump .Ldfr; |
51be24c3 | 103 | ENDPROC(_blackfin_dflush_page) |