OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [arm/] [mm/] [proc-arm2,3.S] - Rev 1765

Compare with Previous | Blame | View Log

/*
 *  linux/arch/arm/mm/proc-arm2,3.S
 *
 *  Copyright (C) 1997-1999 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  MMU functions for ARM2,3
 *
 *  These are the low level assembler for performing cache
 *  and memory functions on ARM2, ARM250 and ARM3 processors.
 */
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/constants.h>
#include <asm/procinfo.h>

/*
 * MEMC workhorse code.  It's both a horse which things it's a pig.
 */
/*
 * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr)
 * Params  : pgd        Page tables/MEMC mapping
 *         : phys_pte   physical address, or PTE
 *         : addr       virtual address
 */
ENTRY(cpu_memc_update_entry)
                tst     r1, #PAGE_PRESENT               @ is the page present
                orreq   r1, r1, #PAGE_OLD | PAGE_CLEAN
                moveq   r2, #0x01f00000
                mov     r3, r1, lsr #13                 @ convert to physical page nr
                and     r3, r3, #0x3fc
                adr     ip, memc_phys_table_32
                ldr     r3, [ip, r3]
                tst     r1, #PAGE_OLD | PAGE_NOT_USER
                biceq   r3, r3, #0x200
                tsteq   r1, #PAGE_READONLY | PAGE_CLEAN
                biceq   r3, r3, #0x300
                mov     r2, r2, lsr #15                 @ virtual -> nr
                orr     r3, r3, r2, lsl #15
                and     r2, r2, #0x300
                orr     r3, r3, r2, lsl #2
                and     r2, r3, #255
                sub     r0, r0, #256 * 4
                str     r3, [r0, r2, lsl #2]
                strb    r3, [r3]
                movs    pc, lr
/*
 * Params  : r0 = preserved
 *         : r1 = memc table base (preserved)
 *         : r2 = page table entry
 *         : r3 = preserved
 *         : r4 = unused
 *         : r5 = memc physical address translation table
 *         : ip = virtual address (preserved)
 */
update_pte:
                mov     r4, r2, lsr #13
                and     r4, r4, #0x3fc
                ldr     r4, [r5, r4]                    @ covert to MEMC page

                tst     r2, #PAGE_OLD | PAGE_NOT_USER   @ check for MEMC read
                biceq   r4, r4, #0x200
                tsteq   r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write
                biceq   r4, r4, #0x300

                orr     r4, r4, ip
                and     r2, ip, #0x01800000
                orr     r4, r4, r2, lsr #13

                and     r2, r4, #255
                str     r4, [r1, r2, lsl #2]
                movs    pc, lr

/*
 * Params  : r0 = preserved
 *         : r1 = memc table base (preserved)
 *         : r2 = page table base
 *         : r3 = preserved
 *         : r4 = unused
 *         : r5 = memc physical address translation table
 *         : ip = virtual address (updated)
 */
update_pte_table:
                stmfd   sp!, {r0, lr}
                bic     r0, r2, #3
1:              ldr     r2, [r0], #4                    @ get entry
                tst     r2, #PAGE_PRESENT               @ page present
                blne    update_pte                      @ process pte
                add     ip, ip, #32768                  @ increment virt addr
                ldr     r2, [r0], #4                    @ get entry
                tst     r2, #PAGE_PRESENT               @ page present
                blne    update_pte                      @ process pte
                add     ip, ip, #32768                  @ increment virt addr
                ldr     r2, [r0], #4                    @ get entry
                tst     r2, #PAGE_PRESENT               @ page present
                blne    update_pte                      @ process pte
                add     ip, ip, #32768                  @ increment virt addr
                ldr     r2, [r0], #4                    @ get entry
                tst     r2, #PAGE_PRESENT               @ page present
                blne    update_pte                      @ process pte
                add     ip, ip, #32768                  @ increment virt addr
                tst     ip, #32768 * 31                 @ finished?
                bne     1b
                ldmfd   sp!, {r0, pc}^

/*
 * Function: cpu_memc_update_all(pgd_t *pgd)
 * Params  : pgd        Page tables/MEMC mapping
 * Notes   : this is optimised for 32k pages
 */
ENTRY(cpu_memc_update_all)
                stmfd   sp!, {r4, r5, lr}
                bl      clear_tables
                sub     r1, r0, #256 * 4                @ start of MEMC tables
                adr     r5, memc_phys_table_32          @ Convert to logical page number
                mov     ip, #0                          @ virtual address
1:              ldmia   r0!, {r2, r3}
                tst     r2, #PAGE_PRESENT
                addeq   ip, ip, #1048576
                blne    update_pte_table
                mov     r2, r3
                tst     r2, #PAGE_PRESENT
                addeq   ip, ip, #1048576
                blne    update_pte_table
                teq     ip, #32 * 1048576
                bne     1b
                ldmfd   sp!, {r4, r5, pc}^

/*
 * Build the table to map from physical page number to memc page number
 */
                .type   memc_phys_table_32, #object
memc_phys_table_32:
                .irp    b7, 0x00, 0x80
                .irp    b6, 0x00, 0x02
                .irp    b5, 0x00, 0x04
                .irp    b4, 0x00, 0x01

                .irp    b3, 0x00, 0x40
                .irp    b2, 0x00, 0x20
                .irp    b1, 0x00, 0x10
                .irp    b0, 0x00, 0x08
                .long   0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0
                .endr
                .endr
                .endr
                .endr

                .endr
                .endr
                .endr
                .endr
                .size   memc_phys_table_32, . - memc_phys_table_32

/*
 * helper for cpu_memc_update_all, this clears out all
 * mappings, setting them close to the top of memory,
 * and inaccessible (0x01f00000).
 * Params  : r0 = page table pointer
 */
clear_tables:   ldr     r1, _arm3_set_pgd - 4
                ldr     r2, [r1]
                sub     r1, r0, #256 * 4                @ start of MEMC tables
                add     r2, r1, r2, lsl #2              @ end of tables
                mov     r3, #0x03f00000                 @ Default mapping (null mapping)
                orr     r3, r3, #0x00000f00
                orr     r4, r3, #1
                orr     r5, r3, #2
                orr     ip, r3, #3
1:              stmia   r1!, {r3, r4, r5, ip}
                add     r3, r3, #4
                add     r4, r4, #4
                add     r5, r5, #4
                add     ip, ip, #4
                stmia   r1!, {r3, r4, r5, ip}
                add     r3, r3, #4
                add     r4, r4, #4
                add     r5, r5, #4
                add     ip, ip, #4
                teq     r1, r2
                bne     1b
                mov     pc, lr

/*
 * Function: *_set_pgd(pgd_t *pgd)
 * Params  : pgd        New page tables/MEMC mapping
 * Purpose : update MEMC hardware with new mapping
 */
                .word   SYMBOL_NAME(page_nr)
_arm3_set_pgd:  mcr     p15, 0, r1, c1, c0, 0           @ flush cache
_arm2_set_pgd:  stmfd   sp!, {lr}
                ldr     r1, _arm3_set_pgd - 4
                ldr     r2, [r1]
                sub     r0, r0, #256 * 4                @ start of MEMC tables
                add     r1, r0, r2, lsl #2              @ end of tables
1:              ldmia   r0!, {r2, r3, ip, lr}
                strb    r2, [r2]
                strb    r3, [r3]
                strb    ip, [ip]
                strb    lr, [lr]
                ldmia   r0!, {r2, r3, ip, lr}
                strb    r2, [r2]
                strb    r3, [r3]
                strb    ip, [ip]
                strb    lr, [lr]
                teq     r0, r1
                bne     1b
                ldmfd   sp!, {pc}^

/*
 * Function: *_proc_init (void)
 * Purpose : Initialise the cache control registers
 */
_arm3_proc_init:
                mov     r0, #0x001f0000
                orr     r0, r0, #0x0000ff00
                orr     r0, r0, #0x000000ff
                mcr     p15, 0, r0, c3, c0              @ ARM3 Cacheable
                mcr     p15, 0, r0, c4, c0              @ ARM3 Updateable
                mov     r0, #0
                mcr     p15, 0, r0, c5, c0              @ ARM3 Disruptive
                mcr     p15, 0, r0, c1, c0              @ ARM3 Flush
                mov     r0, #3
                mcr     p15, 0, r0, c2, c0              @ ARM3 Control
_arm2_proc_init:
                movs    pc, lr

/*
 * Function: *_proc_fin (void)
 * Purpose : Finalise processor (disable caches)
 */
_arm3_proc_fin: mov     r0, #2
                mcr     p15, 0, r0, c2, c0
_arm2_proc_fin: orrs    pc, lr, #I_BIT|F_BIT

/*
 * Function: *_xchg_1 (int new, volatile void *ptr)
 * Params  : new        New value to store at...
 *         : ptr        pointer to byte-wide location
 * Purpose : Performs an exchange operation
 * Returns : Original byte data at 'ptr'
 */
_arm2_xchg_1:   mov     r2, pc
                orr     r2, r2, #I_BIT
                teqp    r2, #0
                ldrb    r2, [r1]
                strb    r0, [r1]
                mov     r0, r2
                movs    pc, lr

_arm3_xchg_1:   swpb    r0, r0, [r1]
                movs    pc, lr

/*
 * Function: *_xchg_4 (int new, volatile void *ptr)
 * Params  : new        New value to store at...
 *         : ptr        pointer to word-wide location
 * Purpose : Performs an exchange operation
 * Returns : Original word data at 'ptr'
 */
_arm2_xchg_4:   mov     r2, pc
                orr     r2, r2, #I_BIT
                teqp    r2, #0
                ldr     r2, [r1]
                str     r0, [r1]
                mov     r0, r2
                movs    pc, lr

_arm3_xchg_4:   swp     r0, r0, [r1]
                movs    pc, lr

_arm2_3_check_bugs:
                bics    pc, lr, #0x04000000             @ Clear FIQ disable bit

_arm2_name:     .asciz  "ARM 2"
_arm250_name:   .asciz  "ARM 250"
_arm3_name:     .asciz  "ARM 3"

                .section ".text.init", #alloc, #execinstr
/*
 * Purpose : Function pointers used to access above functions - all calls
 *           come through these
 */
                .globl  SYMBOL_NAME(arm2_processor_functions)
SYMBOL_NAME(arm2_processor_functions):
                .word   _arm2_3_check_bugs
                .word   _arm2_proc_init
                .word   _arm2_proc_fin
                .word   _arm2_set_pgd
                .word   _arm2_xchg_1
                .word   _arm2_xchg_4

cpu_arm2_info:
                .long   0
                .long   _arm2_name

                .globl  SYMBOL_NAME(arm250_processor_functions)
SYMBOL_NAME(arm250_processor_functions):
                .word   _arm2_3_check_bugs
                .word   _arm2_proc_init
                .word   _arm2_proc_fin
                .word   _arm2_set_pgd
                .word   _arm3_xchg_1
                .word   _arm3_xchg_4

cpu_arm250_info:
                .long   0
                .long   _arm250_name

                .globl  SYMBOL_NAME(arm3_processor_functions)
SYMBOL_NAME(arm3_processor_functions):
                .word   _arm2_3_check_bugs
                .word   _arm3_proc_init
                .word   _arm3_proc_fin
                .word   _arm3_set_pgd
                .word   _arm3_xchg_1
                .word   _arm3_xchg_4

cpu_arm3_info:
                .long   0
                .long   _arm3_name

arm2_arch_name: .asciz  "armv1"
arm3_arch_name: .asciz  "armv2"
arm2_elf_name:  .asciz  "v1"
arm3_elf_name:  .asciz  "v2"
                .align

                .section ".proc.info", #alloc, #execinstr

                .long   0x41560200
                .long   0xfffffff0
                .long   0
                mov     pc, lr
                .long   arm2_arch_name
                .long   arm2_elf_name
                .long   0
                .long   cpu_arm2_info
                .long   SYMBOL_NAME(arm2_processor_functions)

                .long   0x41560250
                .long   0xfffffff0
                .long   0
                mov     pc, lr
                .long   arm3_arch_name
                .long   arm3_elf_name
                .long   0
                .long   cpu_arm250_info
                .long   SYMBOL_NAME(arm250_processor_functions)

                .long   0x41560300
                .long   0xfffffff0
                .long   0
                mov     pc, lr
                .long   arm3_arch_name
                .long   arm3_elf_name
                .long   0
                .long   cpu_arm3_info
                .long   SYMBOL_NAME(arm3_processor_functions)

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.