Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.

My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
diff --git a/firmware/target/arm/mmu-arm.S b/firmware/target/arm/mmu-arm.S
index 1bb5181..5a21ff6 100644
--- a/firmware/target/arm/mmu-arm.S
+++ b/firmware/target/arm/mmu-arm.S
@@ -24,6 +24,17 @@
 /* Used by ARMv4 & ARMv5 CPUs with cp15 register and MMU */
 /* WARNING : assume size of a data cache line == 32 bytes */

+#if     CONFIG_CPU == TCC7801   || CONFIG_CPU == AT91SAM9260 \
+    ||  CONFIG_CPU == DM320     || CONFIG_CPU == AS3525v2
+#define HAVE_TEST_AND_CLEAN_CACHE
+#elif CONFIG_CPU == AS3535
+#define CACHE_SIZE 8
+#elif CONFIG_CPU == S3C2440
+#define CACHE_SIZE 16
+#else
+#error Cache settings unknown for this CPU !
+#endif
+
 /** MMU setup **/

 /*
@@ -263,6 +274,16 @@ clean_dcache_range:
     bx      lr                      @
     .size   dump_dcache_range, .-dump_dcache_range

+
+@ Index format: 31:26 = index, N:5 = segment, remainder = SBZ
+@ assume 64-way set associative separate I/D caches, 32B (2^5) cache line size
+@ CACHE_SIZE = N (kB) = N*2^10 B
+@ number of lines = N*2^(10-5) = N*2^(5)
+@ Index bits = 6
+@ Segment loops = N*2^(5-6) = N*2^(-1) = N/2
+
+#define INDEX_STEPS (CACHE_SIZE/2)
+
 /*
  * Cleans entire DCache
  * void clean_dcache(void);
@@ -274,26 +295,25 @@ clean_dcache_range:
     .global     cpucache_flush      @ Alias
 clean_dcache:
 cpucache_flush:
-    @ Index format: 31:26 = index, 7:5 = segment, remainder = SBZ
+#ifdef HAVE_TEST_AND_CLEAN_CACHE
+    mrc     p15, 0, r15, c7, c10, 3 @ test and clean dcache
+    bne     clean_dcache
+    mov     r1, #0
+#else
+    @ Index format: 31:26 = index, N:5 = segment, remainder = SBZ, assume 64-way set associative separate I/D caches
+    @ N = log2(cache size in bytes / cache line size in bytes == 32) - 6 /* index bits */ + 4 /* start offset */
     mov     r1, #0x00000000         @
 1:  @ clean_start                   @
     mcr     p15, 0, r1, c7, c10, 2  @ Clean entry by index
     add     r0, r1, #0x00000020     @
     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
+.rept INDEX_STEPS - 2 /* 2 steps already executed */
     add     r0, r0, #0x00000020     @
     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
+.endr
     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
     bne     1b @ clean_start        @
+#endif /* HAVE_TEST_AND_CLEAN_CACHE */
     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
     bx      lr                      @ 
     .size   clean_dcache, .-clean_dcache
@@ -308,26 +328,25 @@ cpucache_flush:
     .global     invalidate_dcache
     .type       invalidate_dcache, %function
 invalidate_dcache:
-    @ Index format: 31:26 = index, 7:5 = segment, remainder = SBZ
+#ifdef HAVE_TEST_AND_CLEAN_CACHE
+    mrc     p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
+    bne     invalidate_dcache
+    mov     r1, #0
+#else
+    @ Index format: 31:26 = index, N:5 = segment, remainder = SBZ, assume 64-way set associative separate I/D caches
+    @ N = log2(cache size in bytes / cache line size in bytes == 32) - 6 /* index bits */ + 4 /* start offset */
     mov     r1, #0x00000000         @
 1:  @ inv_start                     @
     mcr     p15, 0, r1, c7, c14, 2  @ Clean and invalidate entry by index
     add     r0, r1, #0x00000020     @
     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
+.rept INDEX_STEPS - 2 /* 2 steps already executed */
     add     r0, r0, #0x00000020     @
     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
-    add     r0, r0, #0x00000020     @
-    mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
+.endr
     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
     bne     1b @ inv_start          @
+#endif /* HAVE_TEST_AND_CLEAN_CACHE */
     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
     bx      lr                      @
     .size   invalidate_dcache, .-invalidate_dcache