mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	The rest of the unmigrated CONFIG symbols in the CONFIG_SYS namespace do not easily transition to Kconfig. In many cases they likely should come from the device tree instead. Move these out of CONFIG namespace and in to CFG namespace. Signed-off-by: Tom Rini <trini@konsulko.com> Reviewed-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			1906 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			1906 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0+ */
 | |
| /*
 | |
|  * Copyright 2004, 2007-2012 Freescale Semiconductor, Inc.
 | |
|  * Copyright (C) 2003  Motorola,Inc.
 | |
|  */
 | |
| 
 | |
| /* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
 | |
|  *
 | |
|  * The processor starts at 0xfffffffc and the code is first executed in the
 | |
|  * last 4K page(0xfffff000-0xffffffff) in flash/rom.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <asm-offsets.h>
 | |
| #include <config.h>
 | |
| #include <mpc85xx.h>
 | |
| #include <system-constants.h>
 | |
| 
 | |
| #include <ppc_asm.tmpl>
 | |
| #include <ppc_defs.h>
 | |
| 
 | |
| #include <asm/cache.h>
 | |
| #include <asm/mmu.h>
 | |
| 
 | |
| #undef	MSR_KERNEL
 | |
| #define MSR_KERNEL ( MSR_ME )	/* Machine Check */
 | |
| 
 | |
| #define LAW_EN		0x80000000
 | |
| 
 | |
| #if defined(CONFIG_NAND_SPL) || \
 | |
| 	(defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(INIT_MINIMAL))
 | |
| #define MINIMAL_SPL
 | |
| #endif
 | |
| 
 | |
| #if !defined(CONFIG_SPL) && !defined(CONFIG_SYS_RAMBOOT) && \
 | |
| 	!defined(CONFIG_NXP_ESBC) && !defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
 | |
| #define NOR_BOOT
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Set up GOT: Global Offset Table
 | |
|  *
 | |
|  * Use r12 to access the GOT
 | |
|  */
 | |
| 	START_GOT
 | |
| 	GOT_ENTRY(_GOT2_TABLE_)
 | |
| 	GOT_ENTRY(_FIXUP_TABLE_)
 | |
| 
 | |
| #ifndef MINIMAL_SPL
 | |
| 	GOT_ENTRY(_start_of_vectors)
 | |
| 	GOT_ENTRY(_end_of_vectors)
 | |
| 	GOT_ENTRY(transfer_to_handler)
 | |
| #endif
 | |
| 
 | |
| 	GOT_ENTRY(__init_end)
 | |
| 	GOT_ENTRY(__bss_end)
 | |
| 	GOT_ENTRY(__bss_start)
 | |
| 	END_GOT
 | |
| 
 | |
| #ifdef CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR
 | |
| #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 | |
| 
 | |
| /* Maximal size of the image */
 | |
| #ifdef CONFIG_SPL_BUILD
 | |
| #define MAX_IMAGE_SIZE (CONFIG_SPL_MAX_SIZE - (CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR_DATA * 512))
 | |
| #else
 | |
| #define MAX_IMAGE_SIZE CONFIG_SYS_L2_SIZE
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_SPL_BUILD) && CONFIG_SPL_MAX_SIZE < CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR_DATA * 512
 | |
| #error "CONFIG_SPL_MAX_SIZE is too small for CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR_DATA"
 | |
| #endif
 | |
| 
 | |
| #if MAX_IMAGE_SIZE > CONFIG_SYS_L2_SIZE
 | |
| #error "Image is too big"
 | |
| #endif
 | |
| 
 | |
| #define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b))
 | |
| #define ALIGN(x, a) (DIV_ROUND_UP(x, a) * (a))
 | |
| 
 | |
| /* Definitions from C header file asm/immap_85xx.h */
 | |
| 
 | |
| #define CFG_SYS_MPC85xx_L2_OFFSET		0x20000
 | |
| 
 | |
| #define MPC85xx_L2CTL				0x000
 | |
| #define MPC85xx_L2CTL_L2E			0x80000000
 | |
| #define MPC85xx_L2CTL_L2SRAM_ENTIRE		0x00010000
 | |
| 
 | |
| #define MPC85xx_L2SRBAR0			0x100
 | |
| 
 | |
| #define MPC85xx_L2ERRDIS			0xe44
 | |
| #define MPC85xx_L2ERRDIS_MBECC			0x00000008
 | |
| #define MPC85xx_L2ERRDIS_SBECC			0x00000004
 | |
| 
 | |
| /* Definitions from C header file fsl_esdhc.h */
 | |
| 
 | |
| #define ESDHCCTL				0x0002e40c
 | |
| #define ESDHCCTL_SNOOP				0x00000040
 | |
| 
 | |
| /*
 | |
|  * QorIQ pre-PBL eSDHC boot sector:
 | |
|  * Instruct BootROM to configure L2 SRAM and eSDHC then load image
 | |
|  * from SD card into L2 SRAM and finally jump to image entry point.
 | |
|  */
 | |
| 	.section .bootsect, "a"
 | |
| 	.globl bootsect
 | |
| 
 | |
| bootsect:
 | |
| 	.org 0x40 /* BOOT signature */
 | |
| 	.ascii "BOOT"
 | |
| 
 | |
| 	.org 0x48 /* Number of bytes to be copied, must be multiple of block size (512) */
 | |
| 	.long ALIGN(MAX_IMAGE_SIZE, 512)
 | |
| 
 | |
| 	.org 0x50 /* Source address from the beginning of boot sector in byte address format, must be multiple of block size (512) */
 | |
| 	.long (CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR_START + CONFIG_FSL_PREPBL_ESDHC_BOOT_SECTOR_DATA) * 512
 | |
| 
 | |
| 	.org 0x58 /* Target address in the system's local memory address space */
 | |
| 	.long CONFIG_SYS_MONITOR_BASE
 | |
| 
 | |
| 	.org 0x60 /* Execution starting address */
 | |
| 	.long _start
 | |
| 
 | |
| 	.org 0x68 /* Number of configuration data pairs */
 | |
| 	.long DIV_ROUND_UP(.Lconf_pair_end - .Lconf_pair_start, 8)
 | |
| 
 | |
| 	.org 0x80 /* Start of configuration */
 | |
| 	.Lconf_pair_start:
 | |
| 
 | |
| 	.long CONFIG_SYS_CCSRBAR_DEFAULT + CFG_SYS_MPC85xx_L2_OFFSET + MPC85xx_L2SRBAR0 /* Address: L2 memory-mapped SRAM base addr 0 */
 | |
| 	.long CFG_SYS_INIT_L2_ADDR
 | |
| 
 | |
| 	.long CONFIG_SYS_CCSRBAR_DEFAULT + CFG_SYS_MPC85xx_L2_OFFSET + MPC85xx_L2ERRDIS /* Address: L2 cache error disable */
 | |
| 	.long MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC
 | |
| 
 | |
| 	.long CONFIG_SYS_CCSRBAR_DEFAULT + CFG_SYS_MPC85xx_L2_OFFSET + MPC85xx_L2CTL /* Address: L2 configuration 0 */
 | |
| 	.long MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE
 | |
| 
 | |
| 	.long CONFIG_SYS_CCSRBAR_DEFAULT + ESDHCCTL /* Address: eSDHC DMA control */
 | |
| 	.long ESDHCCTL_SNOOP
 | |
| 
 | |
| 	.long 0x40000001 /* Command: Delay in 8 CCB clocks */
 | |
| 	.long 256
 | |
| 
 | |
| 	.long 0x80000001 /* End of configuration */
 | |
| 	.Lconf_pair_end:
 | |
| 
 | |
| 	.org 0x1b8 /* Reserved for MBR/DBR */
 | |
| 	.org 0x200 /* End of boot sector */
 | |
| 
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * e500 Startup -- after reset only the last 4KB of the effective
 | |
|  * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
 | |
|  * section is located at THIS LAST page and basically does three
 | |
|  * things: clear some registers, set up exception tables and
 | |
|  * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
 | |
|  * continue the boot procedure.
 | |
| 
 | |
|  * Once the boot rom is mapped by TLB entries we can proceed
 | |
|  * with normal startup.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| 	.section .bootpg,"ax"
 | |
| 	.globl _start
 | |
| 
 | |
| _start:
 | |
| /* Enable debug exception */
 | |
| 	li	r1,MSR_DE
 | |
| 	mtmsr	r1
 | |
| 
 | |
| 	/*
 | |
| 	 * If we got an ePAPR device tree pointer passed in as r3, we need that
 | |
| 	 * later in cpu_init_early_f(). Save it to a safe register before we
 | |
| 	 * clobber it so that we can fetch it from there later.
 | |
| 	 */
 | |
| 	mr	r24, r3
 | |
| 
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
 | |
| 	mfspr	r3,SPRN_SVR
 | |
| 	rlwinm	r3,r3,0,0xff
 | |
| 	li	r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
 | |
| 	cmpw	r3,r4
 | |
| 	beq	1f
 | |
| 
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
 | |
| 	li	r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
 | |
| 	cmpw	r3,r4
 | |
| 	beq	1f
 | |
| #endif
 | |
| 
 | |
| 	/* Not a supported revision affected by erratum */
 | |
| 	li	r27,0
 | |
| 	b	2f
 | |
| 
 | |
| 1:	li	r27,1	/* Remember for later that we have the erratum */
 | |
| 	/* Erratum says set bits 55:60 to 001001 */
 | |
| 	msync
 | |
| 	isync
 | |
| 	mfspr	r3,SPRN_HDBCR0
 | |
| 	li	r4,0x48
 | |
| 	rlwimi	r3,r4,0,0x1f8
 | |
| 	mtspr	SPRN_HDBCR0,r3
 | |
| 	isync
 | |
| 2:
 | |
| #endif
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_A005125
 | |
| 	msync
 | |
