xref: /linux/arch/arm/mm/proc-sa110.S (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
1/*
2 *  linux/arch/arm/mm/proc-sa110.S
3 *
4 *  Copyright (C) 1997-2002 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 *  MMU functions for SA110
11 *
12 *  These are the low level assembler for performing cache and TLB
13 *  functions on the StrongARM-110.
14 */
15#include <linux/linkage.h>
16#include <linux/init.h>
17#include <asm/assembler.h>
18#include <asm/asm-offsets.h>
19#include <asm/procinfo.h>
20#include <asm/hardware.h>
21#include <asm/pgtable-hwdef.h>
22#include <asm/pgtable.h>
23#include <asm/ptrace.h>
24
25/*
26 * the cache line size of the I and D cache
27 */
28#define DCACHELINESIZE	32
29#define FLUSH_OFFSET	32768
30
31	.macro flush_110_dcache	rd, ra, re
32	ldr	\rd, =flush_base
33	ldr	\ra, [\rd]
34	eor	\ra, \ra, #FLUSH_OFFSET
35	str	\ra, [\rd]
36	add	\re, \ra, #16384		@ only necessary for 16k
371001:	ldr	\rd, [\ra], #DCACHELINESIZE
38	teq	\re, \ra
39	bne	1001b
40	.endm
41
42	.data
43flush_base:
44	.long	FLUSH_BASE
45	.text
46
47/*
48 * cpu_sa110_proc_init()
49 */
50ENTRY(cpu_sa110_proc_init)
51	mov	r0, #0
52	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
53	mov	pc, lr
54
55/*
56 * cpu_sa110_proc_fin()
57 */
58ENTRY(cpu_sa110_proc_fin)
59	stmfd	sp!, {lr}
60	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
61	msr	cpsr_c, ip
62	bl	v4wb_flush_kern_cache_all	@ clean caches
631:	mov	r0, #0
64	mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
65	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
66	bic	r0, r0, #0x1000			@ ...i............
67	bic	r0, r0, #0x000e			@ ............wca.
68	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
69	ldmfd	sp!, {pc}
70
71/*
72 * cpu_sa110_reset(loc)
73 *
74 * Perform a soft reset of the system.  Put the CPU into the
75 * same state as it would be if it had been reset, and branch
76 * to what would be the reset vector.
77 *
78 * loc: location to jump to for soft reset
79 */
80	.align	5
81ENTRY(cpu_sa110_reset)
82	mov	ip, #0
83	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
84	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
85	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
86	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
87	bic	ip, ip, #0x000f			@ ............wcam
88	bic	ip, ip, #0x1100			@ ...i...s........
89	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
90	mov	pc, r0
91
92/*
93 * cpu_sa110_do_idle(type)
94 *
95 * Cause the processor to idle
96 *
97 * type: call type:
98 *   0 = slow idle
99 *   1 = fast idle
100 *   2 = switch to slow processor clock
101 *   3 = switch to fast processor clock
102 */
103	.align	5
104
105ENTRY(cpu_sa110_do_idle)
106	mcr	p15, 0, ip, c15, c2, 2		@ disable clock switching
107	ldr	r1, =UNCACHEABLE_ADDR		@ load from uncacheable loc
108	ldr	r1, [r1, #0]			@ force switch to MCLK
109	mov	r0, r0				@ safety
110	mov	r0, r0				@ safety
111	mov	r0, r0				@ safety
112	mcr	p15, 0, r0, c15, c8, 2		@ Wait for interrupt, cache aligned
113	mov	r0, r0				@ safety
114	mov	r0, r0				@ safety
115	mov	r0, r0				@ safety
116	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
117	mov	pc, lr
118
119/* ================================= CACHE ================================ */
120
121/*
122 * cpu_sa110_dcache_clean_area(addr,sz)
123 *
124 * Clean the specified entry of any caches such that the MMU
125 * translation fetches will obtain correct data.
126 *
127 * addr: cache-unaligned virtual address
128 */
129	.align	5
130ENTRY(cpu_sa110_dcache_clean_area)
1311:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
132	add	r0, r0, #DCACHELINESIZE
133	subs	r1, r1, #DCACHELINESIZE
134	bhi	1b
135	mov	pc, lr
136
137/* =============================== PageTable ============================== */
138
139/*
140 * cpu_sa110_switch_mm(pgd)
141 *
142 * Set the translation base pointer to be as described by pgd.
143 *
144 * pgd: new page tables
145 */
146	.align	5
147ENTRY(cpu_sa110_switch_mm)
148	flush_110_dcache	r3, ip, r1
149	mov	r1, #0
150	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I cache
151	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
152	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
153	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
154	mov	pc, lr
155
156/*
157 * cpu_sa110_set_pte(ptep, pte)
158 *
159 * Set a PTE and flush it out
160 */
161	.align	5
162ENTRY(cpu_sa110_set_pte)
163	str	r1, [r0], #-2048		@ linux version
164
165	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
166
167	bic	r2, r1, #PTE_SMALL_AP_MASK
168	bic	r2, r2, #PTE_TYPE_MASK
169	orr	r2, r2, #PTE_TYPE_SMALL
170
171	tst	r1, #L_PTE_USER			@ User?
172	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
173
174	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
175	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
176
177	tst	r1, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
178	movne	r2, #0
179
180	str	r2, [r0]			@ hardware version
181	mov	r0, r0
182	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
183	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
184	mov	pc, lr
185
186	__INIT
187
188	.type	__sa110_setup, #function
189__sa110_setup:
190	mov	r10, #0
191	mcr	p15, 0, r10, c7, c7		@ invalidate I,D caches on v4
192	mcr	p15, 0, r10, c7, c10, 4		@ drain write buffer on v4
193	mcr	p15, 0, r10, c8, c7		@ invalidate I,D TLBs on v4
194	mrc	p15, 0, r0, c1, c0		@ get control register v4
195	ldr	r5, sa110_cr1_clear
196	bic	r0, r0, r5
197	ldr	r5, sa110_cr1_set
198	orr	r0, r0, r5
199	mov	pc, lr
200	.size	__sa110_setup, . - __sa110_setup
201
202	/*
203	 *  R
204	 * .RVI ZFRS BLDP WCAM
205	 * ..01 0001 ..11 1101
206	 *
207	 */
208	.type	sa110_cr1_clear, #object
209	.type	sa110_cr1_set, #object
210sa110_cr1_clear:
211	.word	0x3f3f
212sa110_cr1_set:
213	.word	0x113d
214
215	__INITDATA
216
217/*
218 * Purpose : Function pointers used to access above functions - all calls
219 *	     come through these
220 */
221
222	.type	sa110_processor_functions, #object
223ENTRY(sa110_processor_functions)
224	.word	v4_early_abort
225	.word	cpu_sa110_proc_init
226	.word	cpu_sa110_proc_fin
227	.word	cpu_sa110_reset
228	.word	cpu_sa110_do_idle
229	.word	cpu_sa110_dcache_clean_area
230	.word	cpu_sa110_switch_mm
231	.word	cpu_sa110_set_pte
232	.size	sa110_processor_functions, . - sa110_processor_functions
233
234	.section ".rodata"
235
236	.type	cpu_arch_name, #object
237cpu_arch_name:
238	.asciz	"armv4"
239	.size	cpu_arch_name, . - cpu_arch_name
240
241	.type	cpu_elf_name, #object
242cpu_elf_name:
243	.asciz	"v4"
244	.size	cpu_elf_name, . - cpu_elf_name
245
246	.type	cpu_sa110_name, #object
247cpu_sa110_name:
248	.asciz	"StrongARM-110"
249	.size	cpu_sa110_name, . - cpu_sa110_name
250
251	.align
252
253	.section ".proc.info.init", #alloc, #execinstr
254
255	.type	__sa110_proc_info,#object
256__sa110_proc_info:
257	.long	0x4401a100
258	.long	0xfffffff0
259	.long   PMD_TYPE_SECT | \
260		PMD_SECT_BUFFERABLE | \
261		PMD_SECT_CACHEABLE | \
262		PMD_SECT_AP_WRITE | \
263		PMD_SECT_AP_READ
264	b	__sa110_setup
265	.long	cpu_arch_name
266	.long	cpu_elf_name
267	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
268	.long	cpu_sa110_name
269	.long	sa110_processor_functions
270	.long	v4wb_tlb_fns
271	.long	v4wb_user_fns
272	.long	v4wb_cache_fns
273	.size	__sa110_proc_info, . - __sa110_proc_info
274