xref: /linux/arch/arm/mm/proc-arm926.S (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 *  linux/arch/arm/mm/proc-arm926.S: MMU functions for ARM926EJ-S
4 *
5 *  Copyright (C) 1999-2001 ARM Limited
6 *  Copyright (C) 2000 Deep Blue Solutions Ltd.
7 *  hacked for non-paged-MM by Hyok S. Choi, 2003.
8 *
9 * These are the low level assembler for performing cache and TLB
10 * functions on the arm926.
11 */
12#include <linux/linkage.h>
13#include <linux/init.h>
14#include <linux/cfi_types.h>
15#include <linux/pgtable.h>
16#include <asm/assembler.h>
17#include <asm/hwcap.h>
18#include <asm/pgtable-hwdef.h>
19#include <asm/page.h>
20#include <asm/ptrace.h>
21#include "proc-macros.S"
22
23/*
24 * This is the maximum size of an area which will be invalidated
25 * using the single invalidate entry instructions.  Anything larger
26 * than this, and we go for the whole cache.
27 *
28 * This value should be chosen such that we choose the cheapest
29 * alternative.
30 */
31#define CACHE_DLIMIT	16384
32
33/*
34 * the cache line size of the I and D cache
35 */
36#define CACHE_DLINESIZE	32
37
38	.text
39/*
40 * cpu_arm926_proc_init()
41 */
42SYM_TYPED_FUNC_START(cpu_arm926_proc_init)
43	ret	lr
44SYM_FUNC_END(cpu_arm926_proc_init)
45
46/*
47 * cpu_arm926_proc_fin()
48 */
49SYM_TYPED_FUNC_START(cpu_arm926_proc_fin)
50	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
51	bic	r0, r0, #0x1000			@ ...i............
52	bic	r0, r0, #0x000e			@ ............wca.
53	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
54	ret	lr
55SYM_FUNC_END(cpu_arm926_proc_fin)
56
57/*
58 * cpu_arm926_reset(loc)
59 *
60 * Perform a soft reset of the system.  Put the CPU into the
61 * same state as it would be if it had been reset, and branch
62 * to what would be the reset vector.
63 *
64 * loc: location to jump to for soft reset
65 */
66	.align	5
67	.pushsection	.idmap.text, "ax"
68SYM_TYPED_FUNC_START(cpu_arm926_reset)
69	mov	ip, #0
70	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
71	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
72#ifdef CONFIG_MMU
73	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
74#endif
75	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
76	bic	ip, ip, #0x000f			@ ............wcam
77	bic	ip, ip, #0x1100			@ ...i...s........
78	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
79	ret	r0
80SYM_FUNC_END(cpu_arm926_reset)
81	.popsection
82
83/*
84 * cpu_arm926_do_idle()
85 *
86 * Called with IRQs disabled
87 */
88	.align	10
89SYM_TYPED_FUNC_START(cpu_arm926_do_idle)
90	mov	r0, #0
91	mrc	p15, 0, r1, c1, c0, 0		@ Read control register
92	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
93	bic	r2, r1, #1 << 12
94	mrs	r3, cpsr			@ Disable FIQs while Icache
95	orr	ip, r3, #PSR_F_BIT		@ is disabled
96	msr	cpsr_c, ip
97	mcr	p15, 0, r2, c1, c0, 0		@ Disable I cache
98	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
99	mcr	p15, 0, r1, c1, c0, 0		@ Restore ICache enable
100	msr	cpsr_c, r3			@ Restore FIQ state
101	ret	lr
102SYM_FUNC_END(cpu_arm926_do_idle)
103
104/*
105 *	flush_icache_all()
106 *
107 *	Unconditionally clean and invalidate the entire icache.
108 */
109SYM_TYPED_FUNC_START(arm926_flush_icache_all)
110	mov	r0, #0
111	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
112	ret	lr
113SYM_FUNC_END(arm926_flush_icache_all)
114
115/*
116 *	flush_user_cache_all()
117 *
118 *	Clean and invalidate all cache entries in a particular
119 *	address space.
120 */
121SYM_FUNC_ALIAS(arm926_flush_user_cache_all, arm926_flush_kern_cache_all)
122
123/*
124 *	flush_kern_cache_all()
125 *
126 *	Clean and invalidate the entire cache.
127 */
128SYM_TYPED_FUNC_START(arm926_flush_kern_cache_all)
129	mov	r2, #VM_EXEC
130	mov	ip, #0
131__flush_whole_cache:
132#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
133	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
134#else
1351:	mrc	p15, 0, APSR_nzcv, c7, c14, 3 	@ test,clean,invalidate
136	bne	1b
137#endif
138	tst	r2, #VM_EXEC
139	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
140	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
141	ret	lr
142SYM_FUNC_END(arm926_flush_kern_cache_all)
143
144/*
145 *	flush_user_cache_range(start, end, flags)
146 *
147 *	Clean and invalidate a range of cache entries in the
148 *	specified address range.
149 *
150 *	- start	- start address (inclusive)
151 *	- end	- end address (exclusive)
152 *	- flags	- vm_flags describing address space
153 */
154SYM_TYPED_FUNC_START(arm926_flush_user_cache_range)
155	mov	ip, #0
156	sub	r3, r1, r0			@ calculate total size
157	cmp	r3, #CACHE_DLIMIT
158	bgt	__flush_whole_cache
1591:	tst	r2, #VM_EXEC
160#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
161	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
162	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
163	add	r0, r0, #CACHE_DLINESIZE
164	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
165	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
166	add	r0, r0, #CACHE_DLINESIZE
167#else
168	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
169	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
170	add	r0, r0, #CACHE_DLINESIZE
171	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
172	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
173	add	r0, r0, #CACHE_DLINESIZE
174#endif
175	cmp	r0, r1
176	blo	1b
177	tst	r2, #VM_EXEC
178	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
179	ret	lr
180SYM_FUNC_END(arm926_flush_user_cache_range)
181
182/*
183 *	coherent_kern_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 */
192SYM_TYPED_FUNC_START(arm926_coherent_kern_range)
193#ifdef CONFIG_CFI /* Fallthrough if !CFI */
194	b	arm926_coherent_user_range
195#endif
196SYM_FUNC_END(arm926_coherent_kern_range)
197
198/*
199 *	coherent_user_range(start, end)
200 *
201 *	Ensure coherency between the Icache and the Dcache in the
202 *	region described by start, end.  If you have non-snooping
203 *	Harvard caches, you need to implement this function.
204 *
205 *	- start	- virtual start address
206 *	- end	- virtual end address
207 */
208SYM_TYPED_FUNC_START(arm926_coherent_user_range)
209	bic	r0, r0, #CACHE_DLINESIZE - 1
2101:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
211	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
212	add	r0, r0, #CACHE_DLINESIZE
213	cmp	r0, r1
214	blo	1b
215	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
216	mov	r0, #0
217	ret	lr
218SYM_FUNC_END(arm926_coherent_user_range)
219
220/*
221 *	flush_kern_dcache_area(void *addr, size_t size)
222 *
223 *	Ensure no D cache aliasing occurs, either with itself or
224 *	the I cache
225 *
226 *	- addr	- kernel address
227 *	- size	- region size
228 */
229SYM_TYPED_FUNC_START(arm926_flush_kern_dcache_area)
230	add	r1, r0, r1
2311:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
232	add	r0, r0, #CACHE_DLINESIZE
233	cmp	r0, r1
234	blo	1b
235	mov	r0, #0
236	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
237	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
238	ret	lr
239SYM_FUNC_END(arm926_flush_kern_dcache_area)
240
241/*
242 *	dma_inv_range(start, end)
243 *
244 *	Invalidate (discard) the specified virtual address range.
245 *	May not write back any entries.  If 'start' or 'end'
246 *	are not cache line aligned, those lines must be written
247 *	back.
248 *
249 *	- start	- virtual start address
250 *	- end	- virtual end address
251 *
252 * (same as v4wb)
253 */
254arm926_dma_inv_range:
255#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
256	tst	r0, #CACHE_DLINESIZE - 1
257	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
258	tst	r1, #CACHE_DLINESIZE - 1
259	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
260#endif
261	bic	r0, r0, #CACHE_DLINESIZE - 1
2621:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
263	add	r0, r0, #CACHE_DLINESIZE
264	cmp	r0, r1
265	blo	1b
266	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
267	ret	lr
268
269/*
270 *	dma_clean_range(start, end)
271 *
272 *	Clean the specified virtual address range.
273 *
274 *	- start	- virtual start address
275 *	- end	- virtual end address
276 *
277 * (same as v4wb)
278 */
279arm926_dma_clean_range:
280#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
281	bic	r0, r0, #CACHE_DLINESIZE - 1
2821:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
283	add	r0, r0, #CACHE_DLINESIZE
284	cmp	r0, r1
285	blo	1b
286#endif
287	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
288	ret	lr
289
290/*
291 *	dma_flush_range(start, end)
292 *
293 *	Clean and invalidate the specified virtual address range.
294 *
295 *	- start	- virtual start address
296 *	- end	- virtual end address
297 */
298SYM_TYPED_FUNC_START(arm926_dma_flush_range)
299	bic	r0, r0, #CACHE_DLINESIZE - 1
3001:
301#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
302	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
303#else
304	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
305#endif
306	add	r0, r0, #CACHE_DLINESIZE
307	cmp	r0, r1
308	blo	1b
309	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
310	ret	lr
311SYM_FUNC_END(arm926_dma_flush_range)
312
313/*
314 *	dma_map_area(start, size, dir)
315 *	- start	- kernel virtual start address
316 *	- size	- size of region
317 *	- dir	- DMA direction
318 */
319SYM_TYPED_FUNC_START(arm926_dma_map_area)
320	add	r1, r1, r0
321	cmp	r2, #DMA_TO_DEVICE
322	beq	arm926_dma_clean_range
323	bcs	arm926_dma_inv_range
324	b	arm926_dma_flush_range
325SYM_FUNC_END(arm926_dma_map_area)
326
327/*
328 *	dma_unmap_area(start, size, dir)
329 *	- start	- kernel virtual start address
330 *	- size	- size of region
331 *	- dir	- DMA direction
332 */
333SYM_TYPED_FUNC_START(arm926_dma_unmap_area)
334	ret	lr
335SYM_FUNC_END(arm926_dma_unmap_area)
336
337SYM_TYPED_FUNC_START(cpu_arm926_dcache_clean_area)
338#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
3391:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
340	add	r0, r0, #CACHE_DLINESIZE
341	subs	r1, r1, #CACHE_DLINESIZE
342	bhi	1b
343#endif
344	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
345	ret	lr
346SYM_FUNC_END(cpu_arm926_dcache_clean_area)
347
348/* =============================== PageTable ============================== */
349
350/*
351 * cpu_arm926_switch_mm(pgd)
352 *
353 * Set the translation base pointer to be as described by pgd.
354 *
355 * pgd: new page tables
356 */
357	.align	5
358
359SYM_TYPED_FUNC_START(cpu_arm926_switch_mm)
360#ifdef CONFIG_MMU
361	mov	ip, #0
362#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
363	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
364#else
365@ && 'Clean & Invalidate whole DCache'
3661:	mrc	p15, 0, APSR_nzcv, c7, c14, 3 	@ test,clean,invalidate
367	bne	1b
368#endif
369	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
370	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
371	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
372	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
373#endif
374	ret	lr
375SYM_FUNC_END(cpu_arm926_switch_mm)
376
377/*
378 * cpu_arm926_set_pte_ext(ptep, pte, ext)
379 *
380 * Set a PTE and flush it out
381 */
382	.align	5
383SYM_TYPED_FUNC_START(cpu_arm926_set_pte_ext)
384#ifdef CONFIG_MMU
385	armv3_set_pte_ext
386	mov	r0, r0
387#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
388	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
389#endif
390	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
391#endif
392	ret	lr
393SYM_FUNC_END(cpu_arm926_set_pte_ext)
394
395/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
396.globl	cpu_arm926_suspend_size
397.equ	cpu_arm926_suspend_size, 4 * 3
398#ifdef CONFIG_ARM_CPU_SUSPEND
399SYM_TYPED_FUNC_START(cpu_arm926_do_suspend)
400	stmfd	sp!, {r4 - r6, lr}
401	mrc	p15, 0, r4, c13, c0, 0	@ PID
402	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
403	mrc	p15, 0, r6, c1, c0, 0	@ Control register
404	stmia	r0, {r4 - r6}
405	ldmfd	sp!, {r4 - r6, pc}
406SYM_FUNC_END(cpu_arm926_do_suspend)
407
408SYM_TYPED_FUNC_START(cpu_arm926_do_resume)
409	mov	ip, #0
410	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
411	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
412	ldmia	r0, {r4 - r6}
413	mcr	p15, 0, r4, c13, c0, 0	@ PID
414	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
415	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
416	mov	r0, r6			@ control register
417	b	cpu_resume_mmu
418SYM_FUNC_END(cpu_arm926_do_resume)
419#endif
420
421	.type	__arm926_setup, #function
422__arm926_setup:
423	mov	r0, #0
424	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches on v4
425	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
426#ifdef CONFIG_MMU
427	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs on v4
428#endif
429
430
431#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
432	mov	r0, #4				@ disable write-back on caches explicitly
433	mcr	p15, 7, r0, c15, c0, 0
434#endif
435
436	adr	r5, arm926_crval
437	ldmia	r5, {r5, r6}
438	mrc	p15, 0, r0, c1, c0		@ get control register v4
439	bic	r0, r0, r5
440	orr	r0, r0, r6
441#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
442	orr	r0, r0, #0x4000			@ .1.. .... .... ....
443#endif
444	ret	lr
445	.size	__arm926_setup, . - __arm926_setup
446
447	/*
448	 *  R
449	 * .RVI ZFRS BLDP WCAM
450	 * .011 0001 ..11 0101
451	 *
452	 */
453	.type	arm926_crval, #object
454arm926_crval:
455	crval	clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134
456
457	__INITDATA
458
459	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
460	define_processor_functions arm926, dabort=v5tj_early_abort, pabort=legacy_pabort, suspend=1
461
462	.section ".rodata"
463
464	string	cpu_arch_name, "armv5tej"
465	string	cpu_elf_name, "v5"
466	string	cpu_arm926_name, "ARM926EJ-S"
467
468	.align
469
470	.section ".proc.info.init", "a"
471
472	.type	__arm926_proc_info,#object
473__arm926_proc_info:
474	.long	0x41069260			@ ARM926EJ-S (v5TEJ)
475	.long	0xff0ffff0
476	.long   PMD_TYPE_SECT | \
477		PMD_SECT_BUFFERABLE | \
478		PMD_SECT_CACHEABLE | \
479		PMD_BIT4 | \
480		PMD_SECT_AP_WRITE | \
481		PMD_SECT_AP_READ
482	.long   PMD_TYPE_SECT | \
483		PMD_BIT4 | \
484		PMD_SECT_AP_WRITE | \
485		PMD_SECT_AP_READ
486	initfn	__arm926_setup, __arm926_proc_info
487	.long	cpu_arch_name
488	.long	cpu_elf_name
489	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
490	.long	cpu_arm926_name
491	.long	arm926_processor_functions
492	.long	v4wbi_tlb_fns
493	.long	v4wb_user_fns
494	.long	arm926_cache_fns
495	.size	__arm926_proc_info, . - __arm926_proc_info
496