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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [arch/] [ppc/] [boot/] [common/] [util.S] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * Useful bootup functions, which are more easily done in asm than C.
 *
 * NOTE:  Be very very careful about the registers you use here.
 *      We don't follow any ABI calling convention among the
 *      assembler functions that call each other, especially early
 *      in the initialization.  Please preserve at least r3 and r4
 *      for these early functions, as they often contain information
 *      passed from boot roms into the C decompress function.
 *
 * Author: Tom Rini
 *         trini@mvista.com
 * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
 *
 * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
 * the terms of the GNU General Public License version 2.  This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include <asm/processor.h>
#include <asm/cache.h>
#include <asm/ppc_asm.h>


        .text

#ifdef CONFIG_6xx
        .globl  disable_6xx_mmu
disable_6xx_mmu:
        /* Establish default MSR value, exception prefix 0xFFF.
         * If necessary, this function must fix up the LR if we
         * return to a different address space once the MMU is
         * disabled.
         */
        li      r8,MSR_IP|MSR_FP
        mtmsr   r8
        isync

        /* Test for a 601 */
        mfpvr   r10
        srwi    r10,r10,16
        cmpwi   0,r10,1         /* 601 ? */
        beq     .clearbats_601

        /* Clear BATs */
        li      r8,0
        mtspr   SPRN_DBAT0U,r8
        mtspr   SPRN_DBAT0L,r8
        mtspr   SPRN_DBAT1U,r8
        mtspr   SPRN_DBAT1L,r8
        mtspr   SPRN_DBAT2U,r8
        mtspr   SPRN_DBAT2L,r8
        mtspr   SPRN_DBAT3U,r8
        mtspr   SPRN_DBAT3L,r8
.clearbats_601:
        mtspr   SPRN_IBAT0U,r8
        mtspr   SPRN_IBAT0L,r8
        mtspr   SPRN_IBAT1U,r8
        mtspr   SPRN_IBAT1L,r8
        mtspr   SPRN_IBAT2U,r8
        mtspr   SPRN_IBAT2L,r8
        mtspr   SPRN_IBAT3U,r8
        mtspr   SPRN_IBAT3L,r8
        isync
        sync
        sync

        /* Set segment registers */
        li      r8,16           /* load up segment register values */
        mtctr   r8              /* for context 0 */
        lis     r8,0x2000       /* Ku = 1, VSID = 0 */
        li      r10,0
3:      mtsrin  r8,r10
        addi    r8,r8,0x111     /* increment VSID */
        addis   r10,r10,0x1000  /* address of next segment */
        bdnz    3b
        blr

        .globl  disable_6xx_l1cache
disable_6xx_l1cache:
        /* Enable, invalidate and then disable the L1 icache/dcache. */
        li      r8,0
        ori     r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
        mfspr   r11,SPRN_HID0
        or      r11,r11,r8
        andc    r10,r11,r8
        isync
        mtspr   SPRN_HID0,r8
        sync
        isync
        mtspr   SPRN_HID0,r10
        sync
        isync
        blr
#endif

        .globl  _setup_L2CR
_setup_L2CR:
/*
 * We should be skipping this section on CPUs where this results in an
 * illegal instruction.  If not, please send trini@kernel.crashing.org
 * the PVR of your CPU.
 */
        /* Invalidate/disable L2 cache */
        sync
        isync
        mfspr   r8,SPRN_L2CR
        rlwinm  r8,r8,0,1,31
        oris    r8,r8,L2CR_L2I@h
        sync
        isync
        mtspr   SPRN_L2CR,r8
        sync
        isync

        /* Wait for the invalidation to complete */
        mfspr   r8,SPRN_PVR
        srwi    r8,r8,16
        cmplwi  cr0,r8,0x8000                   /* 7450 */
        cmplwi  cr1,r8,0x8001                   /* 7455 */
        cmplwi  cr2,r8,0x8002                   /* 7457 */
        cror    4*cr0+eq,4*cr0+eq,4*cr1+eq      /* Now test if any are true. */
        cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
        bne     2f

1:      mfspr   r8,SPRN_L2CR    /* On 745x, poll L2I bit (bit 10) */
        rlwinm. r9,r8,0,10,10
        bne     1b
        b       3f

2:      mfspr   r8,SPRN_L2CR    /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
        rlwinm. r9,r8,0,31,31
        bne     2b

3:      rlwinm  r8,r8,0,11,9    /* Turn off L2I bit */
        sync
        isync
        mtspr   SPRN_L2CR,r8
        sync
        isync
        blr

        .globl  _setup_L3CR
