aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/proc-feroceon.S
diff options
context:
space:
mode:
authorAssaf Hoffman <hoffman@marvell.com>2007-10-23 15:14:41 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 10:03:38 -0500
commite50d64097b6e63278789ee3a4394d127bd6e4254 (patch)
treea33325c4ea814bdcd1ef187559b9ec751ae553e2 /arch/arm/mm/proc-feroceon.S
parent2fd2b1242810fb4d2ba36548fecc1f005c36770c (diff)
[ARM] Marvell Feroceon CPU core support
The Feroceon is a family of independent ARMv5TE compliant CPU core implementations, supporting a variable depth pipeline and out-of-order execution. The Feroceon is configurable with VFP support, and the later models in the series are superscalar with up to two instructions per clock cycle. This patch adds the initial low-level cache/TLB handling for this core. Signed-off-by: Assaf Hoffman <hoffman@marvell.com> Reviewed-by: Tzachi Perelstein <tzachi@marvell.com> Reviewed-by: Nicolas Pitre <nico@marvell.com> Reviewed-by: Lennert Buytenhek <buytenh@marvell.com> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/proc-feroceon.S')
-rw-r--r--arch/arm/mm/proc-feroceon.S479
1 files changed, 479 insertions, 0 deletions
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
new file mode 100644
index 000000000000..8ad341af7906
--- /dev/null
+++ b/arch/arm/mm/proc-feroceon.S
@@ -0,0 +1,479 @@
1/*
2 * linux/arch/arm/mm/proc-feroceon.S: MMU functions for Feroceon
3 *
4 * Heavily based on proc-arm926.S
5 * Maintainer: Assaf Hoffman <hoffman@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/linkage.h>
23#include <linux/init.h>
24#include <asm/assembler.h>
25#include <asm/elf.h>
26#include <asm/pgtable-hwdef.h>
27#include <asm/pgtable.h>
28#include <asm/page.h>
29#include <asm/ptrace.h>
30#include "proc-macros.S"
31
32/*
33 * This is the maximum size of an area which will be invalidated
34 * using the single invalidate entry instructions. Anything larger
35 * than this, and we go for the whole cache.
36 *
37 * This value should be chosen such that we choose the cheapest
38 * alternative.
39 */
40#define CACHE_DLIMIT 16384
41
42/*
43 * the cache line size of the I and D cache
44 */
45#define CACHE_DLINESIZE 32
46
47 .text
48/*
49 * cpu_feroceon_proc_init()
50 */
51ENTRY(cpu_feroceon_proc_init)
52 mov pc, lr
53
54/*
55 * cpu_feroceon_proc_fin()
56 */
57ENTRY(cpu_feroceon_proc_fin)
58 stmfd sp!, {lr}
59 mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
60 msr cpsr_c, ip
61 bl feroceon_flush_kern_cache_all
62 mrc p15, 0, r0, c1, c0, 0 @ ctrl register
63 bic r0, r0, #0x1000 @ ...i............
64 bic r0, r0, #0x000e @ ............wca.
65 mcr p15, 0, r0, c1, c0, 0 @ disable caches
66 ldmfd sp!, {pc}
67
68/*
69 * cpu_feroceon_reset(loc)
70 *
71 * Perform a soft reset of the system. Put the CPU into the
72 * same state as it would be if it had been reset, and branch
73 * to what would be the reset vector.
74 *
75 * loc: location to jump to for soft reset
76 */
77 .align 5
78ENTRY(cpu_feroceon_reset)
79 mov ip, #0
80 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
81 mcr p15, 0, ip, c7, c10, 4 @ drain WB
82#ifdef CONFIG_MMU
83 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
84#endif
85 mrc p15, 0, ip, c1, c0, 0 @ ctrl register
86 bic ip, ip, #0x000f @ ............wcam
87 bic ip, ip, #0x1100 @ ...i...s........
88 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
89 mov pc, r0
90
91/*
92 * cpu_feroceon_do_idle()
93 *
94 * Called with IRQs disabled
95 */
96 .align 10
97ENTRY(cpu_feroceon_do_idle)
98 mov r0, #0
99 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
100 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
101 mov pc, lr
102
103/*
104 * flush_user_cache_all()
105 *
106 * Clean and invalidate all cache entries in a particular
107 * address space.
108 */
109ENTRY(feroceon_flush_user_cache_all)
110 /* FALLTHROUGH */
111
112/*
113 * flush_kern_cache_all()
114 *
115 * Clean and invalidate the entire cache.
116 */
117ENTRY(feroceon_flush_kern_cache_all)
118 mov r2, #VM_EXEC
119 mov ip, #0
120__flush_whole_cache:
121#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
122 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
123#else
1241: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
125 bne 1b
126#endif
127 tst r2, #VM_EXEC
128 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
129 mcrne p15, 0, ip, c7, c10, 4 @ drain WB
130 mov pc, lr
131
132/*
133 * flush_user_cache_range(start, end, flags)
134 *
135 * Clean and invalidate a range of cache entries in the
136 * specified address range.
137 *
138 * - start - start address (inclusive)
139 * - end - end address (exclusive)
140 * - flags - vm_flags describing address space
141 */
142ENTRY(feroceon_flush_user_cache_range)
143 mov ip, #0
144 sub r3, r1, r0 @ calculate total size
145 cmp r3, #CACHE_DLIMIT
146 bgt __flush_whole_cache
1471: tst r2, #VM_EXEC
148#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
149 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
150 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
151 add r0, r0, #CACHE_DLINESIZE
152 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
153 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
154 add r0, r0, #CACHE_DLINESIZE
155#else
156 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
157 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
158 add r0, r0, #CACHE_DLINESIZE
159 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
160 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
161 add r0, r0, #CACHE_DLINESIZE
162#endif
163 cmp r0, r1
164 blo 1b
165 tst r2, #VM_EXEC
166 mcrne p15, 0, ip, c7, c10, 4 @ drain WB
167 mov pc, lr
168
169/*
170 * coherent_kern_range(start, end)
171 *
172 * Ensure coherency between the Icache and the Dcache in the
173 * region described by start, end. If you have non-snooping
174 * Harvard caches, you need to implement this function.
175 *
176 * - start - virtual start address
177 * - end - virtual end address
178 */
179ENTRY(feroceon_coherent_kern_range)
180 /* FALLTHROUGH */
181
182/*
183 * coherent_user_range(start, end)
184 *
185 * Ensure coherency between the Icache and the Dcache in the
186 * region described by start, end. If you have non-snooping
187 * Harvard caches, you need to implement this function.
188 *
189 * - start - virtual start address
190 * - end - virtual end address
191 */
192ENTRY(feroceon_coherent_user_range)
193 bic r0, r0, #CACHE_DLINESIZE - 1
1941: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
195 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
196 add r0, r0, #CACHE_DLINESIZE
197 cmp r0, r1
198 blo 1b
199 mcr p15, 0, r0, c7, c10, 4 @ drain WB
200 mov pc, lr
201
202/*
203 * flush_kern_dcache_page(void *page)
204 *
205 * Ensure no D cache aliasing occurs, either with itself or
206 * the I cache
207 *
208 * - addr - page aligned address
209 */
210ENTRY(feroceon_flush_kern_dcache_page)
211 add r1, r0, #PAGE_SZ
2121: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
213 add r0, r0, #CACHE_DLINESIZE
214 cmp r0, r1
215 blo 1b
216 mov r0, #0
217 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
218 mcr p15, 0, r0, c7, c10, 4 @ drain WB
219 mov pc, lr
220
221/*
222 * dma_inv_range(start, end)
223 *
224 * Invalidate (discard) the specified virtual address range.
225 * May not write back any entries. If 'start' or 'end'
226 * are not cache line aligned, those lines must be written
227 * back.
228 *
229 * - start - virtual start address
230 * - end - virtual end address
231 *
232 * (same as v4wb)
233 */
234ENTRY(feroceon_dma_inv_range)
235#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
236 tst r0, #CACHE_DLINESIZE - 1
237 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
238 tst r1, #CACHE_DLINESIZE - 1
239 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
240#endif
241 bic r0, r0, #CACHE_DLINESIZE - 1
2421: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
243 add r0, r0, #CACHE_DLINESIZE
244 cmp r0, r1
245 blo 1b
246 mcr p15, 0, r0, c7, c10, 4 @ drain WB
247 mov pc, lr
248
249/*
250 * dma_clean_range(start, end)
251 *
252 * Clean the specified virtual address range.
253 *
254 * - start - virtual start address
255 * - end - virtual end address
256 *
257 * (same as v4wb)
258 */
259ENTRY(feroceon_dma_clean_range)
260#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
261 bic r0, r0, #CACHE_DLINESIZE - 1
2621: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
263 add r0, r0, #CACHE_DLINESIZE
264 cmp r0, r1
265 blo 1b
266#endif
267 mcr p15, 0, r0, c7, c10, 4 @ drain WB
268 mov pc, lr
269
270/*
271 * dma_flush_range(start, end)
272 *
273 * Clean and invalidate the specified virtual address range.
274 *
275 * - start - virtual start address
276 * - end - virtual end address
277 */
278ENTRY(feroceon_dma_flush_range)
279 bic r0, r0, #CACHE_DLINESIZE - 1
2801:
281#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
282 mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
283#else
284 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
285#endif
286 add r0, r0, #CACHE_DLINESIZE
287 cmp r0, r1
288 blo 1b
289 mcr p15, 0, r0, c7, c10, 4 @ drain WB
290 mov pc, lr
291
292ENTRY(feroceon_cache_fns)
293 .long feroceon_flush_kern_cache_all
294 .long feroceon_flush_user_cache_all
295 .long feroceon_flush_user_cache_range
296 .long feroceon_coherent_kern_range
297 .long feroceon_coherent_user_range
298 .long feroceon_flush_kern_dcache_page
299 .long feroceon_dma_inv_range
300 .long feroceon_dma_clean_range
301 .long feroceon_dma_flush_range
302
303ENTRY(cpu_feroceon_dcache_clean_area)
304#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
3051: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
306 add r0, r0, #CACHE_DLINESIZE
307 subs r1, r1, #CACHE_DLINESIZE
308 bhi 1b
309#endif
310 mcr p15, 0, r0, c7, c10, 4 @ drain WB
311 mov pc, lr
312
313/* =============================== PageTable ============================== */
314
315/*
316 * cpu_feroceon_switch_mm(pgd)
317 *
318 * Set the translation base pointer to be as described by pgd.
319 *
320 * pgd: new page tables
321 */
322 .align 5
323ENTRY(cpu_feroceon_switch_mm)
324#ifdef CONFIG_MMU
325 mov ip, #0
326#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
327 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
328#else
329@ && 'Clean & Invalidate whole DCache'
3301: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
331 bne 1b
332#endif
333 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
334 mcr p15, 0, ip, c7, c10, 4 @ drain WB
335 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
336 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
337#endif
338 mov pc, lr
339
340/*
341 * cpu_feroceon_set_pte_ext(ptep, pte, ext)
342 *
343 * Set a PTE and flush it out
344 */
345 .align 5
346ENTRY(cpu_feroceon_set_pte_ext)
347#ifdef CONFIG_MMU
348 str r1, [r0], #-2048 @ linux version
349
350 eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
351
352 bic r2, r1, #PTE_SMALL_AP_MASK
353 bic r2, r2, #PTE_TYPE_MASK
354 orr r2, r2, #PTE_TYPE_SMALL
355
356 tst r1, #L_PTE_USER @ User?
357 orrne r2, r2, #PTE_SMALL_AP_URO_SRW
358
359 tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
360 orreq r2, r2, #PTE_SMALL_AP_UNO_SRW
361
362 tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
363 movne r2, #0
364
365#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
366 eor r3, r2, #0x0a @ C & small page?
367 tst r3, #0x0b
368 biceq r2, r2, #4
369#endif
370 str r2, [r0] @ hardware version
371 mov r0, r0
372#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
373 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
374#endif
375 mcr p15, 0, r0, c7, c10, 4 @ drain WB
376#endif
377 mov pc, lr
378
379 __INIT
380
381 .type __feroceon_setup, #function
382__feroceon_setup:
383 mov r0, #0
384 mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
385 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
386#ifdef CONFIG_MMU
387 mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
388#endif
389
390
391#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
392 mov r0, #4 @ disable write-back on caches explicitly
393 mcr p15, 7, r0, c15, c0, 0
394#endif
395
396 adr r5, feroceon_crval
397 ldmia r5, {r5, r6}
398 mrc p15, 0, r0, c1, c0 @ get control register v4
399 bic r0, r0, r5
400 orr r0, r0, r6
401#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
402 orr r0, r0, #0x4000 @ .1.. .... .... ....
403#endif
404 mov pc, lr
405 .size __feroceon_setup, . - __feroceon_setup
406
407 /*
408 * R
409 * .RVI ZFRS BLDP WCAM
410 * .011 0001 ..11 0101
411 *
412 */
413 .type feroceon_crval, #object
414feroceon_crval:
415 crval clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134
416
417 __INITDATA
418
419/*
420 * Purpose : Function pointers used to access above functions - all calls
421 * come through these
422 */
423 .type feroceon_processor_functions, #object
424feroceon_processor_functions:
425 .word v5t_early_abort
426 .word cpu_feroceon_proc_init
427 .word cpu_feroceon_proc_fin
428 .word cpu_feroceon_reset
429 .word cpu_feroceon_do_idle
430 .word cpu_feroceon_dcache_clean_area
431 .word cpu_feroceon_switch_mm
432 .word cpu_feroceon_set_pte_ext
433 .size feroceon_processor_functions, . - feroceon_processor_functions
434
435 .section ".rodata"
436
437 .type cpu_arch_name, #object
438cpu_arch_name:
439 .asciz "armv5te"
440 .size cpu_arch_name, . - cpu_arch_name
441
442 .type cpu_elf_name, #object
443cpu_elf_name:
444 .asciz "v5"
445 .size cpu_elf_name, . - cpu_elf_name
446
447 .type cpu_feroceon_name, #object
448cpu_feroceon_name:
449 .asciz "Feroceon"
450 .size cpu_feroceon_name, . - cpu_feroceon_name
451
452 .align
453
454 .section ".proc.info.init", #alloc, #execinstr
455
456 .type __feroceon_proc_info,#object
457__feroceon_proc_info:
458 .long 0x56055310
459 .long 0xfffffff0
460 .long PMD_TYPE_SECT | \
461 PMD_SECT_BUFFERABLE | \
462 PMD_SECT_CACHEABLE | \
463 PMD_BIT4 | \
464 PMD_SECT_AP_WRITE | \
465 PMD_SECT_AP_READ
466 .long PMD_TYPE_SECT | \
467 PMD_BIT4 | \
468 PMD_SECT_AP_WRITE | \
469 PMD_SECT_AP_READ
470 b __feroceon_setup
471 .long cpu_arch_name
472 .long cpu_elf_name
473 .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
474 .long cpu_feroceon_name
475 .long feroceon_processor_functions
476 .long v4wbi_tlb_fns
477 .long v4wb_user_fns
478 .long feroceon_cache_fns
479 .size __feroceon_proc_info, . - __feroceon_proc_info