diff options
author | Tom Rini <trini@konsulko.com> | 2016-11-30 14:08:28 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-11-30 19:31:17 -0500 |
commit | a2cb31086f68cc0db95d4373e6dbdb612954f445 (patch) | |
tree | 0da2e0ac66e184ba536d525f5007d88cea6f0372 /arch | |
parent | bb417f1c9055dc17df08d1e2c9edc281ad19b648 (diff) | |
parent | 6fd596a1aa57bd431263f45b0c57ee8ae6b2403c (diff) | |
download | u-boot-imx-a2cb31086f68cc0db95d4373e6dbdb612954f445.zip u-boot-imx-a2cb31086f68cc0db95d4373e6dbdb612954f445.tar.gz u-boot-imx-a2cb31086f68cc0db95d4373e6dbdb612954f445.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-mips
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 32 | ||||
-rw-r--r-- | arch/mips/cpu/start.S | 173 | ||||
-rw-r--r-- | arch/mips/include/asm/asm-offsets.h | 5 | ||||
-rw-r--r-- | arch/mips/include/asm/cache.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/io.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/mipsregs.h | 1 | ||||
-rw-r--r-- | arch/mips/include/asm/system.h | 8 | ||||
-rw-r--r-- | arch/mips/include/asm/u-boot-mips.h | 4 | ||||
-rw-r--r-- | arch/mips/lib/Makefile | 3 | ||||
-rw-r--r-- | arch/mips/lib/asm-offsets.c | 61 | ||||
-rw-r--r-- | arch/mips/lib/bootm.c | 2 | ||||
-rw-r--r-- | arch/mips/lib/genex.S | 224 | ||||
-rw-r--r-- | arch/mips/lib/stack.c | 19 | ||||
-rw-r--r-- | arch/mips/lib/traps.c | 106 | ||||
-rw-r--r-- | arch/mips/mach-ath79/Kconfig | 2 | ||||
-rw-r--r-- | arch/mips/mach-pic32/Kconfig | 1 |
16 files changed, 582 insertions, 63 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 097ad58..d97930e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -20,6 +20,7 @@ config TARGET_QEMU_MIPS select SUPPORTS_CPU_MIPS32_R2 select SUPPORTS_CPU_MIPS64_R1 select SUPPORTS_CPU_MIPS64_R2 + select ROM_EXCEPTION_VECTORS config TARGET_MALTA bool "Support malta" @@ -40,6 +41,7 @@ config TARGET_MALTA select SUPPORTS_CPU_MIPS64_R6 select SWAP_IO_SPACE select MIPS_L1_CACHE_SHIFT_6 + select ROM_EXCEPTION_VECTORS config TARGET_VCT bool "Support vct" @@ -47,6 +49,7 @@ config TARGET_VCT select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select SYS_MIPS_CACHE_INIT_RAM_LOAD + select ROM_EXCEPTION_VECTORS config TARGET_DBAU1X00 bool "Support dbau1x00" @@ -55,6 +58,7 @@ config TARGET_DBAU1X00 select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select SYS_MIPS_CACHE_INIT_RAM_LOAD + select ROM_EXCEPTION_VECTORS select MIPS_TUNE_4KC config TARGET_PB1X00 @@ -63,6 +67,7 @@ config TARGET_PB1X00 select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select SYS_MIPS_CACHE_INIT_RAM_LOAD + select ROM_EXCEPTION_VECTORS select MIPS_TUNE_4KC config ARCH_ATH79 @@ -91,6 +96,7 @@ config TARGET_BOSTON select SUPPORTS_CPU_MIPS64_R1 select SUPPORTS_CPU_MIPS64_R2 select SUPPORTS_CPU_MIPS64_R6 + select ROM_EXCEPTION_VECTORS config TARGET_XILFPGA bool "Support Imagination Xilfpga" @@ -103,6 +109,7 @@ config TARGET_XILFPGA select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select MIPS_L1_CACHE_SHIFT_4 + select ROM_EXCEPTION_VECTORS help This supports IMGTEC MIPSfpga platform @@ -192,6 +199,20 @@ config CPU_MIPS64_R6 endchoice +menu "General setup" + +config ROM_EXCEPTION_VECTORS + bool "Build U-Boot image with exception vectors" + help + Enable this to include exception vectors in the U-Boot image. This is + required if the U-Boot entry point is equal to the address of the + CPU reset exception vector (e.g. U-Boot as ROM loader in Qemu, + U-Boot booted from parallel NOR flash). + Disable this, if the U-Boot image is booted from DRAM (e.g. by SPL). + In that case the image size will be reduced by 0x500 bytes. + +endmenu + menu "OS boot interface" config MIPS_BOOT_CMDLINE_LEGACY @@ -281,6 +302,17 @@ config SWAP_IO_SPACE config SYS_MIPS_CACHE_INIT_RAM_LOAD bool +config MIPS_INIT_STACK_IN_SRAM + bool + default n + help + Select this if the initial stack frame could be setup in SRAM. + Normally the initial stack frame is set up in DRAM which is often + only available after lowlevel_init. With this option the initial + stack frame and the early C environment is set up before + lowlevel_init. Thus lowlevel_init does not need to be implemented + in assembler. + config SYS_DCACHE_SIZE int default 0 diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 3f0fc12..6740fdf 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -34,30 +34,57 @@ # define STATUS_SET ST0_KX #endif - /* - * For the moment disable interrupts, mark the kernel mode and - * set ST0_KX so that the CPU does not spit fire when using - * 64-bit addresses. - */ - .macro setup_c0_status set clr - .set push - mfc0 t0, CP0_STATUS - or t0, ST0_CU0 | \set | 0x1f | \clr - xor t0, 0x1f | \clr - mtc0 t0, CP0_STATUS - .set noreorder - sll zero, 3 # ehb - .set pop + .set noreorder + + .macro init_wr sel + MTC0 zero, CP0_WATCHLO,\sel + mtc0 t1, CP0_WATCHHI,\sel + mfc0 t0, CP0_WATCHHI,\sel + bgez t0, wr_done + nop .endm - .set noreorder + .macro uhi_mips_exception + move k0, t9 # preserve t9 in k0 + move k1, a0 # preserve a0 in k1 + li t9, 15 # UHI exception operation + li a0, 0 # Use hard register context + sdbbp 1 # Invoke UHI operation + .endm + + .macro setup_stack_gd + li t0, -16 + PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR + and sp, t1, t0 # force 16 byte alignment + PTR_SUBU \ + sp, sp, GD_SIZE # reserve space for gd + and sp, sp, t0 # force 16 byte alignment + move k0, sp # save gd pointer +#ifdef CONFIG_SYS_MALLOC_F_LEN + li t2, CONFIG_SYS_MALLOC_F_LEN + PTR_SUBU \ + sp, sp, t2 # reserve space for early malloc + and sp, sp, t0 # force 16 byte alignment +#endif + move fp, sp + + /* Clear gd */ + move t0, k0 +1: + PTR_S zero, 0(t0) + blt t0, t1, 1b + PTR_ADDIU t0, PTRSIZE + +#ifdef CONFIG_SYS_MALLOC_F_LEN + PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#endif + .endm ENTRY(_start) /* U-Boot entry point */ b reset - nop + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing - .org 0x10 #if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG) /* * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to @@ -66,47 +93,53 @@ ENTRY(_start) * initial configuration for that EBU in order to access the flash * device with correct parameters. This config option is board-specific. */ + .org 0x10 .word CONFIG_SYS_XWAY_EBU_BOOTCFG .word 0x0 -#elif defined(CONFIG_MALTA) +#endif +#if defined(CONFIG_MALTA) /* * Linux expects the Board ID here. */ + .org 0x10 .word 0x00000420 # 0x420 (Malta Board with CoreLV) .word 0x00000000 #endif +#if defined(CONFIG_ROM_EXCEPTION_VECTORS) + /* + * Exception vector entry points. When running from ROM, an exception + * cannot be handled. Halt execution and transfer control to debugger, + * if one is attached. + */ .org 0x200 /* TLB refill, 32 bit task */ -1: b 1b - nop + uhi_mips_exception .org 0x280 /* XTLB refill, 64 bit task */ -1: b 1b - nop + uhi_mips_exception .org 0x300 /* Cache error exception */ -1: b 1b - nop + uhi_mips_exception .org 0x380 /* General exception */ -1: b 1b - nop + uhi_mips_exception .org 0x400 /* Catch interrupt exceptions */ -1: b 1b - nop + uhi_mips_exception .org 0x480 /* EJTAG debug exception */ 1: b 1b nop - .align 4 + .org 0x500 +#endif + reset: #if __mips_isa_rev >= 6 mfc0 t0, CP0_CONFIG, 5 @@ -128,17 +161,51 @@ reset: b 3b nop - /* Clear watch registers */ -4: MTC0 zero, CP0_WATCHLO + /* Init CP0 Status */ +4: mfc0 t0, CP0_STATUS + and t0, ST0_IMPL + or t0, ST0_BEV | ST0_ERL | STATUS_SET + mtc0 t0, CP0_STATUS + + /* + * Check whether CP0 Config1 is implemented. If not continue + * with legacy Watch register initialization. + */ + mfc0 t0, CP0_CONFIG + bgez t0, wr_legacy + nop + + /* + * Check WR bit in CP0 Config1 to determine if Watch registers + * are implemented. + */ + mfc0 t0, CP0_CONFIG, 1 + andi t0, (1 << 3) + beqz t0, wr_done + nop + + /* Clear Watch Status bits and disable watch exceptions */ + li t1, 0x7 # Clear I, R and W conditions + init_wr 0 + init_wr 1 + init_wr 2 + init_wr 3 + init_wr 4 + init_wr 5 + init_wr 6 + init_wr 7 + b wr_done + nop + +wr_legacy: + MTC0 zero, CP0_WATCHLO mtc0 zero, CP0_WATCHHI - /* WP(Watch Pending), SW0/1 should be cleared */ +wr_done: + /* Clear WP, IV and SW interrupts */ mtc0 zero, CP0_CAUSE - setup_c0_status STATUS_SET 0 - - /* Init Timer */ - mtc0 zero, CP0_COUNT + /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ mtc0 zero, CP0_COMPARE #ifndef CONFIG_SKIP_LOWLEVEL_INIT @@ -167,6 +234,11 @@ reset: nop #endif +#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM + /* Set up initial stack and global data */ + setup_stack_gd +#endif + #ifndef CONFIG_SKIP_LOWLEVEL_INIT # ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* Initialize any external memory */ @@ -188,35 +260,14 @@ reset: # endif #endif - /* Set up temporary stack */ - li t0, -16 - PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR - and sp, t1, t0 # force 16 byte alignment - PTR_SUBU \ - sp, sp, GD_SIZE # reserve space for gd - and sp, sp, t0 # force 16 byte alignment - move k0, sp # save gd pointer -#ifdef CONFIG_SYS_MALLOC_F_LEN - li t2, CONFIG_SYS_MALLOC_F_LEN - PTR_SUBU \ - sp, sp, t2 # reserve space for early malloc - and sp, sp, t0 # force 16 byte alignment -#endif - move fp, sp - - /* Clear gd */ - move t0, k0 -1: - PTR_S zero, 0(t0) - blt t0, t1, 1b - PTR_ADDIU t0, PTRSIZE - -#ifdef CONFIG_SYS_MALLOC_F_LEN - PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM + /* Set up initial stack and global data */ + setup_stack_gd #endif move a0, zero # a0 <-- boot_flags = 0 PTR_LA t9, board_init_f + jr t9 move ra, zero diff --git a/arch/mips/include/asm/asm-offsets.h b/arch/mips/include/asm/asm-offsets.h new file mode 100644 index 0000000..5352b1c --- /dev/null +++ b/arch/mips/include/asm/asm-offsets.h @@ -0,0 +1,5 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <generated/asm-offsets.h> diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index 669c362..83165d5 100644 --- a/arch/mips/include/asm/cache.h +++ b/arch/mips/include/asm/cache.h @@ -19,6 +19,7 @@ */ #define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN +#ifndef __ASSEMBLY__ /** * mips_cache_probe() - Probe the properties of the caches * @@ -27,5 +28,6 @@ * functions such as flush_cache may be called. */ void mips_cache_probe(void); +#endif #endif /* __MIPS_CACHE_H__ */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 5b86386..ee7a592 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -501,7 +501,7 @@ map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) if (flags == MAP_NOCACHE) return ioremap(paddr, len); - return (void *)paddr; + return (void *)CKSEG0ADDR(paddr); } /* diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 9ab5063..7a9d222 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -299,6 +299,7 @@ #define STATUSF_IP14 (_ULCAST_(1) << 6) #define STATUSB_IP15 7 #define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_IMPL (_ULCAST_(3) << 16) #define ST0_CH 0x00040000 #define ST0_NMI 0x00080000 #define ST0_SR 0x00100000 diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index e6435cc..c9c5961 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -262,4 +262,12 @@ extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, #define die_if_kernel(msg, regs) \ __die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) +static inline void execution_hazard_barrier(void) +{ + __asm__ __volatile__( + ".set noreorder\n" + "ehb\n" + ".set reorder"); +} + #endif /* _ASM_SYSTEM_H */ diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index 1f527bb..71ff41d 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -5,4 +5,8 @@ #ifndef _U_BOOT_MIPS_H_ #define _U_BOOT_MIPS_H_ +void exc_handler(void); +void except_vec3_generic(void); +void except_vec_ejtag_debug(void); + #endif /* _U_BOOT_MIPS_H_ */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index b7ce5df..659c6ad 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,6 +7,9 @@ obj-y += cache.o obj-y += cache_init.o +obj-y += genex.o +obj-y += stack.o +obj-y += traps.o obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/mips/lib/asm-offsets.c b/arch/mips/lib/asm-offsets.c new file mode 100644 index 0000000..9ed295a --- /dev/null +++ b/arch/mips/lib/asm-offsets.c @@ -0,0 +1,61 @@ +/* + * offset.c: Calculate pt_regs and task_struct offsets. + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/ptrace.h> +#include <linux/stddef.h> +#include <linux/kbuild.h> + +void output_ptreg_defines(void) +{ + COMMENT("MIPS pt_regs offsets."); + OFFSET(PT_R0, pt_regs, regs[0]); + OFFSET(PT_R1, pt_regs, regs[1]); + OFFSET(PT_R2, pt_regs, regs[2]); + OFFSET(PT_R3, pt_regs, regs[3]); + OFFSET(PT_R4, pt_regs, regs[4]); + OFFSET(PT_R5, pt_regs, regs[5]); + OFFSET(PT_R6, pt_regs, regs[6]); + OFFSET(PT_R7, pt_regs, regs[7]); + OFFSET(PT_R8, pt_regs, regs[8]); + OFFSET(PT_R9, pt_regs, regs[9]); + OFFSET(PT_R10, pt_regs, regs[10]); + OFFSET(PT_R11, pt_regs, regs[11]); + OFFSET(PT_R12, pt_regs, regs[12]); + OFFSET(PT_R13, pt_regs, regs[13]); + OFFSET(PT_R14, pt_regs, regs[14]); + OFFSET(PT_R15, pt_regs, regs[15]); + OFFSET(PT_R16, pt_regs, regs[16]); + OFFSET(PT_R17, pt_regs, regs[17]); + OFFSET(PT_R18, pt_regs, regs[18]); + OFFSET(PT_R19, pt_regs, regs[19]); + OFFSET(PT_R20, pt_regs, regs[20]); + OFFSET(PT_R21, pt_regs, regs[21]); + OFFSET(PT_R22, pt_regs, regs[22]); + OFFSET(PT_R23, pt_regs, regs[23]); + OFFSET(PT_R24, pt_regs, regs[24]); + OFFSET(PT_R25, pt_regs, regs[25]); + OFFSET(PT_R26, pt_regs, regs[26]); + OFFSET(PT_R27, pt_regs, regs[27]); + OFFSET(PT_R28, pt_regs, regs[28]); + OFFSET(PT_R29, pt_regs, regs[29]); + OFFSET(PT_R30, pt_regs, regs[30]); + OFFSET(PT_R31, pt_regs, regs[31]); + OFFSET(PT_LO, pt_regs, lo); + OFFSET(PT_HI, pt_regs, hi); + OFFSET(PT_EPC, pt_regs, cp0_epc); + OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr); + OFFSET(PT_STATUS, pt_regs, cp0_status); + OFFSET(PT_CAUSE, pt_regs, cp0_cause); + DEFINE(PT_SIZE, sizeof(struct pt_regs)); + BLANK(); +} diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index 0c6a4ab..9fec4ad 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -42,7 +42,7 @@ void arch_lmb_reserve(struct lmb *lmb) /* adjust sp by 4K to be safe */ sp -= 4096; - lmb_reserve(lmb, sp, CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp); + lmb_reserve(lmb, sp, gd->ram_top - sp); } static void linux_cmdline_init(void) diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S new file mode 100644 index 0000000..2d6d7b0 --- /dev/null +++ b/arch/mips/lib/genex.S @@ -0,0 +1,224 @@ +/* + * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2002, 2007 Maciej W. Rozycki + * Copyright (C) 2001, 2012 MIPS Technologies, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/asm-offsets.h> + +#define STATMASK 0x1f + + .set noreorder + + /* + * Macros copied and adapted from Linux MIPS + */ + .macro SAVE_AT + .set push + .set noat + LONG_S $1, PT_R1(sp) + .set pop + .endm + + .macro SAVE_TEMP +#if __mips_isa_rev < 6 + mfhi v1 +#endif +#ifdef CONFIG_32BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S $10, PT_R10(sp) + LONG_S $11, PT_R11(sp) + LONG_S $12, PT_R12(sp) +#if __mips_isa_rev < 6 + LONG_S v1, PT_HI(sp) + mflo v1 +#endif + LONG_S $13, PT_R13(sp) + LONG_S $14, PT_R14(sp) + LONG_S $15, PT_R15(sp) + LONG_S $24, PT_R24(sp) +#if __mips_isa_rev < 6 + LONG_S v1, PT_LO(sp) +#endif + .endm + + .macro SAVE_STATIC + LONG_S $16, PT_R16(sp) + LONG_S $17, PT_R17(sp) + LONG_S $18, PT_R18(sp) + LONG_S $19, PT_R19(sp) + LONG_S $20, PT_R20(sp) + LONG_S $21, PT_R21(sp) + LONG_S $22, PT_R22(sp) + LONG_S $23, PT_R23(sp) + LONG_S $30, PT_R30(sp) + .endm + + .macro SAVE_SOME + .set push + .set noat + PTR_SUBU k1, sp, PT_SIZE + LONG_S sp, PT_R29(k1) + move sp, k1 + + LONG_S $3, PT_R3(sp) + LONG_S $0, PT_R0(sp) + mfc0 v1, CP0_STATUS + LONG_S $2, PT_R2(sp) + LONG_S v1, PT_STATUS(sp) + LONG_S $4, PT_R4(sp) + mfc0 v1, CP0_CAUSE + LONG_S $5, PT_R5(sp) + LONG_S v1, PT_CAUSE(sp) + LONG_S $6, PT_R6(sp) + MFC0 v1, CP0_EPC + LONG_S $7, PT_R7(sp) +#ifdef CONFIG_64BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S v1, PT_EPC(sp) + LONG_S $25, PT_R25(sp) + LONG_S $28, PT_R28(sp) + LONG_S $31, PT_R31(sp) + .set pop + .endm + + .macro RESTORE_AT + .set push + .set noat + LONG_L $1, PT_R1(sp) + .set pop + .endm + + .macro RESTORE_TEMP +#if __mips_isa_rev < 6 + LONG_L $24, PT_LO(sp) + mtlo $24 + LONG_L $24, PT_HI(sp) + mthi $24 +#endif +#ifdef CONFIG_32BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $10, PT_R10(sp) + LONG_L $11, PT_R11(sp) + LONG_L $12, PT_R12(sp) + LONG_L $13, PT_R13(sp) + LONG_L $14, PT_R14(sp) + LONG_L $15, PT_R15(sp) + LONG_L $24, PT_R24(sp) + .endm + + .macro RESTORE_STATIC + LONG_L $16, PT_R16(sp) + LONG_L $17, PT_R17(sp) + LONG_L $18, PT_R18(sp) + LONG_L $19, PT_R19(sp) + LONG_L $20, PT_R20(sp) + LONG_L $21, PT_R21(sp) + LONG_L $22, PT_R22(sp) + LONG_L $23, PT_R23(sp) + LONG_L $30, PT_R30(sp) + .endm + + .macro RESTORE_SOME + .set push + .set reorder + .set noat + mfc0 a0, CP0_STATUS + ori a0, STATMASK + xori a0, STATMASK + mtc0 a0, CP0_STATUS + li v1, ST0_CU1 | ST0_FR | ST0_IM + and a0, v1 + LONG_L v0, PT_STATUS(sp) + nor v1, $0, v1 + and v0, v1 + or v0, a0 + mtc0 v0, CP0_STATUS + LONG_L v1, PT_EPC(sp) + MTC0 v1, CP0_EPC + LONG_L $31, PT_R31(sp) + LONG_L $28, PT_R28(sp) + LONG_L $25, PT_R25(sp) +#ifdef CONFIG_64BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $7, PT_R7(sp) + LONG_L $6, PT_R6(sp) + LONG_L $5, PT_R5(sp) + LONG_L $4, PT_R4(sp) + LONG_L $3, PT_R3(sp) + LONG_L $2, PT_R2(sp) + .set pop + .endm + + .macro RESTORE_SP + LONG_L sp, PT_R29(sp) + .endm + +NESTED(except_vec3_generic, 0, sp) + PTR_LA k1, handle_reserved + jr k1 + nop + END(except_vec3_generic) + +NESTED(except_vec_ejtag_debug, 0, sp) + PTR_LA k1, handle_ejtag_debug + jr k1 + nop + END(except_vec_ejtag_debug) + +NESTED(handle_reserved, PT_SIZE, sp) + SAVE_SOME + SAVE_AT + SAVE_TEMP + SAVE_STATIC + + PTR_LA t9, do_reserved + jr t9 + move a0, sp + END(handle_reserved) + +NESTED(handle_ejtag_debug, PT_SIZE, sp) + .set push + .set noat + MTC0 k1, CP0_DESAVE + + /* Check for SDBBP */ + MFC0 k1, CP0_DEBUG + sll k1, k1, 30 + bgez k1, ejtag_return + nop + + SAVE_SOME + SAVE_AT + SAVE_TEMP + SAVE_STATIC + + PTR_LA t9, do_ejtag_debug + jalr t9 + move a0, sp + + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP + +ejtag_return: + MFC0 k1, CP0_DESAVE + deret + .set pop + END(handle_ejtag_debug) diff --git a/arch/mips/lib/stack.c b/arch/mips/lib/stack.c new file mode 100644 index 0000000..c80f5fe --- /dev/null +++ b/arch/mips/lib/stack.c @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +int arch_reserve_stacks(void) +{ + /* reserve space for exception vector table */ + gd->start_addr_sp -= 0x500; + gd->start_addr_sp &= ~0xFFF; + gd->irq_sp = gd->start_addr_sp; + debug("Reserving %d Bytes for exception vector at: %08lx\n", + 0x500, gd->start_addr_sp); + + return 0; +} diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c new file mode 100644 index 0000000..18622c2 --- /dev/null +++ b/arch/mips/lib/traps.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle + * Copyright (C) 1995, 1996 Paul M. Antoine + * Copyright (C) 1998 Ulf Carlsson + * Copyright (C) 1999 Silicon Graphics, Inc. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2014, Imagination Technologies Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/system.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void show_regs(const struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + unsigned int cause = regs->cp0_cause; + unsigned int exccode; + int i; + + /* + * Saved main processor registers + */ + for (i = 0; i < 32; ) { + if ((i % 4) == 0) + printf("$%2d :", i); + if (i == 0) + printf(" %0*lx", field, 0UL); + else if (i == 26 || i == 27) + printf(" %*s", field, ""); + else + printf(" %0*lx", field, regs->regs[i]); + + i++; + if ((i % 4) == 0) + puts("\n"); + } + + printf("Hi : %0*lx\n", field, regs->hi); + printf("Lo : %0*lx\n", field, regs->lo); + + /* + * Saved cp0 registers + */ + printf("epc : %0*lx (text %0*lx)\n", field, regs->cp0_epc, + field, regs->cp0_epc - gd->reloc_off); + printf("ra : %0*lx (text %0*lx)\n", field, regs->regs[31], + field, regs->regs[31] - gd->reloc_off); + + printf("Status: %08x\n", (uint32_t) regs->cp0_status); + + exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; + printf("Cause : %08x (ExcCode %02x)\n", cause, exccode); + + if (1 <= exccode && exccode <= 5) + printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr); + + printf("PrId : %08x\n", read_c0_prid()); +} + +void do_reserved(const struct pt_regs *regs) +{ + puts("\nOoops:\n"); + show_regs(regs); + hang(); +} + +void do_ejtag_debug(const struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + unsigned long depc; + unsigned int debug; + + depc = read_c0_depc(); + debug = read_c0_debug(); + + printf("SDBBP EJTAG debug exception: c0_depc = %0*lx, DEBUG = %08x\n", + field, depc, debug); +} + +static void set_handler(unsigned long offset, void *addr, unsigned long size) +{ + unsigned long ebase = gd->irq_sp; + + memcpy((void *)(ebase + offset), addr, size); + flush_cache(ebase + offset, size); +} + +void trap_init(ulong reloc_addr) +{ + unsigned long ebase = gd->irq_sp; + + set_handler(0x180, &except_vec3_generic, 0x80); + set_handler(0x280, &except_vec_ejtag_debug, 0x80); + + write_c0_ebase(ebase); + clear_c0_status(ST0_BEV); + execution_hazard_barrier(); +} diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index 7d483aa..d982b0f 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -9,6 +9,7 @@ config SOC_AR933X select SUPPORTS_BIG_ENDIAN select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 + select ROM_EXCEPTION_VECTORS select MIPS_TUNE_24KC help This supports QCA/Atheros ar933x family SOCs. @@ -27,6 +28,7 @@ config SOC_QCA953X select SUPPORTS_BIG_ENDIAN select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 + select ROM_EXCEPTION_VECTORS select MIPS_TUNE_24KC help This supports QCA/Atheros qca953x family SOCs. diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig index 2e38bb7..8fad4cf 100644 --- a/arch/mips/mach-pic32/Kconfig +++ b/arch/mips/mach-pic32/Kconfig @@ -14,6 +14,7 @@ config SOC_PIC32MZDA select SUPPORTS_CPU_MIPS32_R2 select MIPS_L1_CACHE_SHIFT_4 select SYS_MIPS_CACHE_INIT_RAM_LOAD + select ROM_EXCEPTION_VECTORS help This supports Microchip PIC32MZ[DA] family of microcontrollers. |