| 	isync
 | |
| 	mfspr	r3, SPRN_HDBCR0
 | |
| 	oris	r3, r3, 0x0080
 | |
| 	mtspr	SPRN_HDBCR0, r3
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #if defined(CONFIG_NXP_ESBC) && defined(CONFIG_E500MC) && \
 | |
| 	!defined(CONFIG_E6500)
 | |
| 	/* ISBC uses L2 as stack.
 | |
| 	 * Disable L2 cache here so that u-boot can enable it later
 | |
| 	 * as part of it's normal flow
 | |
| 	*/
 | |
| 
 | |
| 	/* Check if L2 is enabled */
 | |
| 	mfspr	r3, SPRN_L2CSR0
 | |
| 	lis	r2, L2CSR0_L2E@h
 | |
| 	ori	r2, r2, L2CSR0_L2E@l
 | |
| 	and.	r4, r3, r2
 | |
| 	beq	l2_disabled
 | |
| 
 | |
| 	mfspr r3, SPRN_L2CSR0
 | |
| 	/* Flush L2 cache */
 | |
| 	lis     r2,(L2CSR0_L2FL)@h
 | |
| 	ori     r2, r2, (L2CSR0_L2FL)@l
 | |
| 	or      r3, r2, r3
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr   SPRN_L2CSR0,r3
 | |
| 	isync
 | |
| 1:
 | |
| 	mfspr r3, SPRN_L2CSR0
 | |
| 	and. r1, r3, r2
 | |
| 	bne 1b
 | |
| 
 | |
| 	mfspr r3, SPRN_L2CSR0
 | |
| 	lis r2, L2CSR0_L2E@h
 | |
| 	ori r2, r2, L2CSR0_L2E@l
 | |
| 	andc r4, r3, r2
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr SPRN_L2CSR0,r4
 | |
| 	isync
 | |
| 
 | |
| l2_disabled:
 | |
| #endif
 | |
| 
 | |
| /* clear registers/arrays not reset by hardware */
 | |
| 
 | |
| 	/* L1 */
 | |
| 	li	r0,2
 | |
| 	mtspr	L1CSR0,r0	/* invalidate d-cache */
 | |
| 	mtspr	L1CSR1,r0	/* invalidate i-cache */
 | |
| 
 | |
| 	mfspr	r1,DBSR
 | |
| 	mtspr	DBSR,r1		/* Clear all valid bits */
 | |
| 
 | |
| 
 | |
| 	.macro	create_tlb1_entry esel ts tsize epn wimg rpn perm phy_high scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
 | |
| 	mtspr	MAS0, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@l
 | |
| 	mtspr	MAS1, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
 | |
| 	mtspr	MAS2, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
 | |
| 	mtspr	MAS3, \scratch
 | |
| 	lis	\scratch, \phy_high@h
 | |
| 	ori	\scratch, \scratch, \phy_high@l
 | |
| 	mtspr	MAS7, \scratch
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	.endm
 | |
| 
 | |
| 	.macro	create_tlb0_entry esel ts tsize epn wimg rpn perm phy_high scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
 | |
| 	mtspr	MAS0, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@l
 | |
| 	mtspr	MAS1, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
 | |
| 	mtspr	MAS2, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
 | |
| 	mtspr	MAS3, \scratch
 | |
| 	lis	\scratch, \phy_high@h
 | |
| 	ori	\scratch, \scratch, \phy_high@l
 | |
| 	mtspr	MAS7, \scratch
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	.endm
 | |
| 
 | |
| 	.macro	delete_tlb1_entry esel scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
 | |
| 	mtspr	MAS0, \scratch
 | |
| 	li	\scratch, 0
 | |
| 	mtspr	MAS1, \scratch
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	.endm
 | |
| 
 | |
| 	.macro	delete_tlb0_entry esel epn wimg scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
 | |
| 	mtspr	MAS0, \scratch
 | |
| 	li	\scratch, 0
 | |
| 	mtspr	MAS1, \scratch
 | |
| 	lis	\scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
 | |
| 	ori	\scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
 | |
| 	mtspr	MAS2, \scratch
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	.endm
 | |
| 
 | |
| /* Interrupt vectors do not fit in minimal SPL. */
 | |
| #if !defined(MINIMAL_SPL)
 | |
| 	/* Setup interrupt vectors */
 | |
| 	lis	r1,CONFIG_VAL(SYS_MONITOR_BASE)@h
 | |
| 	mtspr	IVPR,r1
 | |
| 
 | |
| 	li	r4,CriticalInput@l
 | |
| 	mtspr	IVOR0,r4	/* 0: Critical input */
 | |
| 	li	r4,MachineCheck@l
 | |
| 	mtspr	IVOR1,r4	/* 1: Machine check */
 | |
| 	li	r4,DataStorage@l
 | |
| 	mtspr	IVOR2,r4	/* 2: Data storage */
 | |
| 	li	r4,InstStorage@l
 | |
| 	mtspr	IVOR3,r4	/* 3: Instruction storage */
 | |
| 	li	r4,ExtInterrupt@l
 | |
| 	mtspr	IVOR4,r4	/* 4: External interrupt */
 | |
| 	li	r4,Alignment@l
 | |
| 	mtspr	IVOR5,r4	/* 5: Alignment */
 | |
| 	li	r4,ProgramCheck@l
 | |
| 	mtspr	IVOR6,r4	/* 6: Program check */
 | |
| 	li	r4,FPUnavailable@l
 | |
| 	mtspr	IVOR7,r4	/* 7: floating point unavailable */
 | |
| 	li	r4,SystemCall@l
 | |
| 	mtspr	IVOR8,r4	/* 8: System call */
 | |
| 	/* 9: Auxiliary processor unavailable(unsupported) */
 | |
| 	li	r4,Decrementer@l
 | |
| 	mtspr	IVOR10,r4	/* 10: Decrementer */
 | |
| 	li	r4,IntervalTimer@l
 | |
| 	mtspr	IVOR11,r4	/* 11: Interval timer */
 | |
| 	li	r4,WatchdogTimer@l
 | |
| 	mtspr	IVOR12,r4	/* 12: Watchdog timer */
 | |
| 	li	r4,DataTLBError@l
 | |
| 	mtspr	IVOR13,r4	/* 13: Data TLB error */
 | |
| 	li	r4,InstructionTLBError@l
 | |
| 	mtspr	IVOR14,r4	/* 14: Instruction TLB error */
 | |
| 	li	r4,DebugBreakpoint@l
 | |
| 	mtspr	IVOR15,r4	/* 15: Debug */
 | |
| #endif
 | |
| 
 | |
| 	/* Clear and set up some registers. */
 | |
| 	li      r0,0x0000
 | |
| 	lis	r1,0xffff
 | |
| 	mtspr	DEC,r0			/* prevent dec exceptions */
 | |
| 	mttbl	r0			/* prevent fit & wdt exceptions */
 | |
| 	mttbu	r0
 | |
| 	mtspr	TSR,r1			/* clear all timer exception status */
 | |
| 	mtspr	TCR,r0			/* disable all */
 | |
| 	mtspr	ESR,r0			/* clear exception syndrome register */
 | |
| 	mtspr	MCSR,r0			/* machine check syndrome register */
 | |
| 	mtxer	r0			/* clear integer exception register */
 | |
| 
 | |
| #ifdef CONFIG_SYS_BOOK3E_HV
 | |
| 	mtspr	MAS8,r0			/* make sure MAS8 is clear */
 | |
| #endif
 | |
| 
 | |
| 	/* Enable Time Base and Select Time Base Clock */
 | |
| 	lis	r0,HID0_EMCP@h		/* Enable machine check */
 | |
| #if defined(CONFIG_ENABLE_36BIT_PHYS)
 | |
| 	ori	r0,r0,HID0_ENMAS7@l	/* Enable MAS7 */
 | |
| #endif
 | |
| #ifndef CONFIG_E500MC
 | |
| 	ori	r0,r0,HID0_TBEN@l	/* Enable Timebase */
 | |
| #endif
 | |
| 	mtspr	HID0,r0
 | |
| 
 | |
| #if !defined(CONFIG_E500MC) && !defined(CONFIG_ARCH_QEMU_E500)
 | |
| 	li	r0,(HID1_ASTME|HID1_ABE)@l	/* Addr streaming & broadcast */
 | |
| 	mfspr	r3,PVR
 | |
| 	andi.	r3,r3, 0xff
 | |
| 	cmpwi	r3,0x50@l	/* if we are rev 5.0 or greater set MBDD */
 | |
| 	blt 1f
 | |
| 	/* Set MBDD bit also */
 | |
| 	ori r0, r0, HID1_MBDD@l
 | |
| 1:
 | |
| 	mtspr	HID1,r0
 | |
| #endif
 | |
| 
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 | |
| 	mfspr	r3,SPRN_HDBCR1
 | |
| 	oris	r3,r3,0x0100
 | |
| 	mtspr	SPRN_HDBCR1,r3
 | |
| #endif
 | |
| 
 | |
| 	/* Enable Branch Prediction */
 | |
| #if defined(CONFIG_BTB)
 | |
| 	lis	r0,BUCSR_ENABLE@h
 | |
| 	ori	r0,r0,BUCSR_ENABLE@l
 | |
| 	mtspr	SPRN_BUCSR,r0
 | |
| #endif
 | |
| 
 | |
| #if defined(CFG_SYS_INIT_DBCR)
 | |
| 	lis	r1,0xffff
 | |
| 	ori	r1,r1,0xffff
 | |
| 	mtspr	DBSR,r1			/* Clear all status bits */
 | |
| 	lis	r0,CFG_SYS_INIT_DBCR@h	/* DBCR0[IDM] must be set */
 | |
| 	ori	r0,r0,CFG_SYS_INIT_DBCR@l
 | |
