1/* 2 * linux/arch/arm/mm/arm926.S: MMU functions for ARM926EJ-S 3 * 4 * Copyright (C) 1999-2001 ARM Limited 5 * Copyright (C) 2000 Deep Blue Solutions Ltd. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * 22 * These are the low level assembler for performing cache and TLB 23 * functions on the arm926. 24 */ 25#include <linux/linkage.h> 26#include <linux/config.h> 27#include <asm/assembler.h> 28#include <asm/constants.h> 29#include <asm/procinfo.h> 30#include <asm/hardware.h> 31 32/* 33 * This is the maximum size of an area which will be invalidated 34 * using the single invalidate entry instructions. Anything larger 35 * than this, and we go for the whole cache. 36 * 37 * This value should be chosen such that we choose the cheapest 38 * alternative. 39 */ 40#define MAX_AREA_SIZE 16384 41 42/* 43 * the cache line size of the I and D cache 44 */ 45#define DCACHELINESIZE 32 46#define ICACHELINESIZE 32 47 48/* 49 * and the page size 50 */ 51#define PAGESIZE 4096 52 53 .text 54 55/* 56 * cpu_arm926_data_abort() 57 * 58 * obtain information about current aborted instruction 59 * Note: we read user space. This means we might cause a data 60 * abort here if the I-TLB and D-TLB aren't seeing the same 61 * picture. Unfortunately, this does happen. We live with it. 62 * 63 * Inputs: 64 * r2 = address of abort 65 * r3 = cpsr of abort 66 * 67 * Returns: 68 * r0 = address of abort 69 * r1 != 0 if writing 70 * r3 = FSR 71 * r4 = corrupted 72 */ 73 .align 5 74ENTRY(cpu_arm926_data_abort) 75 mrc p15, 0, r0, c6, c0, 0 @ get FAR 76 mrc p15, 0, r4, c5, c0, 0 @ get FSR 77 78 tst r3, #1<<24 @ Check for Jbit (NE -> found) 79 movne r3, #-1 @ Mark as writing 80 bne 2f 81 82 tst r3, #1<<5 @ Check for Thumb-bit (NE -> found) 83 ldrneh r1, [r2] @ Read aborted Thumb instruction 84 ldreq r1, [r2] @ Read aborted ARM instruction 85 movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20 86 tsteq r1, r1, lsr #21 @ C = bit 20 87 88 sbc r1, r1, r1 @ r1 = C - 1 892: 90 and r3, r4, #255 91 mov pc, lr 92 93/* 94 * cpu_arm926_check_bugs() 95 */ 96ENTRY(cpu_arm926_check_bugs) 97 mrs ip, cpsr 98 bic ip, ip, #F_BIT 99 msr cpsr, ip 100 mov pc, lr 101 102/* 103 * cpu_arm926_proc_init() 104 */ 105ENTRY(cpu_arm926_proc_init) 106 mov pc, lr 107 108/* 109 * cpu_arm926_proc_fin() 110 */ 111ENTRY(cpu_arm926_proc_fin) 112 stmfd sp!, {lr} 113 mov ip, #F_BIT | I_BIT | SVC_MODE 114 msr cpsr_c, ip 115 bl cpu_arm926_cache_clean_invalidate_all 116 mrc p15, 0, r0, c1, c0, 0 @ ctrl register 117 bic r0, r0, #0x1000 @ ...i............ 118 bic r0, r0, #0x000e @ ............wca. 119 mcr p15, 0, r0, c1, c0, 0 @ disable caches 120 ldmfd sp!, {pc} 121 122/* 123 * cpu_arm926_reset(loc) 124 * 125 * Perform a soft reset of the system. Put the CPU into the 126 * same state as it would be if it had been reset, and branch 127 * to what would be the reset vector. 128 * 129 * loc: location to jump to for soft reset 130 */ 131 .align 5 132ENTRY(cpu_arm926_reset) 133 mov ip, #0 134 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches 135 mcr p15, 0, ip, c7, c10, 4 @ drain WB 136 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 137 mrc p15, 0, ip, c1, c0, 0 @ ctrl register 138 bic ip, ip, #0x000f @ ............wcam 139 bic ip, ip, #0x1100 @ ...i...s........ 140 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 141 mov pc, r0 142 143/* 144 * cpu_arm926_do_idle() 145 */ 146 .align 5 147ENTRY(cpu_arm926_do_idle) 148 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt 149 mov pc, lr 150 151/* ================================= CACHE ================================ */ 152 153 154/* 155 * cpu_arm926_cache_clean_invalidate_all() 156 * 157 * clean and invalidate all cache lines 158 * 159 * Note: 160 * 1. we should preserve r0 at all times 161 */ 162 .align 5 163ENTRY(cpu_arm926_cache_clean_invalidate_all) 164 mov r2, #1 165cpu_arm926_cache_clean_invalidate_all_r2: 166 mov ip, #0 167#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 168 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 169#else 1701: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate 171 bne 1b 172#endif 173 teq r2, #0 174 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 175 mcr p15, 0, ip, c7, c10, 4 @ drain WB 176 mov pc, lr 177 178/* 179 * cpu_arm926_cache_clean_invalidate_range(start, end, flags) 180 * 181 * clean and invalidate all cache lines associated with this area of memory 182 * 183 * This is a little misleading, it is not intended to clean out 184 * the i-cache but to make sure that any data written to the 185 * range is made consistant. This means that when we execute code 186 * in that region, everything works as we expect. 187 * 188 * This generally means writing back data in the Dcache and 189 * write buffer and flushing the Icache over that region 190 * start: Area start address 191 * end: Area end address 192 * flags: nonzero for I cache as well 193 */ 194 .align 5 195ENTRY(cpu_arm926_cache_clean_invalidate_range) 196 bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM 197 sub r3, r1, r0 198 cmp r3, #MAX_AREA_SIZE 199 bhi cpu_arm926_cache_clean_invalidate_all_r2 200 2011: teq r2, #0 202#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 203 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 204 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 205 add r0, r0, #DCACHELINESIZE 206 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 207 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 208 add r0, r0, #DCACHELINESIZE 209#else 210 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 211 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 212 add r0, r0, #DCACHELINESIZE 213 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 214 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 215 add r0, r0, #DCACHELINESIZE 216#endif 217 218 cmp r0, r1 219 blo 1b 220 221 mcr p15, 0, r1, c7, c10, 4 @ drain WB 222 223 mov pc, lr 224 225/* 226 * cpu_arm926_flush_ram_page(page) 227 * 228 * clean and invalidate all cache lines associated with this area of memory 229 * 230 * page: page to clean and invalidate 231 */ 232 .align 5 233ENTRY(cpu_arm926_flush_ram_page) 234 mov r1, #PAGESIZE 235#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 2361: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 237 add r0, r0, #DCACHELINESIZE 238 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 239 add r0, r0, #DCACHELINESIZE 240#else 2411: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 242 add r0, r0, #DCACHELINESIZE 243 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 244 add r0, r0, #DCACHELINESIZE 245#endif 246 subs r1, r1, #2 * DCACHELINESIZE 247 bne 1b 248 mcr p15, 0, r1, c7, c10, 4 @ drain WB 249 mov pc, lr 250 251/* ================================ D-CACHE =============================== */ 252 253/* 254 * cpu_arm926_dcache_invalidate_range(start, end) 255 * 256 * throw away all D-cached data in specified region without an obligation 257 * to write them back. Note however that we must clean the D-cached entries 258 * around the boundaries if the start and/or end address are not cache 259 * aligned. 260 * 261 * start: virtual start address 262 * end: virtual end address 263 */ 264 .align 5 265ENTRY(cpu_arm926_dcache_invalidate_range) 266#ifndef CONFIG_CPU_ARM926_WRITETHROUGH 267 tst r0, #DCACHELINESIZE - 1 268 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 269 tst r1, #DCACHELINESIZE - 1 270 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 271#endif 272 bic r0, r0, #DCACHELINESIZE - 1 2731: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 274 add r0, r0, #DCACHELINESIZE 275 cmp r0, r1 276 blo 1b 277 mov pc, lr 278 279/* 280 * cpu_arm926_dcache_clean_range(start, end) 281 * 282 * For the specified virtual address range, ensure that all caches contain 283 * clean data, such that peripheral accesses to the physical RAM fetch 284 * correct data. 285 * 286 * start: virtual start address 287 * end: virtual end address 288 */ 289 .align 5 290ENTRY(cpu_arm926_dcache_clean_range) 291#ifndef CONFIG_CPU_ARM926_WRITETHROUGH 292 bic r0, r0, #DCACHELINESIZE - 1 293 sub r3, r1, r0 294 cmp r3, #MAX_AREA_SIZE 295 mov r2, #0 296 bhi cpu_arm926_cache_clean_invalidate_all_r2 297 2981: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 299 add r0, r0, #DCACHELINESIZE 300 cmp r0, r1 301 blo 1b 302#endif 303 mcr p15, 0, r2, c7, c10, 4 @ drain WB 304 mov pc, lr 305 306/* 307 * cpu_arm926_dcache_clean_page(page) 308 * 309 * Cleans a single page of dcache so that if we have any future aliased 310 * mappings, they will be consistent at the time that they are created. 311 * 312 * page: virtual address of page to clean from dcache 313 * 314 * Note: 315 * 1. we don't need to flush the write buffer in this case. 316 * 2. we don't invalidate the entries since when we write the page 317 * out to disk, the entries may get reloaded into the cache. 318 */ 319 .align 5 320ENTRY(cpu_arm926_dcache_clean_page) 321#ifndef CONFIG_CPU_ARM926_WRITETHROUGH 322 mov r1, #PAGESIZE 3231: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 324 add r0, r0, #DCACHELINESIZE 325 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 326 add r0, r0, #DCACHELINESIZE 327 subs r1, r1, #2 * DCACHELINESIZE 328 bne 1b 329#endif 330 mov pc, lr 331 332/* 333 * cpu_arm926_dcache_clean_entry(addr) 334 * 335 * Clean the specified entry of any caches such that the MMU 336 * translation fetches will obtain correct data. 337 * 338 * addr: cache-unaligned virtual address 339 */ 340 .align 5 341ENTRY(cpu_arm926_dcache_clean_entry) 342#ifndef CONFIG_CPU_ARM926_WRITETHROUGH 343 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 344#endif 345 mcr p15, 0, r0, c7, c10, 4 @ drain WB 346 mov pc, lr 347 348/* ================================ I-CACHE =============================== */ 349 350/* 351 * cpu_arm926_icache_invalidate_range(start, end) 352 * 353 * This *is not* just icache. It is to make data written to memory 354 * consistent such that instructions fetched from the region are what 355 * we expect. 356 * 357 * This is typically used after we have copied a module into kernel space, 358 * and we're about to start executing code from that module. 359 * 360 * start: virtual start address 361 * end: virtual end address 362 */ 363 .align 5 364ENTRY(cpu_arm926_icache_invalidate_range) 365 bic r0, r0, #DCACHELINESIZE - 1 @ Safety check 366 sub r3, r1, r0 367 cmp r3, #MAX_AREA_SIZE 368 bhi cpu_arm926_cache_clean_invalidate_all_r2 369 3701: mcr p15, 0, r0, c7, c5, 1 @ clean I entries 371 add r0, r0, #DCACHELINESIZE 372 cmp r0, r1 373 blo 1b 374 375 mov r0, #0 376 mcr p15, 0, r0, c7, c10, 4 @ drain WB 377 mov pc, lr 378 379ENTRY(cpu_arm926_icache_invalidate_page) 380 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 381 mov pc, lr 382 383 384/* ================================== TLB ================================= */ 385 386/* 387 * cpu_arm926_tlb_invalidate_all() 388 * 389 * Invalidate all TLB entries 390 */ 391 .align 5 392ENTRY(cpu_arm926_tlb_invalidate_all) 393 mov r0, #0 394 mcr p15, 0, r0, c7, c10, 4 @ drain WB 395 mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D TLBs 396 mov pc, lr 397 398/* 399 * cpu_arm926_tlb_invalidate_range(start, end) 400 * 401 * invalidate TLB entries covering the specified range 402 * 403 * start: range start address 404 * end: range end address 405 */ 406 .align 5 407ENTRY(cpu_arm926_tlb_invalidate_range) 408 sub r3, r1, r0 409 cmp r3, #256 * PAGESIZE @ arbitary, should be tuned 410 bhi cpu_arm926_tlb_invalidate_all 411 412 mov r3, #0 413 mcr p15, 0, r3, c7, c10, 4 @ drain WB 414 415 bic r0, r0, #(PAGESIZE - 1) & 0x00ff 416 bic r0, r0, #(PAGESIZE - 1) & 0xff00 417 4181: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry 419 mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry 420 add r0, r0, #PAGESIZE 421 cmp r0, r1 422 blo 1b 423 mov pc, lr 424 425/* 426 * cpu_arm926_tlb_invalidate_page(page, flags) 427 * 428 * invalidate the TLB entries for the specified page. 429 * 430 * page: page to invalidate 431 * flags: non-zero if we include the I TLB 432 */ 433 .align 5 434ENTRY(cpu_arm926_tlb_invalidate_page) 435 mov r3, #0 436 mcr p15, 0, r3, c7, c10, 4 @ drain WB 437 teq r1, #0 438 mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry 439 mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry 440 mov pc, lr 441 442/* =============================== PageTable ============================== */ 443 444/* 445 * cpu_arm926_set_pgd(pgd) 446 * 447 * Set the translation base pointer to be as described by pgd. 448 * 449 * pgd: new page tables 450 */ 451 .align 5 452ENTRY(cpu_arm926_set_pgd) 453 mov ip, #0 454#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 455 /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ 456 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 457#else 458@ && 'Clean & Invalidate whole DCache' 4591: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate 460 bne 1b 461#endif 462 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 463 mcr p15, 0, ip, c7, c10, 4 @ drain WB 464 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer 465 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 466 mov pc, lr 467 468/* 469 * cpu_arm926_set_pmd(pmdp, pmd) 470 * 471 * Set a level 1 translation table entry, and clean it out of 472 * any caches such that the MMUs can load it correctly. 473 * 474 * pmdp: pointer to PMD entry 475 * pmd: PMD value to store 476 */ 477 .align 5 478ENTRY(cpu_arm926_set_pmd) 479#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 480 eor r2, r1, #0x0a @ C & Section 481 tst r2, #0x0b 482 biceq r1, r1, #4 @ clear bufferable bit 483#endif 484 str r1, [r0] 485#ifndef CONFIG_CPU_ARM926_WRITETHROUGH 486 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 487#endif 488 mcr p15, 0, r0, c7, c10, 4 @ drain WB 489 mov pc, lr 490 491/* 492 * cpu_arm926_set_pte(ptep, pte) 493 * 494 * Set a PTE and flush it out 495 */ 496 .align 5 497ENTRY(cpu_arm926_set_pte) 498 str r1, [r0], #-1024 @ linux version 499 500 eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY 501 502 bic r2, r1, #0xff0 503 bic r2, r2, #3 504 orr r2, r2, #HPTE_TYPE_SMALL 505 506 tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? 507 orrne r2, r2, #HPTE_AP_READ 508 509 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? 510 orreq r2, r2, #HPTE_AP_WRITE 511 512 tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? 513 movne r2, #0 514 515#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 516 eor r3, r2, #0x0a @ C & small page? 517 tst r3, #0x0b 518 biceq r2, r2, #4 519#endif 520 str r2, [r0] @ hardware version 521 mov r0, r0 522#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 523 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 524#endif 525 mcr p15, 0, r0, c7, c10, 4 @ drain WB 526 mov pc, lr 527 528 529ENTRY(cpu_arm926_name) 530 .ascii "ARM926EJ-S" 531#ifndef CONFIG_CPU_ICACHE_DISABLE 532 .ascii "i" 533#endif 534#ifndef CONFIG_CPU_DCACHE_DISABLE 535 .ascii "d" 536#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 537 .ascii "(wt)" 538#else 539 .ascii "(wb)" 540#endif 541#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 542 .ascii "RR" 543#endif 544#endif 545 .ascii "\0" 546 .align 547 548 .section ".text.init", #alloc, #execinstr 549 550__arm926_setup: 551 mov r0, #0 552 mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 553 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 554 mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 555 mcr p15, 0, r4, c2, c0 @ load page table pointer 556 557 558#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 559 mov r0, #4 @ disable write-back on caches explicitly 560 mcr p15, 7, r0, c15, c0, 0 561#endif 562 563 mov r0, #0x1f @ Domains 0, 1 = client 564 mcr p15, 0, r0, c3, c0 @ load domain access register 565 mrc p15, 0, r0, c1, c0 @ get control register v4 566/* 567 * Clear out 'unwanted' bits (then put them in if we need them) 568 */ 569 @ VI ZFRS BLDP WCAM 570 bic r0, r0, #0x0e00 571 bic r0, r0, #0x0002 572 bic r0, r0, #0x000c 573 bic r0, r0, #0x1000 @ ...0 000. .... 000. 574/* 575 * Turn on what we want 576 */ 577 orr r0, r0, #0x0031 578 orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 579 580#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 581 orr r0, r0, #0x4000 @ .1.. .... .... .... 582#endif 583#ifndef CONFIG_CPU_DCACHE_DISABLE 584 orr r0, r0, #0x0004 @ .... .... .... .1.. 585#endif 586#ifndef CONFIG_CPU_ICACHE_DISABLE 587 orr r0, r0, #0x1000 @ ...1 .... .... .... 588#endif 589 mov pc, lr 590 591 .text 592 593/* 594 * Purpose : Function pointers used to access above functions - all calls 595 * come through these 596 */ 597 .type arm926_processor_functions, #object 598arm926_processor_functions: 599 .word cpu_arm926_data_abort 600 .word cpu_arm926_check_bugs 601 .word cpu_arm926_proc_init 602 .word cpu_arm926_proc_fin 603 .word cpu_arm926_reset 604 .word cpu_arm926_do_idle 605 606 /* cache */ 607 .word cpu_arm926_cache_clean_invalidate_all 608 .word cpu_arm926_cache_clean_invalidate_range 609 .word cpu_arm926_flush_ram_page 610 611 /* dcache */ 612 .word cpu_arm926_dcache_invalidate_range 613 .word cpu_arm926_dcache_clean_range 614 .word cpu_arm926_dcache_clean_page 615 .word cpu_arm926_dcache_clean_entry 616 617 /* icache */ 618 .word cpu_arm926_icache_invalidate_range 619 .word cpu_arm926_icache_invalidate_page 620 621 /* tlb */ 622 .word cpu_arm926_tlb_invalidate_all 623 .word cpu_arm926_tlb_invalidate_range 624 .word cpu_arm926_tlb_invalidate_page 625 626 /* pgtable */ 627 .word cpu_arm926_set_pgd 628 .word cpu_arm926_set_pmd 629 .word cpu_arm926_set_pte 630 .size arm926_processor_functions, . - arm926_processor_functions 631 632 .type cpu_arm926_info, #object 633cpu_arm926_info: 634 .long 0 635 .long cpu_arm926_name 636 .size cpu_arm926_info, . - cpu_arm926_info 637 638 .type cpu_arch_name, #object 639cpu_arch_name: 640 .asciz "armv5EJ" 641 .size cpu_arch_name, . - cpu_arch_name 642 643 .type cpu_elf_name, #object 644cpu_elf_name: 645 .asciz "v5EJ" 646 .size cpu_elf_name, . - cpu_elf_name 647 .align 648 649 .section ".proc.info", #alloc, #execinstr 650 651 .type __arm926_proc_info,#object 652__arm926_proc_info: 653 .long 0x41009260 654 .long 0xff00fff0 655 .long 0x00000c1e @ mmuflags 656 b __arm926_setup 657 .long cpu_arch_name 658 .long cpu_elf_name 659 .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \ 660 HWCAP_FAST_MULT 661 .long cpu_arm926_info 662 .long arm926_processor_functions 663 .size __arm926_proc_info, . - __arm926_proc_info 664