_setup_L3CR:
        /* Invalidate/disable L3 cache */
        sync
        isync
        mfspr   r8,SPRN_L3CR
        rlwinm  r8,r8,0,1,31
        ori     r8,r8,L3CR_L3I@l
        sync
        isync
        mtspr   SPRN_L3CR,r8
        sync
        isync

        /* Wait for the invalidation to complete */
1:      mfspr   r8,SPRN_L3CR
        rlwinm. r9,r8,0,21,21
        bne     1b

        rlwinm  r8,r8,0,22,20           /* Turn off L3I bit */
        sync
        isync
        mtspr   SPRN_L3CR,r8
        sync
        isync
        blr


/* udelay (on non-601 processors) needs to know the period of the
 * timebase in nanoseconds.  This used to be hardcoded to be 60ns
 * (period of 66MHz/4).  Now a variable is used that is initialized to
 * 60 for backward compatibility, but it can be overridden as necessary
 * with code something like this:
 *    extern unsigned long timebase_period_ns;
 *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
 */
        .data
        .globl timebase_period_ns
timebase_period_ns:
        .long   60

        .text
/*
 * Delay for a number of microseconds
 */
        .globl  udelay
udelay:
        mfspr   r4,SPRN_PVR
        srwi    r4,r4,16
        cmpwi   0,r4,1          /* 601 ? */
        bne     .udelay_not_601
00:     li      r0,86   /* Instructions / microsecond? */
        mtctr   r0
10:     addi    r0,r0,0 /* NOP */
        bdnz    10b
        subic.  r3,r3,1
        bne     00b
        blr

.udelay_not_601:
        mulli   r4,r3,1000      /* nanoseconds */
        /*  Change r4 to be the number of ticks using:  
         *      (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
         *  timebase_period_ns defaults to 60 (16.6MHz) */
        lis     r5,timebase_period_ns@ha
        lwz     r5,timebase_period_ns@l(r5)
        add     r4,r4,r5
        addi    r4,r4,-1
        divw    r4,r4,r5        /* BUS ticks */
1:      mftbu   r5
        mftb    r6
        mftbu   r7
        cmpw    0,r5,r7
        bne     1b              /* Get [synced] base time */
        addc    r9,r6,r4        /* Compute end time */
        addze   r8,r5
2:      mftbu   r5
        cmpw    0,r5,r8
        blt     2b
        bgt     3f
        mftb    r6
        cmpw    0,r6,r9
        blt     2b
3:      blr

        .section ".relocate_code","xa"
/*
 * Flush and enable instruction cache
 * First, flush the data cache in case it was enabled and may be
 * holding instructions for copy back.
 */
        .globl flush_instruction_cache
flush_instruction_cache:        
        mflr    r6
        bl      flush_data_cache

#ifdef CONFIG_8xx
        lis     r3, IDC_INVALL@h
        mtspr   SPRN_IC_CST, r3
        lis     r3, IDC_ENABLE@h
        mtspr   SPRN_IC_CST, r3
        lis     r3, IDC_DISABLE@h
        mtspr   SPRN_DC_CST, r3
#elif CONFIG_4xx
        lis     r3,start@h              # r9 = &_start
        lis     r4,_etext@ha
        addi    r4,r4,_etext@l          # r8 = &_etext
1:      dcbf    r0,r3                   # Flush the data cache
        icbi    r0,r3                   # Invalidate the instruction cache
        addi    r3,r3,0x10              # Increment by one cache line
        cmplw   cr0,r3,r4               # Are we at the end yet?
        blt     1b                      # No, keep flushing and invalidating
#else
        /* Enable, invalidate and then disable the L1 icache/dcache. */
        li      r3,0
        ori     r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
        mfspr   r4,SPRN_HID0
        or      r5,r4,r3
        isync
        mtspr   SPRN_HID0,r5
        sync
        isync
        ori     r5,r4,HID0_ICE  /* Enable cache */
        mtspr   SPRN_HID0,r5
        sync
        isync
#endif
        mtlr    r6
        blr

#define NUM_CACHE_LINES 128*8
#define cache_flush_buffer 0x1000

/*
 * Flush data cache
 * Do this by just reading lots of stuff into the cache.
 */
        .globl flush_data_cache
flush_data_cache:       
        lis     r3,cache_flush_buffer@h
        ori     r3,r3,cache_flush_buffer@l
        li      r4,NUM_CACHE_LINES
        mtctr   r4
00:     lwz     r4,0(r3)
        addi    r3,r3,L1_CACHE_BYTES    /* Next line, please */
        bdnz    00b
10:     blr

        .previous

Go to most recent revision | 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.