blob: fffb061a45a558ee8dc5883dcba4a0e64ef53311 [file] [log] [blame]
Hyok S. Choid60674e2006-09-26 17:38:18 +09001/*
2 * linux/arch/arm/mm/arm940.S: utility functions for ARM940T
3 *
4 * Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
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 */
11#include <linux/linkage.h>
12#include <linux/init.h>
13#include <asm/assembler.h>
Russell King5ec94072008-09-07 19:15:31 +010014#include <asm/hwcap.h>
Hyok S. Choid60674e2006-09-26 17:38:18 +090015#include <asm/pgtable-hwdef.h>
16#include <asm/pgtable.h>
Hyok S. Choid60674e2006-09-26 17:38:18 +090017#include <asm/ptrace.h>
Russell King8a5544c2008-08-12 14:02:23 +010018#include "proc-macros.S"
Hyok S. Choid60674e2006-09-26 17:38:18 +090019
20/* ARM940T has a 4KB DCache comprising 256 lines of 4 words */
21#define CACHE_DLINESIZE 16
22#define CACHE_DSEGMENTS 4
23#define CACHE_DENTRIES 64
24
25 .text
26/*
27 * cpu_arm940_proc_init()
28 * cpu_arm940_switch_mm()
29 *
30 * These are not required.
31 */
32ENTRY(cpu_arm940_proc_init)
33ENTRY(cpu_arm940_switch_mm)
34 mov pc, lr
35
36/*
37 * cpu_arm940_proc_fin()
38 */
39ENTRY(cpu_arm940_proc_fin)
Hyok S. Choid60674e2006-09-26 17:38:18 +090040 mrc p15, 0, r0, c1, c0, 0 @ ctrl register
41 bic r0, r0, #0x00001000 @ i-cache
42 bic r0, r0, #0x00000004 @ d-cache
43 mcr p15, 0, r0, c1, c0, 0 @ disable caches
Russell King9ca03a22010-07-26 12:22:12 +010044 mov pc, lr
Hyok S. Choid60674e2006-09-26 17:38:18 +090045
46/*
47 * cpu_arm940_reset(loc)
48 * Params : r0 = address to jump to
49 * Notes : This sets up everything for a reset
50 */
51ENTRY(cpu_arm940_reset)
52 mov ip, #0
53 mcr p15, 0, ip, c7, c5, 0 @ flush I cache
54 mcr p15, 0, ip, c7, c6, 0 @ flush D cache
55 mcr p15, 0, ip, c7, c10, 4 @ drain WB
56 mrc p15, 0, ip, c1, c0, 0 @ ctrl register
57 bic ip, ip, #0x00000005 @ .............c.p
58 bic ip, ip, #0x00001000 @ i-cache
59 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
60 mov pc, r0
61
62/*
63 * cpu_arm940_do_idle()
64 */
65 .align 5
66ENTRY(cpu_arm940_do_idle)
67 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
68 mov pc, lr
69
70/*
71 * flush_user_cache_all()
72 */
73ENTRY(arm940_flush_user_cache_all)
74 /* FALLTHROUGH */
75
76/*
77 * flush_kern_cache_all()
78 *
79 * Clean and invalidate the entire cache.
80 */
81ENTRY(arm940_flush_kern_cache_all)
82 mov r2, #VM_EXEC
83 /* FALLTHROUGH */
84
85/*
86 * flush_user_cache_range(start, end, flags)
87 *
88 * There is no efficient way to flush a range of cache entries
89 * in the specified address range. Thus, flushes all.
90 *
91 * - start - start address (inclusive)
92 * - end - end address (exclusive)
93 * - flags - vm_flags describing address space
94 */
95ENTRY(arm940_flush_user_cache_range)
96 mov ip, #0
97#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
98 mcr p15, 0, ip, c7, c6, 0 @ flush D cache
99#else
100 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1011: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
1022: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index
103 subs r3, r3, #1 << 26
104 bcs 2b @ entries 63 to 0
105 subs r1, r1, #1 << 4
106 bcs 1b @ segments 3 to 0
107#endif
108 tst r2, #VM_EXEC
109 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
110 mcrne p15, 0, ip, c7, c10, 4 @ drain WB
111 mov pc, lr
112
113/*
114 * coherent_kern_range(start, end)
115 *
116 * Ensure coherency between the Icache and the Dcache in the
117 * region described by start, end. If you have non-snooping
118 * Harvard caches, you need to implement this function.
119 *
120 * - start - virtual start address
121 * - end - virtual end address
122 */
123ENTRY(arm940_coherent_kern_range)
124 /* FALLTHROUGH */
125
126/*
127 * coherent_user_range(start, end)
128 *
129 * Ensure coherency between the Icache and the Dcache in the
130 * region described by start, end. If you have non-snooping
131 * Harvard caches, you need to implement this function.
132 *
133 * - start - virtual start address
134 * - end - virtual end address
135 */
136ENTRY(arm940_coherent_user_range)
137 /* FALLTHROUGH */
138
139/*
Russell King2c9b9c82009-11-26 12:56:21 +0000140 * flush_kern_dcache_area(void *addr, size_t size)
Hyok S. Choid60674e2006-09-26 17:38:18 +0900141 *
142 * Ensure no D cache aliasing occurs, either with itself or
143 * the I cache
144 *
Russell King2c9b9c82009-11-26 12:56:21 +0000145 * - addr - kernel address
146 * - size - region size
Hyok S. Choid60674e2006-09-26 17:38:18 +0900147 */
Russell King2c9b9c82009-11-26 12:56:21 +0000148ENTRY(arm940_flush_kern_dcache_area)
Hyok S. Choid60674e2006-09-26 17:38:18 +0900149 mov ip, #0
150 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1511: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
1522: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index
153 subs r3, r3, #1 << 26
154 bcs 2b @ entries 63 to 0
155 subs r1, r1, #1 << 4
156 bcs 1b @ segments 7 to 0
157 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
158 mcr p15, 0, ip, c7, c10, 4 @ drain WB
159 mov pc, lr
160
161/*
162 * dma_inv_range(start, end)
163 *
164 * There is no efficient way to invalidate a specifid virtual
165 * address range. Thus, invalidates all.
166 *
167 * - start - virtual start address
168 * - end - virtual end address
169 */
Russell King702b94b2009-11-26 16:24:19 +0000170arm940_dma_inv_range:
Hyok S. Choid60674e2006-09-26 17:38:18 +0900171 mov ip, #0
172 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1731: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
1742: mcr p15, 0, r3, c7, c6, 2 @ flush D entry
175 subs r3, r3, #1 << 26
176 bcs 2b @ entries 63 to 0
177 subs r1, r1, #1 << 4
178 bcs 1b @ segments 7 to 0
179 mcr p15, 0, ip, c7, c10, 4 @ drain WB
180 mov pc, lr
181
182/*
183 * dma_clean_range(start, end)
184 *
185 * There is no efficient way to clean a specifid virtual
186 * address range. Thus, cleans all.
187 *
188 * - start - virtual start address
189 * - end - virtual end address
190 */
Russell King702b94b2009-11-26 16:24:19 +0000191arm940_dma_clean_range:
Hyok S. Choid60674e2006-09-26 17:38:18 +0900192ENTRY(cpu_arm940_dcache_clean_area)
193 mov ip, #0
194#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
195 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1961: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
1972: mcr p15, 0, r3, c7, c10, 2 @ clean D entry
198 subs r3, r3, #1 << 26
199 bcs 2b @ entries 63 to 0
200 subs r1, r1, #1 << 4
201 bcs 1b @ segments 7 to 0
202#endif
203 mcr p15, 0, ip, c7, c10, 4 @ drain WB
204 mov pc, lr
205
206/*
207 * dma_flush_range(start, end)
208 *
209 * There is no efficient way to clean and invalidate a specifid
210 * virtual address range.
211 *
212 * - start - virtual start address
213 * - end - virtual end address
214 */
215ENTRY(arm940_dma_flush_range)
216 mov ip, #0
217 mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
2181: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
2192:
220#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
221 mcr p15, 0, r3, c7, c14, 2 @ clean/flush D entry
222#else
Lennert Buytenhekb3a8b752008-05-10 21:05:31 +0100223 mcr p15, 0, r3, c7, c6, 2 @ invalidate D entry
Hyok S. Choid60674e2006-09-26 17:38:18 +0900224#endif
225 subs r3, r3, #1 << 26
226 bcs 2b @ entries 63 to 0
227 subs r1, r1, #1 << 4
228 bcs 1b @ segments 7 to 0
229 mcr p15, 0, ip, c7, c10, 4 @ drain WB
230 mov pc, lr
231
Russell Kinga9c91472009-11-26 16:19:58 +0000232/*
233 * dma_map_area(start, size, dir)
234 * - start - kernel virtual start address
235 * - size - size of region
236 * - dir - DMA direction
237 */
238ENTRY(arm940_dma_map_area)
239 add r1, r1, r0
240 cmp r2, #DMA_TO_DEVICE
241 beq arm940_dma_clean_range
242 bcs arm940_dma_inv_range
243 b arm940_dma_flush_range
244ENDPROC(arm940_dma_map_area)
245
246/*
247 * dma_unmap_area(start, size, dir)
248 * - start - kernel virtual start address
249 * - size - size of region
250 * - dir - DMA direction
251 */
252ENTRY(arm940_dma_unmap_area)
253 mov pc, lr
254ENDPROC(arm940_dma_unmap_area)
255
Hyok S. Choid60674e2006-09-26 17:38:18 +0900256ENTRY(arm940_cache_fns)
257 .long arm940_flush_kern_cache_all
258 .long arm940_flush_user_cache_all
259 .long arm940_flush_user_cache_range
260 .long arm940_coherent_kern_range
261 .long arm940_coherent_user_range
Russell King2c9b9c82009-11-26 12:56:21 +0000262 .long arm940_flush_kern_dcache_area
Russell Kinga9c91472009-11-26 16:19:58 +0000263 .long arm940_dma_map_area
264 .long arm940_dma_unmap_area
Hyok S. Choid60674e2006-09-26 17:38:18 +0900265 .long arm940_dma_flush_range
266
267 __INIT
268
269 .type __arm940_setup, #function
270__arm940_setup:
271 mov r0, #0
272 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
273 mcr p15, 0, r0, c7, c6, 0 @ invalidate D cache
274 mcr p15, 0, r0, c7, c10, 4 @ drain WB
275
276 mcr p15, 0, r0, c6, c3, 0 @ disable data area 3~7
277 mcr p15, 0, r0, c6, c4, 0
278 mcr p15, 0, r0, c6, c5, 0
279 mcr p15, 0, r0, c6, c6, 0
280 mcr p15, 0, r0, c6, c7, 0
281
282 mcr p15, 0, r0, c6, c3, 1 @ disable instruction area 3~7
283 mcr p15, 0, r0, c6, c4, 1
284 mcr p15, 0, r0, c6, c5, 1
285 mcr p15, 0, r0, c6, c6, 1
286 mcr p15, 0, r0, c6, c7, 1
287
288 mov r0, #0x0000003F @ base = 0, size = 4GB
289 mcr p15, 0, r0, c6, c0, 0 @ set area 0, default
290 mcr p15, 0, r0, c6, c0, 1
291
292 ldr r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
293 ldr r1, =(CONFIG_DRAM_SIZE >> 12) @ size of RAM (must be >= 4KB)
294 mov r2, #10 @ 11 is the minimum (4KB)
2951: add r2, r2, #1 @ area size *= 2
296 mov r1, r1, lsr #1
297 bne 1b @ count not zero r-shift
298 orr r0, r0, r2, lsl #1 @ the area register value
299 orr r0, r0, #1 @ set enable bit
300 mcr p15, 0, r0, c6, c1, 0 @ set area 1, RAM
301 mcr p15, 0, r0, c6, c1, 1
302
303 ldr r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
304 ldr r1, =(CONFIG_FLASH_SIZE >> 12) @ size of FLASH (must be >= 4KB)
305 mov r2, #10 @ 11 is the minimum (4KB)
3061: add r2, r2, #1 @ area size *= 2
307 mov r1, r1, lsr #1
308 bne 1b @ count not zero r-shift
309 orr r0, r0, r2, lsl #1 @ the area register value
310 orr r0, r0, #1 @ set enable bit
311 mcr p15, 0, r0, c6, c2, 0 @ set area 2, ROM/FLASH
312 mcr p15, 0, r0, c6, c2, 1
313
314 mov r0, #0x06
315 mcr p15, 0, r0, c2, c0, 0 @ Region 1&2 cacheable
316 mcr p15, 0, r0, c2, c0, 1
317#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
318 mov r0, #0x00 @ disable whole write buffer
319#else
320 mov r0, #0x02 @ Region 1 write bufferred
321#endif
322 mcr p15, 0, r0, c3, c0, 0
323
324 mov r0, #0x10000
325 sub r0, r0, #1 @ r0 = 0xffff
326 mcr p15, 0, r0, c5, c0, 0 @ all read/write access
327 mcr p15, 0, r0, c5, c0, 1
328
329 mrc p15, 0, r0, c1, c0 @ get control register
330 orr r0, r0, #0x00001000 @ I-cache
331 orr r0, r0, #0x00000005 @ MPU/D-cache
332
333 mov pc, lr
334
335 .size __arm940_setup, . - __arm940_setup
336
337 __INITDATA
338
339/*
340 * Purpose : Function pointers used to access above functions - all calls
341 * come through these
342 */
343 .type arm940_processor_functions, #object
344ENTRY(arm940_processor_functions)
Hyok S. Choi0f45d7f2006-09-28 21:46:16 +0900345 .word nommu_early_abort
Kirill A. Shutemov4fb28472009-09-25 13:39:47 +0100346 .word legacy_pabort
Hyok S. Choid60674e2006-09-26 17:38:18 +0900347 .word cpu_arm940_proc_init
348 .word cpu_arm940_proc_fin
349 .word cpu_arm940_reset
350 .word cpu_arm940_do_idle
351 .word cpu_arm940_dcache_clean_area
352 .word cpu_arm940_switch_mm
353 .word 0 @ cpu_*_set_pte
354 .size arm940_processor_functions, . - arm940_processor_functions
355
356 .section ".rodata"
357
358.type cpu_arch_name, #object
359cpu_arch_name:
360 .asciz "armv4t"
361 .size cpu_arch_name, . - cpu_arch_name
362
363 .type cpu_elf_name, #object
364cpu_elf_name:
365 .asciz "v4"
366 .size cpu_elf_name, . - cpu_elf_name
367
368 .type cpu_arm940_name, #object
369cpu_arm940_name:
370 .ascii "ARM940T"
371 .size cpu_arm940_name, . - cpu_arm940_name
372
373 .align
374
375 .section ".proc.info.init", #alloc, #execinstr
376
377 .type __arm940_proc_info,#object
378__arm940_proc_info:
379 .long 0x41009400
380 .long 0xff00fff0
381 .long 0
382 b __arm940_setup
383 .long cpu_arch_name
384 .long cpu_elf_name
385 .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
386 .long cpu_arm940_name
387 .long arm940_processor_functions
388 .long 0
389 .long 0
390 .long arm940_cache_fns
391 .size __arm940_proc_info, . - __arm940_proc_info
392