| 	mtspr	DBCR0,r0
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Search for the TLB that covers the code we're executing, and shrink it
 | |
|  * so that it covers only this 4K page.  That will ensure that any other
 | |
|  * TLB we create won't interfere with it.  We assume that the TLB exists,
 | |
|  * which is why we don't check the Valid bit of MAS1.  We also assume
 | |
|  * it is in TLB1.
 | |
|  *
 | |
|  * This is necessary, for example, when booting from the on-chip ROM,
 | |
|  * which (oddly) creates a single 4GB TLB that covers CCSR and DDR.
 | |
|  */
 | |
| 	bl	nexti		/* Find our address */
 | |
| nexti:	mflr	r1		/* R1 = our PC */
 | |
| 	li	r2, 0
 | |
| 	mtspr	MAS6, r2	/* Assume the current PID and AS are 0 */
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbsx	0, r1		/* This must succeed */
 | |
| 
 | |
| 	mfspr	r14, MAS0	/* Save ESEL for later */
 | |
| 	rlwinm	r14, r14, 16, 0xfff
 | |
| 
 | |
| 	/* Set the size of the TLB to 4KB */
 | |
| 	mfspr	r3, MAS1
 | |
| 	li	r2, 0xF80
 | |
| 	andc	r3, r3, r2	/* Clear the TSIZE bits */
 | |
| 	ori	r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l
 | |
| 	oris	r3, r3, MAS1_IPROT@h
 | |
| 	mtspr	MAS1, r3
 | |
| 
 | |
| 	/*
 | |
| 	 * Set the base address of the TLB to our PC.  We assume that
 | |
| 	 * virtual == physical.  We also assume that MAS2_EPN == MAS3_RPN.
 | |
| 	 */
 | |
| 	lis	r3, MAS2_EPN@h
 | |
| 	ori	r3, r3, MAS2_EPN@l	/* R3 = MAS2_EPN */
 | |
| 
 | |
| 	and	r1, r1, r3	/* Our PC, rounded down to the nearest page */
 | |
| 
 | |
| 	mfspr	r2, MAS2
 | |
| 	andc	r2, r2, r3
 | |
| 	or	r2, r2, r1
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
 | |
| 	cmpwi	r27,0
 | |
| 	beq	1f
 | |
| 	andi.	r15, r2, MAS2_I|MAS2_G /* save the old I/G for later */
 | |
| 	rlwinm	r2, r2, 0, ~MAS2_I
 | |
| 	ori	r2, r2, MAS2_G
 | |
| 1:
 | |
| #endif
 | |
| 	mtspr	MAS2, r2	/* Set the EPN to our PC base address */
 | |
| 
 | |
| 	mfspr	r2, MAS3
 | |
| 	andc	r2, r2, r3
 | |
| 	or	r2, r2, r1
 | |
| 	mtspr	MAS3, r2	/* Set the RPN to our PC base address */
 | |
| 
 | |
| 	isync
 | |
| 	msync
 | |
| 	tlbwe
 | |
| 
 | |
| /*
 | |
|  * Clear out any other TLB entries that may exist, to avoid conflicts.
 | |
|  * Our TLB entry is in r14.
 | |
|  */
 | |
| 	li	r0, TLBIVAX_ALL | TLBIVAX_TLB0
 | |
| 	tlbivax 0, r0
 | |
| 	tlbsync
 | |
| 
 | |
| 	mfspr	r4, SPRN_TLB1CFG
 | |
| 	rlwinm	r4, r4, 0, TLBnCFG_NENTRY_MASK
 | |
| 
 | |
| 	li	r3, 0
 | |
| 	mtspr	MAS1, r3
 | |
| 1:	cmpw	r3, r14
 | |
| 	rlwinm	r5, r3, 16, MAS0_ESEL_MSK
 | |
| 	addi	r3, r3, 1
 | |
| 	beq	2f		/* skip the entry we're executing from */
 | |
| 
 | |
| 	oris	r5, r5, MAS0_TLBSEL(1)@h
 | |
| 	mtspr	MAS0, r5
 | |
| 
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 2:	cmpw	r3, r4
 | |
| 	blt	1b
 | |
| 
 | |
| #if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(MINIMAL_SPL) && \
 | |
| 	!defined(CONFIG_NXP_ESBC)
 | |
| /*
 | |
|  * TLB entry for debuggging in AS1
 | |
|  * Create temporary TLB entry in AS0 to handle debug exception
 | |
|  * As on debug exception MSR is cleared i.e. Address space is changed
 | |
|  * to 0. A TLB entry (in AS0) is required to handle debug exception generated
 | |
|  * in AS1.
 | |
|  */
 | |
| 
 | |
| #ifdef NOR_BOOT
 | |
| /*
 | |
|  * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
 | |
|  * bacause flash's virtual address maps to 0xff800000 - 0xffffffff.
 | |
|  * and this window is outside of 4K boot window.
 | |
|  */
 | |
| 	create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
 | |
| 		0, BOOKE_PAGESZ_4M, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xffc00000,  MAS2_I|MAS2_G, \
 | |
| 		0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| 
 | |
| #else
 | |
| /*
 | |
|  * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
 | |
|  * because "nexti" will resize TLB to 4K
 | |
|  */
 | |
| 	create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
 | |
| 		0, BOOKE_PAGESZ_256K, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfffc0000, MAS2_I, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfffc0000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Relocate CCSR, if necessary.  We relocate CCSR if (obviously) the default
 | |
|  * location is not where we want it.  This typically happens on a 36-bit
 | |
|  * system, where we want to move CCSR to near the top of 36-bit address space.
 | |
|  *
 | |
|  * To move CCSR, we create two temporary TLBs, one for the old location, and
 | |
|  * another for the new location.  On CoreNet systems, we also need to create
 | |
|  * a special, temporary LAW.
 | |
|  *
 | |
|  * As a general rule, TLB0 is used for short-term TLBs, and TLB1 is used for
 | |
|  * long-term TLBs, so we use TLB0 here.
 | |
|  */
 | |
| #if (CONFIG_SYS_CCSRBAR_DEFAULT != CFG_SYS_CCSRBAR_PHYS)
 | |
| 
 | |
| #if !defined(CFG_SYS_CCSRBAR_PHYS_HIGH) || !defined(CFG_SYS_CCSRBAR_PHYS_LOW)
 | |
| #error "CFG_SYS_CCSRBAR_PHYS_HIGH and CFG_SYS_CCSRBAR_PHYS_LOW) must be defined."
 | |
| #endif
 | |
| 
 | |
| create_ccsr_new_tlb:
 | |
| 	/*
 | |
| 	 * Create a TLB for the new location of CCSR.  Register R8 is reserved
 | |
| 	 * for the virtual address of this TLB (CFG_SYS_CCSRBAR).
 | |
| 	 */
 | |
| 	lis	r8, CFG_SYS_CCSRBAR@h
 | |
| 	ori	r8, r8, CFG_SYS_CCSRBAR@l
 | |
| 	lis	r9, (CFG_SYS_CCSRBAR + 0x1000)@h
 | |
| 	ori	r9, r9, (CFG_SYS_CCSRBAR + 0x1000)@l
 | |
| 	create_tlb0_entry 0, \
 | |
| 		0, BOOKE_PAGESZ_4K, \
 | |
| 		CFG_SYS_CCSRBAR, MAS2_I|MAS2_G, \
 | |
| 		CFG_SYS_CCSRBAR_PHYS_LOW, MAS3_SW|MAS3_SR, \
 | |
| 		CFG_SYS_CCSRBAR_PHYS_HIGH, r3
 | |
| 	/*
 | |
| 	 * Create a TLB for the current location of CCSR.  Register R9 is reserved
 | |
| 	 * for the virtual address of this TLB (CFG_SYS_CCSRBAR + 0x1000).
 | |
| 	 */
 | |
| create_ccsr_old_tlb:
 | |
| 	create_tlb0_entry 1, \
 | |
| 		0, BOOKE_PAGESZ_4K, \
 | |
| 		CFG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, \
 | |
| 		CONFIG_SYS_CCSRBAR_DEFAULT, MAS3_SW|MAS3_SR, \
 | |
| 		0, r3 /* The default CCSR address is always a 32-bit number */
 | |
| 
 | |
| 
 | |
| 	/*
 | |
| 	 * We have a TLB for what we think is the current (old) CCSR.  Let's
 | |
| 	 * verify that, otherwise we won't be able to move it.
 | |
| 	 * CONFIG_SYS_CCSRBAR_DEFAULT is always a 32-bit number, so we only
 | |
| 	 * need to compare the lower 32 bits of CCSRBAR on CoreNet systems.
 | |
| 	 */
 | |
| verify_old_ccsr:
 | |
| 	lis     r0, CONFIG_SYS_CCSRBAR_DEFAULT@h
 | |
| 	ori     r0, r0, CONFIG_SYS_CCSRBAR_DEFAULT@l
 | |
| #ifdef CONFIG_FSL_CORENET
 | |
| 	lwz	r1, 4(r9)		/* CCSRBARL */
 | |
| #else
 | |
| 	lwz	r1, 0(r9)		/* CCSRBAR, shifted right by 12 */
 | |
| 	slwi	r1, r1, 12
 | |
| #endif
 | |
| 
 | |
| 	cmpl	0, r0, r1
 | |
| 
 | |
| 	/*
 | |
| 	 * If the value we read from CCSRBARL is not what we expect, then
 | |
| 	 * enter an infinite loop.  This will at least allow a debugger to
 | |
| 	 * halt execution and examine TLBs, etc.  There's no point in going
 | |
| 	 * on.
 | |
| 	 */
 | |
| infinite_debug_loop:
 | |
| 	bne	infinite_debug_loop
 | |
| 
 | |
| #ifdef CONFIG_FSL_CORENET
 | |
| 
 | |
