1/* 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> 14#include <asm/hwcap.h> 15#include <asm/pgtable-hwdef.h> 16#include <asm/pgtable.h> 17#include <asm/ptrace.h> 18#include "proc-macros.S" 19 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) 40 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 44 mov pc, lr 45 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/* 140 * flush_kern_dcache_area(void *addr, size_t size) 141 * 142 * Ensure no D cache aliasing occurs, either with itself or 143 * the I cache 144 * 145 * - addr - kernel address 146 * - size - region size 147 */ 148ENTRY(arm940_flush_kern_dcache_area) 149 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 */ 170arm940_dma_inv_range: 171 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 */ 191arm940_dma_clean_range: 192ENTRY(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 223 mcr p15, 0, r3, c7, c6, 2 @ invalidate D entry 224#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 232/* 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 256ENTRY(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 262 .long arm940_flush_kern_dcache_area 263 .long arm940_dma_map_area 264 .long arm940_dma_unmap_area 265 .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) 345 .word nommu_early_abort 346 .word legacy_pabort 347 .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