1/* 2 * linux/arch/arm/mm/arm946.S: utility functions for ARM946E-S 3 * 4 * Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com) 5 * 6 * (Many of cache codes are from proc-arm926.S) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13#include <linux/linkage.h> 14#include <linux/init.h> 15#include <asm/assembler.h> 16#include <asm/hwcap.h> 17#include <asm/pgtable-hwdef.h> 18#include <asm/pgtable.h> 19#include <asm/ptrace.h> 20#include "proc-macros.S" 21 22/* 23 * ARM946E-S is synthesizable to have 0KB to 1MB sized D-Cache, 24 * comprising 256 lines of 32 bytes (8 words). 25 */ 26#define CACHE_DSIZE (CONFIG_CPU_DCACHE_SIZE) /* typically 8KB. */ 27#define CACHE_DLINESIZE 32 /* fixed */ 28#define CACHE_DSEGMENTS 4 /* fixed */ 29#define CACHE_DENTRIES (CACHE_DSIZE / CACHE_DSEGMENTS / CACHE_DLINESIZE) 30#define CACHE_DLIMIT (CACHE_DSIZE * 4) /* benchmark needed */ 31 32 .text 33/* 34 * cpu_arm946_proc_init() 35 * cpu_arm946_switch_mm() 36 * 37 * These are not required. 38 */ 39ENTRY(cpu_arm946_proc_init) 40ENTRY(cpu_arm946_switch_mm) 41 ret lr 42 43/* 44 * cpu_arm946_proc_fin() 45 */ 46ENTRY(cpu_arm946_proc_fin) 47 mrc p15, 0, r0, c1, c0, 0 @ ctrl register 48 bic r0, r0, #0x00001000 @ i-cache 49 bic r0, r0, #0x00000004 @ d-cache 50 mcr p15, 0, r0, c1, c0, 0 @ disable caches 51 ret lr 52 53/* 54 * cpu_arm946_reset(loc) 55 * Params : r0 = address to jump to 56 * Notes : This sets up everything for a reset 57 */ 58 .pushsection .idmap.text, "ax" 59ENTRY(cpu_arm946_reset) 60 mov ip, #0 61 mcr p15, 0, ip, c7, c5, 0 @ flush I cache 62 mcr p15, 0, ip, c7, c6, 0 @ flush D cache 63 mcr p15, 0, ip, c7, c10, 4 @ drain WB 64 mrc p15, 0, ip, c1, c0, 0 @ ctrl register 65 bic ip, ip, #0x00000005 @ .............c.p 66 bic ip, ip, #0x00001000 @ i-cache 67 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 68 ret r0 69ENDPROC(cpu_arm946_reset) 70 .popsection 71 72/* 73 * cpu_arm946_do_idle() 74 */ 75 .align 5 76ENTRY(cpu_arm946_do_idle) 77 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt 78 ret lr 79 80/* 81 * flush_icache_all() 82 * 83 * Unconditionally clean and invalidate the entire icache. 84 */ 85ENTRY(arm946_flush_icache_all) 86 mov r0, #0 87 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 88 ret lr 89ENDPROC(arm946_flush_icache_all) 90 91/* 92 * flush_user_cache_all() 93 */ 94ENTRY(arm946_flush_user_cache_all) 95 /* FALLTHROUGH */ 96 97/* 98 * flush_kern_cache_all() 99 * 100 * Clean and invalidate the entire cache. 101 */ 102ENTRY(arm946_flush_kern_cache_all) 103 mov r2, #VM_EXEC 104 mov ip, #0 105__flush_whole_cache: 106#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 107 mcr p15, 0, ip, c7, c6, 0 @ flush D cache 108#else 109 mov r1, #(CACHE_DSEGMENTS - 1) << 29 @ 4 segments 1101: orr r3, r1, #(CACHE_DENTRIES - 1) << 4 @ n entries 1112: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index 112 subs r3, r3, #1 << 4 113 bcs 2b @ entries n to 0 114 subs r1, r1, #1 << 29 115 bcs 1b @ segments 3 to 0 116#endif 117 tst r2, #VM_EXEC 118 mcrne p15, 0, ip, c7, c5, 0 @ flush I cache 119 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 120 ret lr 121 122/* 123 * flush_user_cache_range(start, end, flags) 124 * 125 * Clean and invalidate a range of cache entries in the 126 * specified address range. 127 * 128 * - start - start address (inclusive) 129 * - end - end address (exclusive) 130 * - flags - vm_flags describing address space 131 * (same as arm926) 132 */ 133ENTRY(arm946_flush_user_cache_range) 134 mov ip, #0 135 sub r3, r1, r0 @ calculate total size 136 cmp r3, #CACHE_DLIMIT 137 bhs __flush_whole_cache 138 1391: tst r2, #VM_EXEC 140#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 141 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 142 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 143 add r0, r0, #CACHE_DLINESIZE 144 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 145 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 146 add r0, r0, #CACHE_DLINESIZE 147#else 148 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 149 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 150 add r0, r0, #CACHE_DLINESIZE 151 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 152 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 153 add r0, r0, #CACHE_DLINESIZE 154#endif 155 cmp r0, r1 156 blo 1b 157 tst r2, #VM_EXEC 158 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 159 ret lr 160 161/* 162 * coherent_kern_range(start, end) 163 * 164 * Ensure coherency between the Icache and the Dcache in the 165 * region described by start, end. If you have non-snooping 166 * Harvard caches, you need to implement this function. 167 * 168 * - start - virtual start address 169 * - end - virtual end address 170 */ 171ENTRY(arm946_coherent_kern_range) 172 /* FALLTHROUGH */ 173 174/* 175 * coherent_user_range(start, end) 176 * 177 * Ensure coherency between the Icache and the Dcache in the 178 * region described by start, end. If you have non-snooping 179 * Harvard caches, you need to implement this function. 180 * 181 * - start - virtual start address 182 * - end - virtual end address 183 * (same as arm926) 184 */ 185ENTRY(arm946_coherent_user_range) 186 bic r0, r0, #CACHE_DLINESIZE - 1 1871: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 188 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 189 add r0, r0, #CACHE_DLINESIZE 190 cmp r0, r1 191 blo 1b 192 mcr p15, 0, r0, c7, c10, 4 @ drain WB 193 mov r0, #0 194 ret lr 195 196/* 197 * flush_kern_dcache_area(void *addr, size_t size) 198 * 199 * Ensure no D cache aliasing occurs, either with itself or 200 * the I cache 201 * 202 * - addr - kernel address 203 * - size - region size 204 * (same as arm926) 205 */ 206ENTRY(arm946_flush_kern_dcache_area) 207 add r1, r0, r1 2081: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 209 add r0, r0, #CACHE_DLINESIZE 210 cmp r0, r1 211 blo 1b 212 mov r0, #0 213 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 214 mcr p15, 0, r0, c7, c10, 4 @ drain WB 215 ret lr 216 217/* 218 * dma_inv_range(start, end) 219 * 220 * Invalidate (discard) the specified virtual address range. 221 * May not write back any entries. If 'start' or 'end' 222 * are not cache line aligned, those lines must be written 223 * back. 224 * 225 * - start - virtual start address 226 * - end - virtual end address 227 * (same as arm926) 228 */ 229arm946_dma_inv_range: 230#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 231 tst r0, #CACHE_DLINESIZE - 1 232 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 233 tst r1, #CACHE_DLINESIZE - 1 234 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 235#endif 236 bic r0, r0, #CACHE_DLINESIZE - 1 2371: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 238 add r0, r0, #CACHE_DLINESIZE 239 cmp r0, r1 240 blo 1b 241 mcr p15, 0, r0, c7, c10, 4 @ drain WB 242 ret lr 243 244/* 245 * dma_clean_range(start, end) 246 * 247 * Clean the specified virtual address range. 248 * 249 * - start - virtual start address 250 * - end - virtual end address 251 * 252 * (same as arm926) 253 */ 254arm946_dma_clean_range: 255#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 256 bic r0, r0, #CACHE_DLINESIZE - 1 2571: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 258 add r0, r0, #CACHE_DLINESIZE 259 cmp r0, r1 260 blo 1b 261#endif 262 mcr p15, 0, r0, c7, c10, 4 @ drain WB 263 ret lr 264 265/* 266 * dma_flush_range(start, end) 267 * 268 * Clean and invalidate the specified virtual address range. 269 * 270 * - start - virtual start address 271 * - end - virtual end address 272 * 273 * (same as arm926) 274 */ 275ENTRY(arm946_dma_flush_range) 276 bic r0, r0, #CACHE_DLINESIZE - 1 2771: 278#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 279 mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 280#else 281 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 282#endif 283 add r0, r0, #CACHE_DLINESIZE 284 cmp r0, r1 285 blo 1b 286 mcr p15, 0, r0, c7, c10, 4 @ drain WB 287 ret lr 288 289/* 290 * dma_map_area(start, size, dir) 291 * - start - kernel virtual start address 292 * - size - size of region 293 * - dir - DMA direction 294 */ 295ENTRY(arm946_dma_map_area) 296 add r1, r1, r0 297 cmp r2, #DMA_TO_DEVICE 298 beq arm946_dma_clean_range 299 bcs arm946_dma_inv_range 300 b arm946_dma_flush_range 301ENDPROC(arm946_dma_map_area) 302 303/* 304 * dma_unmap_area(start, size, dir) 305 * - start - kernel virtual start address 306 * - size - size of region 307 * - dir - DMA direction 308 */ 309ENTRY(arm946_dma_unmap_area) 310 ret lr 311ENDPROC(arm946_dma_unmap_area) 312 313 .globl arm946_flush_kern_cache_louis 314 .equ arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all 315 316 @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 317 define_cache_functions arm946 318 319ENTRY(cpu_arm946_dcache_clean_area) 320#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 3211: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 322 add r0, r0, #CACHE_DLINESIZE 323 subs r1, r1, #CACHE_DLINESIZE 324 bhi 1b 325#endif 326 mcr p15, 0, r0, c7, c10, 4 @ drain WB 327 ret lr 328 329 .type __arm946_setup, #function 330__arm946_setup: 331 mov r0, #0 332 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 333 mcr p15, 0, r0, c7, c6, 0 @ invalidate D cache 334 mcr p15, 0, r0, c7, c10, 4 @ drain WB 335 336 mcr p15, 0, r0, c6, c3, 0 @ disable memory region 3~7 337 mcr p15, 0, r0, c6, c4, 0 338 mcr p15, 0, r0, c6, c5, 0 339 mcr p15, 0, r0, c6, c6, 0 340 mcr p15, 0, r0, c6, c7, 0 341 342 mov r0, #0x0000003F @ base = 0, size = 4GB 343 mcr p15, 0, r0, c6, c0, 0 @ set region 0, default 344 345 ldr r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM 346 ldr r1, =(CONFIG_DRAM_SIZE >> 12) @ size of RAM (must be >= 4KB) 347 mov r2, #10 @ 11 is the minimum (4KB) 3481: add r2, r2, #1 @ area size *= 2 349 mov r1, r1, lsr #1 350 bne 1b @ count not zero r-shift 351 orr r0, r0, r2, lsl #1 @ the region register value 352 orr r0, r0, #1 @ set enable bit 353 mcr p15, 0, r0, c6, c1, 0 @ set region 1, RAM 354 355 ldr r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH 356 ldr r1, =(CONFIG_FLASH_SIZE >> 12) @ size of FLASH (must be >= 4KB) 357 mov r2, #10 @ 11 is the minimum (4KB) 3581: add r2, r2, #1 @ area size *= 2 359 mov r1, r1, lsr #1 360 bne 1b @ count not zero r-shift 361 orr r0, r0, r2, lsl #1 @ the region register value 362 orr r0, r0, #1 @ set enable bit 363 mcr p15, 0, r0, c6, c2, 0 @ set region 2, ROM/FLASH 364 365 mov r0, #0x06 366 mcr p15, 0, r0, c2, c0, 0 @ region 1,2 d-cacheable 367 mcr p15, 0, r0, c2, c0, 1 @ region 1,2 i-cacheable 368#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 369 mov r0, #0x00 @ disable whole write buffer 370#else 371 mov r0, #0x02 @ region 1 write bufferred 372#endif 373 mcr p15, 0, r0, c3, c0, 0 374 375/* 376 * Access Permission Settings for future permission control by PU. 377 * 378 * priv. user 379 * region 0 (whole) rw -- : b0001 380 * region 1 (RAM) rw rw : b0011 381 * region 2 (FLASH) rw r- : b0010 382 * region 3~7 (none) -- -- : b0000 383 */ 384 mov r0, #0x00000031 385 orr r0, r0, #0x00000200 386 mcr p15, 0, r0, c5, c0, 2 @ set data access permission 387 mcr p15, 0, r0, c5, c0, 3 @ set inst. access permission 388 389 mrc p15, 0, r0, c1, c0 @ get control register 390 orr r0, r0, #0x00001000 @ I-cache 391 orr r0, r0, #0x00000005 @ MPU/D-cache 392#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 393 orr r0, r0, #0x00004000 @ .1.. .... .... .... 394#endif 395 ret lr 396 397 .size __arm946_setup, . - __arm946_setup 398 399 __INITDATA 400 401 @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) 402 define_processor_functions arm946, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1 403 404 .section ".rodata" 405 406 string cpu_arch_name, "armv5te" 407 string cpu_elf_name, "v5t" 408 string cpu_arm946_name, "ARM946E-S" 409 410 .align 411 412 .section ".proc.info.init", #alloc, #execinstr 413 .type __arm946_proc_info,#object 414__arm946_proc_info: 415 .long 0x41009460 416 .long 0xff00fff0 417 .long 0 418 .long 0 419 b __arm946_setup 420 .long cpu_arch_name 421 .long cpu_elf_name 422 .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB 423 .long cpu_arm946_name 424 .long arm946_processor_functions 425 .long 0 426 .long 0 427 .long arm946_cache_fns 428 .size __arm946_proc_info, . - __arm946_proc_info 429 430