| #define CCSR_LAWBARH0	(CFG_SYS_CCSRBAR + 0x1000)
 | |
| #define LAW_SIZE_4K	0xb
 | |
| #define CCSRBAR_LAWAR	(LAW_EN | (0x1e << 20) | LAW_SIZE_4K)
 | |
| #define CCSRAR_C	0x80000000	/* Commit */
 | |
| 
 | |
| create_temp_law:
 | |
| 	/*
 | |
| 	 * On CoreNet systems, we create the temporary LAW using a special LAW
 | |
| 	 * target ID of 0x1e.  LAWBARH is at offset 0xc00 in CCSR.
 | |
| 	 */
 | |
| 	lis     r0, CFG_SYS_CCSRBAR_PHYS_HIGH@h
 | |
| 	ori     r0, r0, CFG_SYS_CCSRBAR_PHYS_HIGH@l
 | |
| 	lis     r1, CFG_SYS_CCSRBAR_PHYS_LOW@h
 | |
| 	ori     r1, r1, CFG_SYS_CCSRBAR_PHYS_LOW@l
 | |
| 	lis     r2, CCSRBAR_LAWAR@h
 | |
| 	ori     r2, r2, CCSRBAR_LAWAR@l
 | |
| 
 | |
| 	stw     r0, 0xc00(r9)	/* LAWBARH0 */
 | |
| 	stw     r1, 0xc04(r9)	/* LAWBARL0 */
 | |
| 	sync
 | |
| 	stw     r2, 0xc08(r9)	/* LAWAR0 */
 | |
| 
 | |
| 	/*
 | |
| 	 * Read back from LAWAR to ensure the update is complete.  e500mc
 | |
| 	 * cores also require an isync.
 | |
| 	 */
 | |
| 	lwz	r0, 0xc08(r9)	/* LAWAR0 */
 | |
| 	isync
 | |
| 
 | |
| 	/*
 | |
| 	 * Read the current CCSRBARH and CCSRBARL using load word instructions.
 | |
| 	 * Follow this with an isync instruction. This forces any outstanding
 | |
| 	 * accesses to configuration space to completion.
 | |
| 	 */
 | |
| read_old_ccsrbar:
 | |
| 	lwz	r0, 0(r9)	/* CCSRBARH */
 | |
| 	lwz	r0, 4(r9)	/* CCSRBARL */
 | |
| 	isync
 | |
| 
 | |
| 	/*
 | |
| 	 * Write the new values for CCSRBARH and CCSRBARL to their old
 | |
| 	 * locations.  The CCSRBARH has a shadow register. When the CCSRBARH
 | |
| 	 * has a new value written it loads a CCSRBARH shadow register. When
 | |
| 	 * the CCSRBARL is written, the CCSRBARH shadow register contents
 | |
| 	 * along with the CCSRBARL value are loaded into the CCSRBARH and
 | |
| 	 * CCSRBARL registers, respectively.  Follow this with a sync
 | |
| 	 * instruction.
 | |
| 	 */
 | |
| write_new_ccsrbar:
 | |
| 	lis	r0, CFG_SYS_CCSRBAR_PHYS_HIGH@h
 | |
| 	ori	r0, r0, CFG_SYS_CCSRBAR_PHYS_HIGH@l
 | |
| 	lis	r1, CFG_SYS_CCSRBAR_PHYS_LOW@h
 | |
| 	ori	r1, r1, CFG_SYS_CCSRBAR_PHYS_LOW@l
 | |
| 	lis	r2, CCSRAR_C@h
 | |
| 	ori	r2, r2, CCSRAR_C@l
 | |
| 
 | |
| 	stw	r0, 0(r9)	/* Write to CCSRBARH */
 | |
| 	sync			/* Make sure we write to CCSRBARH first */
 | |
| 	stw	r1, 4(r9)	/* Write to CCSRBARL */
 | |
| 	sync
 | |
| 
 | |
| 	/*
 | |
| 	 * Write a 1 to the commit bit (C) of CCSRAR at the old location.
 | |
| 	 * Follow this with a sync instruction.
 | |
| 	 */
 | |
| 	stw	r2, 8(r9)
 | |
| 	sync
 | |
| 
 | |
| 	/* Delete the temporary LAW */
 | |
| delete_temp_law:
 | |
| 	li	r1, 0
 | |
| 	stw	r1, 0xc08(r8)
 | |
| 	sync
 | |
| 	stw	r1, 0xc00(r8)
 | |
| 	stw	r1, 0xc04(r8)
 | |
| 	sync
 | |
| 
 | |
| #else /* #ifdef CONFIG_FSL_CORENET */
 | |
| 
 | |
| write_new_ccsrbar:
 | |
| 	/*
 | |
| 	 * Read the current value of CCSRBAR using a load word instruction
 | |
| 	 * followed by an isync. This forces all accesses to configuration
 | |
| 	 * space to complete.
 | |
| 	 */
 | |
| 	sync
 | |
| 	lwz	r0, 0(r9)
 | |
| 	isync
 | |
| 
 | |
| /* CFG_SYS_CCSRBAR_PHYS right shifted by 12 */
 | |
| #define CCSRBAR_PHYS_RS12 ((CFG_SYS_CCSRBAR_PHYS_HIGH << 20) | \
 | |
| 			   (CFG_SYS_CCSRBAR_PHYS_LOW >> 12))
 | |
| 
 | |
| 	/* Write the new value to CCSRBAR. */
 | |
| 	lis	r0, CCSRBAR_PHYS_RS12@h
 | |
| 	ori	r0, r0, CCSRBAR_PHYS_RS12@l
 | |
| 	stw	r0, 0(r9)
 | |
| 	sync
 | |
| 
 | |
| 	/*
 | |
| 	 * The manual says to perform a load of an address that does not
 | |
| 	 * access configuration space or the on-chip SRAM using an existing TLB,
 | |
| 	 * but that doesn't appear to be necessary.  We will do the isync,
 | |
| 	 * though.
 | |
| 	 */
 | |
| 	isync
 | |
| 
 | |
| 	/*
 | |
| 	 * Read the contents of CCSRBAR from its new location, followed by
 | |
| 	 * another isync.
 | |
| 	 */
 | |
| 	lwz	r0, 0(r8)
 | |
| 	isync
 | |
| 
 | |
| #endif  /* #ifdef CONFIG_FSL_CORENET */
 | |
| 
 | |
| 	/* Delete the temporary TLBs */
 | |
| delete_temp_tlbs:
 | |
| 	delete_tlb0_entry 0, CFG_SYS_CCSRBAR, MAS2_I|MAS2_G, r3
 | |
| 	delete_tlb0_entry 1, CFG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, r3
 | |
| 
 | |
| #endif /* #if (CONFIG_SYS_CCSRBAR_DEFAULT != CFG_SYS_CCSRBAR_PHYS) */
 | |
| 
 | |
| #if defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2) && defined(CONFIG_E6500)
 | |
| create_ccsr_l2_tlb:
 | |
| 	/*
 | |
| 	 * Create a TLB for the MMR location of CCSR
 | |
| 	 * to access L2CSR0 register
 | |
| 	 */
 | |
| 	create_tlb0_entry 0, \
 | |
| 		0, BOOKE_PAGESZ_4K, \
 | |
| 		CFG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, \
 | |
| 		CFG_SYS_CCSRBAR_PHYS_LOW + 0xC20000, MAS3_SW|MAS3_SR, \
 | |
| 		CFG_SYS_CCSRBAR_PHYS_HIGH, r3
 | |
| 
 | |
| enable_l2_cluster_l2:
 | |
| 	/* enable L2 cache */
 | |
| 	lis	r3, (CFG_SYS_CCSRBAR + 0xC20000)@h
 | |
| 	ori	r3, r3, (CFG_SYS_CCSRBAR + 0xC20000)@l
 | |
| 	li	r4, 33	/* stash id */
 | |
| 	stw	r4, 4(r3)
 | |
| 	lis	r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@h
 | |
| 	ori	r4, r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@l
 | |
| 	sync
 | |
| 	stw	r4, 0(r3)	/* invalidate L2 */
 | |
| 	/* Poll till the bits are cleared */
 | |
| 1:	sync
 | |
| 	lwz	r0, 0(r3)
 | |
| 	twi	0, r0, 0
 | |
| 	isync
 | |
| 	and.	r1, r0, r4
 | |
| 	bne	1b
 | |
| 
 | |
| 	/* L2PE must be set before L2 cache is enabled */
 | |
| 	lis	r4, (L2CSR0_L2PE)@h
 | |
| 	ori	r4, r4, (L2CSR0_L2PE)@l
 | |
| 	sync
 | |
| 	stw	r4, 0(r3)	/* enable L2 parity/ECC error checking */
 | |
| 	/* Poll till the bit is set */
 | |
| 1:	sync
 | |
| 	lwz	r0, 0(r3)
 | |
| 	twi	0, r0, 0
 | |
| 	isync
 | |
| 	and.	r1, r0, r4
 | |
| 	beq	1b
 | |
| 
 | |
| 	lis	r4, (L2CSR0_L2E|L2CSR0_L2PE)@h
 | |
| 	ori	r4, r4, (L2CSR0_L2REP_MODE)@l
 | |
| 	sync
 | |
| 	stw	r4, 0(r3)	/* enable L2 */
 | |
| 	/* Poll till the bit is set */
 | |
| 1:	sync
 | |
| 	lwz	r0, 0(r3)
 | |
| 	twi	0, r0, 0
 | |
| 	isync
 | |
| 	and.	r1, r0, r4
 | |
| 	beq	1b
 | |
| 
 | |
| delete_ccsr_l2_tlb:
 | |
| 	delete_tlb0_entry 0, CFG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, r3
 | |
| #endif
 | |
| 
 | |
