2
* linux/arch/arm/mm/proc-arm1020.S: MMU functions for ARM1020
4
* Copyright (C) 2000 ARM Limited
5
* Copyright (C) 2000 Deep Blue Solutions Ltd.
6
* hacked for non-paged-MM by Hyok S. Choi, 2003.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
* These are the low level assembler for performing cache and TLB
24
* functions on the arm1020.
26
* CONFIG_CPU_ARM1020_CPU_IDLE -> nohlt
28
#include <linux/linkage.h>
29
#include <linux/init.h>
30
#include <asm/assembler.h>
31
#include <asm/asm-offsets.h>
32
#include <asm/hwcap.h>
33
#include <asm/pgtable-hwdef.h>
34
#include <asm/pgtable.h>
35
#include <asm/ptrace.h>
37
#include "proc-macros.S"
40
* This is the maximum size of an area which will be invalidated
41
* using the single invalidate entry instructions. Anything larger
42
* than this, and we go for the whole cache.
44
* This value should be chosen such that we choose the cheapest
47
#define MAX_AREA_SIZE 32768
50
* The size of one data cache line.
52
#define CACHE_DLINESIZE 32
55
* The number of data cache segments.
57
#define CACHE_DSEGMENTS 16
60
* The number of lines in a cache segment.
62
#define CACHE_DENTRIES 64
65
* This is the size at which it becomes more efficient to
66
* clean the whole cache, rather than using the individual
67
* cache line maintenance instructions.
69
#define CACHE_DLIMIT 32768
73
* cpu_arm1020_proc_init()
75
ENTRY(cpu_arm1020_proc_init)
79
* cpu_arm1020_proc_fin()
81
ENTRY(cpu_arm1020_proc_fin)
82
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
83
bic r0, r0, #0x1000 @ ...i............
84
bic r0, r0, #0x000e @ ............wca.
85
mcr p15, 0, r0, c1, c0, 0 @ disable caches
89
* cpu_arm1020_reset(loc)
91
* Perform a soft reset of the system. Put the CPU into the
92
* same state as it would be if it had been reset, and branch
93
* to what would be the reset vector.
95
* loc: location to jump to for soft reset
98
ENTRY(cpu_arm1020_reset)
100
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
101
mcr p15, 0, ip, c7, c10, 4 @ drain WB
103
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
105
mrc p15, 0, ip, c1, c0, 0 @ ctrl register
106
bic ip, ip, #0x000f @ ............wcam
107
bic ip, ip, #0x1100 @ ...i...s........
108
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
112
* cpu_arm1020_do_idle()
115
ENTRY(cpu_arm1020_do_idle)
116
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
119
/* ================================= CACHE ================================ */
126
* Unconditionally clean and invalidate the entire icache.
128
ENTRY(arm1020_flush_icache_all)
129
#ifndef CONFIG_CPU_ICACHE_DISABLE
131
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
134
ENDPROC(arm1020_flush_icache_all)
137
* flush_user_cache_all()
139
* Invalidate all cache entries in a particular address
142
ENTRY(arm1020_flush_user_cache_all)
145
* flush_kern_cache_all()
147
* Clean and invalidate the entire cache.
149
ENTRY(arm1020_flush_kern_cache_all)
153
#ifndef CONFIG_CPU_DCACHE_DISABLE
154
mcr p15, 0, ip, c7, c10, 4 @ drain WB
155
mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 16 segments
156
1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
157
2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index
158
mcr p15, 0, ip, c7, c10, 4 @ drain WB
159
subs r3, r3, #1 << 26
160
bcs 2b @ entries 63 to 0
162
bcs 1b @ segments 15 to 0
165
#ifndef CONFIG_CPU_ICACHE_DISABLE
166
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
168
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
172
* flush_user_cache_range(start, end, flags)
174
* Invalidate a range of cache entries in the specified
177
* - start - start address (inclusive)
178
* - end - end address (exclusive)
179
* - flags - vm_flags for this space
181
ENTRY(arm1020_flush_user_cache_range)
183
sub r3, r1, r0 @ calculate total size
184
cmp r3, #CACHE_DLIMIT
185
bhs __flush_whole_cache
187
#ifndef CONFIG_CPU_DCACHE_DISABLE
188
mcr p15, 0, ip, c7, c10, 4
189
1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
190
mcr p15, 0, ip, c7, c10, 4 @ drain WB
191
add r0, r0, #CACHE_DLINESIZE
196
#ifndef CONFIG_CPU_ICACHE_DISABLE
197
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
199
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
203
* coherent_kern_range(start, end)
205
* Ensure coherency between the Icache and the Dcache in the
206
* region described by start. If you have non-snooping
207
* Harvard caches, you need to implement this function.
209
* - start - virtual start address
210
* - end - virtual end address
212
ENTRY(arm1020_coherent_kern_range)
216
* coherent_user_range(start, end)
218
* Ensure coherency between the Icache and the Dcache in the
219
* region described by start. If you have non-snooping
220
* Harvard caches, you need to implement this function.
222
* - start - virtual start address
223
* - end - virtual end address
225
ENTRY(arm1020_coherent_user_range)
227
bic r0, r0, #CACHE_DLINESIZE - 1
228
mcr p15, 0, ip, c7, c10, 4
230
#ifndef CONFIG_CPU_DCACHE_DISABLE
231
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
232
mcr p15, 0, ip, c7, c10, 4 @ drain WB
234
#ifndef CONFIG_CPU_ICACHE_DISABLE
235
mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
237
add r0, r0, #CACHE_DLINESIZE
240
mcr p15, 0, ip, c7, c10, 4 @ drain WB
244
* flush_kern_dcache_area(void *addr, size_t size)
246
* Ensure no D cache aliasing occurs, either with itself or
249
* - addr - kernel address
250
* - size - region size
252
ENTRY(arm1020_flush_kern_dcache_area)
254
#ifndef CONFIG_CPU_DCACHE_DISABLE
256
1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
257
mcr p15, 0, ip, c7, c10, 4 @ drain WB
258
add r0, r0, #CACHE_DLINESIZE
262
mcr p15, 0, ip, c7, c10, 4 @ drain WB
266
* dma_inv_range(start, end)
268
* Invalidate (discard) the specified virtual address range.
269
* May not write back any entries. If 'start' or 'end'
270
* are not cache line aligned, those lines must be written
273
* - start - virtual start address
274
* - end - virtual end address
278
arm1020_dma_inv_range:
280
#ifndef CONFIG_CPU_DCACHE_DISABLE
281
tst r0, #CACHE_DLINESIZE - 1
282
bic r0, r0, #CACHE_DLINESIZE - 1
283
mcrne p15, 0, ip, c7, c10, 4
284
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
285
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
286
tst r1, #CACHE_DLINESIZE - 1
287
mcrne p15, 0, ip, c7, c10, 4
288
mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
289
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
290
1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
291
add r0, r0, #CACHE_DLINESIZE
295
mcr p15, 0, ip, c7, c10, 4 @ drain WB
299
* dma_clean_range(start, end)
301
* Clean the specified virtual address range.
303
* - start - virtual start address
304
* - end - virtual end address
308
arm1020_dma_clean_range:
310
#ifndef CONFIG_CPU_DCACHE_DISABLE
311
bic r0, r0, #CACHE_DLINESIZE - 1
312
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
313
mcr p15, 0, ip, c7, c10, 4 @ drain WB
314
add r0, r0, #CACHE_DLINESIZE
318
mcr p15, 0, ip, c7, c10, 4 @ drain WB
322
* dma_flush_range(start, end)
324
* Clean and invalidate the specified virtual address range.
326
* - start - virtual start address
327
* - end - virtual end address
329
ENTRY(arm1020_dma_flush_range)
331
#ifndef CONFIG_CPU_DCACHE_DISABLE
332
bic r0, r0, #CACHE_DLINESIZE - 1
333
mcr p15, 0, ip, c7, c10, 4
334
1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
335
mcr p15, 0, ip, c7, c10, 4 @ drain WB
336
add r0, r0, #CACHE_DLINESIZE
340
mcr p15, 0, ip, c7, c10, 4 @ drain WB
344
* dma_map_area(start, size, dir)
345
* - start - kernel virtual start address
346
* - size - size of region
347
* - dir - DMA direction
349
ENTRY(arm1020_dma_map_area)
351
cmp r2, #DMA_TO_DEVICE
352
beq arm1020_dma_clean_range
353
bcs arm1020_dma_inv_range
354
b arm1020_dma_flush_range
355
ENDPROC(arm1020_dma_map_area)
358
* dma_unmap_area(start, size, dir)
359
* - start - kernel virtual start address
360
* - size - size of region
361
* - dir - DMA direction
363
ENTRY(arm1020_dma_unmap_area)
365
ENDPROC(arm1020_dma_unmap_area)
367
@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
368
define_cache_functions arm1020
371
ENTRY(cpu_arm1020_dcache_clean_area)
372
#ifndef CONFIG_CPU_DCACHE_DISABLE
374
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
375
mcr p15, 0, ip, c7, c10, 4 @ drain WB
376
add r0, r0, #CACHE_DLINESIZE
377
subs r1, r1, #CACHE_DLINESIZE
382
/* =============================== PageTable ============================== */
385
* cpu_arm1020_switch_mm(pgd)
387
* Set the translation base pointer to be as described by pgd.
389
* pgd: new page tables
392
ENTRY(cpu_arm1020_switch_mm)
394
#ifndef CONFIG_CPU_DCACHE_DISABLE
395
mcr p15, 0, r3, c7, c10, 4
396
mov r1, #0xF @ 16 segments
397
1: mov r3, #0x3F @ 64 entries
398
2: mov ip, r3, LSL #26 @ shift up entry
399
orr ip, ip, r1, LSL #5 @ shift in/up index
400
mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry
402
mcr p15, 0, ip, c7, c10, 4
405
bge 2b @ entries 3F to 0
408
bge 1b @ segments 15 to 0
412
#ifndef CONFIG_CPU_ICACHE_DISABLE
413
mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
415
mcr p15, 0, r1, c7, c10, 4 @ drain WB
416
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
417
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
418
#endif /* CONFIG_MMU */
422
* cpu_arm1020_set_pte(ptep, pte)
424
* Set a PTE and flush it out
427
ENTRY(cpu_arm1020_set_pte_ext)
431
#ifndef CONFIG_CPU_DCACHE_DISABLE
432
mcr p15, 0, r0, c7, c10, 4
433
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
435
mcr p15, 0, r0, c7, c10, 4 @ drain WB
436
#endif /* CONFIG_MMU */
441
.type __arm1020_setup, #function
444
mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
445
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
447
mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
450
adr r5, arm1020_crval
452
mrc p15, 0, r0, c1, c0 @ get control register v4
455
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
456
orr r0, r0, #0x4000 @ .R.. .... .... ....
459
.size __arm1020_setup, . - __arm1020_setup
463
* .RVI ZFRS BLDP WCAM
464
* .011 1001 ..11 0101
466
.type arm1020_crval, #object
468
crval clear=0x0000593f, mmuset=0x00003935, ucset=0x00001930
471
@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
472
define_processor_functions arm1020, dabort=v4t_early_abort, pabort=legacy_pabort
477
string cpu_arch_name, "armv5t"
478
string cpu_elf_name, "v5"
480
.type cpu_arm1020_name, #object
483
#ifndef CONFIG_CPU_ICACHE_DISABLE
486
#ifndef CONFIG_CPU_DCACHE_DISABLE
488
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
494
#ifndef CONFIG_CPU_BPREDICT_DISABLE
497
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
501
.size cpu_arm1020_name, . - cpu_arm1020_name
505
.section ".proc.info.init", #alloc, #execinstr
507
.type __arm1020_proc_info,#object
509
.long 0x4104a200 @ ARM 1020T (Architecture v5T)
511
.long PMD_TYPE_SECT | \
512
PMD_SECT_AP_WRITE | \
514
.long PMD_TYPE_SECT | \
515
PMD_SECT_AP_WRITE | \
520
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
521
.long cpu_arm1020_name
522
.long arm1020_processor_functions
525
.long arm1020_cache_fns
526
.size __arm1020_proc_info, . - __arm1020_proc_info