Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
[pandora-kernel.git] / arch / sparc / include / asm / spitfire.h
1 /* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
2  *
3  * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
4  */
5
6 #ifndef _SPARC64_SPITFIRE_H
7 #define _SPARC64_SPITFIRE_H
8
9 #ifdef CONFIG_SPARC64
10
11 #include <asm/asi.h>
12
13 /* The following register addresses are accessible via ASI_DMMU
14  * and ASI_IMMU, that is there is a distinct and unique copy of
15  * each these registers for each TLB.
16  */
17 #define TSB_TAG_TARGET          0x0000000000000000 /* All chips                         */
18 #define TLB_SFSR                0x0000000000000018 /* All chips                         */
19 #define TSB_REG                 0x0000000000000028 /* All chips                         */
20 #define TLB_TAG_ACCESS          0x0000000000000030 /* All chips                         */
21 #define VIRT_WATCHPOINT         0x0000000000000038 /* All chips                         */
22 #define PHYS_WATCHPOINT         0x0000000000000040 /* All chips                         */
23 #define TSB_EXTENSION_P         0x0000000000000048 /* Ultra-III and later               */
24 #define TSB_EXTENSION_S         0x0000000000000050 /* Ultra-III and later, D-TLB only   */
25 #define TSB_EXTENSION_N         0x0000000000000058 /* Ultra-III and later               */
26 #define TLB_TAG_ACCESS_EXT      0x0000000000000060 /* Ultra-III+ and later              */
27
28 /* These registers only exist as one entity, and are accessed
29  * via ASI_DMMU only.
30  */
31 #define PRIMARY_CONTEXT         0x0000000000000008
32 #define SECONDARY_CONTEXT       0x0000000000000010
33 #define DMMU_SFAR               0x0000000000000020
34 #define VIRT_WATCHPOINT         0x0000000000000038
35 #define PHYS_WATCHPOINT         0x0000000000000040
36
37 #define SPITFIRE_HIGHEST_LOCKED_TLBENT  (64 - 1)
38 #define CHEETAH_HIGHEST_LOCKED_TLBENT   (16 - 1)
39
40 #define L1DCACHE_SIZE           0x4000
41
42 #define SUN4V_CHIP_INVALID      0x00
43 #define SUN4V_CHIP_NIAGARA1     0x01
44 #define SUN4V_CHIP_NIAGARA2     0x02
45 #define SUN4V_CHIP_NIAGARA3     0x03
46 #define SUN4V_CHIP_NIAGARA4     0x04
47 #define SUN4V_CHIP_NIAGARA5     0x05
48 #define SUN4V_CHIP_SPARC64X     0x8a
49 #define SUN4V_CHIP_UNKNOWN      0xff
50
51 #ifndef __ASSEMBLY__
52
53 enum ultra_tlb_layout {
54         spitfire = 0,
55         cheetah = 1,
56         cheetah_plus = 2,
57         hypervisor = 3,
58 };
59
60 extern enum ultra_tlb_layout tlb_type;
61
62 extern int sun4v_chip_type;
63
64 extern int cheetah_pcache_forced_on;
65 void cheetah_enable_pcache(void);
66
67 #define sparc64_highest_locked_tlbent() \
68         (tlb_type == spitfire ? \
69          SPITFIRE_HIGHEST_LOCKED_TLBENT : \
70          CHEETAH_HIGHEST_LOCKED_TLBENT)
71
72 extern int num_kernel_image_mappings;
73
74 /* The data cache is write through, so this just invalidates the
75  * specified line.
76  */
77 static inline void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
78 {
79         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
80                              "membar    #Sync"
81                              : /* No outputs */
82                              : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
83 }
84
85 /* The instruction cache lines are flushed with this, but note that
86  * this does not flush the pipeline.  It is possible for a line to
87  * get flushed but stale instructions to still be in the pipeline,
88  * a flush instruction (to any address) is sufficient to handle
89  * this issue after the line is invalidated.
90  */
91 static inline void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
92 {
93         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
94                              "membar    #Sync"
95                              : /* No outputs */
96                              : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
97 }
98
99 static inline unsigned long spitfire_get_dtlb_data(int entry)
100 {
101         unsigned long data;
102
103         __asm__ __volatile__("ldxa      [%1] %2, %0"
104                              : "=r" (data)
105                              : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
106
107         /* Clear TTE diag bits. */
108         data &= ~0x0003fe0000000000UL;
109
110         return data;
111 }
112
113 static inline unsigned long spitfire_get_dtlb_tag(int entry)
114 {
115         unsigned long tag;
116
117         __asm__ __volatile__("ldxa      [%1] %2, %0"
118                              : "=r" (tag)
119                              : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
120         return tag;
121 }
122
123 static inline void spitfire_put_dtlb_data(int entry, unsigned long data)
124 {
125         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
126                              "membar    #Sync"
127                              : /* No outputs */
128                              : "r" (data), "r" (entry << 3),
129                                "i" (ASI_DTLB_DATA_ACCESS));
130 }
131
132 static inline unsigned long spitfire_get_itlb_data(int entry)
133 {
134         unsigned long data;
135
136         __asm__ __volatile__("ldxa      [%1] %2, %0"
137                              : "=r" (data)
138                              : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
139
140         /* Clear TTE diag bits. */
141         data &= ~0x0003fe0000000000UL;
142
143         return data;
144 }
145
146 static inline unsigned long spitfire_get_itlb_tag(int entry)
147 {
148         unsigned long tag;
149
150         __asm__ __volatile__("ldxa      [%1] %2, %0"
151                              : "=r" (tag)
152                              : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
153         return tag;
154 }
155
156 static inline void spitfire_put_itlb_data(int entry, unsigned long data)
157 {
158         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
159                              "membar    #Sync"
160                              : /* No outputs */
161                              : "r" (data), "r" (entry << 3),
162                                "i" (ASI_ITLB_DATA_ACCESS));
163 }
164
165 static inline void spitfire_flush_dtlb_nucleus_page(unsigned long page)
166 {
167         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
168                              "membar    #Sync"
169                              : /* No outputs */
170                              : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
171 }
172
173 static inline void spitfire_flush_itlb_nucleus_page(unsigned long page)
174 {
175         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
176                              "membar    #Sync"
177                              : /* No outputs */
178                              : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
179 }
180
181 /* Cheetah has "all non-locked" tlb flushes. */
182 static inline void cheetah_flush_dtlb_all(void)
183 {
184         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
185                              "membar    #Sync"
186                              : /* No outputs */
187                              : "r" (0x80), "i" (ASI_DMMU_DEMAP));
188 }
189
190 static inline void cheetah_flush_itlb_all(void)
191 {
192         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
193                              "membar    #Sync"
194                              : /* No outputs */
195                              : "r" (0x80), "i" (ASI_IMMU_DEMAP));
196 }
197
198 /* Cheetah has a 4-tlb layout so direct access is a bit different.
199  * The first two TLBs are fully assosciative, hold 16 entries, and are
200  * used only for locked and >8K sized translations.  One exists for
201  * data accesses and one for instruction accesses.
202  *
203  * The third TLB is for data accesses to 8K non-locked translations, is
204  * 2 way assosciative, and holds 512 entries.  The fourth TLB is for
205  * instruction accesses to 8K non-locked translations, is 2 way
206  * assosciative, and holds 128 entries.
207  *
208  * Cheetah has some bug where bogus data can be returned from
209  * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
210  * the problem for me. -DaveM
211  */
212 static inline unsigned long cheetah_get_ldtlb_data(int entry)
213 {
214         unsigned long data;
215
216         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
217                              "ldxa      [%1] %2, %0"
218                              : "=r" (data)
219                              : "r" ((0 << 16) | (entry << 3)),
220                              "i" (ASI_DTLB_DATA_ACCESS));
221
222         return data;
223 }
224
225 static inline unsigned long cheetah_get_litlb_data(int entry)
226 {
227         unsigned long data;
228
229         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
230                              "ldxa      [%1] %2, %0"
231                              : "=r" (data)
232                              : "r" ((0 << 16) | (entry << 3)),
233                              "i" (ASI_ITLB_DATA_ACCESS));
234
235         return data;
236 }
237
238 static inline unsigned long cheetah_get_ldtlb_tag(int entry)
239 {
240         unsigned long tag;
241
242         __asm__ __volatile__("ldxa      [%1] %2, %0"
243                              : "=r" (tag)
244                              : "r" ((0 << 16) | (entry << 3)),
245                              "i" (ASI_DTLB_TAG_READ));
246
247         return tag;
248 }
249
250 static inline unsigned long cheetah_get_litlb_tag(int entry)
251 {
252         unsigned long tag;
253
254         __asm__ __volatile__("ldxa      [%1] %2, %0"
255                              : "=r" (tag)
256                              : "r" ((0 << 16) | (entry << 3)),
257                              "i" (ASI_ITLB_TAG_READ));
258
259         return tag;
260 }
261
262 static inline void cheetah_put_ldtlb_data(int entry, unsigned long data)
263 {
264         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
265                              "membar    #Sync"
266                              : /* No outputs */
267                              : "r" (data),
268                                "r" ((0 << 16) | (entry << 3)),
269                                "i" (ASI_DTLB_DATA_ACCESS));
270 }
271
272 static inline void cheetah_put_litlb_data(int entry, unsigned long data)
273 {
274         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
275                              "membar    #Sync"
276                              : /* No outputs */
277                              : "r" (data),
278                                "r" ((0 << 16) | (entry << 3)),
279                                "i" (ASI_ITLB_DATA_ACCESS));
280 }
281
282 static inline unsigned long cheetah_get_dtlb_data(int entry, int tlb)
283 {
284         unsigned long data;
285
286         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
287                              "ldxa      [%1] %2, %0"
288                              : "=r" (data)
289                              : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
290
291         return data;
292 }
293
294 static inline unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
295 {
296         unsigned long tag;
297
298         __asm__ __volatile__("ldxa      [%1] %2, %0"
299                              : "=r" (tag)
300                              : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
301         return tag;
302 }
303
304 static inline void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
305 {
306         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
307                              "membar    #Sync"
308                              : /* No outputs */
309                              : "r" (data),
310                                "r" ((tlb << 16) | (entry << 3)),
311                                "i" (ASI_DTLB_DATA_ACCESS));
312 }
313
314 static inline unsigned long cheetah_get_itlb_data(int entry)
315 {
316         unsigned long data;
317
318         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
319                              "ldxa      [%1] %2, %0"
320                              : "=r" (data)
321                              : "r" ((2 << 16) | (entry << 3)),
322                                "i" (ASI_ITLB_DATA_ACCESS));
323
324         return data;
325 }
326
327 static inline unsigned long cheetah_get_itlb_tag(int entry)
328 {
329         unsigned long tag;
330
331         __asm__ __volatile__("ldxa      [%1] %2, %0"
332                              : "=r" (tag)
333                              : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
334         return tag;
335 }
336
337 static inline void cheetah_put_itlb_data(int entry, unsigned long data)
338 {
339         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
340                              "membar    #Sync"
341                              : /* No outputs */
342                              : "r" (data), "r" ((2 << 16) | (entry << 3)),
343                                "i" (ASI_ITLB_DATA_ACCESS));
344 }
345
346 #endif /* !(__ASSEMBLY__) */
347 #endif /* CONFIG_SPARC64 */
348 #endif /* !(_SPARC64_SPITFIRE_H) */