| 	/*
 | |
| 	 * Enable the L1. On e6500, this has to be done
 | |
| 	 * after the L2 is up.
 | |
| 	 */
 | |
| 
 | |
| #ifdef CONFIG_SYS_CACHE_STASHING
 | |
| 	/* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
 | |
| 	li	r2,(32 + 0)
 | |
| 	mtspr	L1CSR2,r2
 | |
| #endif
 | |
| 
 | |
| 	/* Enable/invalidate the I-Cache */
 | |
| 	lis	r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
 | |
| 	ori	r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
 | |
| 	mtspr	SPRN_L1CSR1,r2
 | |
| 1:
 | |
| 	mfspr	r3,SPRN_L1CSR1
 | |
| 	and.	r1,r3,r2
 | |
| 	bne	1b
 | |
| 
 | |
| 	lis	r3,(L1CSR1_CPE|L1CSR1_ICE)@h
 | |
| 	ori	r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
 | |
| 	mtspr	SPRN_L1CSR1,r3
 | |
| 	isync
 | |
| 2:
 | |
| 	mfspr	r3,SPRN_L1CSR1
 | |
| 	andi.	r1,r3,L1CSR1_ICE@l
 | |
| 	beq	2b
 | |
| 
 | |
| 	/* Enable/invalidate the D-Cache */
 | |
| 	lis	r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
 | |
| 	ori	r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
 | |
| 	mtspr	SPRN_L1CSR0,r2
 | |
| 1:
 | |
| 	mfspr	r3,SPRN_L1CSR0
 | |
| 	and.	r1,r3,r2
 | |
| 	bne	1b
 | |
| 
 | |
| 	lis	r3,(L1CSR0_CPE|L1CSR0_DCE)@h
 | |
| 	ori	r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
 | |
| 	mtspr	SPRN_L1CSR0,r3
 | |
| 	isync
 | |
| 2:
 | |
| 	mfspr	r3,SPRN_L1CSR0
 | |
| 	andi.	r1,r3,L1CSR0_DCE@l
 | |
| 	beq	2b
 | |
| #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
 | |
| #define DCSR_LAWBARH0	(CFG_SYS_CCSRBAR + 0x1000)
 | |
| #define LAW_SIZE_1M	0x13
 | |
| #define DCSRBAR_LAWAR	(LAW_EN | (0x1d << 20) | LAW_SIZE_1M)
 | |
| 
 | |
| 	cmpwi	r27,0
 | |
| 	beq	9f
 | |
| 
 | |
| 	/*
 | |
| 	 * Create a TLB entry for CCSR
 | |
| 	 *
 | |
| 	 * We're executing out of TLB1 entry in r14, and that's the only
 | |
| 	 * TLB entry that exists.  To allocate some TLB entries for our
 | |
| 	 * own use, flip a bit high enough that we won't flip it again
 | |
| 	 * via incrementing.
 | |
| 	 */
 | |
| 
 | |
| 	xori	r8, r14, 32
 | |
| 	lis	r0, MAS0_TLBSEL(1)@h
 | |
| 	rlwimi	r0, r8, 16, MAS0_ESEL_MSK
 | |
| 	lis	r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@h
 | |
| 	ori	r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@l
 | |
| 	lis	r7, CFG_SYS_CCSRBAR@h
 | |
| 	ori	r7, r7, CFG_SYS_CCSRBAR@l
 | |
| 	ori	r2, r7, MAS2_I|MAS2_G
 | |
