diff options
Diffstat (limited to 'arch/ppc/cpu/ppc4xx/start.S')
-rw-r--r-- | arch/ppc/cpu/ppc4xx/start.S | 2170 |
1 files changed, 2170 insertions, 0 deletions
diff --git a/arch/ppc/cpu/ppc4xx/start.S b/arch/ppc/cpu/ppc4xx/start.S new file mode 100644 index 0000000..c739deb --- /dev/null +++ b/arch/ppc/cpu/ppc4xx/start.S @@ -0,0 +1,2170 @@ +/* + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de> + * Copyright (C) 2007 Stefan Roese <sr@denx.de>, DENX Software Engineering + * Copyright (c) 2008 Nuovation System Designs, LLC + * Grant Erickson <gerickson@nuovations.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/*------------------------------------------------------------------------------+ + * This source code is dual-licensed. You may use it under the terms of the + * GNU General Public License version 2, or under the license below. + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *------------------------------------------------------------------------------- + */ + +/* U-Boot - Startup Code for AMCC 4xx PowerPC based Embedded Boards + * + * + * The processor starts at 0xfffffffc and the code is executed + * from flash/rom. + * in memory, but as long we don't jump around before relocating. + * board_init lies at a quite high address and when the cpu has + * jumped there, everything is ok. + * This works because the cpu gives the FLASH (CS0) the whole + * address space at startup, and board_init lies as a echo of + * the flash somewhere up there in the memorymap. + * + * board_init will change CS0 to be positioned at the correct + * address and (s)dram will be positioned at address 0 + */ +#include <config.h> +#include <ppc4xx.h> +#include <timestamp.h> +#include <version.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> +#include <asm/ppc4xx-isram.h> + +#ifndef CONFIG_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + +#ifdef CONFIG_SYS_INIT_DCACHE_CS +# if (CONFIG_SYS_INIT_DCACHE_CS == 0) +# define PBxAP PB1AP +# define PBxCR PB0CR +# if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB0AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB0CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 1) +# define PBxAP PB1AP +# define PBxCR PB1CR +# if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB1AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB1CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 2) +# define PBxAP PB2AP +# define PBxCR PB2CR +# if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB2AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB2CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 3) +# define PBxAP PB3AP +# define PBxCR PB3CR +# if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB3AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB3CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 4) +# define PBxAP PB4AP +# define PBxCR PB4CR +# if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB4AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB4CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 5) +# define PBxAP PB5AP +# define PBxCR PB5CR +# if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB5AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB5CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 6) +# define PBxAP PB6AP +# define PBxCR PB6CR +# if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB6AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB6CR +# endif +# endif +# if (CONFIG_SYS_INIT_DCACHE_CS == 7) +# define PBxAP PB7AP +# define PBxCR PB7CR +# if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR)) +# define PBxAP_VAL CONFIG_SYS_EBC_PB7AP +# define PBxCR_VAL CONFIG_SYS_EBC_PB7CR +# endif +# endif +# ifndef PBxAP_VAL +# define PBxAP_VAL 0 +# endif +# ifndef PBxCR_VAL +# define PBxCR_VAL 0 +# endif +/* + * Memory Bank x (nothingness) initialization CONFIG_SYS_INIT_RAM_ADDR + 64 MiB + * used as temporary stack pointer for the primordial stack + */ +# ifndef CONFIG_SYS_INIT_DCACHE_PBxAR +# define CONFIG_SYS_INIT_DCACHE_PBxAR (EBC_BXAP_BME_DISABLED | \ + EBC_BXAP_TWT_ENCODE(7) | \ + EBC_BXAP_BCE_DISABLE | \ + EBC_BXAP_BCT_2TRANS | \ + EBC_BXAP_CSN_ENCODE(0) | \ + EBC_BXAP_OEN_ENCODE(0) | \ + EBC_BXAP_WBN_ENCODE(0) | \ + EBC_BXAP_WBF_ENCODE(0) | \ + EBC_BXAP_TH_ENCODE(2) | \ + EBC_BXAP_RE_DISABLED | \ + EBC_BXAP_SOR_NONDELAYED | \ + EBC_BXAP_BEM_WRITEONLY | \ + EBC_BXAP_PEN_DISABLED) +# endif /* CONFIG_SYS_INIT_DCACHE_PBxAR */ +# ifndef CONFIG_SYS_INIT_DCACHE_PBxCR +# define CONFIG_SYS_INIT_DCACHE_PBxCR (EBC_BXCR_BAS_ENCODE(CONFIG_SYS_INIT_RAM_ADDR) | \ + EBC_BXCR_BS_64MB | \ + EBC_BXCR_BU_RW | \ + EBC_BXCR_BW_16BIT) +# endif /* CONFIG_SYS_INIT_DCACHE_PBxCR */ +# ifndef CONFIG_SYS_INIT_RAM_PATTERN +# define CONFIG_SYS_INIT_RAM_PATTERN 0xDEADDEAD +# endif +#endif /* CONFIG_SYS_INIT_DCACHE_CS */ + +#if (defined(CONFIG_SYS_INIT_RAM_DCACHE) && (CONFIG_SYS_INIT_RAM_END > (4 << 10))) +#error Only 4k of init-ram is supported - please adjust CONFIG_SYS_INIT_RAM_END! +#endif + +/* + * Unless otherwise overriden, enable two 128MB cachable instruction regions + * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering + * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions. + */ +#if !defined(CONFIG_SYS_FLASH_BASE) +/* If not already defined, set it to the "last" 128MByte region */ +# define CONFIG_SYS_FLASH_BASE 0xf8000000 +#endif +#if !defined(CONFIG_SYS_ICACHE_SACR_VALUE) +# define CONFIG_SYS_ICACHE_SACR_VALUE \ + (PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + ( 0 << 20)) | \ + PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) | \ + PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE)) +#endif /* !defined(CONFIG_SYS_ICACHE_SACR_VALUE) */ + +#if !defined(CONFIG_SYS_DCACHE_SACR_VALUE) +# define CONFIG_SYS_DCACHE_SACR_VALUE \ + (0x00000000) +#endif /* !defined(CONFIG_SYS_DCACHE_SACR_VALUE) */ + +#define function_prolog(func_name) .text; \ + .align 2; \ + .globl func_name; \ + func_name: +#define function_epilog(func_name) .type func_name,@function; \ + .size func_name,.-func_name + +/* We don't want the MMU yet. +*/ +#undef MSR_KERNEL +#define MSR_KERNEL ( MSR_ME ) /* Machine Check */ + + + .extern ext_bus_cntlr_init +#ifdef CONFIG_NAND_U_BOOT + .extern reconfig_tlb0 +#endif + +/* + * Set up GOT: Global Offset Table + * + * Use r12 to access the GOT + */ +#if !defined(CONFIG_NAND_SPL) + START_GOT + GOT_ENTRY(_GOT2_TABLE_) + GOT_ENTRY(_FIXUP_TABLE_) + + GOT_ENTRY(_start) + GOT_ENTRY(_start_of_vectors) + GOT_ENTRY(_end_of_vectors) + GOT_ENTRY(transfer_to_handler) + + GOT_ENTRY(__init_end) + GOT_ENTRY(_end) + GOT_ENTRY(__bss_start) + END_GOT +#endif /* CONFIG_NAND_SPL */ + +#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) + /* + * NAND U-Boot image is started from offset 0 + */ + .text +#if defined(CONFIG_440) + bl reconfig_tlb0 +#endif + GET_GOT + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + bl board_init_f +#endif + +#if defined(CONFIG_SYS_RAMBOOT) + /* + * 4xx RAM-booting U-Boot image is started from offset 0 + */ + .text + bl _start_440 +#endif + +/* + * 440 Startup -- on reset only the top 4k of the effective + * address space is mapped in by an entry in the instruction + * and data shadow TLB. The .bootpg section is located in the + * top 4k & does only what's necessary to map in the the rest + * of the boot rom. Once the boot rom is mapped in we can + * proceed with normal startup. + * + * NOTE: CS0 only covers the top 2MB of the effective address + * space after reset. + */ + +#if defined(CONFIG_440) +#if !defined(CONFIG_NAND_SPL) + .section .bootpg,"ax" +#endif + .globl _start_440 + +/**************************************************************************/ +_start_440: + /*--------------------------------------------------------------------+ + | 440EPX BUP Change - Hardware team request + +--------------------------------------------------------------------*/ +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + sync + nop + nop +#endif + /*----------------------------------------------------------------+ + | Core bug fix. Clear the esr + +-----------------------------------------------------------------*/ + li r0,0 + mtspr SPRN_ESR,r0 + /*----------------------------------------------------------------*/ + /* Clear and set up some registers. */ + /*----------------------------------------------------------------*/ + iccci r0,r0 /* NOTE: operands not used for 440 */ + dccci r0,r0 /* NOTE: operands not used for 440 */ + sync + li r0,0 + mtspr SPRN_SRR0,r0 + mtspr SPRN_SRR1,r0 + mtspr SPRN_CSRR0,r0 + mtspr SPRN_CSRR1,r0 + /* NOTE: 440GX adds machine check status regs */ +#if defined(CONFIG_440) && !defined(CONFIG_440GP) + mtspr SPRN_MCSRR0,r0 + mtspr SPRN_MCSRR1,r0 + mfspr r1,SPRN_MCSR + mtspr SPRN_MCSR,r1 +#endif + + /*----------------------------------------------------------------*/ + /* CCR0 init */ + /*----------------------------------------------------------------*/ + /* Disable store gathering & broadcast, guarantee inst/data + * cache block touch, force load/store alignment + * (see errata 1.12: 440_33) + */ + lis r1,0x0030 /* store gathering & broadcast disable */ + ori r1,r1,0x6000 /* cache touch */ + mtspr SPRN_CCR0,r1 + + /*----------------------------------------------------------------*/ + /* Initialize debug */ + /*----------------------------------------------------------------*/ + mfspr r1,SPRN_DBCR0 + andis. r1, r1, 0x8000 /* test DBCR0[EDM] bit */ + bne skip_debug_init /* if set, don't clear debug register */ + mtspr SPRN_DBCR0,r0 + mtspr SPRN_DBCR1,r0 + mtspr SPRN_DBCR2,r0 + mtspr SPRN_IAC1,r0 + mtspr SPRN_IAC2,r0 + mtspr SPRN_IAC3,r0 + mtspr SPRN_DAC1,r0 + mtspr SPRN_DAC2,r0 + mtspr SPRN_DVC1,r0 + mtspr SPRN_DVC2,r0 + + mfspr r1,SPRN_DBSR + mtspr SPRN_DBSR,r1 /* Clear all valid bits */ +skip_debug_init: + +#if defined (CONFIG_440SPE) + /*----------------------------------------------------------------+ + | Initialize Core Configuration Reg1. + | a. ICDPEI: Record even parity. Normal operation. + | b. ICTPEI: Record even parity. Normal operation. + | c. DCTPEI: Record even parity. Normal operation. + | d. DCDPEI: Record even parity. Normal operation. + | e. DCUPEI: Record even parity. Normal operation. + | f. DCMPEI: Record even parity. Normal operation. + | g. FCOM: Normal operation + | h. MMUPEI: Record even parity. Normal operation. + | i. FFF: Flush only as much data as necessary. + | j. TCS: Timebase increments from CPU clock. + +-----------------------------------------------------------------*/ + li r0,0 + mtspr SPRN_CCR1, r0 + + /*----------------------------------------------------------------+ + | Reset the timebase. + | The previous write to CCR1 sets the timebase source. + +-----------------------------------------------------------------*/ + mtspr SPRN_TBWL, r0 + mtspr SPRN_TBWU, r0 +#endif + + /*----------------------------------------------------------------*/ + /* Setup interrupt vectors */ + /*----------------------------------------------------------------*/ + mtspr SPRN_IVPR,r0 /* Vectors start at 0x0000_0000 */ + li r1,0x0100 + mtspr SPRN_IVOR0,r1 /* Critical input */ + li r1,0x0200 + mtspr SPRN_IVOR1,r1 /* Machine check */ + li r1,0x0300 + mtspr SPRN_IVOR2,r1 /* Data storage */ + li r1,0x0400 + mtspr SPRN_IVOR3,r1 /* Instruction storage */ + li r1,0x0500 + mtspr SPRN_IVOR4,r1 /* External interrupt */ + li r1,0x0600 + mtspr SPRN_IVOR5,r1 /* Alignment */ + li r1,0x0700 + mtspr SPRN_IVOR6,r1 /* Program check */ + li r1,0x0800 + mtspr SPRN_IVOR7,r1 /* Floating point unavailable */ + li r1,0x0c00 + mtspr SPRN_IVOR8,r1 /* System call */ + li r1,0x0a00 + mtspr SPRN_IVOR9,r1 /* Auxiliary Processor unavailable */ + li r1,0x0900 + mtspr SPRN_IVOR10,r1 /* Decrementer */ + li r1,0x1300 + mtspr SPRN_IVOR13,r1 /* Data TLB error */ + li r1,0x1400 + mtspr SPRN_IVOR14,r1 /* Instr TLB error */ + li r1,0x2000 + mtspr SPRN_IVOR15,r1 /* Debug */ + + /*----------------------------------------------------------------*/ + /* Configure cache regions */ + /*----------------------------------------------------------------*/ + mtspr SPRN_INV0,r0 + mtspr SPRN_INV1,r0 + mtspr SPRN_INV2,r0 + mtspr SPRN_INV3,r0 + mtspr SPRN_DNV0,r0 + mtspr SPRN_DNV1,r0 + mtspr SPRN_DNV2,r0 + mtspr SPRN_DNV3,r0 + mtspr SPRN_ITV0,r0 + mtspr SPRN_ITV1,r0 + mtspr SPRN_ITV2,r0 + mtspr SPRN_ITV3,r0 + mtspr SPRN_DTV0,r0 + mtspr SPRN_DTV1,r0 + mtspr SPRN_DTV2,r0 + mtspr SPRN_DTV3,r0 + + /*----------------------------------------------------------------*/ + /* Cache victim limits */ + /*----------------------------------------------------------------*/ + /* floors 0, ceiling max to use the entire cache -- nothing locked + */ + lis r1,0x0001 + ori r1,r1,0xf800 + mtspr SPRN_IVLIM,r1 + mtspr SPRN_DVLIM,r1 + + /*----------------------------------------------------------------+ + |Initialize MMUCR[STID] = 0. + +-----------------------------------------------------------------*/ + mfspr r0,SPRN_MMUCR + addis r1,0,0xFFFF + ori r1,r1,0xFF00 + and r0,r0,r1 + mtspr SPRN_MMUCR,r0 + + /*----------------------------------------------------------------*/ + /* Clear all TLB entries -- TID = 0, TS = 0 */ + /*----------------------------------------------------------------*/ + addis r0,0,0x0000 +#ifdef CONFIG_SYS_RAMBOOT + li r4,0 /* Start with TLB #0 */ +#else + li r4,1 /* Start with TLB #1 */ +#endif + li r1,64 /* 64 TLB entries */ + sub r1,r1,r4 /* calculate last TLB # */ + mtctr r1 +rsttlb: +#ifdef CONFIG_SYS_RAMBOOT + tlbre r3,r4,0 /* Read contents from TLB word #0 to get EPN */ + rlwinm. r3,r3,0,0xfffffc00 /* Mask EPN */ + beq tlbnxt /* Skip EPN=0 TLB, this is the SDRAM TLB */ +#endif + tlbwe r0,r4,0 /* Invalidate all entries (V=0)*/ + tlbwe r0,r4,1 + tlbwe r0,r4,2 +tlbnxt: addi r4,r4,1 /* Next TLB */ + bdnz rsttlb + + /*----------------------------------------------------------------*/ + /* TLB entry setup -- step thru tlbtab */ + /*----------------------------------------------------------------*/ +#if defined(CONFIG_440SPE_REVA) + /*----------------------------------------------------------------*/ + /* We have different TLB tables for revA and rev B of 440SPe */ + /*----------------------------------------------------------------*/ + mfspr r1, PVR + lis r0,0x5342 + ori r0,r0,0x1891 + cmpw r7,r1,r0 + bne r7,..revA + bl tlbtabB + b ..goon +..revA: + bl tlbtabA +..goon: +#else + bl tlbtab /* Get tlbtab pointer */ +#endif + mr r5,r0 + li r1,0x003f /* 64 TLB entries max */ + mtctr r1 + li r4,0 /* TLB # */ + + addi r5,r5,-4 +1: +#ifdef CONFIG_SYS_RAMBOOT + tlbre r3,r4,0 /* Read contents from TLB word #0 */ + rlwinm. r3,r3,0,0x00000200 /* Mask V (valid) bit */ + bne tlbnx2 /* Skip V=1 TLB, this is the SDRAM TLB */ +#endif + lwzu r0,4(r5) + cmpwi r0,0 + beq 2f /* 0 marks end */ + lwzu r1,4(r5) + lwzu r2,4(r5) + tlbwe r0,r4,0 /* TLB Word 0 */ + tlbwe r1,r4,1 /* TLB Word 1 */ + tlbwe r2,r4,2 /* TLB Word 2 */ +tlbnx2: addi r4,r4,1 /* Next TLB */ + bdnz 1b + + /*----------------------------------------------------------------*/ + /* Continue from 'normal' start */ + /*----------------------------------------------------------------*/ +2: + bl 3f + b _start + +3: li r0,0 + mtspr SPRN_SRR1,r0 /* Keep things disabled for now */ + mflr r1 + mtspr SPRN_SRR0,r1 + rfi +#endif /* CONFIG_440 */ + +/* + * r3 - 1st arg to board_init(): IMMP pointer + * r4 - 2nd arg to board_init(): boot flag + */ +#ifndef CONFIG_NAND_SPL + .text + .long 0x27051956 /* U-Boot Magic Number */ + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" + .ascii CONFIG_IDENT_STRING, "\0" + + . = EXC_OFF_SYS_RESET + .globl _start_of_vectors +_start_of_vectors: + +/* Critical input. */ + CRIT_EXCEPTION(0x100, CritcalInput, UnknownException) + +#ifdef CONFIG_440 +/* Machine check */ + MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException) +#else + CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException) +#endif /* CONFIG_440 */ + +/* Data Storage exception. */ + STD_EXCEPTION(0x300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ + STD_EXCEPTION(0x400, InstStorage, UnknownException) + +/* External Interrupt exception. */ + STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) + +/* Alignment exception. */ + . = 0x600 +Alignment: + EXCEPTION_PROLOG(SRR0, SRR1) + mfspr r4,DAR + stw r4,_DAR(r21) + mfspr r5,DSISR + stw r5,_DSISR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) + +/* Program check exception */ + . = 0x700 +ProgramCheck: + EXCEPTION_PROLOG(SRR0, SRR1) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, + MSR_KERNEL, COPY_EE) + +#ifdef CONFIG_440 + STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + STD_EXCEPTION(0x900, Decrementer, DecrementerPITException) + STD_EXCEPTION(0xa00, APU, UnknownException) +#endif + STD_EXCEPTION(0xc00, SystemCall, UnknownException) + +#ifdef CONFIG_440 + STD_EXCEPTION(0x1300, DataTLBError, UnknownException) + STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException) +#else + STD_EXCEPTION(0x1000, PIT, DecrementerPITException) + STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) + STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) +#endif + CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException ) + + .globl _end_of_vectors +_end_of_vectors: + . = _START_OFFSET +#endif + .globl _start +_start: + +/*****************************************************************************/ +#if defined(CONFIG_440) + + /*----------------------------------------------------------------*/ + /* Clear and set up some registers. */ + /*----------------------------------------------------------------*/ + li r0,0x0000 + lis r1,0xffff + mtspr SPRN_DEC,r0 /* prevent dec exceptions */ + mtspr SPRN_TBWL,r0 /* prevent fit & wdt exceptions */ + mtspr SPRN_TBWU,r0 + mtspr SPRN_TSR,r1 /* clear all timer exception status */ + mtspr SPRN_TCR,r0 /* disable all */ + mtspr SPRN_ESR,r0 /* clear exception syndrome register */ + mtxer r0 /* clear integer exception register */ + + /*----------------------------------------------------------------*/ + /* Debug setup -- some (not very good) ice's need an event*/ + /* to establish control :-( Define CONFIG_SYS_INIT_DBCR to the dbsr */ + /* value you need in this case 0x8cff 0000 should do the trick */ + /*----------------------------------------------------------------*/ +#if defined(CONFIG_SYS_INIT_DBCR) + lis r1,0xffff + ori r1,r1,0xffff + mtspr SPRN_DBSR,r1 /* Clear all status bits */ + lis r0,CONFIG_SYS_INIT_DBCR@h + ori r0,r0,CONFIG_SYS_INIT_DBCR@l + mtspr SPRN_DBCR0,r0 + isync +#endif + + /*----------------------------------------------------------------*/ + /* Setup the internal SRAM */ + /*----------------------------------------------------------------*/ + li r0,0 + +#ifdef CONFIG_SYS_INIT_RAM_DCACHE + /* Clear Dcache to use as RAM */ + addis r3,r0,CONFIG_SYS_INIT_RAM_ADDR@h + ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l + addis r4,r0,CONFIG_SYS_INIT_RAM_END@h + ori r4,r4,CONFIG_SYS_INIT_RAM_END@l + rlwinm. r5,r4,0,27,31 + rlwinm r5,r4,27,5,31 + beq ..d_ran + addi r5,r5,0x0001 +..d_ran: + mtctr r5 +..d_ag: + dcbz r0,r3 + addi r3,r3,32 + bdnz ..d_ag + + /* + * Lock the init-ram/stack in d-cache, so that other regions + * may use d-cache as well + * Note, that this current implementation locks exactly 4k + * of d-cache, so please make sure that you don't define a + * bigger init-ram area. Take a look at the lwmon5 440EPx + * implementation as a reference. + */ + msync + isync + /* 8. set TFLOOR/NFLOOR to 8 (-> 8*16*32 bytes locked -> 4k) */ + lis r1,0x0201 + ori r1,r1,0xf808 + mtspr SPRN_DVLIM,r1 + lis r1,0x0808 + ori r1,r1,0x0808 + mtspr SPRN_DNV0,r1 + mtspr SPRN_DNV1,r1 + mtspr SPRN_DNV2,r1 + mtspr SPRN_DNV3,r1 + mtspr SPRN_DTV0,r1 + mtspr SPRN_DTV1,r1 + mtspr SPRN_DTV2,r1 + mtspr SPRN_DTV3,r1 + msync + isync +#endif /* CONFIG_SYS_INIT_RAM_DCACHE */ + + /* 440EP & 440GR are only 440er PPC's without internal SRAM */ +#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) + /* not all PPC's have internal SRAM usable as L2-cache */ +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_460SX) + mtdcr L2_CACHE_CFG,r0 /* Ensure L2 Cache is off */ +#elif defined(CONFIG_460EX) || defined(CONFIG_460GT) + lis r1, 0x0000 + ori r1,r1,0x0008 /* Set L2_CACHE_CFG[RDBW]=1 */ + mtdcr L2_CACHE_CFG,r1 +#endif + + lis r2,0x7fff + ori r2,r2,0xffff + mfdcr r1,ISRAM0_DPC + and r1,r1,r2 /* Disable parity check */ + mtdcr ISRAM0_DPC,r1 + mfdcr r1,ISRAM0_PMEG + and r1,r1,r2 /* Disable pwr mgmt */ + mtdcr ISRAM0_PMEG,r1 + + lis r1,0x8000 /* BAS = 8000_0000 */ +#if defined(CONFIG_440GX) || defined(CONFIG_440SP) + ori r1,r1,0x0980 /* first 64k */ + mtdcr ISRAM0_SB0CR,r1 + lis r1,0x8001 + ori r1,r1,0x0980 /* second 64k */ + mtdcr ISRAM0_SB1CR,r1 + lis r1, 0x8002 + ori r1,r1, 0x0980 /* third 64k */ + mtdcr ISRAM0_SB2CR,r1 + lis r1, 0x8003 + ori r1,r1, 0x0980 /* fourth 64k */ + mtdcr ISRAM0_SB3CR,r1 +#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || defined(CONFIG_460GT) + lis r1,0x0000 /* BAS = X_0000_0000 */ + ori r1,r1,0x0984 /* first 64k */ + mtdcr ISRAM0_SB0CR,r1 + lis r1,0x0001 + ori r1,r1,0x0984 /* second 64k */ + mtdcr ISRAM0_SB1CR,r1 + lis r1, 0x0002 + ori r1,r1, 0x0984 /* third 64k */ + mtdcr ISRAM0_SB2CR,r1 + lis r1, 0x0003 + ori r1,r1, 0x0984 /* fourth 64k */ + mtdcr ISRAM0_SB3CR,r1 +#if defined(CONFIG_460EX) || defined(CONFIG_460GT) + lis r2,0x7fff + ori r2,r2,0xffff + mfdcr r1,ISRAM1_DPC + and r1,r1,r2 /* Disable parity check */ + mtdcr ISRAM1_DPC,r1 + mfdcr r1,ISRAM1_PMEG + and r1,r1,r2 /* Disable pwr mgmt */ + mtdcr ISRAM1_PMEG,r1 + + lis r1,0x0004 /* BAS = 4_0004_0000 */ + ori r1,r1,0x0984 /* 64k */ + mtdcr ISRAM1_SB0CR,r1 +#endif +#elif defined(CONFIG_460SX) + lis r1,0x0000 /* BAS = 0000_0000 */ + ori r1,r1,0x0B84 /* first 128k */ + mtdcr ISRAM0_SB0CR,r1 + lis r1,0x0001 + ori r1,r1,0x0B84 /* second 128k */ + mtdcr ISRAM0_SB1CR,r1 + lis r1, 0x0002 + ori r1,r1, 0x0B84 /* third 128k */ + mtdcr ISRAM0_SB2CR,r1 + lis r1, 0x0003 + ori r1,r1, 0x0B84 /* fourth 128k */ + mtdcr ISRAM0_SB3CR,r1 +#elif defined(CONFIG_440GP) + ori r1,r1,0x0380 /* 8k rw */ + mtdcr ISRAM0_SB0CR,r1 + mtdcr ISRAM0_SB1CR,r0 /* Disable bank 1 */ +#endif +#endif /* #if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) */ + + /*----------------------------------------------------------------*/ + /* Setup the stack in internal SRAM */ + /*----------------------------------------------------------------*/ + lis r1,CONFIG_SYS_INIT_RAM_ADDR@h + ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l + li r0,0 + stwu r0,-4(r1) + stwu r0,-4(r1) /* Terminate call chain */ + + stwu r1,-8(r1) /* Save back chain and move SP */ + lis r0,RESET_VECTOR@h /* Address of reset vector */ + ori r0,r0, RESET_VECTOR@l + stwu r1,-8(r1) /* Save back chain and move SP */ + stw r0,+12(r1) /* Save return addr (underflow vect) */ + +#ifdef CONFIG_NAND_SPL + bl nand_boot_common /* will not return */ +#else + GET_GOT + + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + bl board_init_f +#endif + +#endif /* CONFIG_440 */ + +/*****************************************************************************/ +#ifdef CONFIG_IOP480 + /*----------------------------------------------------------------------- */ + /* Set up some machine state registers. */ + /*----------------------------------------------------------------------- */ + addi r0,r0,0x0000 /* initialize r0 to zero */ + mtspr SPRN_ESR,r0 /* clear Exception Syndrome Reg */ + mttcr r0 /* timer control register */ + mtexier r0 /* disable all interrupts */ + addis r4,r0,0xFFFF /* set r4 to 0xFFFFFFFF (status in the */ + ori r4,r4,0xFFFF /* dbsr is cleared by setting bits to 1) */ + mtdbsr r4 /* clear/reset the dbsr */ + mtexisr r4 /* clear all pending interrupts */ + addis r4,r0,0x8000 + mtexier r4 /* enable critical exceptions */ + addis r4,r0,0x0000 /* assume 403GCX - enable core clk */ + ori r4,r4,0x4020 /* dbling (no harm done on GA and GC */ + mtiocr r4 /* since bit not used) & DRC to latch */ + /* data bus on rising edge of CAS */ + /*----------------------------------------------------------------------- */ + /* Clear XER. */ + /*----------------------------------------------------------------------- */ + mtxer r0 + /*----------------------------------------------------------------------- */ + /* Invalidate i-cache and d-cache TAG arrays. */ + /*----------------------------------------------------------------------- */ + addi r3,0,1024 /* 1/4 of I-cache size, half of D-cache */ + addi r4,0,1024 /* 1/4 of I-cache */ +..cloop: + iccci 0,r3 + iccci r4,r3 + dccci 0,r3 + addic. r3,r3,-16 /* move back one cache line */ + bne ..cloop /* loop back to do rest until r3 = 0 */ + + /* */ + /* initialize IOP480 so it can read 1 MB code area for SRAM spaces */ + /* this requires enabling MA[17..0], by default only MA[12..0] are enabled. */ + /* */ + + /* first copy IOP480 register base address into r3 */ + addis r3,0,0x5000 /* IOP480 register base address hi */ +/* ori r3,r3,0x0000 / IOP480 register base address lo */ + +#ifdef CONFIG_ADCIOP + /* use r4 as the working variable */ + /* turn on CS3 (LOCCTL.7) */ + lwz r4,0x84(r3) /* LOCTL is at offset 0x84 */ + andi. r4,r4,0xff7f /* make bit 7 = 0 -- CS3 mode */ + stw r4,0x84(r3) /* LOCTL is at offset 0x84 */ +#endif + +#ifdef CONFIG_DASA_SIM + /* use r4 as the working variable */ + /* turn on MA17 (LOCCTL.7) */ + lwz r4,0x84(r3) /* LOCTL is at offset 0x84 */ + ori r4,r4,0x80 /* make bit 7 = 1 -- MA17 mode */ + stw r4,0x84(r3) /* LOCTL is at offset 0x84 */ +#endif + + /* turn on MA16..13 (LCS0BRD.12 = 0) */ + lwz r4,0x100(r3) /* LCS0BRD is at offset 0x100 */ + andi. r4,r4,0xefff /* make bit 12 = 0 */ + stw r4,0x100(r3) /* LCS0BRD is at offset 0x100 */ + + /* make sure above stores all comlete before going on */ + sync + + /* last thing, set local init status done bit (DEVINIT.31) */ + lwz r4,0x80(r3) /* DEVINIT is at offset 0x80 */ + oris r4,r4,0x8000 /* make bit 31 = 1 */ + stw r4,0x80(r3) /* DEVINIT is at offset 0x80 */ + + /* clear all pending interrupts and disable all interrupts */ + li r4,-1 /* set p1 to 0xffffffff */ + stw r4,0x1b0(r3) /* clear all pending interrupts */ + stw r4,0x1b8(r3) /* clear all pending interrupts */ + li r4,0 /* set r4 to 0 */ + stw r4,0x1b4(r3) /* disable all interrupts */ + stw r4,0x1bc(r3) /* disable all interrupts */ + + /* make sure above stores all comlete before going on */ + sync + + /* Set-up icache cacheability. */ + lis r1, CONFIG_SYS_ICACHE_SACR_VALUE@h + ori r1, r1, CONFIG_SYS_ICACHE_SACR_VALUE@l + mticcr r1 + isync + + /* Set-up dcache cacheability. */ + lis r1, CONFIG_SYS_DCACHE_SACR_VALUE@h + ori r1, r1, CONFIG_SYS_DCACHE_SACR_VALUE@l + mtdccr r1 + + addis r1,r0,CONFIG_SYS_INIT_RAM_ADDR@h + ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack to SDRAM */ + li r0, 0 /* Make room for stack frame header and */ + stwu r0, -4(r1) /* clear final stack frame so that */ + stwu r0, -4(r1) /* stack backtraces terminate cleanly */ + + GET_GOT /* initialize GOT access */ + + bl board_init_f /* run first part of init code (from Flash) */ + +#endif /* CONFIG_IOP480 */ + +/*****************************************************************************/ +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ + defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ + defined(CONFIG_405EX) || defined(CONFIG_405) + /*----------------------------------------------------------------------- */ + /* Clear and set up some registers. */ + /*----------------------------------------------------------------------- */ + addi r4,r0,0x0000 +#if !defined(CONFIG_405EX) + mtspr SPRN_SGR,r4 +#else + /* + * On 405EX, completely clearing the SGR leads to PPC hangup + * upon PCIe configuration access. The PCIe memory regions + * need to be guarded! + */ + lis r3,0x0000 + ori r3,r3,0x7FFC + mtspr SPRN_SGR,r3 +#endif + mtspr SPRN_DCWR,r4 + mtesr r4 /* clear Exception Syndrome Reg */ + mttcr r4 /* clear Timer Control Reg */ + mtxer r4 /* clear Fixed-Point Exception Reg */ + mtevpr r4 /* clear Exception Vector Prefix Reg */ + addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */ + /* dbsr is cleared by setting bits to 1) */ + mtdbsr r4 /* clear/reset the dbsr */ + + /* Invalidate the i- and d-caches. */ + bl invalidate_icache + bl invalidate_dcache + + /* Set-up icache cacheability. */ + lis r4, CONFIG_SYS_ICACHE_SACR_VALUE@h + ori r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l + mticcr r4 + isync + + /* Set-up dcache cacheability. */ + lis r4, CONFIG_SYS_DCACHE_SACR_VALUE@h + ori r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l + mtdccr r4 + +#if !(defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))\ + && !defined (CONFIG_XILINX_405) + /*----------------------------------------------------------------------- */ + /* Tune the speed and size for flash CS0 */ + /*----------------------------------------------------------------------- */ + bl ext_bus_cntlr_init +#endif + +#if !(defined(CONFIG_SYS_INIT_DCACHE_CS) || defined(CONFIG_SYS_TEMP_STACK_OCM)) + /* + * For boards that don't have OCM and can't use the data cache + * for their primordial stack, setup stack here directly after the + * SDRAM is initialized in ext_bus_cntlr_init. + */ + lis r1, CONFIG_SYS_INIT_RAM_ADDR@h + ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in SDRAM */ + + li r0, 0 /* Make room for stack frame header and */ + stwu r0, -4(r1) /* clear final stack frame so that */ + stwu r0, -4(r1) /* stack backtraces terminate cleanly */ + /* + * Set up a dummy frame to store reset vector as return address. + * this causes stack underflow to reset board. + */ + stwu r1, -8(r1) /* Save back chain and move SP */ + lis r0, RESET_VECTOR@h /* Address of reset vector */ + ori r0, r0, RESET_VECTOR@l + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save return addr (underflow vect) */ +#endif /* !(CONFIG_SYS_INIT_DCACHE_CS || !CONFIG_SYS_TEM_STACK_OCM) */ + +#if defined(CONFIG_405EP) + /*----------------------------------------------------------------------- */ + /* DMA Status, clear to come up clean */ + /*----------------------------------------------------------------------- */ + addis r3,r0, 0xFFFF /* Clear all existing DMA status */ + ori r3,r3, 0xFFFF + mtdcr DMASR, r3 + + bl ppc405ep_init /* do ppc405ep specific init */ +#endif /* CONFIG_405EP */ + +#if defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE) +#if defined(CONFIG_405EZ) + /******************************************************************** + * Setup OCM - On Chip Memory - PPC405EZ uses OCM Controller V2 + *******************************************************************/ + /* + * We can map the OCM on the PLB3, so map it at + * CONFIG_SYS_OCM_DATA_ADDR + 0x8000 + */ + lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ + ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l + ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */ + mtdcr OCM0_PLBCR1,r3 /* Set PLB Access */ + ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */ + mtdcr OCM0_PLBCR2,r3 /* Set PLB Access */ + isync + + lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ + ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l + ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */ + mtdcr OCM0_DSRC1, r3 /* Set Data Side */ + mtdcr OCM0_ISRC1, r3 /* Set Instruction Side */ + ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */ + mtdcr OCM0_DSRC2, r3 /* Set Data Side */ + mtdcr OCM0_ISRC2, r3 /* Set Instruction Side */ + addis r3,0,0x0800 /* OCM Data Parity Disable - 1 Wait State */ + mtdcr OCM0_DISDPC,r3 + + isync +#else /* CONFIG_405EZ */ + /******************************************************************** + * Setup OCM - On Chip Memory + *******************************************************************/ + /* Setup OCM */ + lis r0, 0x7FFF + ori r0, r0, 0xFFFF + mfdcr r3, OCM0_ISCNTL /* get instr-side IRAM config */ + mfdcr r4, OCM0_DSCNTL /* get data-side IRAM config */ + and r3, r3, r0 /* disable data-side IRAM */ + and r4, r4, r0 /* disable data-side IRAM */ + mtdcr OCM0_ISCNTL, r3 /* set instr-side IRAM config */ + mtdcr OCM0_DSCNTL, r4 /* set data-side IRAM config */ + isync + + lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ + ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l + mtdcr OCM0_DSARC, r3 + addis r4, 0, 0xC000 /* OCM data area enabled */ + mtdcr OCM0_DSCNTL, r4 + isync +#endif /* CONFIG_405EZ */ +#endif + + /*----------------------------------------------------------------------- */ + /* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */ + /*----------------------------------------------------------------------- */ +#ifdef CONFIG_SYS_INIT_DCACHE_CS + li r4, PBxAP + mtdcr EBC0_CFGADDR, r4 + lis r4, CONFIG_SYS_INIT_DCACHE_PBxAR@h + ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxAR@l + mtdcr EBC0_CFGDATA, r4 + + addi r4, 0, PBxCR + mtdcr EBC0_CFGADDR, r4 + lis r4, CONFIG_SYS_INIT_DCACHE_PBxCR@h + ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxCR@l + mtdcr EBC0_CFGDATA, r4 + + /* + * Enable the data cache for the 128MB storage access control region + * at CONFIG_SYS_INIT_RAM_ADDR. + */ + mfdccr r4 + oris r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h + ori r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l + mtdccr r4 + + /* + * Preallocate data cache lines to be used to avoid a subsequent + * cache miss and an ensuing machine check exception when exceptions + * are enabled. + */ + li r0, 0 + + lis r3, CONFIG_SYS_INIT_RAM_ADDR@h + ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l + + lis r4, CONFIG_SYS_INIT_RAM_END@h + ori r4, r4, CONFIG_SYS_INIT_RAM_END@l + + /* + * Convert the size, in bytes, to the number of cache lines/blocks + * to preallocate. + */ + clrlwi. r5, r4, (32 - L1_CACHE_SHIFT) + srwi r5, r4, L1_CACHE_SHIFT + beq ..load_counter + addi r5, r5, 0x0001 +..load_counter: + mtctr r5 + + /* Preallocate the computed number of cache blocks. */ +..alloc_dcache_block: + dcba r0, r3 + addi r3, r3, L1_CACHE_BYTES + bdnz ..alloc_dcache_block + sync + + /* + * Load the initial stack pointer and data area and convert the size, + * in bytes, to the number of words to initialize to a known value. + */ + lis r1, CONFIG_SYS_INIT_RAM_ADDR@h + ori r1, r1, CONFIG_SYS_INIT_SP_OFFSET@l + + lis r4, (CONFIG_SYS_INIT_RAM_END >> 2)@h + ori r4, r4, (CONFIG_SYS_INIT_RAM_END >> 2)@l + mtctr r4 + + lis r2, CONFIG_SYS_INIT_RAM_ADDR@h + ori r2, r2, CONFIG_SYS_INIT_RAM_END@l + + lis r4, CONFIG_SYS_INIT_RAM_PATTERN@h + ori r4, r4, CONFIG_SYS_INIT_RAM_PATTERN@l + +..stackloop: + stwu r4, -4(r2) + bdnz ..stackloop + + /* + * Make room for stack frame header and clear final stack frame so + * that stack backtraces terminate cleanly. + */ + stwu r0, -4(r1) + stwu r0, -4(r1) + + /* + * Set up a dummy frame to store reset vector as return address. + * this causes stack underflow to reset board. + */ + stwu r1, -8(r1) /* Save back chain and move SP */ + addis r0, 0, RESET_VECTOR@h /* Address of reset vector */ + ori r0, r0, RESET_VECTOR@l + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save return addr (underflow vect) */ + +#elif defined(CONFIG_SYS_TEMP_STACK_OCM) && \ + (defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE)) + /* + * Stack in OCM. + */ + + /* Set up Stack at top of OCM */ + lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@h + ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@l + + /* Set up a zeroized stack frame so that backtrace works right */ + li r0, 0 + stwu r0, -4(r1) + stwu r0, -4(r1) + + /* + * Set up a dummy frame to store reset vector as return address. + * this causes stack underflow to reset board. + */ + stwu r1, -8(r1) /* Save back chain and move SP */ + lis r0, RESET_VECTOR@h /* Address of reset vector */ + ori r0, r0, RESET_VECTOR@l + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save return addr (underflow vect) */ +#endif /* CONFIG_SYS_INIT_DCACHE_CS */ + +#ifdef CONFIG_NAND_SPL + bl nand_boot_common /* will not return */ +#else + GET_GOT /* initialize GOT access */ + + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + + /* NEVER RETURNS! */ + bl board_init_f /* run first part of init code (from Flash) */ +#endif /* CONFIG_NAND_SPL */ + +#endif /* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */ + /*----------------------------------------------------------------------- */ + + +#ifndef CONFIG_NAND_SPL +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ + .globl transfer_to_handler +transfer_to_handler: + stw r22,_NIP(r21) + lis r22,MSR_POW@h + andc r23,r23,r22 + stw r23,_MSR(r21) + SAVE_GPR(7, r21) + SAVE_4GPRS(8, r21) + SAVE_8GPRS(12, r21) + SAVE_8GPRS(24, r21) + mflr r23 + andi. r24,r23,0x3f00 /* get vector offset */ + stw r24,TRAP(r21) + li r22,0 + stw r22,RESULT(r21) + mtspr SPRG2,r22 /* r1 is now kernel sp */ + lwz r24,0(r23) /* virtual address of handler */ + lwz r23,4(r23) /* where to go when done */ + mtspr SRR0,r24 + mtspr SRR1,r20 + mtlr r23 + SYNC + rfi /* jump to handler, enable MMU */ + +int_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SRR0,r2 + mtspr SRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfi + +crit_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SPRN_CSRR0,r2 + mtspr SPRN_CSRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfci + +#ifdef CONFIG_440 +mck_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SPRN_MCSRR0,r2 + mtspr SPRN_MCSRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfmci +#endif /* CONFIG_440 */ + + + .globl get_pvr +get_pvr: + mfspr r3, PVR + blr + +/*------------------------------------------------------------------------------- */ +/* Function: out16 */ +/* Description: Output 16 bits */ +/*------------------------------------------------------------------------------- */ + .globl out16 +out16: + sth r4,0x0000(r3) + blr + +/*------------------------------------------------------------------------------- */ +/* Function: out16r */ +/* Description: Byte reverse and output 16 bits */ +/*------------------------------------------------------------------------------- */ + .globl out16r +out16r: + sthbrx r4,r0,r3 + blr + +/*------------------------------------------------------------------------------- */ +/* Function: out32r */ +/* Description: Byte reverse and output 32 bits */ +/*------------------------------------------------------------------------------- */ + .globl out32r +out32r: + stwbrx r4,r0,r3 + blr + +/*------------------------------------------------------------------------------- */ +/* Function: in16 */ +/* Description: Input 16 bits */ +/*------------------------------------------------------------------------------- */ + .globl in16 +in16: + lhz r3,0x0000(r3) + blr + +/*------------------------------------------------------------------------------- */ +/* Function: in16r */ +/* Description: Input 16 bits and byte reverse */ +/*------------------------------------------------------------------------------- */ + .globl in16r +in16r: + lhbrx r3,r0,r3 + blr + +/*------------------------------------------------------------------------------- */ +/* Function: in32r */ +/* Description: Input 32 bits and byte reverse */ +/*------------------------------------------------------------------------------- */ + .globl in32r +in32r: + lwbrx r3,r0,r3 + blr + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = Relocated stack pointer + * r4 = Relocated global data pointer + * r5 = Relocated text pointer + */ + .globl relocate_code +relocate_code: +#if defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) + /* + * We need to flush the initial global data (gd_t) before the dcache + * will be invalidated. + */ + + /* Save registers */ + mr r9, r3 + mr r10, r4 + mr r11, r5 + + /* Flush initial global data range */ + mr r3, r4 + addi r4, r4, CONFIG_SYS_GBL_DATA_SIZE@l + bl flush_dcache_range + +#if defined(CONFIG_SYS_INIT_DCACHE_CS) + /* + * Undo the earlier data cache set-up for the primordial stack and + * data area. First, invalidate the data cache and then disable data + * cacheability for that area. Finally, restore the EBC values, if + * any. + */ + + /* Invalidate the primordial stack and data area in cache */ + lis r3, CONFIG_SYS_INIT_RAM_ADDR@h + ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l + + lis r4, CONFIG_SYS_INIT_RAM_END@h + ori r4, r4, CONFIG_SYS_INIT_RAM_END@l + add r4, r4, r3 + + bl invalidate_dcache_range + + /* Disable cacheability for the region */ + mfdccr r3 + lis r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h + ori r4, r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l + and r3, r3, r4 + mtdccr r3 + + /* Restore the EBC parameters */ + li r3, PBxAP + mtdcr EBC0_CFGADDR, r3 + lis r3, PBxAP_VAL@h + ori r3, r3, PBxAP_VAL@l + mtdcr EBC0_CFGDATA, r3 + + li r3, PBxCR + mtdcr EBC0_CFGADDR, r3 + lis r3, PBxCR_VAL@h + ori r3, r3, PBxCR_VAL@l + mtdcr EBC0_CFGDATA, r3 +#endif /* defined(CONFIG_SYS_INIT_DCACHE_CS) */ + + /* Restore registers */ + mr r3, r9 + mr r4, r10 + mr r5, r11 +#endif /* defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) */ + +#ifdef CONFIG_SYS_INIT_RAM_DCACHE + /* + * Unlock the previously locked d-cache + */ + msync + isync + /* set TFLOOR/NFLOOR to 0 again */ + lis r6,0x0001 + ori r6,r6,0xf800 + mtspr SPRN_DVLIM,r6 + lis r6,0x0000 + ori r6,r6,0x0000 + mtspr SPRN_DNV0,r6 + mtspr SPRN_DNV1,r6 + mtspr SPRN_DNV2,r6 + mtspr SPRN_DNV3,r6 + mtspr SPRN_DTV0,r6 + mtspr SPRN_DTV1,r6 + mtspr SPRN_DTV2,r6 + mtspr SPRN_DTV3,r6 + msync + isync +#endif /* CONFIG_SYS_INIT_RAM_DCACHE */ + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ + defined(CONFIG_460SX) + /* + * On some 440er platforms the cache is enabled in the first TLB (Boot-CS) + * to speed up the boot process. Now this cache needs to be disabled. + */ + iccci 0,0 /* Invalidate inst cache */ + dccci 0,0 /* Invalidate data cache, now no longer our stack */ + sync + isync + + /* Clear all potential pending exceptions */ + mfspr r1,SPRN_MCSR + mtspr SPRN_MCSR,r1 +#ifdef CONFIG_SYS_TLB_FOR_BOOT_FLASH + addi r1,r0,CONFIG_SYS_TLB_FOR_BOOT_FLASH /* Use defined TLB */ +#else + addi r1,r0,0x0000 /* Default TLB entry is #0 */ +#endif /* CONFIG_SYS_TLB_FOR_BOOT_FLASH */ + tlbre r0,r1,0x0002 /* Read contents */ + ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */ + tlbwe r0,r1,0x0002 /* Save it out */ + sync + isync +#endif /* defined(CONFIG_440EP) || ... || defined(CONFIG_460GT) */ + mr r1, r3 /* Set new stack pointer */ + mr r9, r4 /* Save copy of Init Data pointer */ + mr r10, r5 /* Save copy of Destination Address */ + + GET_GOT + mr r3, r5 /* Destination Address */ + lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ + ori r4, r4, CONFIG_SYS_MONITOR_BASE@l + lwz r5, GOT(__init_end) + sub r5, r5, r4 + li r6, L1_CACHE_BYTES /* Cache Line Size */ + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address + * + * Offset: + */ + sub r15, r10, r4 + + /* First our own GOT */ + add r12, r12, r15 + /* then the one used by the C code */ + add r30, r30, r15 + + /* + * Now relocate code + */ + + cmplw cr1,r3,r4 + addi r0,r5,3 + srwi. r0,r0,2 + beq cr1,4f /* In place copy is not necessary */ + beq 7f /* Protect against 0 count */ + mtctr r0 + bge cr1,2f + + la r8,-4(r4) + la r7,-4(r3) +1: lwzu r0,4(r8) + stwu r0,4(r7) + bdnz 1b + b 4f + +2: slwi r0,r0,2 + add r8,r4,r0 + add r7,r3,r0 +3: lwzu r0,-4(r8) + stwu r0,-4(r7) + bdnz 3b + +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4: cmpwi r6,0 + add r5,r3,r5 + beq 7f /* Always flush prefetch queue in any case */ + subi r0,r6,1 + andc r3,r3,r0 + mr r4,r3 +5: dcbst 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 5b + sync /* Wait for all dcbst to complete on bus */ + mr r4,r3 +6: icbi 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 6b +7: sync /* Wait for all icbi to complete on bus */ + isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + + addi r0, r10, in_ram - _start + _START_OFFSET + mtlr r0 + blr /* NEVER RETURNS! */ + +in_ram: + + /* + * Relocation Function, r12 point to got2+0x8000 + * + * Adjust got2 pointers, no need to check for 0, this code + * already puts a few entries in the table. + */ + li r0,__got2_entries@sectoff@l + la r3,GOT(_GOT2_TABLE_) + lwz r11,GOT(_GOT2_TABLE_) + mtctr r0 + sub r11,r3,r11 + addi r3,r3,-4 +1: lwzu r0,4(r3) + cmpwi r0,0 + beq- 2f + add r0,r0,r11 + stw r0,0(r3) +2: bdnz 1b + + /* + * Now adjust the fixups and the pointers to the fixups + * in case we need to move ourselves again. + */ + li r0,__fixup_entries@sectoff@l + lwz r3,GOT(_FIXUP_TABLE_) + cmpwi r0,0 + mtctr r0 + addi r3,r3,-4 + beq 4f +3: lwzu r4,4(r3) + lwzux r0,r4,r11 + add r0,r0,r11 + stw r10,0(r3) + stw r0,0(r4) + bdnz 3b +4: +clear_bss: + /* + * Now clear BSS segment + */ + lwz r3,GOT(__bss_start) + lwz r4,GOT(_end) + + cmplw 0, r3, r4 + beq 7f + + li r0, 0 + + andi. r5, r4, 3 + beq 6f + sub r4, r4, r5 + mtctr r5 + mr r5, r4 +5: stb r0, 0(r5) + addi r5, r5, 1 + bdnz 5b +6: + stw r0, 0(r3) + addi r3, r3, 4 + cmplw 0, r3, r4 + bne 6b + +7: + mr r3, r9 /* Init Data pointer */ + mr r4, r10 /* Destination Address */ + bl board_init_r + + /* + * Copy exception vector code to low memory + * + * r3: dest_addr + * r7: source address, r8: end address, r9: target address + */ + .globl trap_init +trap_init: + mflr r4 /* save link register */ + GET_GOT + lwz r7, GOT(_start_of_vectors) + lwz r8, GOT(_end_of_vectors) + + li r9, 0x100 /* reset vector always at 0x100 */ + + cmplw 0, r7, r8 + bgelr /* return if r7>=r8 - just in case */ +1: + lwz r0, 0(r7) + stw r0, 0(r9) + addi r7, r7, 4 + addi r9, r9, 4 + cmplw 0, r7, r8 + bne 1b + + /* + * relocate `hdlr' and `int_return' entries + */ + li r7, .L_MachineCheck - _start + _START_OFFSET + li r8, Alignment - _start + _START_OFFSET +2: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 2b + + li r7, .L_Alignment - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_ProgramCheck - _start + _START_OFFSET + bl trap_reloc + +#ifdef CONFIG_440 + li r7, .L_FPUnavailable - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_Decrementer - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_APU - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_InstructionTLBError - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_DataTLBError - _start + _START_OFFSET + bl trap_reloc +#else /* CONFIG_440 */ + li r7, .L_PIT - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_InstructionTLBMiss - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_DataTLBMiss - _start + _START_OFFSET + bl trap_reloc +#endif /* CONFIG_440 */ + + li r7, .L_DebugBreakpoint - _start + _START_OFFSET + bl trap_reloc + +#if !defined(CONFIG_440) + addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ + oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ + mtmsr r7 /* change MSR */ +#else + bl __440_msr_set + b __440_msr_continue + +__440_msr_set: + addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ + oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ + mtspr SPRN_SRR1,r7 + mflr r7 + mtspr SPRN_SRR0,r7 + rfi +__440_msr_continue: +#endif + + mtlr r4 /* restore link register */ + blr + +#if defined(CONFIG_440) +/*----------------------------------------------------------------------------+ +| dcbz_area. ++----------------------------------------------------------------------------*/ + function_prolog(dcbz_area) + rlwinm. r5,r4,0,27,31 + rlwinm r5,r4,27,5,31 + beq ..d_ra2 + addi r5,r5,0x0001 +..d_ra2:mtctr r5 +..d_ag2:dcbz r0,r3 + addi r3,r3,32 + bdnz ..d_ag2 + sync + blr + function_epilog(dcbz_area) +#endif /* CONFIG_440 */ +#endif /* CONFIG_NAND_SPL */ + +/*------------------------------------------------------------------------------- */ +/* Function: in8 */ +/* Description: Input 8 bits */ +/*------------------------------------------------------------------------------- */ + .globl in8 +in8: + lbz r3,0x0000(r3) + blr + +/*------------------------------------------------------------------------------- */ +/* Function: out8 */ +/* Description: Output 8 bits */ +/*------------------------------------------------------------------------------- */ + .globl out8 +out8: + stb r4,0x0000(r3) + blr + +/*------------------------------------------------------------------------------- */ +/* Function: out32 */ +/* Description: Output 32 bits */ +/*------------------------------------------------------------------------------- */ + .globl out32 +out32: + stw r4,0x0000(r3) + blr + +/*------------------------------------------------------------------------------- */ +/* Function: in32 */ +/* Description: Input 32 bits */ +/*------------------------------------------------------------------------------- */ + .globl in32 +in32: + lwz 3,0x0000(3) + blr + +/**************************************************************************/ +/* PPC405EP specific stuff */ +/**************************************************************************/ +#ifdef CONFIG_405EP +ppc405ep_init: + +#ifdef CONFIG_BUBINGA + /* + * Initialize EBC chip selects 1 & 4 and GPIO pins (for alternate + * function) to support FPGA and NVRAM accesses below. + */ + + lis r3,GPIO0_OSRH@h /* config GPIO output select */ + ori r3,r3,GPIO0_OSRH@l + lis r4,CONFIG_SYS_GPIO0_OSRH@h + ori r4,r4,CONFIG_SYS_GPIO0_OSRH@l + stw r4,0(r3) + lis r3,GPIO0_OSRL@h + ori r3,r3,GPIO0_OSRL@l + lis r4,CONFIG_SYS_GPIO0_OSRL@h + ori r4,r4,CONFIG_SYS_GPIO0_OSRL@l + stw r4,0(r3) + + lis r3,GPIO0_ISR1H@h /* config GPIO input select */ + ori r3,r3,GPIO0_ISR1H@l + lis r4,CONFIG_SYS_GPIO0_ISR1H@h + ori r4,r4,CONFIG_SYS_GPIO0_ISR1H@l + stw r4,0(r3) + lis r3,GPIO0_ISR1L@h + ori r3,r3,GPIO0_ISR1L@l + lis r4,CONFIG_SYS_GPIO0_ISR1L@h + ori r4,r4,CONFIG_SYS_GPIO0_ISR1L@l + stw r4,0(r3) + + lis r3,GPIO0_TSRH@h /* config GPIO three-state select */ + ori r3,r3,GPIO0_TSRH@l + lis r4,CONFIG_SYS_GPIO0_TSRH@h + ori r4,r4,CONFIG_SYS_GPIO0_TSRH@l + stw r4,0(r3) + lis r3,GPIO0_TSRL@h + ori r3,r3,GPIO0_TSRL@l + lis r4,CONFIG_SYS_GPIO0_TSRL@h + ori r4,r4,CONFIG_SYS_GPIO0_TSRL@l + stw r4,0(r3) + + lis r3,GPIO0_TCR@h /* config GPIO driver output enables */ + ori r3,r3,GPIO0_TCR@l + lis r4,CONFIG_SYS_GPIO0_TCR@h + ori r4,r4,CONFIG_SYS_GPIO0_TCR@l + stw r4,0(r3) + + li r3,PB1AP /* program EBC bank 1 for RTC access */ + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB1AP@h + ori r3,r3,CONFIG_SYS_EBC_PB1AP@l + mtdcr EBC0_CFGDATA,r3 + li r3,PB1CR + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB1CR@h + ori r3,r3,CONFIG_SYS_EBC_PB1CR@l + mtdcr EBC0_CFGDATA,r3 + + li r3,PB1AP /* program EBC bank 1 for RTC access */ + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB1AP@h + ori r3,r3,CONFIG_SYS_EBC_PB1AP@l + mtdcr EBC0_CFGDATA,r3 + li r3,PB1CR + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB1CR@h + ori r3,r3,CONFIG_SYS_EBC_PB1CR@l + mtdcr EBC0_CFGDATA,r3 + + li r3,PB4AP /* program EBC bank 4 for FPGA access */ + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB4AP@h + ori r3,r3,CONFIG_SYS_EBC_PB4AP@l + mtdcr EBC0_CFGDATA,r3 + li r3,PB4CR + mtdcr EBC0_CFGADDR,r3 + lis r3,CONFIG_SYS_EBC_PB4CR@h + ori r3,r3,CONFIG_SYS_EBC_PB4CR@l + mtdcr EBC0_CFGDATA,r3 +#endif + + /* + !----------------------------------------------------------------------- + ! Check to see if chip is in bypass mode. + ! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a + ! CPU reset Otherwise, skip this step and keep going. + ! Note: Running BIOS in bypass mode is not supported since PLB speed + ! will not be fast enough for the SDRAM (min 66MHz) + !----------------------------------------------------------------------- + */ + mfdcr r5, CPC0_PLLMR1 + rlwinm r4,r5,1,0x1 /* get system clock source (SSCS) */ + cmpi cr0,0,r4,0x1 + + beq pll_done /* if SSCS =b'1' then PLL has */ + /* already been set */ + /* and CPU has been reset */ + /* so skip to next section */ + +#ifdef CONFIG_BUBINGA + /* + !----------------------------------------------------------------------- + ! Read NVRAM to get value to write in PLLMR. + ! If value has not been correctly saved, write default value + ! Default config values (assuming on-board 33MHz SYS_CLK) are above. + ! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above. + ! + ! WARNING: This code assumes the first three words in the nvram_t + ! structure in openbios.h. Changing the beginning of + ! the structure will break this code. + ! + !----------------------------------------------------------------------- + */ + addis r3,0,NVRAM_BASE@h + addi r3,r3,NVRAM_BASE@l + + lwz r4, 0(r3) + addis r5,0,NVRVFY1@h + addi r5,r5,NVRVFY1@l + cmp cr0,0,r4,r5 /* Compare 1st NVRAM Magic number*/ + bne ..no_pllset + addi r3,r3,4 + lwz r4, 0(r3) + addis r5,0,NVRVFY2@h + addi r5,r5,NVRVFY2@l + cmp cr0,0,r4,r5 /* Compare 2 NVRAM Magic number */ + bne ..no_pllset + addi r3,r3,8 /* Skip over conf_size */ + lwz r4, 4(r3) /* Load PLLMR1 value from NVRAM */ + lwz r3, 0(r3) /* Load PLLMR0 value from NVRAM */ + rlwinm r5,r4,1,0x1 /* get system clock source (SSCS) */ + cmpi cr0,0,r5,1 /* See if PLL is locked */ + beq pll_write +..no_pllset: +#endif /* CONFIG_BUBINGA */ + +#ifdef CONFIG_TAIHU + mfdcr r4, CPC0_BOOT + andi. r5, r4, CPC0_BOOT_SEP@l + bne strap_1 /* serial eeprom present */ + addis r5,0,CPLD_REG0_ADDR@h + ori r5,r5,CPLD_REG0_ADDR@l + andi. r5, r5, 0x10 + bne _pci_66mhz +#endif /* CONFIG_TAIHU */ + +#if defined(CONFIG_ZEUS) + mfdcr r4, CPC0_BOOT + andi. r5, r4, CPC0_BOOT_SEP@l + bne strap_1 /* serial eeprom present */ + lis r3,0x0000 + addi r3,r3,0x3030 + lis r4,0x8042 + addi r4,r4,0x223e + b 1f +strap_1: + mfdcr r3, CPC0_PLLMR0 + mfdcr r4, CPC0_PLLMR1 + b 1f +#endif + + addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */ + ori r3,r3,PLLMR0_DEFAULT@l /* */ + addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */ + ori r4,r4,PLLMR1_DEFAULT@l /* */ + +#ifdef CONFIG_TAIHU + b 1f +_pci_66mhz: + addis r3,0,PLLMR0_DEFAULT_PCI66@h + ori r3,r3,PLLMR0_DEFAULT_PCI66@l + addis r4,0,PLLMR1_DEFAULT_PCI66@h + ori r4,r4,PLLMR1_DEFAULT_PCI66@l + b 1f +strap_1: + mfdcr r3, CPC0_PLLMR0 + mfdcr r4, CPC0_PLLMR1 +#endif /* CONFIG_TAIHU */ + +1: + b pll_write /* Write the CPC0_PLLMR with new value */ + +pll_done: + /* + !----------------------------------------------------------------------- + ! Clear Soft Reset Register + ! This is needed to enable PCI if not booting from serial EPROM + !----------------------------------------------------------------------- + */ + addi r3, 0, 0x0 + mtdcr CPC0_SRR, r3 + + addis r3,0,0x0010 + mtctr r3 +pci_wait: + bdnz pci_wait + + blr /* return to main code */ + +/* +!----------------------------------------------------------------------------- +! Function: pll_write +! Description: Updates the value of the CPC0_PLLMR according to CMOS27E documentation +! That is: +! 1. Pll is first disabled (de-activated by putting in bypass mode) +! 2. PLL is reset +! 3. Clock dividers are set while PLL is held in reset and bypassed +! 4. PLL Reset is cleared +! 5. Wait 100us for PLL to lock +! 6. A core reset is performed +! Input: r3 = Value to write to CPC0_PLLMR0 +! Input: r4 = Value to write to CPC0_PLLMR1 +! Output r3 = none +!----------------------------------------------------------------------------- +*/ + .globl pll_write +pll_write: + mfdcr r5, CPC0_UCR + andis. r5,r5,0xFFFF + ori r5,r5,0x0101 /* Stop the UART clocks */ + mtdcr CPC0_UCR,r5 /* Before changing PLL */ + + mfdcr r5, CPC0_PLLMR1 + rlwinm r5,r5,0,0x7FFFFFFF /* Disable PLL */ + mtdcr CPC0_PLLMR1,r5 + oris r5,r5,0x4000 /* Set PLL Reset */ + mtdcr CPC0_PLLMR1,r5 + + mtdcr CPC0_PLLMR0,r3 /* Set clock dividers */ + rlwinm r5,r4,0,0x3FFFFFFF /* Reset & Bypass new PLL dividers */ + oris r5,r5,0x4000 /* Set PLL Reset */ + mtdcr CPC0_PLLMR1,r5 /* Set clock dividers */ + rlwinm r5,r5,0,0xBFFFFFFF /* Clear PLL Reset */ + mtdcr CPC0_PLLMR1,r5 + + /* + ! Wait min of 100us for PLL to lock. + ! See CMOS 27E databook for more info. + ! At 200MHz, that means waiting 20,000 instructions + */ + addi r3,0,20000 /* 2000 = 0x4e20 */ + mtctr r3 +pll_wait: + bdnz pll_wait + + oris r5,r5,0x8000 /* Enable PLL */ + mtdcr CPC0_PLLMR1,r5 /* Engage */ + + /* + * Reset CPU to guarantee timings are OK + * Not sure if this is needed... + */ + addis r3,0,0x1000 + mtspr SPRN_DBCR0,r3 /* This will cause a CPU core reset, and */ + /* execution will continue from the poweron */ + /* vector of 0xfffffffc */ +#endif /* CONFIG_405EP */ + +#if defined(CONFIG_440) +/*----------------------------------------------------------------------------+ +| mttlb3. ++----------------------------------------------------------------------------*/ + function_prolog(mttlb3) + TLBWE(4,3,2) + blr + function_epilog(mttlb3) + +/*----------------------------------------------------------------------------+ +| mftlb3. ++----------------------------------------------------------------------------*/ + function_prolog(mftlb3) + TLBRE(3,3,2) + blr + function_epilog(mftlb3) + +/*----------------------------------------------------------------------------+ +| mttlb2. ++----------------------------------------------------------------------------*/ + function_prolog(mttlb2) + TLBWE(4,3,1) + blr + function_epilog(mttlb2) + +/*----------------------------------------------------------------------------+ +| mftlb2. ++----------------------------------------------------------------------------*/ + function_prolog(mftlb2) + TLBRE(3,3,1) + blr + function_epilog(mftlb2) + +/*----------------------------------------------------------------------------+ +| mttlb1. ++----------------------------------------------------------------------------*/ + function_prolog(mttlb1) + TLBWE(4,3,0) + blr + function_epilog(mttlb1) + +/*----------------------------------------------------------------------------+ +| mftlb1. ++----------------------------------------------------------------------------*/ + function_prolog(mftlb1) + TLBRE(3,3,0) + blr + function_epilog(mftlb1) +#endif /* CONFIG_440 */ + +#if defined(CONFIG_NAND_SPL) +/* + * void nand_boot_relocate(dst, src, bytes) + * + * r3 = Destination address to copy code to (in SDRAM) + * r4 = Source address to copy code from + * r5 = size to copy in bytes + */ +nand_boot_relocate: + mr r6,r3 + mr r7,r4 + mflr r8 + + /* + * Copy SPL from icache into SDRAM + */ + subi r3,r3,4 + subi r4,r4,4 + srwi r5,r5,2 + mtctr r5 +..spl_loop: + lwzu r0,4(r4) + stwu r0,4(r3) + bdnz ..spl_loop + + /* + * Calculate "corrected" link register, so that we "continue" + * in execution in destination range + */ + sub r3,r7,r6 /* r3 = src - dst */ + sub r8,r8,r3 /* r8 = link-reg - (src - dst) */ + mtlr r8 + blr + +nand_boot_common: + /* + * First initialize SDRAM. It has to be available *before* calling + * nand_boot(). + */ + lis r3,CONFIG_SYS_SDRAM_BASE@h + ori r3,r3,CONFIG_SYS_SDRAM_BASE@l + bl initdram + + /* + * Now copy the 4k SPL code into SDRAM and continue execution + * from there. + */ + lis r3,CONFIG_SYS_NAND_BOOT_SPL_DST@h + ori r3,r3,CONFIG_SYS_NAND_BOOT_SPL_DST@l + lis r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@h + ori r4,r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@l + lis r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@h + ori r5,r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@l + bl nand_boot_relocate + + /* + * We're running from SDRAM now!!! + * + * It is necessary for 4xx systems to relocate from running at + * the original location (0xfffffxxx) to somewhere else (SDRAM + * preferably). This is because CS0 needs to be reconfigured for + * NAND access. And we can't reconfigure this CS when currently + * "running" from it. + */ + + /* + * Finally call nand_boot() to load main NAND U-Boot image from + * NAND and jump to it. + */ + bl nand_boot /* will not return */ +#endif /* CONFIG_NAND_SPL */ |