xref: /openbmc/linux/arch/arm/mm/proc-sa1100.S (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds/*
2*1da177e4SLinus Torvalds *  linux/arch/arm/mm/proc-sa1100.S
3*1da177e4SLinus Torvalds *
4*1da177e4SLinus Torvalds *  Copyright (C) 1997-2002 Russell King
5*1da177e4SLinus Torvalds *
6*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify
7*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as
8*1da177e4SLinus Torvalds * published by the Free Software Foundation.
9*1da177e4SLinus Torvalds *
10*1da177e4SLinus Torvalds *  MMU functions for SA110
11*1da177e4SLinus Torvalds *
12*1da177e4SLinus Torvalds *  These are the low level assembler for performing cache and TLB
13*1da177e4SLinus Torvalds *  functions on the StrongARM-1100 and StrongARM-1110.
14*1da177e4SLinus Torvalds *
15*1da177e4SLinus Torvalds *  Note that SA1100 and SA1110 share everything but their name and CPU ID.
16*1da177e4SLinus Torvalds *
17*1da177e4SLinus Torvalds *  12-jun-2000, Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
18*1da177e4SLinus Torvalds *    Flush the read buffer at context switches
19*1da177e4SLinus Torvalds */
20*1da177e4SLinus Torvalds#include <linux/linkage.h>
21*1da177e4SLinus Torvalds#include <linux/init.h>
22*1da177e4SLinus Torvalds#include <asm/assembler.h>
23*1da177e4SLinus Torvalds#include <asm/constants.h>
24*1da177e4SLinus Torvalds#include <asm/procinfo.h>
25*1da177e4SLinus Torvalds#include <asm/hardware.h>
26*1da177e4SLinus Torvalds#include <asm/pgtable.h>
27*1da177e4SLinus Torvalds
28*1da177e4SLinus Torvalds/*
29*1da177e4SLinus Torvalds * the cache line size of the I and D cache
30*1da177e4SLinus Torvalds */
31*1da177e4SLinus Torvalds#define DCACHELINESIZE	32
32*1da177e4SLinus Torvalds#define FLUSH_OFFSET	32768
33*1da177e4SLinus Torvalds
34*1da177e4SLinus Torvalds	.macro flush_1100_dcache rd, ra, re
35*1da177e4SLinus Torvalds	ldr	\rd, =flush_base
36*1da177e4SLinus Torvalds	ldr	\ra, [\rd]
37*1da177e4SLinus Torvalds	eor	\ra, \ra, #FLUSH_OFFSET
38*1da177e4SLinus Torvalds	str	\ra, [\rd]
39*1da177e4SLinus Torvalds	add	\re, \ra, #8192			@ only necessary for 8k
40*1da177e4SLinus Torvalds1001:	ldr	\rd, [\ra], #DCACHELINESIZE
41*1da177e4SLinus Torvalds	teq	\re, \ra
42*1da177e4SLinus Torvalds	bne	1001b
43*1da177e4SLinus Torvalds#ifdef FLUSH_BASE_MINICACHE
44*1da177e4SLinus Torvalds	add	\ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
45*1da177e4SLinus Torvalds	add	\re, \ra, #512			@ only 512 bytes
46*1da177e4SLinus Torvalds1002:	ldr	\rd, [\ra], #DCACHELINESIZE
47*1da177e4SLinus Torvalds	teq	\re, \ra
48*1da177e4SLinus Torvalds	bne	1002b
49*1da177e4SLinus Torvalds#endif
50*1da177e4SLinus Torvalds	.endm
51*1da177e4SLinus Torvalds
52*1da177e4SLinus Torvalds	.data
53*1da177e4SLinus Torvaldsflush_base:
54*1da177e4SLinus Torvalds	.long	FLUSH_BASE
55*1da177e4SLinus Torvalds	.text
56*1da177e4SLinus Torvalds
57*1da177e4SLinus Torvalds	__INIT
58*1da177e4SLinus Torvalds
59*1da177e4SLinus Torvalds/*
60*1da177e4SLinus Torvalds * cpu_sa1100_proc_init()
61*1da177e4SLinus Torvalds */
62*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_proc_init)
63*1da177e4SLinus Torvalds	mov	r0, #0
64*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
65*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland
66*1da177e4SLinus Torvalds	mov	pc, lr
67*1da177e4SLinus Torvalds
68*1da177e4SLinus Torvalds	.previous
69*1da177e4SLinus Torvalds
70*1da177e4SLinus Torvalds/*
71*1da177e4SLinus Torvalds * cpu_sa1100_proc_fin()
72*1da177e4SLinus Torvalds *
73*1da177e4SLinus Torvalds * Prepare the CPU for reset:
74*1da177e4SLinus Torvalds *  - Disable interrupts
75*1da177e4SLinus Torvalds *  - Clean and turn off caches.
76*1da177e4SLinus Torvalds */
77*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_proc_fin)
78*1da177e4SLinus Torvalds	stmfd	sp!, {lr}
79*1da177e4SLinus Torvalds	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
80*1da177e4SLinus Torvalds	msr	cpsr_c, ip
81*1da177e4SLinus Torvalds	flush_1100_dcache r0, r1, r2		@ clean caches
82*1da177e4SLinus Torvalds	mov	r0, #0
83*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
84*1da177e4SLinus Torvalds	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
85*1da177e4SLinus Torvalds	bic	r0, r0, #0x1000			@ ...i............
86*1da177e4SLinus Torvalds	bic	r0, r0, #0x000e			@ ............wca.
87*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
88*1da177e4SLinus Torvalds	ldmfd	sp!, {pc}
89*1da177e4SLinus Torvalds
90*1da177e4SLinus Torvalds/*
91*1da177e4SLinus Torvalds * cpu_sa1100_reset(loc)
92*1da177e4SLinus Torvalds *
93*1da177e4SLinus Torvalds * Perform a soft reset of the system.  Put the CPU into the
94*1da177e4SLinus Torvalds * same state as it would be if it had been reset, and branch
95*1da177e4SLinus Torvalds * to what would be the reset vector.
96*1da177e4SLinus Torvalds *
97*1da177e4SLinus Torvalds * loc: location to jump to for soft reset
98*1da177e4SLinus Torvalds */
99*1da177e4SLinus Torvalds	.align	5
100*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_reset)
101*1da177e4SLinus Torvalds	mov	ip, #0
102*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
103*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
104*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
105*1da177e4SLinus Torvalds	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
106*1da177e4SLinus Torvalds	bic	ip, ip, #0x000f			@ ............wcam
107*1da177e4SLinus Torvalds	bic	ip, ip, #0x1100			@ ...i...s........
108*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
109*1da177e4SLinus Torvalds	mov	pc, r0
110*1da177e4SLinus Torvalds
111*1da177e4SLinus Torvalds/*
112*1da177e4SLinus Torvalds * cpu_sa1100_do_idle(type)
113*1da177e4SLinus Torvalds *
114*1da177e4SLinus Torvalds * Cause the processor to idle
115*1da177e4SLinus Torvalds *
116*1da177e4SLinus Torvalds * type: call type:
117*1da177e4SLinus Torvalds *   0 = slow idle
118*1da177e4SLinus Torvalds *   1 = fast idle
119*1da177e4SLinus Torvalds *   2 = switch to slow processor clock
120*1da177e4SLinus Torvalds *   3 = switch to fast processor clock
121*1da177e4SLinus Torvalds */
122*1da177e4SLinus Torvalds	.align	5
123*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_do_idle)
124*1da177e4SLinus Torvalds	mov	r0, r0				@ 4 nop padding
125*1da177e4SLinus Torvalds	mov	r0, r0
126*1da177e4SLinus Torvalds	mov	r0, r0
127*1da177e4SLinus Torvalds	mov	r0, r0				@ 4 nop padding
128*1da177e4SLinus Torvalds	mov	r0, r0
129*1da177e4SLinus Torvalds	mov	r0, r0
130*1da177e4SLinus Torvalds	mov	r0, #0
131*1da177e4SLinus Torvalds	ldr	r1, =UNCACHEABLE_ADDR		@ ptr to uncacheable address
132*1da177e4SLinus Torvalds	@ --- aligned to a cache line
133*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c15, c2, 2		@ disable clock switching
134*1da177e4SLinus Torvalds	ldr	r1, [r1, #0]			@ force switch to MCLK
135*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c15, c8, 2		@ wait for interrupt
136*1da177e4SLinus Torvalds	mov	r0, r0				@ safety
137*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
138*1da177e4SLinus Torvalds	mov	pc, lr
139*1da177e4SLinus Torvalds
140*1da177e4SLinus Torvalds/* ================================= CACHE ================================ */
141*1da177e4SLinus Torvalds
142*1da177e4SLinus Torvalds/*
143*1da177e4SLinus Torvalds * cpu_sa1100_dcache_clean_area(addr,sz)
144*1da177e4SLinus Torvalds *
145*1da177e4SLinus Torvalds * Clean the specified entry of any caches such that the MMU
146*1da177e4SLinus Torvalds * translation fetches will obtain correct data.
147*1da177e4SLinus Torvalds *
148*1da177e4SLinus Torvalds * addr: cache-unaligned virtual address
149*1da177e4SLinus Torvalds */
150*1da177e4SLinus Torvalds	.align	5
151*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_dcache_clean_area)
152*1da177e4SLinus Torvalds1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
153*1da177e4SLinus Torvalds	add	r0, r0, #DCACHELINESIZE
154*1da177e4SLinus Torvalds	subs	r1, r1, #DCACHELINESIZE
155*1da177e4SLinus Torvalds	bhi	1b
156*1da177e4SLinus Torvalds	mov	pc, lr
157*1da177e4SLinus Torvalds
158*1da177e4SLinus Torvalds/* =============================== PageTable ============================== */
159*1da177e4SLinus Torvalds
160*1da177e4SLinus Torvalds/*
161*1da177e4SLinus Torvalds * cpu_sa1100_switch_mm(pgd)
162*1da177e4SLinus Torvalds *
163*1da177e4SLinus Torvalds * Set the translation base pointer to be as described by pgd.
164*1da177e4SLinus Torvalds *
165*1da177e4SLinus Torvalds * pgd: new page tables
166*1da177e4SLinus Torvalds */
167*1da177e4SLinus Torvalds	.align	5
168*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_switch_mm)
169*1da177e4SLinus Torvalds	flush_1100_dcache r3, ip, r1
170*1da177e4SLinus Torvalds	mov	ip, #0
171*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
172*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c9, c0, 0		@ invalidate RB
173*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
174*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
175*1da177e4SLinus Torvalds	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
176*1da177e4SLinus Torvalds	mov	pc, lr
177*1da177e4SLinus Torvalds
178*1da177e4SLinus Torvalds/*
179*1da177e4SLinus Torvalds * cpu_sa1100_set_pte(ptep, pte)
180*1da177e4SLinus Torvalds *
181*1da177e4SLinus Torvalds * Set a PTE and flush it out
182*1da177e4SLinus Torvalds */
183*1da177e4SLinus Torvalds	.align	5
184*1da177e4SLinus TorvaldsENTRY(cpu_sa1100_set_pte)
185*1da177e4SLinus Torvalds	str	r1, [r0], #-2048		@ linux version
186*1da177e4SLinus Torvalds
187*1da177e4SLinus Torvalds	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
188*1da177e4SLinus Torvalds
189*1da177e4SLinus Torvalds	bic	r2, r1, #PTE_SMALL_AP_MASK
190*1da177e4SLinus Torvalds	bic	r2, r2, #PTE_TYPE_MASK
191*1da177e4SLinus Torvalds	orr	r2, r2, #PTE_TYPE_SMALL
192*1da177e4SLinus Torvalds
193*1da177e4SLinus Torvalds	tst	r1, #L_PTE_USER			@ User?
194*1da177e4SLinus Torvalds	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
195*1da177e4SLinus Torvalds
196*1da177e4SLinus Torvalds	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
197*1da177e4SLinus Torvalds	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
198*1da177e4SLinus Torvalds
199*1da177e4SLinus Torvalds	tst	r1, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
200*1da177e4SLinus Torvalds	movne	r2, #0
201*1da177e4SLinus Torvalds
202*1da177e4SLinus Torvalds	str	r2, [r0]			@ hardware version
203*1da177e4SLinus Torvalds	mov	r0, r0
204*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
205*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
206*1da177e4SLinus Torvalds	mov	pc, lr
207*1da177e4SLinus Torvalds
208*1da177e4SLinus Torvalds	__INIT
209*1da177e4SLinus Torvalds
210*1da177e4SLinus Torvalds	.type	__sa1100_setup, #function
211*1da177e4SLinus Torvalds__sa1100_setup:
212*1da177e4SLinus Torvalds	mov	r0, #0
213*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches on v4
214*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
215*1da177e4SLinus Torvalds	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs on v4
216*1da177e4SLinus Torvalds	mrc	p15, 0, r0, c1, c0		@ get control register v4
217*1da177e4SLinus Torvalds	ldr	r5, sa1100_cr1_clear
218*1da177e4SLinus Torvalds	bic	r0, r0, r5
219*1da177e4SLinus Torvalds	ldr	r5, sa1100_cr1_set
220*1da177e4SLinus Torvalds	orr	r0, r0, r5
221*1da177e4SLinus Torvalds	mov	pc, lr
222*1da177e4SLinus Torvalds	.size	__sa1100_setup, . - __sa1100_setup
223*1da177e4SLinus Torvalds
224*1da177e4SLinus Torvalds	/*
225*1da177e4SLinus Torvalds	 *  R
226*1da177e4SLinus Torvalds	 * .RVI ZFRS BLDP WCAM
227*1da177e4SLinus Torvalds	 * ..11 0001 ..11 1101
228*1da177e4SLinus Torvalds	 *
229*1da177e4SLinus Torvalds	 */
230*1da177e4SLinus Torvalds	.type	sa1100_cr1_clear, #object
231*1da177e4SLinus Torvalds	.type	sa1100_cr1_set, #object
232*1da177e4SLinus Torvaldssa1100_cr1_clear:
233*1da177e4SLinus Torvalds	.word	0x3f3f
234*1da177e4SLinus Torvaldssa1100_cr1_set:
235*1da177e4SLinus Torvalds	.word	0x313d
236*1da177e4SLinus Torvalds
237*1da177e4SLinus Torvalds	__INITDATA
238*1da177e4SLinus Torvalds
239*1da177e4SLinus Torvalds/*
240*1da177e4SLinus Torvalds * Purpose : Function pointers used to access above functions - all calls
241*1da177e4SLinus Torvalds *	     come through these
242*1da177e4SLinus Torvalds */
243*1da177e4SLinus Torvalds
244*1da177e4SLinus Torvalds/*
245*1da177e4SLinus Torvalds * SA1100 and SA1110 share the same function calls
246*1da177e4SLinus Torvalds */
247*1da177e4SLinus Torvalds	.type	sa1100_processor_functions, #object
248*1da177e4SLinus TorvaldsENTRY(sa1100_processor_functions)
249*1da177e4SLinus Torvalds	.word	v4_early_abort
250*1da177e4SLinus Torvalds	.word	cpu_sa1100_proc_init
251*1da177e4SLinus Torvalds	.word	cpu_sa1100_proc_fin
252*1da177e4SLinus Torvalds	.word	cpu_sa1100_reset
253*1da177e4SLinus Torvalds	.word	cpu_sa1100_do_idle
254*1da177e4SLinus Torvalds	.word	cpu_sa1100_dcache_clean_area
255*1da177e4SLinus Torvalds	.word	cpu_sa1100_switch_mm
256*1da177e4SLinus Torvalds	.word	cpu_sa1100_set_pte
257*1da177e4SLinus Torvalds	.size	sa1100_processor_functions, . - sa1100_processor_functions
258*1da177e4SLinus Torvalds
259*1da177e4SLinus Torvalds	.section ".rodata"
260*1da177e4SLinus Torvalds
261*1da177e4SLinus Torvalds	.type	cpu_arch_name, #object
262*1da177e4SLinus Torvaldscpu_arch_name:
263*1da177e4SLinus Torvalds	.asciz	"armv4"
264*1da177e4SLinus Torvalds	.size	cpu_arch_name, . - cpu_arch_name
265*1da177e4SLinus Torvalds
266*1da177e4SLinus Torvalds	.type	cpu_elf_name, #object
267*1da177e4SLinus Torvaldscpu_elf_name:
268*1da177e4SLinus Torvalds	.asciz	"v4"
269*1da177e4SLinus Torvalds	.size	cpu_elf_name, . - cpu_elf_name
270*1da177e4SLinus Torvalds
271*1da177e4SLinus Torvalds	.type	cpu_sa1100_name, #object
272*1da177e4SLinus Torvaldscpu_sa1100_name:
273*1da177e4SLinus Torvalds	.asciz	"StrongARM-1100"
274*1da177e4SLinus Torvalds	.size	cpu_sa1100_name, . - cpu_sa1100_name
275*1da177e4SLinus Torvalds
276*1da177e4SLinus Torvalds	.type	cpu_sa1110_name, #object
277*1da177e4SLinus Torvaldscpu_sa1110_name:
278*1da177e4SLinus Torvalds	.asciz	"StrongARM-1110"
279*1da177e4SLinus Torvalds	.size	cpu_sa1110_name, . - cpu_sa1110_name
280*1da177e4SLinus Torvalds
281*1da177e4SLinus Torvalds	.align
282*1da177e4SLinus Torvalds
283*1da177e4SLinus Torvalds	.section ".proc.info", #alloc, #execinstr
284*1da177e4SLinus Torvalds
285*1da177e4SLinus Torvalds	.type	__sa1100_proc_info,#object
286*1da177e4SLinus Torvalds__sa1100_proc_info:
287*1da177e4SLinus Torvalds	.long	0x4401a110
288*1da177e4SLinus Torvalds	.long	0xfffffff0
289*1da177e4SLinus Torvalds	.long   PMD_TYPE_SECT | \
290*1da177e4SLinus Torvalds		PMD_SECT_BUFFERABLE | \
291*1da177e4SLinus Torvalds		PMD_SECT_CACHEABLE | \
292*1da177e4SLinus Torvalds		PMD_SECT_AP_WRITE | \
293*1da177e4SLinus Torvalds		PMD_SECT_AP_READ
294*1da177e4SLinus Torvalds	b	__sa1100_setup
295*1da177e4SLinus Torvalds	.long	cpu_arch_name
296*1da177e4SLinus Torvalds	.long	cpu_elf_name
297*1da177e4SLinus Torvalds	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
298*1da177e4SLinus Torvalds	.long	cpu_sa1100_name
299*1da177e4SLinus Torvalds	.long	sa1100_processor_functions
300*1da177e4SLinus Torvalds	.long	v4wb_tlb_fns
301*1da177e4SLinus Torvalds	.long	v4_mc_user_fns
302*1da177e4SLinus Torvalds	.long	v4wb_cache_fns
303*1da177e4SLinus Torvalds	.size	__sa1100_proc_info, . - __sa1100_proc_info
304*1da177e4SLinus Torvalds
305*1da177e4SLinus Torvalds	.type	__sa1110_proc_info,#object
306*1da177e4SLinus Torvalds__sa1110_proc_info:
307*1da177e4SLinus Torvalds	.long	0x6901b110
308*1da177e4SLinus Torvalds	.long	0xfffffff0
309*1da177e4SLinus Torvalds	.long   PMD_TYPE_SECT | \
310*1da177e4SLinus Torvalds		PMD_SECT_BUFFERABLE | \
311*1da177e4SLinus Torvalds		PMD_SECT_CACHEABLE | \
312*1da177e4SLinus Torvalds		PMD_SECT_AP_WRITE | \
313*1da177e4SLinus Torvalds		PMD_SECT_AP_READ
314*1da177e4SLinus Torvalds	b	__sa1100_setup
315*1da177e4SLinus Torvalds	.long	cpu_arch_name
316*1da177e4SLinus Torvalds	.long	cpu_elf_name
317*1da177e4SLinus Torvalds	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
318*1da177e4SLinus Torvalds	.long	cpu_sa1110_name
319*1da177e4SLinus Torvalds	.long	sa1100_processor_functions
320*1da177e4SLinus Torvalds	.long	v4wb_tlb_fns
321*1da177e4SLinus Torvalds	.long	v4_mc_user_fns
322*1da177e4SLinus Torvalds	.long	v4wb_cache_fns
323*1da177e4SLinus Torvalds	.size	__sa1110_proc_info, . - __sa1110_proc_info
324