| 	lis	r3, FSL_BOOKE_MAS3(CFG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@h
 | |
| 	ori	r3, r3, FSL_BOOKE_MAS3(CFG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@l
 | |
| 	lis	r4, CFG_SYS_CCSRBAR_PHYS_HIGH@h
 | |
| 	ori	r4, r4, CFG_SYS_CCSRBAR_PHYS_HIGH@l
 | |
| 	mtspr	MAS0, r0
 | |
| 	mtspr	MAS1, r1
 | |
| 	mtspr	MAS2, r2
 | |
| 	mtspr	MAS3, r3
 | |
| 	mtspr	MAS7, r4
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 	/* Map DCSR temporarily to physical address zero */
 | |
| 	li	r0, 0
 | |
| 	lis	r3, DCSRBAR_LAWAR@h
 | |
| 	ori	r3, r3, DCSRBAR_LAWAR@l
 | |
| 
 | |
| 	stw	r0, 0xc00(r7)	/* LAWBARH0 */
 | |
| 	stw	r0, 0xc04(r7)	/* LAWBARL0 */
 | |
| 	sync
 | |
| 	stw	r3, 0xc08(r7)	/* LAWAR0 */
 | |
| 
 | |
| 	/* Read back from LAWAR to ensure the update is complete. */
 | |
| 	lwz	r3, 0xc08(r7)	/* LAWAR0 */
 | |
| 	isync
 | |
| 
 | |
| 	/* Create a TLB entry for DCSR at zero */
 | |
| 
 | |
| 	addi	r9, r8, 1
 | |
| 	lis	r0, MAS0_TLBSEL(1)@h
 | |
| 	rlwimi	r0, r9, 16, MAS0_ESEL_MSK
 | |
| 	lis	r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@h
 | |
| 	ori	r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@l
 | |
| 	li	r6, 0	/* DCSR effective address */
 | |
| 	ori	r2, r6, MAS2_I|MAS2_G
 | |
| 	li	r3, MAS3_SW|MAS3_SR
 | |
| 	li	r4, 0
 | |
| 	mtspr	MAS0, r0
 | |
| 	mtspr	MAS1, r1
 | |
| 	mtspr	MAS2, r2
 | |
| 	mtspr	MAS3, r3
 | |
| 	mtspr	MAS7, r4
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 	/* enable the timebase */
 | |
| #define CTBENR	0xe2084
 | |
| 	li	r3, 1
 | |
| 	addis	r4, r7, CTBENR@ha
 | |
| 	stw	r3, CTBENR@l(r4)
 | |
| 	lwz	r3, CTBENR@l(r4)
 | |
| 	twi	0,r3,0
 | |
| 	isync
 | |
| 
 | |
| 	.macro	erratum_set_ccsr offset value
 | |
| 	addis	r3, r7, \offset@ha
 | |
| 	lis	r4, \value@h
 | |
| 	addi	r3, r3, \offset@l
 | |
| 	ori	r4, r4, \value@l
 | |
| 	bl	erratum_set_value
 | |
| 	.endm
 | |
| 
 | |
| 	.macro	erratum_set_dcsr offset value
 | |
| 	addis	r3, r6, \offset@ha
 | |
| 	lis	r4, \value@h
 | |
| 	addi	r3, r3, \offset@l
 | |
| 	ori	r4, r4, \value@l
 | |
| 	bl	erratum_set_value
 | |
| 	.endm
 | |
| 
 | |
| 	erratum_set_dcsr 0xb0e08 0xe0201800
 | |
| 	erratum_set_dcsr 0xb0e18 0xe0201800
 | |
| 	erratum_set_dcsr 0xb0e38 0xe0400000
 | |
| 	erratum_set_dcsr 0xb0008 0x00900000
 | |
| 	erratum_set_dcsr 0xb0e40 0xe00a0000
 | |
| 	erratum_set_ccsr 0x18600 CFG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
 | |
| #ifdef  CONFIG_RAMBOOT_PBL
 | |
| 	erratum_set_ccsr 0x10f00 0x495e5000
 | |
| #else
 | |
| 	erratum_set_ccsr 0x10f00 0x415e5000
 | |
| #endif
 | |
| 	erratum_set_ccsr 0x11f00 0x415e5000
 | |
| 
 | |
| 	/* Make temp mapping uncacheable again, if it was initially */
 | |
| 	bl	2f
 | |
| 2:	mflr	r3
 | |
| 	tlbsx	0, r3
 | |
| 	mfspr	r4, MAS2
 | |
| 	rlwimi	r4, r15, 0, MAS2_I
 | |
| 	rlwimi	r4, r15, 0, MAS2_G
 | |
| 	mtspr	MAS2, r4
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 	/* Clear the cache */
 | |
| 	lis	r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
 | |
| 	ori	r3,r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr	SPRN_L1CSR1,r3
 | |
| 	isync
 | |
| 2:	sync
 | |
| 	mfspr	r4,SPRN_L1CSR1
 | |
| 	and.	r4,r4,r3
 | |
| 	bne	2b
 | |
| 
 | |
| 	lis	r3,(L1CSR1_CPE|L1CSR1_ICE)@h
 | |
| 	ori	r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr	SPRN_L1CSR1,r3
 | |
| 	isync
 | |
| 2:	sync
 | |
| 	mfspr	r4,SPRN_L1CSR1
 | |
| 	and.	r4,r4,r3
 | |
| 	beq	2b
 | |
| 
 | |
| 	/* Remove temporary mappings */
 | |
| 	lis	r0, MAS0_TLBSEL(1)@h
 | |
| 	rlwimi	r0, r9, 16, MAS0_ESEL_MSK
 | |
| 	li	r3, 0
 | |
| 	mtspr	MAS0, r0
 | |
| 	mtspr	MAS1, r3
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 	li	r3, 0
 | |
| 	stw	r3, 0xc08(r7)	/* LAWAR0 */
 | |
| 	lwz	r3, 0xc08(r7)
 | |
| 	isync
 | |
| 
 | |
| 	lis	r0, MAS0_TLBSEL(1)@h
 | |
| 	rlwimi	r0, r8, 16, MAS0_ESEL_MSK
 | |
| 	li	r3, 0
 | |
| 	mtspr	MAS0, r0
 | |
| 	mtspr	MAS1, r3
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	isync
 | |
| 	msync
 | |
| 
 | |
| 	b	9f
 | |
| 
 | |
| 	/* r3 = addr, r4 = value, clobbers r5, r11, r12 */
 | |
| erratum_set_value:
 | |
| 	/* Lock two cache lines into I-Cache */
 | |
| 	sync
 | |
| 	mfspr	r11, SPRN_L1CSR1
 | |
| 	rlwinm	r11, r11, 0, ~L1CSR1_ICUL
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr	SPRN_L1CSR1, r11
 | |
| 	isync
 | |
| 
 | |
| 	mflr	r12
 | |
| 	bl	5f
 | |
| 5:	mflr	r5
 | |
| 	addi	r5, r5, 2f - 5b
 | |
| 	icbtls	0, 0, r5
 | |
| 	addi	r5, r5, 64
 | |
| 
 | |
| 	sync
 | |
| 	mfspr	r11, SPRN_L1CSR1
 | |
| 3:	andi.	r11, r11, L1CSR1_ICUL
 | |
| 	bne	3b
 | |
| 
 | |
| 	icbtls	0, 0, r5
 | |
| 	addi	r5, r5, 64
 | |
| 
 | |
| 	sync
 | |
| 	mfspr	r11, SPRN_L1CSR1
 | |
| 3:	andi.	r11, r11, L1CSR1_ICUL
 | |
| 	bne	3b
 | |
| 
 | |
| 	b	2f
 | |
| 	.align	6
 | |
| 	/* Inside a locked cacheline, wait a while, write, then wait a while */
 | |
| 2:	sync
 | |
| 
 | |
| 	mfspr	r5, SPRN_TBRL
 | |
| 	addis	r11, r5, 0x10000@h /* wait 65536 timebase ticks */
 | |
| 4:	mfspr	r5, SPRN_TBRL
 | |
| 	subf.	r5, r5, r11
 | |
| 	bgt	4b
 | |
| 
 | |
| 	stw	r4, 0(r3)
 | |
| 
 | |
| 	mfspr	r5, SPRN_TBRL
 | |
| 	addis	r11, r5, 0x10000@h /* wait 65536 timebase ticks */
 | |
| 4:	mfspr	r5, SPRN_TBRL
 | |
| 	subf.	r5, r5, r11
 | |
| 	bgt	4b
 | |
| 
 | |
| 	sync
 | |
| 
 | |
| 	/*
 | |
| 	 * Fill out the rest of this cache line and the next with nops,
 | |
| 	 * to ensure that nothing outside the locked area will be
 | |
| 	 * fetched due to a branch.
 | |
| 	 */
 | |
| 	.rept 19
 | |
| 	nop
 | |
| 	.endr
 | |
| 
 | |
| 	sync
 | |
| 	mfspr	r11, SPRN_L1CSR1
 | |
| 	rlwinm	r11, r11, 0, ~L1CSR1_ICUL
 | |
| 	sync
 | |
| 	isync
 | |
| 	mtspr	SPRN_L1CSR1, r11
 | |
| 	isync
 | |
| 
 | |
| 	mtlr	r12
 | |
| 	blr
 | |
| 
 | |
| 9:
 | |
| #endif
 | |
| 
 | |
| create_init_ram_area:
 | |
| 	lis     r6,FSL_BOOKE_MAS0(1, 15, 0)@h
 | |
| 	ori     r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
 | |
| 
 | |
| #ifdef NOR_BOOT
 | |
| 	/* create a temp mapping in AS=1 to the 4M boot window */
 | |
| 	create_tlb1_entry 15, \
 | |
| 		1, BOOKE_PAGESZ_4M, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xffc00000, MAS2_I|MAS2_G, \
 | |
| 		0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| 
 | |
| #elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_NXP_ESBC)
 | |
| 	/* create a temp mapping in AS = 1 for Flash mapping
 | |
| 	 * created by PBL for ISBC code
 | |
| 	 */
 | |
| 	create_tlb1_entry 15, \
 | |
| 		1, BOOKE_PAGESZ_1M, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfff00000, MAS2_I|MAS2_G, \
 | |
| 		CFG_SYS_PBI_FLASH_WINDOW & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| 
 | |
| /*
 | |
|  * For Targets without CONFIG_SPL like P3, P5
 | |
|  * and for targets with CONFIG_SPL like T1, T2, T4, only for
 | |
|  * u-boot-spl i.e. CONFIG_SPL_BUILD
 | |
|  */
 | |
| #elif defined(CONFIG_RAMBOOT_PBL) && defined(CONFIG_NXP_ESBC) && \
 | |
| 	(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
 | |
| 	/* create a temp mapping in AS = 1 for mapping CONFIG_VAL(SYS_MONITOR_BASE)
 | |
| 	 * to L3 Address configured by PBL for ISBC code
 | |
| 	 */
 | |
| 	create_tlb1_entry 15, \
 | |
| 		1, BOOKE_PAGESZ_1M, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfff00000, MAS2_I|MAS2_G, \
 | |
| 		CFG_SYS_INIT_L3_ADDR & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| 
 | |
| #else
 | |
| 	/*
 | |
| 	 * create a temp mapping in AS=1 to the 1M CONFIG_VAL(SYS_MONITOR_BASE) space, the main
 | |
| 	 * image has been relocated to CONFIG_VAL(SYS_MONITOR_BASE) on the second stage.
 | |
| 	 */
 | |
| 	create_tlb1_entry 15, \
 | |
| 		1, BOOKE_PAGESZ_1M, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfff00000, MAS2_I|MAS2_G, \
 | |
| 		CONFIG_VAL(SYS_MONITOR_BASE) & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| #endif
 | |
| 
 | |
| 	/* create a temp mapping in AS=1 to the stack */
 | |
| #if defined(CFG_SYS_INIT_RAM_ADDR_PHYS_LOW) && \
 | |
|     defined(CFG_SYS_INIT_RAM_ADDR_PHYS_HIGH)
 | |
| 	create_tlb1_entry 14, \
 | |
| 		1, BOOKE_PAGESZ_16K, \
 | |
| 		CFG_SYS_INIT_RAM_ADDR, 0, \
 | |
| 		CFG_SYS_INIT_RAM_ADDR_PHYS_LOW, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		CFG_SYS_INIT_RAM_ADDR_PHYS_HIGH, r6
 | |
| 
 | |
| #else
 | |
| 	create_tlb1_entry 14, \
 | |
| 		1, BOOKE_PAGESZ_16K, \
 | |
| 		CFG_SYS_INIT_RAM_ADDR, 0, \
 | |
| 		CFG_SYS_INIT_RAM_ADDR, MAS3_SX|MAS3_SW|MAS3_SR, \
 | |
| 		0, r6
 | |
| #endif
 | |
| 
 | |
| 	lis	r6,MSR_IS|MSR_DS|MSR_DE@h
 | |
| 	ori	r6,r6,MSR_IS|MSR_DS|MSR_DE@l
 | |
| 	lis	r7,switch_as@h
 | |
| 	ori	r7,r7,switch_as@l
 | |
| 
 | |
| 	mtspr	SPRN_SRR0,r7
 | |
| 	mtspr	SPRN_SRR1,r6
 | |
| 	rfi
 | |
| 
 | |
| switch_as:
 | |
| /* L1 DCache is used for initial RAM */
 | |
| 
 | |
| 	/* Allocate Initial RAM in data cache.
 | |
| 	 */
 | |
| 	lis	r3,CFG_SYS_INIT_RAM_ADDR@h
 | |
| 	ori	r3,r3,CFG_SYS_INIT_RAM_ADDR@l
 | |
| 	mfspr	r2, L1CFG0
 | |
| 	andi.	r2, r2, 0x1ff
 | |
| 	/* cache size * 1024 / (2 * L1 line size) */
 | |
| 	slwi	r2, r2, (10 - 1 - L1_CACHE_SHIFT)
 | |
| 	mtctr	r2
 | |
| 	li	r0,0
 | |
| 1:
 | |
| 	dcbz	r0,r3
 | |
| #ifdef CONFIG_E6500	/* Lock/unlock L2 cache long with L1 */
 | |
| 	dcbtls	2, r0, r3
 | |
| 	dcbtls	0, r0, r3
 | |
| #else
 | |
| 	dcbtls	0, r0, r3
 | |
| #endif
 | |
| 	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
 | |
| 	bdnz	1b
 | |
| 
 | |
| 	/* Jump out the last 4K page and continue to 'normal' start */
 | |
| #if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
 | |
| 	/* We assume that we're already running at the address we're linked at */
 | |
| 	b	_start_cont
 | |
| #else
 | |
| 	/* Calculate absolute address in FLASH and jump there		*/
 | |
| 	/*--------------------------------------------------------------*/
 | |
| 	lis	r3,_start_cont@h
 | |
| 	ori	r3,r3,_start_cont@l
 | |
| 	mtlr	r3
 | |
| 	blr
 | |
| #endif
 | |
| 
 | |
| 	.text
 | |
| 	.globl	_start_cont
 | |
| _start_cont:
 | |
| 	/* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
 | |
| 	lis	r3,(CFG_SYS_INIT_RAM_ADDR)@h
 | |
| 	ori	r3,r3,((CFG_SYS_INIT_SP_OFFSET-16)&~0xf)@l /* Align to 16 */
 | |
| 
 | |
| #if CONFIG_VAL(SYS_MALLOC_F_LEN)
 | |
| #if CONFIG_VAL(SYS_MALLOC_F_LEN) + GENERATED_GBL_DATA_SIZE > CFG_SYS_INIT_RAM_SIZE
 | |
| #error "SYS_MALLOC_F_LEN too large to fit into initial RAM."
 | |
| #endif
 | |
| 
 | |
| 	/* Leave 16+ byte for back chain termination and NULL return address */
 | |
| 	subi	r3,r3,((CONFIG_VAL(SYS_MALLOC_F_LEN)+16+15)&~0xf)
 | |
| #endif
 | |
| 
 | |
| 	/* End of RAM */
 | |
| 	lis	r4,(CFG_SYS_INIT_RAM_ADDR)@h
 | |
| 	ori	r4,r4,(CFG_SYS_INIT_RAM_SIZE)@l
 | |
| 
 | |
| 	li	r0,0
 | |
| 
 | |
| 1:	subi	r4,r4,4
 | |
| 	stw	r0,0(r4)
 | |
| 	cmplw	r4,r3
 | |
| 	bne	1b
 | |
| 
 | |
| #if CONFIG_VAL(SYS_MALLOC_F_LEN)
 | |
| 	lis	r4,SYS_INIT_SP_ADDR@h
 | |
| 	ori	r4,r4,SYS_INIT_SP_ADDR@l
 | |
| 
 | |
| 	addi	r3,r3,16	/* Pre-relocation malloc area */
 | |
| 	stw	r3,GD_MALLOC_BASE(r4)
 | |
| 	subi	r3,r3,16
 | |
| #endif
 | |
| 	li	r0,0
 | |
| 	stw	r0,0(r3)	/* Terminate Back Chain */
 | |
| 	stw	r0,+4(r3)	/* NULL return address. */
 | |
| 	mr	r1,r3		/* Transfer to SP(r1) */
 | |
| 
 | |
| 	GET_GOT
 | |
| 	/* Needed for -msingle-pic-base */
 | |
| 	bl	_GLOBAL_OFFSET_TABLE_@local-4
 | |
| 	mflr	r30
 | |
| 
 | |
| 	/* Pass our potential ePAPR device tree pointer to cpu_init_early_f */
 | |
| 	mr	r3, r24
 | |
| 
 | |
| 	bl	cpu_init_early_f
 | |
| 
 | |
| 	/* switch back to AS = 0 */
 | |
| 	lis	r3,(MSR_CE|MSR_ME|MSR_DE)@h
 | |
| 	ori	r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
 | |
| 	mtmsr	r3
 | |
| 	isync
 | |
| 
 | |
| 	bl	cpu_init_f	/* return boot_flag for calling board_init_f */
 | |
| 	bl	board_init_f
 | |
| 	isync
 | |
| 
 | |
| 	/* NOTREACHED - board_init_f() does not return */
 | |
| 
 | |
| #ifndef MINIMAL_SPL
 | |
| 	.globl	_start_of_vectors
 | |
| _start_of_vectors:
 | |
| 
 | |
| /* Critical input. */
 | |
| 	CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
 | |
| 
 | |
| /* Machine check */
 | |
| 	MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 | |
| 
 | |
| /* Data Storage exception. */
 | |
| 	STD_EXCEPTION(0x0300, DataStorage, UnknownException)
 | |
| 
 | |
| /* Instruction Storage exception. */
 | |
| 	STD_EXCEPTION(0x0400, InstStorage, UnknownException)
 | |
| 
 | |
| /* External Interrupt exception. */
 | |
| 	STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
 | |
| 
 | |
| /* Alignment exception. */
 | |
| 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(0x600, Alignment, AlignmentException,
 | |
| 		MSR_KERNEL, COPY_EE)
 | |
| 
 | |
| /* Program check exception */
 | |
| ProgramCheck:
 | |
| 	EXCEPTION_PROLOG(SRR0, SRR1)
 | |
| 	addi	r3,r1,STACK_FRAME_OVERHEAD
 | |
| 	EXC_XFER_TEMPLATE(0x700, ProgramCheck, ProgramCheckException,
 | |
| 		MSR_KERNEL, COPY_EE)
 | |
| 
 | |
| 	/* No FPU on MPC85xx.  This exception is not supposed to happen.
 | |
| 	*/
 | |
| 	STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
 | |
| 	STD_EXCEPTION(0x0900, SystemCall, UnknownException)
 | |
| 	STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
 | |
| 	STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
 | |
| 	STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
 | |
| 
 | |
| 	STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
 | |
| 	STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
 | |
| 
 | |
| 	CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
 | |
| 
 | |
| 	.globl	_end_of_vectors
 | |
| _end_of_vectors:
 | |
| 
 | |
| 
 | |
| 	. = . + (0x100 - ( . & 0xff ))	/* align for debug */
 | |
| 
 | |
| /*
 | |
|  * 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.
 | |
|  * r23 is the address of the handler.
 | |
|  */
 | |
| 	.globl	transfer_to_handler
 | |
| transfer_to_handler:
 | |
| 	SAVE_GPR(7, r21)
 | |
| 	SAVE_4GPRS(8, r21)
 | |
| 	SAVE_8GPRS(12, r21)
 | |
| 	SAVE_8GPRS(24, r21)
 | |
| 
 | |
| 	li	r22,0
 | |
| 	stw	r22,RESULT(r21)
 | |
| 	mtspr	SPRG2,r22		/* r1 is now kernel sp */
 | |
| 
 | |
| 	mtctr	r23			/* virtual address of handler */
 | |
| 	mtmsr	r20
 | |
| 	bctrl
 | |
| 
 | |
| 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
 | |
| 
 | |
| /* Cache functions.
 | |
| */
 | |
| .globl flush_icache
 | |
| flush_icache:
 | |
| .globl invalidate_icache
 | |
| invalidate_icache:
 | |
| 	mfspr	r0,L1CSR1
 | |
| 	ori	r0,r0,L1CSR1_ICFI
 | |
| 	msync
 | |
| 	isync
 | |
| 	mtspr	L1CSR1,r0
 | |
| 	isync
 | |
| 	blr				/* entire I cache */
 | |
| 
 | |
| .globl invalidate_dcache
 | |
| invalidate_dcache:
 | |
| 	mfspr	r0,L1CSR0
 | |
| 	ori	r0,r0,L1CSR0_DCFI
 | |
| 	msync
 | |
| 	isync
 | |
| 	mtspr	L1CSR0,r0
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| 	.globl	icache_enable
 | |
| icache_enable:
 | |
| 	mflr	r8
 | |
| 	bl	invalidate_icache
 | |
| 	mtlr	r8
 | |
| 	isync
 | |
| 	mfspr	r4,L1CSR1
 | |
| 	ori	r4,r4,(L1CSR1_CPE | L1CSR1_ICE)@l
 | |
| 	oris	r4,r4,(L1CSR1_CPE | L1CSR1_ICE)@h
 | |
| 	mtspr	L1CSR1,r4
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| 	.globl	icache_disable
 | |
| icache_disable:
 | |
| 	mfspr	r0,L1CSR1
 | |
| 	lis	r3,0
 | |
| 	ori	r3,r3,L1CSR1_ICE
 | |
| 	andc	r0,r0,r3
 | |
| 	mtspr	L1CSR1,r0
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| 	.globl	icache_status
 | |
| icache_status:
 | |
| 	mfspr	r3,L1CSR1
 | |
| 	andi.	r3,r3,L1CSR1_ICE
 | |
| 	blr
 | |
| 
 | |
| 	.globl	dcache_enable
 | |
| dcache_enable:
 | |
| 	mflr	r8
 | |
| 	bl	invalidate_dcache
 | |
| 	mtlr	r8
 | |
| 	isync
 | |
| 	mfspr	r0,L1CSR0
 | |
| 	ori	r0,r0,(L1CSR0_CPE |  L1CSR0_DCE)@l
 | |
| 	oris	r0,r0,(L1CSR0_CPE |  L1CSR0_DCE)@h
 | |
| 	msync
 | |
| 	isync
 | |
| 	mtspr	L1CSR0,r0
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| 	.globl	dcache_disable
 | |
| dcache_disable:
 | |
| 	mfspr	r3,L1CSR0
 | |
| 	lis	r4,0
 | |
| 	ori	r4,r4,L1CSR0_DCE
 | |
| 	andc	r3,r3,r4
 | |
| 	mtspr	L1CSR0,r3
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| 	.globl	dcache_status
 | |
| dcache_status:
 | |
| 	mfspr	r3,L1CSR0
 | |
| 	andi.	r3,r3,L1CSR0_DCE
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* 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)
 | |
| 	sync
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* Function:	 out16 */
 | |
| /* Description:	 Output 16 bits */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	out16
 | |
| out16:
 | |
| 	sth	r4,0x0000(r3)
 | |
| 	sync
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* Function:	 out16r */
 | |
| /* Description:	 Byte reverse and output 16 bits */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	out16r
 | |
| out16r:
 | |
| 	sthbrx	r4,r0,r3
 | |
| 	sync
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* Function:	 out32 */
 | |
| /* Description:	 Output 32 bits */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	out32
 | |
| out32:
 | |
| 	stw	r4,0x0000(r3)
 | |
| 	sync
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* Function:	 out32r */
 | |
| /* Description:	 Byte reverse and output 32 bits */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	out32r
 | |
| out32r:
 | |
| 	stwbrx	r4,r0,r3
 | |
| 	sync
 | |
| 	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:	 in32 */
 | |
| /* Description:	 Input 32 bits */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	in32
 | |
| in32:
 | |
| 	lwz	3,0x0000(3)
 | |
| 	blr
 | |
| 
 | |
| /*------------------------------------------------------------------------------- */
 | |
| /* Function:	 in32r */
 | |
| /* Description:	 Input 32 bits and byte reverse */
 | |
| /*------------------------------------------------------------------------------- */
 | |
| 	.globl	in32r
 | |
| in32r:
 | |
| 	lwbrx	r3,r0,r3
 | |
| 	blr
 | |
| #endif  /* !MINIMAL_SPL */
 | |
| 
 | |
| /*------------------------------------------------------------------------------*/
 | |
| 
 | |
| /*
 | |
|  * void write_tlb(mas0, mas1, mas2, mas3, mas7)
 | |
|  */
 | |
| 	.globl	write_tlb
 | |
| write_tlb:
 | |
| 	mtspr	MAS0,r3
 | |
| 	mtspr	MAS1,r4
 | |
| 	mtspr	MAS2,r5
 | |
| 	mtspr	MAS3,r6
 | |
| #ifdef CONFIG_ENABLE_36BIT_PHYS
 | |
| 	mtspr	MAS7,r7
 | |
| #endif
 | |
| 	li	r3,0
 | |
| #ifdef CONFIG_SYS_BOOK3E_HV
 | |
| 	mtspr	MAS8,r3
 | |
| #endif
 | |
| 	isync
 | |
| 	tlbwe
 | |
| 	msync
 | |
| 	isync
 | |
| 	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 = dest
 | |
|  * r4 = src
 | |
|  * r5 = length in bytes
 | |
|  * r6 = cachelinesize
 | |
|  */
 | |
| 	.globl	relocate_code
 | |
| relocate_code:
 | |
| 	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
 | |
| #ifndef CONFIG_SPL_SKIP_RELOCATE
 | |
| 	mr	r3,r5				/* Destination Address	*/
 | |
| 	lis	r4,CONFIG_VAL(SYS_MONITOR_BASE)@h		/* Source      Address	*/
 | |
| 	ori	r4,r4,CONFIG_VAL(SYS_MONITOR_BASE)@l
 | |
| 	lwz	r5,GOT(__init_end)
 | |
| 	sub	r5,r5,r4
 | |
| 	li	r6,CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
 | |
| 
 | |
| 	/*
 | |
| 	 * Fix GOT pointer:
 | |
| 	 *
 | |
| 	 * New GOT-PTR = (old GOT-PTR - CONFIG_VAL(SYS_MONITOR_BASE)) + Destination Address
 | |
| 	 *
 | |
| 	 * Offset:
 | |
| 	 */
 | |
| 	sub	r15,r10,r4
 | |
| 
 | |
| 	/* First our own GOT */
 | |
| 	add	r12,r12,r15
 | |
| 	/* the 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 - CONFIG_VAL(SYS_MONITOR_BASE)
 | |
| 
 | |
| 	/*
 | |
| 	 * As IVPR is going to point RAM address,
 | |
| 	 * Make sure IVOR15 has valid opcode to support debugger
 | |
| 	 */
 | |
| 	mtspr	IVOR15,r0
 | |
| 
 | |
| 	/*
 | |
| 	 * Re-point the IVPR at RAM
 | |
| 	 */
 | |
| 	mtspr	IVPR,r10
 | |
| 
 | |
| 	mtlr	r0
 | |
| 	blr				/* NEVER RETURNS! */
 | |
| #endif
 | |
| 	.globl	in_ram
 | |
| 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
 | |
| 	cmpwi	r0,0
 | |
| 	add	r0,r0,r11
 | |
| 	stw	r4,0(r3)
 | |
| 	beq-	5f
 | |
| 	stw	r0,0(r4)
 | |
| 5:	bdnz	3b
 | |
| 4:
 | |
| clear_bss:
 | |
| 	/*
 | |
| 	 * Now clear BSS segment
 | |
| 	 */
 | |
| 	lwz	r3,GOT(__bss_start)
 | |
| 	lwz	r4,GOT(__bss_end)
 | |
| 
 | |
| 	cmplw	0,r3,r4
 | |
| 	beq	6f
 | |
| 
 | |
| 	li	r0,0
 | |
| 5:
 | |
| 	stw	r0,0(r3)
 | |
| 	addi	r3,r3,4
 | |
| 	cmplw	0,r3,r4
 | |
| 	blt	5b
 | |
| 6:
 | |
| 
 | |
| 	mr	r3,r9		/* Init Data pointer		*/
 | |
| 	mr	r4,r10		/* Destination Address		*/
 | |
| 	bl	board_init_r
 | |
| 
 | |
| #ifndef MINIMAL_SPL
 | |
| 	/*
 | |
| 	 * 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	r11
 | |
| 	bl	_GLOBAL_OFFSET_TABLE_-4
 | |
| 	mflr	r12
 | |
| 
 | |
| 	/* Update IVORs as per relocation */
 | |
| 	mtspr	IVPR,r3
 | |
| 
 | |
| 	lwz	r4,CriticalInput@got(r12)
 | |
| 	mtspr	IVOR0,r4	/* 0: Critical input */
 | |
| 	lwz	r4,MachineCheck@got(r12)
 | |
| 	mtspr	IVOR1,r4	/* 1: Machine check */
 | |
| 	lwz	r4,DataStorage@got(r12)
 | |
| 	mtspr	IVOR2,r4	/* 2: Data storage */
 | |
| 	lwz	r4,InstStorage@got(r12)
 | |
| 	mtspr	IVOR3,r4	/* 3: Instruction storage */
 | |
| 	lwz	r4,ExtInterrupt@got(r12)
 | |
| 	mtspr	IVOR4,r4	/* 4: External interrupt */
 | |
| 	lwz	r4,Alignment@got(r12)
 | |
| 	mtspr	IVOR5,r4	/* 5: Alignment */
 | |
| 	lwz	r4,ProgramCheck@got(r12)
 | |
| 	mtspr	IVOR6,r4	/* 6: Program check */
 | |
| 	lwz	r4,FPUnavailable@got(r12)
 | |
| 	mtspr	IVOR7,r4	/* 7: floating point unavailable */
 | |
| 	lwz	r4,SystemCall@got(r12)
 | |
| 	mtspr	IVOR8,r4	/* 8: System call */
 | |
| 	/* 9: Auxiliary processor unavailable(unsupported) */
 | |
| 	lwz	r4,Decrementer@got(r12)
 | |
| 	mtspr	IVOR10,r4	/* 10: Decrementer */
 | |
| 	lwz	r4,IntervalTimer@got(r12)
 | |
| 	mtspr	IVOR11,r4	/* 11: Interval timer */
 | |
| 	lwz	r4,WatchdogTimer@got(r12)
 | |
| 	mtspr	IVOR12,r4	/* 12: Watchdog timer */
 | |
| 	lwz	r4,DataTLBError@got(r12)
 | |
| 	mtspr	IVOR13,r4	/* 13: Data TLB error */
 | |
| 	lwz	r4,InstructionTLBError@got(r12)
 | |
| 	mtspr	IVOR14,r4	/* 14: Instruction TLB error */
 | |
| 	lwz	r4,DebugBreakpoint@got(r12)
 | |
| 	mtspr	IVOR15,r4	/* 15: Debug */
 | |
| 
 | |
| 	mtlr	r11
 | |
| 	blr
 | |
| 
 | |
| .globl unlock_ram_in_cache
 | |
| unlock_ram_in_cache:
 | |
| 	/* invalidate the INIT_RAM section */
 | |
| 	lis	r3,(CFG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
 | |
| 	ori	r3,r3,(CFG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
 | |
| 	mfspr	r4,L1CFG0
 | |
| 	andi.	r4,r4,0x1ff
 | |
| 	slwi	r4,r4,(10 - 1 - L1_CACHE_SHIFT)
 | |
| 	mtctr	r4
 | |
| 1:	dcbi	r0,r3
 | |
| #ifdef CONFIG_E6500	/* lock/unlock L2 cache long with L1 */
 | |
| 	dcblc	2, r0, r3
 | |
| 	dcblc	0, r0, r3
 | |
| #else
 | |
| 	dcblc	r0,r3
 | |
| #endif
 | |
| 	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
 | |
| 	bdnz	1b
 | |
| 	sync
 | |
| 
 | |
| 	/* Invalidate the TLB entries for the cache */
 | |
| 	lis	r3,CFG_SYS_INIT_RAM_ADDR@h
 | |
| 	ori	r3,r3,CFG_SYS_INIT_RAM_ADDR@l
 | |
| 	tlbivax	0,r3
 | |
| 	addi	r3,r3,0x1000
 | |
| 	tlbivax	0,r3
 | |
| 	addi	r3,r3,0x1000
 | |
| 	tlbivax	0,r3
 | |
| 	addi	r3,r3,0x1000
 | |
| 	tlbivax	0,r3
 | |
| 	isync
 | |
| 	blr
 | |
| 
 | |
| .globl flush_dcache
 | |
| flush_dcache:
 | |
| 	mfspr	r3,SPRN_L1CFG0
 | |
| 
 | |
| 	rlwinm	r5,r3,9,3	/* Extract cache block size */
 | |
| 	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
 | |
| 				 * are currently defined.
 | |
| 				 */
 | |
| 	li	r4,32
 | |
| 	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
 | |
| 				 *      log2(number of ways)
 | |
| 				 */
 | |
| 	slw	r5,r4,r5	/* r5 = cache block size */
 | |
| 
 | |
| 	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
 | |
| 	mulli	r7,r7,13	/* An 8-way cache will require 13
 | |
| 				 * loads per set.
 | |
| 				 */
 | |
| 	slw	r7,r7,r6
 | |
| 
 | |
| 	/* save off HID0 and set DCFA */
 | |
| 	mfspr	r8,SPRN_HID0
 | |
| 	ori	r9,r8,HID0_DCFA@l
 | |
| 	mtspr	SPRN_HID0,r9
 | |
| 	isync
 | |
| 
 | |
| 	lis	r4,0
 | |
| 	mtctr	r7
 | |
| 
 | |
| 1:	lwz	r3,0(r4)	/* Load... */
 | |
| 	add	r4,r4,r5
 | |
| 	bdnz	1b
 | |
| 
 | |
| 	msync
 | |
| 	lis	r4,0
 | |
| 	mtctr	r7
 | |
| 
 | |
| 1:	dcbf	0,r4		/* ...and flush. */
 | |
| 	add	r4,r4,r5
 | |
| 	bdnz	1b
 | |
| 
 | |
| 	/* restore HID0 */
 | |
| 	mtspr	SPRN_HID0,r8
 | |
| 	isync
 | |
| 
 | |
| 	blr
 | |
| #endif /* !MINIMAL_SPL */
 |