upstream u-boot with additional patches for our devices/boards: https://lists.denx.de/pipermail/u-boot/2017-March/282789.html (AXP crashes) ; Gbit ethernet patch for some LIME2 revisions ; with SPI flash support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
u-boot/arch/powerpc/cpu/mpc8xx/start.S

637 lines
14 KiB

powerpc: Partialy restore core of mpc8xx CS Systemes d'Information (CSSI) manufactures 8xx boards for critical communication systems. Those boards have been running U-Boot since 2010 and will have to be maintained until at least 2027. commit 5b8e76c35ec312a3f73126bd1a2d2c0965b98a9f ("powerpc, 8xx: remove support for 8xx") orphaned those boards by removing support for the mpc8xx CPU. This commit partially restores support for the 8xx, with the following limitations: - Restores support for MPC866 and MPC885 only - Does not restore IDE, PCMCIA, I2C, USB - Does not restore examples - Does not restore POST - Does not restore Ethernet on SCC - Does not restore console on SCC - Does not restore bedbug and kgdb support As the 866 and 885 do not support the following features, they are not restored either: - VIDEO / LCD - RTC clock The CPM uCODE patch is not restored either, because: - 866 and 885 already have support for I2C and SPI relocation without a uCODE patch - relocation of SMC, I2C or SPI is only needed for using SCCs for Ethernet or QMC The dynamic setup/calculation of clocks is removed, we expect the target being use with the clock and PLPRCR register defined in the configuration. All the clock settings for 8xx prior to 866 is removed as well as we now only support 866 and 885. This code is mature and addresses mature boards. Therefore all code enclosed in '#if 0/#endif' and '#if XX_DEBUG/#endif' is unneeded. The following files are not restored by this patch: - arch/powerpc/cpu/mpc8xx/bedbug_860.c - arch/powerpc/cpu/mpc8xx/fec.h - arch/powerpc/cpu/mpc8xx/kgdb.S - arch/powerpc/cpu/mpc8xx/plprcr_write.S - arch/powerpc/cpu/mpc8xx/scc.c - arch/powerpc/cpu/mpc8xx/upatch.c - arch/powerpc/cpu/mpc8xx/video.c - arch/powerpc/include/asm/status_led.h - arch/powerpc/lib/ide.c - arch/powerpc/lib/ide.h - doc/README.MPC866 - drivers/pcmcia/mpc8xx_pcmcia.c - drivers/rtc/mpc8xx.c - drivers/usb/gadget/mpc8xx_udc.c - drivers/video/mpc8xx_lcd.c - examples/standalone/test_burst.c - examples/standalone/test_burst.h - examples/standalone/test_burst_lib.S - examples/standalone/timer.c - include/mpc823_lcd.h - include/usb/mpc8xx_udc.h - post/cpu/mpc8xx/Makefile - post/cpu/mpc8xx/cache.c - post/cpu/mpc8xx/cache_8xx.S - post/cpu/mpc8xx/ether.c - post/cpu/mpc8xx/spr.c - post/cpu/mpc8xx/uart.c - post/cpu/mpc8xx/usb.c - post/cpu/mpc8xx/watchdog.c Some of the restored files are not located in a proper location. In order to keep traceability of the changes, they will be moved to their correct location and moved to Kconfig in a followup patch. This patch also declares CSSI as point of contact for the update of the 8xx platform, as those boards are the only ones still being maintained on the 8xx area. A later patch will add those boards to the tree. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
7 years ago
/*
* 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>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* U-Boot - Startup Code for PowerPC based Embedded Boards
*
*
* The processor starts at 0x00000100 and the code is executed
* from flash. The code is organized to be at an other address
* 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 memory map.
*
* board_init will change CS0 to be positioned at the correct
* address and (s)dram will be positioned at address 0
*/
#include <asm-offsets.h>
#include <config.h>
#include <mpc8xx.h>
#include <version.h>
#include <ppc_asm.tmpl>
#include <ppc_defs.h>
#include <asm/cache.h>
#include <asm/mmu.h>
#include <asm/u-boot.h>
/* We don't want the MMU yet.
*/
#undef MSR_KERNEL
#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */
/*
* Set up GOT: Global Offset Table
*
* Use r12 to access the GOT
*/
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(__bss_end)
GOT_ENTRY(__bss_start)
END_GOT
/*
* r3 - 1st arg to board_init(): IMMP pointer
* r4 - 2nd arg to board_init(): boot flag
*/
.text
.long 0x27051956 /* U-Boot Magic Number */
.globl version_string
version_string:
.ascii U_BOOT_VERSION_STRING, "\0"
. = EXC_OFF_SYS_RESET
.globl _start
_start:
lis r3, CONFIG_SYS_IMMR@h /* position IMMR */
mtspr 638, r3
/* Initialize machine status; enable machine check interrupt */
/*----------------------------------------------------------------------*/
li r3, MSR_KERNEL /* Set ME, RI flags */
mtmsr r3
mtspr SRR1, r3 /* Make SRR1 match MSR */
mfspr r3, ICR /* clear Interrupt Cause Register */
/* Initialize debug port registers */
/*----------------------------------------------------------------------*/
xor r0, r0, r0 /* Clear R0 */
mtspr LCTRL1, r0 /* Initialize debug port regs */
mtspr LCTRL2, r0
mtspr COUNTA, r0
mtspr COUNTB, r0
/* Reset the caches */
/*----------------------------------------------------------------------*/
mfspr r3, IC_CST /* Clear error bits */
mfspr r3, DC_CST
lis r3, IDC_UNALL@h /* Unlock all */
mtspr IC_CST, r3
mtspr DC_CST, r3
lis r3, IDC_INVALL@h /* Invalidate all */
mtspr IC_CST, r3
mtspr DC_CST, r3
lis r3, IDC_DISABLE@h /* Disable data cache */
mtspr DC_CST, r3
lis r3, IDC_ENABLE@h /* Enable instruction cache */
mtspr IC_CST, r3
/* invalidate all tlb's */
/*----------------------------------------------------------------------*/
tlbia
isync
/*
* Calculate absolute address in FLASH and jump there
*----------------------------------------------------------------------*/
lis r3, CONFIG_SYS_MONITOR_BASE@h
ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
mtlr r3
blr
in_flash:
/* initialize some SPRs that are hard to access from C */
/*----------------------------------------------------------------------*/
lis r3, CONFIG_SYS_IMMR@h /* pass IMMR as arg1 to C routine */
ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */
/* Note: R0 is still 0 here */
stwu r0, -4(r1) /* clear final stack frame so that */
stwu r0, -4(r1) /* stack backtraces terminate cleanly */
/*
* Disable serialized ifetch and show cycles
* (i.e. set processor to normal mode).
* This is also a silicon bug workaround, see errata
*/
li r2, 0x0007
mtspr ICTRL, r2
/* Set up debug mode entry */
lis r2, CONFIG_SYS_DER@h
ori r2, r2, CONFIG_SYS_DER@l
mtspr DER, r2
/* let the C-code set up the rest */
/* */
/* Be careful to keep code relocatable ! */
/*----------------------------------------------------------------------*/
GET_GOT /* initialize GOT access */
/* r3: IMMR */
bl cpu_init_f /* run low-level CPU init code (from Flash) */
bl board_init_f /* run 1st part of board init code (from Flash) */
/* NOTREACHED - board_init_f() does not return */
.globl _start_of_vectors
_start_of_vectors:
/* Machine check */
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
/* Data Storage exception. "Never" generated on the 860. */
STD_EXCEPTION(0x300, DataStorage, UnknownException)
/* Instruction Storage exception. "Never" generated on the 860. */
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)
/* No FPU on MPC8xx. This exception is not supposed to happen.
*/
STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
/* I guess we could implement decrementer, and may have
* to someday for timekeeping.
*/
STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
STD_EXCEPTION(0xc00, SystemCall, UnknownException)
STD_EXCEPTION(0xd00, SingleStep, UnknownException)
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
/* On the MPC8xx, this is a software emulation interrupt. It occurs
* for all unimplemented and illegal instructions.
*/
STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
STD_EXCEPTION(0x1500, Reserved5, UnknownException)
STD_EXCEPTION(0x1600, Reserved6, UnknownException)
STD_EXCEPTION(0x1700, Reserved7, UnknownException)
STD_EXCEPTION(0x1800, Reserved8, UnknownException)
STD_EXCEPTION(0x1900, Reserved9, UnknownException)
STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
.globl _end_of_vectors
_end_of_vectors:
. = 0x2000
/*
* 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
/* Cache functions.
*/
.globl icache_enable
icache_enable:
SYNC
lis r3, IDC_INVALL@h
mtspr IC_CST, r3
lis r3, IDC_ENABLE@h
mtspr IC_CST, r3
blr
.globl icache_disable
icache_disable:
SYNC
lis r3, IDC_DISABLE@h
mtspr IC_CST, r3
blr
.globl icache_status
icache_status:
mfspr r3, IC_CST
srwi r3, r3, 31 /* >>31 => select bit 0 */
blr
.globl dcache_enable
dcache_enable:
lis r3, 0x0400 /* Set cache mode with MMU off */
mtspr MD_CTR, r3
lis r3, IDC_INVALL@h
mtspr DC_CST, r3
lis r3, IDC_ENABLE@h
mtspr DC_CST, r3
blr
.globl dcache_disable
dcache_disable:
SYNC
lis r3, IDC_DISABLE@h
mtspr DC_CST, r3
lis r3, IDC_INVALL@h
mtspr DC_CST, r3
blr
.globl dcache_status
dcache_status:
mfspr r3, DC_CST
srwi r3, r3, 31 /* >>31 => select bit 0 */
blr
.globl dc_read
dc_read:
mtspr DC_ADR, r3
mfspr r3, DC_DAT
blr
/*
* unsigned int get_immr (unsigned int mask)
*
* return (mask ? (IMMR & mask) : IMMR);
*/
.globl get_immr
get_immr:
mr r4,r3 /* save mask */
mfspr r3, IMMR /* IMMR */
cmpwi 0,r4,0 /* mask != 0 ? */
beq 4f
and r3,r3,r4 /* IMMR & mask */
4:
blr
.globl get_pvr
get_pvr:
mfspr r3, PVR
blr
.globl wr_ic_cst
wr_ic_cst:
mtspr IC_CST, r3
blr
.globl rd_ic_cst
rd_ic_cst:
mfspr r3, IC_CST
blr
.globl wr_ic_adr
wr_ic_adr:
mtspr IC_ADR, r3
blr
.globl wr_dc_cst
wr_dc_cst:
mtspr DC_CST, r3
blr
.globl rd_dc_cst
rd_dc_cst:
mfspr r3, DC_CST
blr
.globl wr_dc_adr
wr_dc_adr:
mtspr DC_ADR, 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 = 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 Global 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, CONFIG_SYS_CACHELINE_SIZE /* 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 + EXC_OFF_SYS_RESET
mtlr r0
blr
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
bne 5b
6:
mr r3, r9 /* Global 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)
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 + EXC_OFF_SYS_RESET
li r8, Alignment - _start + EXC_OFF_SYS_RESET
2:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 2b
li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
li r8, SystemCall - _start + EXC_OFF_SYS_RESET
3:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 3b
li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
4:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 4b
mtlr r4 /* restore link register */
blr