omap3-pandora-kernel2: update
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / cache-display-fix.patch
1 On Tue, 2008-07-01 at 06:23 +0100, Dirk Behme wrote:
2 > Catalin Marinas wrote:
3 > > But, anyway, if you want a patch, Harry is updating it to a recent
4 > > kernel.
5
6 > Any news on this? I think there are some people wanting a patch ;)
7
8 See below for a preliminary patch updated to 2.6.26-rc8. Note that I
9 don't plan to submit it in its current form but clean it up a bit first.
10
11
12 Show the cache type of ARMv7 CPUs
13
14 From: Catalin Marinas <catalin.marinas@arm.com>
15
16 Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
17 ---
18
19  arch/arm/kernel/setup.c  |  137 +++++++++++++++++++++++++++++++++++++++++++++-
20  include/asm-arm/system.h |   18 ++++++
21  2 files changed, 153 insertions(+), 2 deletions(-)
22
23
24 diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
25 index 5ae0eb2..0cd238d 100644
26 --- a/arch/arm/kernel/setup.c
27 +++ b/arch/arm/kernel/setup.c
28 @@ -256,6 +256,24 @@ static const char *proc_arch[] = {
29         "?(17)",
30  };
31  
32 +static const char *v7_cache_policy[4] = {
33 +       "reserved",
34 +       "AVIVT",
35 +       "VIPT",
36 +       "PIPT",
37 +};
38 +
39 +static const char *v7_cache_type[8] = {
40 +       "none",
41 +       "instruction only",
42 +       "data only",
43 +       "separate instruction and data",
44 +       "unified",
45 +       "unknown type",
46 +       "unknown type",
47 +       "unknown type",
48 +};
49 +
50  #define CACHE_TYPE(x)  (((x) >> 25) & 15)
51  #define CACHE_S(x)     ((x) & (1 << 24))
52  #define CACHE_DSIZE(x) (((x) >> 12) & 4095)    /* only if S=1 */
53 @@ -266,6 +284,22 @@ static const char *proc_arch[] = {
54  #define CACHE_M(y)     ((y) & (1 << 2))
55  #define CACHE_LINE(y)  ((y) & 3)
56  
57 +#define CACHE_TYPE_V7(x)       (((x) >> 14) & 3)
58 +#define CACHE_UNIFIED(x)       ((((x) >> 27) & 7)+1)
59 +#define CACHE_COHERENT(x)      ((((x) >> 24) & 7)+1)
60 +
61 +#define CACHE_ID_LEVEL_MASK    7
62 +#define CACHE_ID_LEVEL_BITS    3
63 +
64 +#define CACHE_LINE_V7(v)       ((1 << (((v) & 7)+4)))
65 +#define CACHE_ASSOC_V7(v)      ((((v) >> 3) & ((1<<10)-1))+1)
66 +#define CACHE_SETS_V7(v)       ((((v) >> 13) & ((1<<15)-1))+1)
67 +#define CACHE_SIZE_V7(v)       (CACHE_LINE_V7(v)*CACHE_ASSOC_V7(v)*CACHE_SETS_V7(v))
68 +#define CACHE_WA_V7(v)         (((v) & (1<<28)) != 0)
69 +#define CACHE_RA_V7(v)         (((v) & (1<<29)) != 0)
70 +#define CACHE_WB_V7(v)         (((v) & (1<<30)) != 0)
71 +#define CACHE_WT_V7(v)         (((v) & (1<<31)) != 0)
72 +
73  static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
74  {
75         unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
76 @@ -279,11 +313,57 @@ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
77                         CACHE_LINE(cache)));
78  }
79  
80 +static void dump_v7_cache(const char *type, int cpu, unsigned int level)
81 +{
82 +       unsigned int cachesize;
83 +                    
84 +       write_extended_cpuid(2,0,0,0,level);  /* Set the cache size selection register */
85 +       write_extended_cpuid(0,7,5,4,0);      /* Prefetch flush to wait for above */
86 +       cachesize = read_extended_cpuid(1,0,0,0);
87 +
88 +       printk("CPU%u: %s cache: %d bytes, associativity %d, %d byte lines, %d sets,\n      supports%s%s%s%s\n",
89 +              cpu, type,
90 +              CACHE_SIZE_V7(cachesize),CACHE_ASSOC_V7(cachesize),
91 +              CACHE_LINE_V7(cachesize),CACHE_SETS_V7(cachesize),
92 +              CACHE_WA_V7(cachesize) ? " WA" : "",
93 +              CACHE_RA_V7(cachesize) ? " RA" : "",
94 +              CACHE_WB_V7(cachesize) ? " WB" : "",
95 +              CACHE_WT_V7(cachesize) ? " WT" : "");
96 +}
97 +
98  static void __init dump_cpu_info(int cpu)
99  {
100         unsigned int info = read_cpuid(CPUID_CACHETYPE);
101  
102 -       if (info != processor_id) {
103 +       if (info != processor_id && (info & (1 << 31))) {
104 +               /* ARMv7 style of cache info register */
105 +               unsigned int id = read_extended_cpuid(1,0,0,1);
106 +               unsigned int level = 0;
107 +               printk("CPU%u: L1 I %s cache. Caches unified at level %u, coherent at level %u\n",
108 +                      cpu,
109 +                      v7_cache_policy[CACHE_TYPE_V7(info)],
110 +                      CACHE_UNIFIED(id),
111 +                      CACHE_COHERENT(id));
112 +
113 +               while (id & CACHE_ID_LEVEL_MASK) {
114 +                       printk("CPU%u: Level %u cache is %s\n",
115 +                              cpu, (level >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
116 +
117 +                       if (id & 1) {
118 +                               /* Dump I at this level */
119 +                               dump_v7_cache("I", cpu, level | 1);
120 +                       }
121 +
122 +                       if (id & (4 | 2)) {
123 +                               /* Dump D or unified at this level */
124 +                               dump_v7_cache((id & 4) ? "unified" : "D", cpu, level);
125 +                       }
126 +
127 +                       /* Next level out */
128 +                       level += 2;
129 +                       id >>= CACHE_ID_LEVEL_BITS;
130 +               }
131 +       } else if (info != processor_id) {
132                 printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
133                        cache_types[CACHE_TYPE(info)]);
134                 if (CACHE_S(info)) {
135 @@ -916,6 +996,30 @@ c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
136                             CACHE_LINE(cache)));
137  }
138  
139 +static void c_show_v7_cache(struct seq_file *m, const char *type, unsigned int levelselect)
140 +{
141 +       unsigned int cachesize;
142 +       unsigned int level = (levelselect >> 1) + 1;
143 +                    
144 +       write_extended_cpuid(2,0,0,0,levelselect);  /* Set the cache size selection register */
145 +       write_extended_cpuid(0,7,5,4,0);      /* Prefetch flush to wait for above */
146 +       cachesize = read_extended_cpuid(1,0,0,0);
147 +
148 +       seq_printf(m, "L%u %s size\t\t: %d bytes\n"
149 +                  "L%u %s assoc\t\t: %d\n"
150 +                  "L%u %s line length\t: %d\n"
151 +                  "L%u %s sets\t\t: %d\n"
152 +                  "L%u %s supports\t\t:%s%s%s%s\n",
153 +                  level, type, CACHE_SIZE_V7(cachesize),
154 +                  level, type, CACHE_ASSOC_V7(cachesize),
155 +                  level, type, CACHE_LINE_V7(cachesize),
156 +                  level, type, CACHE_SETS_V7(cachesize),
157 +                  level, type, CACHE_WA_V7(cachesize) ? " WA" : "",
158 +                  CACHE_RA_V7(cachesize) ? " RA" : "",
159 +                  CACHE_WB_V7(cachesize) ? " WB" : "",
160 +                  CACHE_WT_V7(cachesize) ? " WT" : "");
161 +}
162 +
163  static int c_show(struct seq_file *m, void *v)
164  {
165         int i;
166 @@ -971,7 +1075,36 @@ static int c_show(struct seq_file *m, void *v)
167  
168         {
169                 unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
170 -               if (cache_info != processor_id) {
171 +               if (cache_info != processor_id && (cache_info & (1<<31))) {
172 +                       /* V7 style of cache info register */
173 +                       unsigned int id = read_extended_cpuid(1,0,0,1);
174 +                       unsigned int levelselect = 0;
175 +                       seq_printf(m, "L1 I cache\t:%s\n"
176 +                                  "Cache unification level\t: %u\n"
177 +                                  "Cache coherency level\t: %u\n",
178 +                                  v7_cache_policy[CACHE_TYPE_V7(cache_info)],
179 +                                  CACHE_UNIFIED(id),
180 +                                  CACHE_COHERENT(id));
181 +
182 +                       while (id & CACHE_ID_LEVEL_MASK) {
183 +                               seq_printf(m, "Level %u cache\t\t: %s\n",
184 +                                          (levelselect >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
185 +
186 +                               if (id & 1) {
187 +                                       /* Dump I at this level */
188 +                                       c_show_v7_cache(m, "I", levelselect | 1);
189 +                               }
190 +
191 +                               if (id & (4 | 2)) {
192 +                                       /* Dump D or unified at this level */
193 +                                       c_show_v7_cache(m, (id & 4) ? "cache" : "D", levelselect);
194 +                               }
195 +
196 +                               /* Next level out */
197 +                               levelselect += 2;
198 +                               id >>= CACHE_ID_LEVEL_BITS;
199 +                       }
200 +               } else if (cache_info != processor_id) {
201                         seq_printf(m, "Cache type\t: %s\n"
202                                       "Cache clean\t: %s\n"
203                                       "Cache lockdown\t: %s\n"
204 diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
205 index 514af79..704738e 100644
206 --- a/arch/arm/include/asm/system.h
207 +++ b/arch/arm/include/asm/system.h
208 @@ -74,6 +74,24 @@
209                     : "cc");                                            \
210                 __val;                                                  \
211         })
212 +#define read_extended_cpuid(op1,op2,op3,op4)           \
213 +       ({                                                              \
214 +               unsigned int __val;                                     \
215 +               asm("mrc p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4)       \
216 +                   : "=r" (__val)                                      \
217 +                   :                                                   \
218 +                   : "cc");                                            \
219 +               __val;                                                  \
220 +       })
221 +
222 +#define write_extended_cpuid(op1,op2,op3,op4,v)                \
223 +       ({                                                              \
224 +               unsigned int __val = v;                                 \
225 +               asm("mcr p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4)       \
226 +                   :                                                   \
227 +                   : "r" (__val)                                       \
228 +                   : "cc");                                            \
229 +       })
230  #else
231  extern unsigned int processor_id;
232  #define read_cpuid(reg) (processor_id)
233
234
235 -- 
236 Catalin
237
238