1/* 2 * linux/arch/arm/mm/proc-arm2,3.S 3 * 4 * Copyright (C) 1997-1999 Russell King 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 * MMU functions for ARM2,3 11 * 12 * These are the low level assembler for performing cache 13 * and memory functions on ARM2, ARM250 and ARM3 processors. 14 */ 15#include <linux/linkage.h> 16#include <asm/assembler.h> 17#include <asm/constants.h> 18#include <asm/procinfo.h> 19 20/* 21 * MEMC workhorse code. It's both a horse which things it's a pig. 22 */ 23/* 24 * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr) 25 * Params : pgd Page tables/MEMC mapping 26 * : phys_pte physical address, or PTE 27 * : addr virtual address 28 */ 29ENTRY(cpu_memc_update_entry) 30 tst r1, #PAGE_PRESENT @ is the page present 31 orreq r1, r1, #PAGE_OLD | PAGE_CLEAN 32 moveq r2, #0x01f00000 33 mov r3, r1, lsr #13 @ convert to physical page nr 34 and r3, r3, #0x3fc 35 adr ip, memc_phys_table_32 36 ldr r3, [ip, r3] 37 tst r1, #PAGE_OLD | PAGE_NOT_USER 38 biceq r3, r3, #0x200 39 tsteq r1, #PAGE_READONLY | PAGE_CLEAN 40 biceq r3, r3, #0x300 41 mov r2, r2, lsr #15 @ virtual -> nr 42 orr r3, r3, r2, lsl #15 43 and r2, r2, #0x300 44 orr r3, r3, r2, lsl #2 45 and r2, r3, #255 46 sub r0, r0, #256 * 4 47 str r3, [r0, r2, lsl #2] 48 strb r3, [r3] 49 movs pc, lr 50/* 51 * Params : r0 = preserved 52 * : r1 = memc table base (preserved) 53 * : r2 = page table entry 54 * : r3 = preserved 55 * : r4 = unused 56 * : r5 = memc physical address translation table 57 * : ip = virtual address (preserved) 58 */ 59update_pte: 60 mov r4, r2, lsr #13 61 and r4, r4, #0x3fc 62 ldr r4, [r5, r4] @ covert to MEMC page 63 64 tst r2, #PAGE_OLD | PAGE_NOT_USER @ check for MEMC read 65 biceq r4, r4, #0x200 66 tsteq r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write 67 biceq r4, r4, #0x300 68 69 orr r4, r4, ip 70 and r2, ip, #0x01800000 71 orr r4, r4, r2, lsr #13 72 73 and r2, r4, #255 74 str r4, [r1, r2, lsl #2] 75 movs pc, lr 76 77/* 78 * Params : r0 = preserved 79 * : r1 = memc table base (preserved) 80 * : r2 = page table base 81 * : r3 = preserved 82 * : r4 = unused 83 * : r5 = memc physical address translation table 84 * : ip = virtual address (updated) 85 */ 86update_pte_table: 87 stmfd sp!, {r0, lr} 88 bic r0, r2, #3 891: ldr r2, [r0], #4 @ get entry 90 tst r2, #PAGE_PRESENT @ page present 91 blne update_pte @ process pte 92 add ip, ip, #32768 @ increment virt addr 93 ldr r2, [r0], #4 @ get entry 94 tst r2, #PAGE_PRESENT @ page present 95 blne update_pte @ process pte 96 add ip, ip, #32768 @ increment virt addr 97 ldr r2, [r0], #4 @ get entry 98 tst r2, #PAGE_PRESENT @ page present 99 blne update_pte @ process pte 100 add ip, ip, #32768 @ increment virt addr 101 ldr r2, [r0], #4 @ get entry 102 tst r2, #PAGE_PRESENT @ page present 103 blne update_pte @ process pte 104 add ip, ip, #32768 @ increment virt addr 105 tst ip, #32768 * 31 @ finished? 106 bne 1b 107 ldmfd sp!, {r0, pc}^ 108 109/* 110 * Function: cpu_memc_update_all(pgd_t *pgd) 111 * Params : pgd Page tables/MEMC mapping 112 * Notes : this is optimised for 32k pages 113 */ 114ENTRY(cpu_memc_update_all) 115 stmfd sp!, {r4, r5, lr} 116 bl clear_tables 117 sub r1, r0, #256 * 4 @ start of MEMC tables 118 adr r5, memc_phys_table_32 @ Convert to logical page number 119 mov ip, #0 @ virtual address 1201: ldmia r0!, {r2, r3} 121 tst r2, #PAGE_PRESENT 122 addeq ip, ip, #1048576 123 blne update_pte_table 124 mov r2, r3 125 tst r2, #PAGE_PRESENT 126 addeq ip, ip, #1048576 127 blne update_pte_table 128 teq ip, #32 * 1048576 129 bne 1b 130 ldmfd sp!, {r4, r5, pc}^ 131 132/* 133 * Build the table to map from physical page number to memc page number 134 */ 135 .type memc_phys_table_32, #object 136memc_phys_table_32: 137 .irp b7, 0x00, 0x80 138 .irp b6, 0x00, 0x02 139 .irp b5, 0x00, 0x04 140 .irp b4, 0x00, 0x01 141 142 .irp b3, 0x00, 0x40 143 .irp b2, 0x00, 0x20 144 .irp b1, 0x00, 0x10 145 .irp b0, 0x00, 0x08 146 .long 0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0 147 .endr 148 .endr 149 .endr 150 .endr 151 152 .endr 153 .endr 154 .endr 155 .endr 156 .size memc_phys_table_32, . - memc_phys_table_32 157 158/* 159 * helper for cpu_memc_update_all, this clears out all 160 * mappings, setting them close to the top of memory, 161 * and inaccessible (0x01f00000). 162 * Params : r0 = page table pointer 163 */ 164clear_tables: ldr r1, _arm3_set_pgd - 4 165 ldr r2, [r1] 166 sub r1, r0, #256 * 4 @ start of MEMC tables 167 add r2, r1, r2, lsl #2 @ end of tables 168 mov r3, #0x03f00000 @ Default mapping (null mapping) 169 orr r3, r3, #0x00000f00 170 orr r4, r3, #1 171 orr r5, r3, #2 172 orr ip, r3, #3 1731: stmia r1!, {r3, r4, r5, ip} 174 add r3, r3, #4 175 add r4, r4, #4 176 add r5, r5, #4 177 add ip, ip, #4 178 stmia r1!, {r3, r4, r5, ip} 179 add r3, r3, #4 180 add r4, r4, #4 181 add r5, r5, #4 182 add ip, ip, #4 183 teq r1, r2 184 bne 1b 185 mov pc, lr 186 187/* 188 * Function: *_set_pgd(pgd_t *pgd) 189 * Params : pgd New page tables/MEMC mapping 190 * Purpose : update MEMC hardware with new mapping 191 */ 192 .word SYMBOL_NAME(page_nr) 193_arm3_set_pgd: mcr p15, 0, r1, c1, c0, 0 @ flush cache 194_arm2_set_pgd: stmfd sp!, {lr} 195 ldr r1, _arm3_set_pgd - 4 196 ldr r2, [r1] 197 sub r0, r0, #256 * 4 @ start of MEMC tables 198 add r1, r0, r2, lsl #2 @ end of tables 1991: ldmia r0!, {r2, r3, ip, lr} 200 strb r2, [r2] 201 strb r3, [r3] 202 strb ip, [ip] 203 strb lr, [lr] 204 ldmia r0!, {r2, r3, ip, lr} 205 strb r2, [r2] 206 strb r3, [r3] 207 strb ip, [ip] 208 strb lr, [lr] 209 teq r0, r1 210 bne 1b 211 ldmfd sp!, {pc}^ 212 213/* 214 * Function: *_proc_init (void) 215 * Purpose : Initialise the cache control registers 216 */ 217_arm3_proc_init: 218 mov r0, #0x001f0000 219 orr r0, r0, #0x0000ff00 220 orr r0, r0, #0x000000ff 221 mcr p15, 0, r0, c3, c0 @ ARM3 Cacheable 222 mcr p15, 0, r0, c4, c0 @ ARM3 Updateable 223 mov r0, #0 224 mcr p15, 0, r0, c5, c0 @ ARM3 Disruptive 225 mcr p15, 0, r0, c1, c0 @ ARM3 Flush 226 mov r0, #3 227 mcr p15, 0, r0, c2, c0 @ ARM3 Control 228_arm2_proc_init: 229 movs pc, lr 230 231/* 232 * Function: *_proc_fin (void) 233 * Purpose : Finalise processor (disable caches) 234 */ 235_arm3_proc_fin: mov r0, #2 236 mcr p15, 0, r0, c2, c0 237_arm2_proc_fin: orrs pc, lr, #I_BIT|F_BIT 238 239/* 240 * Function: *_xchg_1 (int new, volatile void *ptr) 241 * Params : new New value to store at... 242 * : ptr pointer to byte-wide location 243 * Purpose : Performs an exchange operation 244 * Returns : Original byte data at 'ptr' 245 */ 246_arm2_xchg_1: mov r2, pc 247 orr r2, r2, #I_BIT 248 teqp r2, #0 249 ldrb r2, [r1] 250 strb r0, [r1] 251 mov r0, r2 252 movs pc, lr 253 254_arm3_xchg_1: swpb r0, r0, [r1] 255 movs pc, lr 256 257/* 258 * Function: *_xchg_4 (int new, volatile void *ptr) 259 * Params : new New value to store at... 260 * : ptr pointer to word-wide location 261 * Purpose : Performs an exchange operation 262 * Returns : Original word data at 'ptr' 263 */ 264_arm2_xchg_4: mov r2, pc 265 orr r2, r2, #I_BIT 266 teqp r2, #0 267 ldr r2, [r1] 268 str r0, [r1] 269 mov r0, r2 270 movs pc, lr 271 272_arm3_xchg_4: swp r0, r0, [r1] 273 movs pc, lr 274 275_arm2_3_check_bugs: 276 bics pc, lr, #0x04000000 @ Clear FIQ disable bit 277 278_arm2_name: .asciz "ARM 2" 279_arm250_name: .asciz "ARM 250" 280_arm3_name: .asciz "ARM 3" 281 282 .section ".text.init", #alloc, #execinstr 283/* 284 * Purpose : Function pointers used to access above functions - all calls 285 * come through these 286 */ 287 .globl SYMBOL_NAME(arm2_processor_functions) 288SYMBOL_NAME(arm2_processor_functions): 289 .word _arm2_3_check_bugs 290 .word _arm2_proc_init 291 .word _arm2_proc_fin 292 .word _arm2_set_pgd 293 .word _arm2_xchg_1 294 .word _arm2_xchg_4 295 296cpu_arm2_info: 297 .long 0 298 .long _arm2_name 299 300 .globl SYMBOL_NAME(arm250_processor_functions) 301SYMBOL_NAME(arm250_processor_functions): 302 .word _arm2_3_check_bugs 303 .word _arm2_proc_init 304 .word _arm2_proc_fin 305 .word _arm2_set_pgd 306 .word _arm3_xchg_1 307 .word _arm3_xchg_4 308 309cpu_arm250_info: 310 .long 0 311 .long _arm250_name 312 313 .globl SYMBOL_NAME(arm3_processor_functions) 314SYMBOL_NAME(arm3_processor_functions): 315 .word _arm2_3_check_bugs 316 .word _arm3_proc_init 317 .word _arm3_proc_fin 318 .word _arm3_set_pgd 319 .word _arm3_xchg_1 320 .word _arm3_xchg_4 321 322cpu_arm3_info: 323 .long 0 324 .long _arm3_name 325 326arm2_arch_name: .asciz "armv1" 327arm3_arch_name: .asciz "armv2" 328arm2_elf_name: .asciz "v1" 329arm3_elf_name: .asciz "v2" 330 .align 331 332 .section ".proc.info", #alloc, #execinstr 333 334 .long 0x41560200 335 .long 0xfffffff0 336 .long 0 337 mov pc, lr 338 .long arm2_arch_name 339 .long arm2_elf_name 340 .long 0 341 .long cpu_arm2_info 342 .long SYMBOL_NAME(arm2_processor_functions) 343 344 .long 0x41560250 345 .long 0xfffffff0 346 .long 0 347 mov pc, lr 348 .long arm3_arch_name 349 .long arm3_elf_name 350 .long 0 351 .long cpu_arm250_info 352 .long SYMBOL_NAME(arm250_processor_functions) 353 354 .long 0x41560300 355 .long 0xfffffff0 356 .long 0 357 mov pc, lr 358 .long arm3_arch_name 359 .long arm3_elf_name 360 .long 0 361 .long cpu_arm3_info 362 .long SYMBOL_NAME(arm3_processor_functions) 363 364

