xref: /rk3399_rockchip-uboot/arch/nds32/cpu/n1213/start.S (revision 1a05bb3c2804980fa4fbcd2b7a05a2203308af55)
137e5708aSMacpaul Lin/*
237e5708aSMacpaul Lin *	Andesboot - Startup Code for Whitiger core
337e5708aSMacpaul Lin *
437e5708aSMacpaul Lin *	Copyright (C) 2006	Andes Technology Corporation
537e5708aSMacpaul Lin *	Copyright (C) 2006	Shawn Lin <nobuhiro@andestech.com>
637e5708aSMacpaul Lin *	Copyright (C) 2011	Macpaul Lin <macpaul@andestech.com>
737e5708aSMacpaul Lin *				Greentime Hu <greentime@andestech.com>
837e5708aSMacpaul Lin *
937e5708aSMacpaul Lin * See file CREDITS for list of people who contributed to this
1037e5708aSMacpaul Lin * project.
1137e5708aSMacpaul Lin *
1237e5708aSMacpaul Lin * This program is free software; you can redistribute it and/or
1337e5708aSMacpaul Lin * modify it under the terms of the GNU General Public License as
1437e5708aSMacpaul Lin * published by the Free Software Foundation; either version 2 of
1537e5708aSMacpaul Lin * the License, or (at your option) any later version.
1637e5708aSMacpaul Lin *
1737e5708aSMacpaul Lin * This program is distributed in the hope that it will be useful,
1837e5708aSMacpaul Lin * but WITHOUT ANY WARRANTY; without even the implied warranty of
1937e5708aSMacpaul Lin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
2037e5708aSMacpaul Lin * GNU General Public License for more details.
2137e5708aSMacpaul Lin *
2237e5708aSMacpaul Lin * You should have received a copy of the GNU General Public License
2337e5708aSMacpaul Lin * along with this program; if not, write to the Free Software
2437e5708aSMacpaul Lin * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2537e5708aSMacpaul Lin * MA 02111-1307 USA
2637e5708aSMacpaul Lin */
2737e5708aSMacpaul Lin
2837e5708aSMacpaul Lin#include <asm-offsets.h>
2937e5708aSMacpaul Lin#include <config.h>
3037e5708aSMacpaul Lin#include <common.h>
3137e5708aSMacpaul Lin#include <asm/macro.h>
3237e5708aSMacpaul Lin#include <version.h>
3337e5708aSMacpaul Lin
3437e5708aSMacpaul Lin/*
3537e5708aSMacpaul Lin * Jump vector table for EVIC mode
3637e5708aSMacpaul Lin */
3737e5708aSMacpaul Lin#define ENA_DCAC		2UL
3837e5708aSMacpaul Lin#define DIS_DCAC		~ENA_DCAC
3937e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISET	(0x07)	 	! I Cache sets per way
4037e5708aSMacpaul Lin#define ICAC_MEM_KBF_IWAY	(0x07<<3)	! I cache ways
4137e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISZ	(0x07<<6)	! I cache line size
4237e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSET	(0x07)		! D Cache sets per way
4337e5708aSMacpaul Lin#define DCAC_MEM_KBF_DWAY	(0x07<<3)	! D cache ways
4437e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSZ	(0x07<<6)	! D cache line size
4537e5708aSMacpaul Lin
4637e5708aSMacpaul Lin#define PSW			$ir0
4737e5708aSMacpaul Lin#define EIT_INTR_PSW		$ir1		! interruption $PSW
4837e5708aSMacpaul Lin#define EIT_PREV_IPSW		$ir2		! previous $IPSW
4937e5708aSMacpaul Lin#define EIT_IVB			$ir3		! intr vector base address
5037e5708aSMacpaul Lin#define EIT_EVA			$ir4		! MMU related Exception VA reg
5137e5708aSMacpaul Lin#define EIT_PREV_EVA		$ir5		! previous $eva
5237e5708aSMacpaul Lin#define EIT_ITYPE		$ir6		! interruption type
5337e5708aSMacpaul Lin#define EIT_PREV_ITYPE		$ir7		! prev intr type
5437e5708aSMacpaul Lin#define EIT_MACH_ERR		$ir8		! machine error log
5537e5708aSMacpaul Lin#define EIT_INTR_PC		$ir9		! Interruption PC
5637e5708aSMacpaul Lin#define EIT_PREV_IPC		$ir10		! previous $IPC
5737e5708aSMacpaul Lin#define EIT_OVL_INTR_PC		$ir11		! overflow interruption PC
5837e5708aSMacpaul Lin#define EIT_PREV_P0		$ir12		! prev $P0
5937e5708aSMacpaul Lin#define EIT_PREV_P1		$ir13		! prev $p1
6037e5708aSMacpaul Lin#define CR_ICAC_MEM		$cr1		! I-cache/memory config reg
6137e5708aSMacpaul Lin#define CR_DCAC_MEM		$cr2		! D-cache/memory config reg
6237e5708aSMacpaul Lin#define MR_CAC_CTL		$mr8
6337e5708aSMacpaul Lin
6437e5708aSMacpaul Lin.globl _start
6537e5708aSMacpaul Lin
6637e5708aSMacpaul Lin_start:	j	reset
6737e5708aSMacpaul Lin	j	tlb_fill
6837e5708aSMacpaul Lin	j	tlb_not_present
6937e5708aSMacpaul Lin	j	tlb_misc
7037e5708aSMacpaul Lin	j	tlb_vlpt_miss
71*1a05bb3cSMacpaul Lin	j	machine_error
7237e5708aSMacpaul Lin	j	debug
7337e5708aSMacpaul Lin	j	general_exception
74*1a05bb3cSMacpaul Lin	j	syscall
7537e5708aSMacpaul Lin	j	internal_interrupt		! H0I
7637e5708aSMacpaul Lin	j	internal_interrupt		! H1I
7737e5708aSMacpaul Lin	j	internal_interrupt		! H2I
7837e5708aSMacpaul Lin	j	internal_interrupt		! H3I
7937e5708aSMacpaul Lin	j	internal_interrupt		! H4I
8037e5708aSMacpaul Lin	j	internal_interrupt		! H5I
81*1a05bb3cSMacpaul Lin	j	software_interrupt		! S0I
8237e5708aSMacpaul Lin
8337e5708aSMacpaul Lin	.balign 16
8437e5708aSMacpaul Lin
8537e5708aSMacpaul Lin/*
8637e5708aSMacpaul Lin * Andesboot Startup Code (reset vector)
8737e5708aSMacpaul Lin *
8837e5708aSMacpaul Lin *	1.	bootstrap
8937e5708aSMacpaul Lin *		1.1 reset - start of u-boot
9037e5708aSMacpaul Lin *		1.2 to superuser mode - as is when reset
9137e5708aSMacpaul Lin *		1.4 Do lowlevel_init
9237e5708aSMacpaul Lin *			- (this will jump out to lowlevel_init.S in SoC)
9337e5708aSMacpaul Lin *			- (lowlevel_init)
9437e5708aSMacpaul Lin *		1.3 Turn off watchdog timer
9537e5708aSMacpaul Lin *			- (this will jump out to watchdog.S in SoC)
9637e5708aSMacpaul Lin *			- (turnoff_watchdog)
9737e5708aSMacpaul Lin *	2.	Do critical init when reboot (not from mem)
9837e5708aSMacpaul Lin *	3.	Relocate andesboot to ram
9937e5708aSMacpaul Lin *	4.	Setup stack
10037e5708aSMacpaul Lin *	5.	Jump to second stage (board_init_r)
10137e5708aSMacpaul Lin */
10237e5708aSMacpaul Lin
10337e5708aSMacpaul Lin/* Note: TEXT_BASE is defined by the (board-dependent) linker script */
10437e5708aSMacpaul Lin.globl _TEXT_BASE
10537e5708aSMacpaul Lin_TEXT_BASE:
10637e5708aSMacpaul Lin	.word	CONFIG_SYS_TEXT_BASE
10737e5708aSMacpaul Lin
10837e5708aSMacpaul Lin/*
10937e5708aSMacpaul Lin * These are defined in the board-specific linker script.
11037e5708aSMacpaul Lin * Subtracting _start from them lets the linker put their
11137e5708aSMacpaul Lin * relative position in the executable instead of leaving
11237e5708aSMacpaul Lin * them null.
11337e5708aSMacpaul Lin */
11437e5708aSMacpaul Lin#ifdef CONFIG_USE_IRQ
11537e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */
11637e5708aSMacpaul Lin.globl IRQ_STACK_START
11737e5708aSMacpaul LinIRQ_STACK_START:
11837e5708aSMacpaul Lin	.word 0x0badc0de
11937e5708aSMacpaul Lin
12037e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */
12137e5708aSMacpaul Lin.globl FIQ_STACK_START
12237e5708aSMacpaul LinFIQ_STACK_START:
12337e5708aSMacpaul Lin	.word 0x0badc0de
12437e5708aSMacpaul Lin#endif
12537e5708aSMacpaul Lin
12637e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) + 8 bytes */
12737e5708aSMacpaul Lin.globl IRQ_STACK_START_IN
12837e5708aSMacpaul LinIRQ_STACK_START_IN:
12937e5708aSMacpaul Lin	.word 0x0badc0de
13037e5708aSMacpaul Lin
13137e5708aSMacpaul Lin/*
13237e5708aSMacpaul Lin * The bootstrap code of nds32 core
13337e5708aSMacpaul Lin */
13437e5708aSMacpaul Lin
13537e5708aSMacpaul Linreset:
13637e5708aSMacpaul Linset_ivb:
13737e5708aSMacpaul Lin	li	$r0, 0x0
13837e5708aSMacpaul Lin
13937e5708aSMacpaul Lin	/* turn on BTB */
14037e5708aSMacpaul Lin	mtsr	$r0, $misc_ctl
14137e5708aSMacpaul Lin	/* set IVIC, vector size: 4 bytes, base: 0x0 */
14237e5708aSMacpaul Lin	mtsr	$r0, $ivb
14337e5708aSMacpaul Lin
14437e5708aSMacpaul Linload_lli:
14537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT
14637e5708aSMacpaul Lin	jal	load_lowlevel_init
14737e5708aSMacpaul Lin	jral	$p0
14837e5708aSMacpaul Lin#endif
14937e5708aSMacpaul Lin
15037e5708aSMacpaul Lin/*
15137e5708aSMacpaul Lin * Set the N1213 (Whitiger) core to superuser mode
15237e5708aSMacpaul Lin * According to spec, it is already when reset
15337e5708aSMacpaul Lin */
15437e5708aSMacpaul Linturnoff_wtdog:
15537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
15637e5708aSMacpaul Lin	jal	load_turnoff_watchdog
15737e5708aSMacpaul Lin	jral	$p0
15837e5708aSMacpaul Lin#endif
15937e5708aSMacpaul Lin
16037e5708aSMacpaul Lin/*
16137e5708aSMacpaul Lin * Do CPU critical regs init only at reboot,
16237e5708aSMacpaul Lin * not when booting from ram
16337e5708aSMacpaul Lin */
16437e5708aSMacpaul Lin#ifdef CONFIG_INIT_CRITICAL
16537e5708aSMacpaul Lin	bal	cpu_init_crit		! Do CPU critical regs init
16637e5708aSMacpaul Lin#endif
16737e5708aSMacpaul Lin
16837e5708aSMacpaul Lin/*
16937e5708aSMacpaul Lin * Set stackpointer in internal RAM to call board_init_f
17037e5708aSMacpaul Lin * $sp must be 8-byte alignment for ABI compliance.
17137e5708aSMacpaul Lin */
17237e5708aSMacpaul Lincall_board_init_f:
17337e5708aSMacpaul Lin	li	$sp, CONFIG_SYS_INIT_SP_ADDR
17437e5708aSMacpaul Lin	li	$r0, 0x00000000
17537e5708aSMacpaul Lin
17637e5708aSMacpaul Lin#ifdef __PIC__
17737e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__
17837e5708aSMacpaul Lin/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */
17937e5708aSMacpaul Lin	la	$r15, board_init_f	! store function address into $r15
18037e5708aSMacpaul Lin#endif
18137e5708aSMacpaul Lin#endif
18237e5708aSMacpaul Lin	j	board_init_f		! jump to board_init_f() in lib/board.c
18337e5708aSMacpaul Lin
18437e5708aSMacpaul Lin/*
18537e5708aSMacpaul Lin * void relocate_code (addr_sp, gd, addr_moni)
18637e5708aSMacpaul Lin *
18737e5708aSMacpaul Lin * This "function" does not return, instead it continues in RAM
18837e5708aSMacpaul Lin * after relocating the monitor code.
18937e5708aSMacpaul Lin *
19037e5708aSMacpaul Lin */
19137e5708aSMacpaul Lin.globl	relocate_code
19237e5708aSMacpaul Linrelocate_code:
19337e5708aSMacpaul Lin	move	$r4, $r0		/* save addr_sp */
19437e5708aSMacpaul Lin	move	$r5, $r1		/* save addr of gd */
19537e5708aSMacpaul Lin	move	$r6, $r2		/* save addr of destination */
19637e5708aSMacpaul Lin
19737e5708aSMacpaul Lin/* Set up the stack */
19837e5708aSMacpaul Linstack_setup:
19937e5708aSMacpaul Lin	move	$sp, $r4
20037e5708aSMacpaul Lin
20137e5708aSMacpaul Lin	la	$r0, _start
20237e5708aSMacpaul Lin
20337e5708aSMacpaul Lin	beq	$r0, $r6, clear_bss	/* skip relocation */
20437e5708aSMacpaul Lin
20537e5708aSMacpaul Lin	move	$r1, $r6		/* r1 <- scratch for copy_loop */
20637e5708aSMacpaul Lin	la	$r3, __bss_start
20737e5708aSMacpaul Lin	sub	$r3, $r3, $r0		/* r3 <- __bss_start_ofs */
20837e5708aSMacpaul Lin	add	$r2, $r0, $r3		/* r2 <- source end address */
20937e5708aSMacpaul Lin
21037e5708aSMacpaul Lincopy_loop:
21137e5708aSMacpaul Lin	lwi.p	$r7, [$r0], #4
21237e5708aSMacpaul Lin	swi.p	$r7, [$r1], #4
21337e5708aSMacpaul Lin	blt	$r0, $r2, copy_loop
21437e5708aSMacpaul Lin
21537e5708aSMacpaul Lin/*
21637e5708aSMacpaul Lin * fix relocations related issues
21737e5708aSMacpaul Lin */
21837e5708aSMacpaul Linfix_relocations:
21937e5708aSMacpaul Lin	l.w	$r0, _TEXT_BASE		/* r0 <- Text base */
22037e5708aSMacpaul Lin	sub	$r9, $r6, $r0		/* r9 <- relocation offset */
22137e5708aSMacpaul Lin
22237e5708aSMacpaul Linfix_got:
22337e5708aSMacpaul Lin/*
22437e5708aSMacpaul Lin * Now we want to update GOT.
22537e5708aSMacpaul Lin *
22637e5708aSMacpaul Lin * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
22737e5708aSMacpaul Lin * generated by GNU ld. Skip these reserved entries from relocation.
22837e5708aSMacpaul Lin */
22937e5708aSMacpaul Lin	la	$r2, __got_start	/* r2 <- rel __got_start in FLASH */
23037e5708aSMacpaul Lin	add	$r2, $r2, $r9		/* r2 <- rel __got_start in RAM */
23137e5708aSMacpaul Lin	la	$r3, __got_end		/* r3 <- rel __got_end in FLASH */
23237e5708aSMacpaul Lin	add	$r3, $r3, $r9		/* r3 <- rel __got_end in RAM */
23337e5708aSMacpaul Lin	addi	$r2, $r2, #8		/* skipping first two entries */
23437e5708aSMacpaul Linfix_got_loop:
23537e5708aSMacpaul Lin	lwi	$r0, [$r2]		/* r0 <- location in FLASH to fix up */
23637e5708aSMacpaul Lin	add	$r0, $r0, $r9		/* r0 <- location fix up to RAM */
23737e5708aSMacpaul Lin	swi.p	$r0, [$r2], #4		/* r0 <- store fix into .got in RAM */
23837e5708aSMacpaul Lin	blt	$r2, $r3, fix_got_loop
23937e5708aSMacpaul Lin
24037e5708aSMacpaul Linclear_bss:
24137e5708aSMacpaul Lin	la	$r0, __bss_start	/* r0 <- rel __bss_start in FLASH */
24237e5708aSMacpaul Lin	add	$r0, $r0, $r9		/* r0 <- rel __bss_start in FLASH */
24337e5708aSMacpaul Lin	la	$r1, __bss_end__	/* r1 <- rel __bss_end in RAM */
24437e5708aSMacpaul Lin	add	$r1, $r1, $r9		/* r0 <- rel __bss_end in RAM */
24537e5708aSMacpaul Lin	li	$r2, 0x00000000		/* clear */
24637e5708aSMacpaul Lin
24737e5708aSMacpaul Linclbss_l:
24837e5708aSMacpaul Lin	sw	$r2, [$r0]		/* clear loop... */
24937e5708aSMacpaul Lin	addi	$r0, $r0, #4
25037e5708aSMacpaul Lin	bne	$r0, $r1, clbss_l
25137e5708aSMacpaul Lin
25237e5708aSMacpaul Lin/*
25337e5708aSMacpaul Lin * We are done. Do not return, instead branch to second part of board
25437e5708aSMacpaul Lin * initialization, now running from RAM.
25537e5708aSMacpaul Lin */
25637e5708aSMacpaul Lincall_board_init_r:
25737e5708aSMacpaul Lin	la	$r0, board_init_r
25837e5708aSMacpaul Lin	move	$lp, $r0		/* offset of board_init_r() */
25937e5708aSMacpaul Lin	add	$lp, $lp, $r9		/* real address of board_init_r() */
26037e5708aSMacpaul Lin	/* setup parameters for board_init_r */
26137e5708aSMacpaul Lin	move	$r0, $r5		/* gd_t */
26237e5708aSMacpaul Lin	move	$r1, $r6		/* dest_addr */
26337e5708aSMacpaul Lin
26437e5708aSMacpaul Lin#ifdef __PIC__
26537e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__		/* NDS32 V0 ISA	*/
26637e5708aSMacpaul Lin	move	$r15, $lp		/* store function address into $r15 */
26737e5708aSMacpaul Lin#endif
26837e5708aSMacpaul Lin#endif
26937e5708aSMacpaul Lin
27037e5708aSMacpaul Lin	/* jump to it ... */
27137e5708aSMacpaul Lin	jr	$lp			/* jump to board_init_r() */
27237e5708aSMacpaul Lin
27337e5708aSMacpaul Lin/*
27437e5708aSMacpaul Lin * Initialize CPU critical registers
27537e5708aSMacpaul Lin *
27637e5708aSMacpaul Lin *	1.	Setup control registers
27737e5708aSMacpaul Lin *		1.1 Mask all IRQs
27837e5708aSMacpaul Lin *		1.2 Flush cache and TLB
27937e5708aSMacpaul Lin *		1.3 Disable MMU and cache
28037e5708aSMacpaul Lin *	2.	Setup memory timing
28137e5708aSMacpaul Lin */
28237e5708aSMacpaul Lin
28337e5708aSMacpaul Lincpu_init_crit:
28437e5708aSMacpaul Lin
28537e5708aSMacpaul Lin	move	$r0, $lp		/* push	ra */
28637e5708aSMacpaul Lin
28737e5708aSMacpaul Lin	/* Disable Interrupts by clear GIE in $PSW reg */
28837e5708aSMacpaul Lin	setgie.d
28937e5708aSMacpaul Lin
29037e5708aSMacpaul Lin	/* Flush caches and TLB */
29137e5708aSMacpaul Lin	/* Invalidate caches */
29237e5708aSMacpaul Lin	bal	invalidate_icac
29337e5708aSMacpaul Lin	bal	invalidate_dcac
29437e5708aSMacpaul Lin
29537e5708aSMacpaul Lin	/* Flush TLB */
29637e5708aSMacpaul Lin	mfsr	$p0, $MMU_CFG
29737e5708aSMacpaul Lin	andi	$p0, $p0, 0x3			! MMPS
29837e5708aSMacpaul Lin	li	$p1, 0x2			! TLB MMU
29937e5708aSMacpaul Lin	bne	$p0, $p1, 1f
30037e5708aSMacpaul Lin	tlbop	flushall			! Flush TLB
30137e5708aSMacpaul Lin
30237e5708aSMacpaul Lin1:
30337e5708aSMacpaul Lin	! Disable MMU, Dcache
30437e5708aSMacpaul Lin	! Whitiger is MMU disabled when reset
30537e5708aSMacpaul Lin	! Disable the D$
30637e5708aSMacpaul Lin	mfsr	$p0, MR_CAC_CTL			! Get the $CACHE_CTL reg
30737e5708aSMacpaul Lin	li	$p1, DIS_DCAC
30837e5708aSMacpaul Lin	and	$p0, $p0, $p1			! Set DC_EN bit
30937e5708aSMacpaul Lin	mtsr	$p0, MR_CAC_CTL			! write back the $CACHE_CTL reg
31037e5708aSMacpaul Lin	isb
31137e5708aSMacpaul Lin
31237e5708aSMacpaul Lin	move	$lp, $r0
31337e5708aSMacpaul Lin2:
31437e5708aSMacpaul Lin	ret
31537e5708aSMacpaul Lin
31637e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT
31737e5708aSMacpaul Linload_lowlevel_init:
31837e5708aSMacpaul Lin	la  $r6, lowlevel_init
31937e5708aSMacpaul Lin	la  $r7, load_lli + 4
32037e5708aSMacpaul Lin	sub $p0, $r6, $r7
32137e5708aSMacpaul Lin	add $p0, $p0, $lp
32237e5708aSMacpaul Linret
32337e5708aSMacpaul Lin#endif
32437e5708aSMacpaul Lin
32537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
32637e5708aSMacpaul Linload_turnoff_watchdog:
32737e5708aSMacpaul Lin	la  $r6, turnoff_watchdog
32837e5708aSMacpaul Lin	la  $r7, turnoff_wtdog + 4
32937e5708aSMacpaul Lin	sub $p0, $r6, $r7
33037e5708aSMacpaul Lin	add $p0, $p0, $lp
33137e5708aSMacpaul Linret
33237e5708aSMacpaul Lin#endif
33337e5708aSMacpaul Lin
33437e5708aSMacpaul Lin/*
33537e5708aSMacpaul Lin * Invalidate I$
33637e5708aSMacpaul Lin */
33737e5708aSMacpaul Lininvalidate_icac:
33837e5708aSMacpaul Lin	! read $cr1(I CAC/MEM cfg. reg.) configuration
33937e5708aSMacpaul Lin	mfsr	$t0, CR_ICAC_MEM
34037e5708aSMacpaul Lin
34137e5708aSMacpaul Lin	! Get the ISZ field
34237e5708aSMacpaul Lin	andi	$p0, $t0, ICAC_MEM_KBF_ISZ
34337e5708aSMacpaul Lin
34437e5708aSMacpaul Lin	! if $p0=0, then no I CAC existed
34537e5708aSMacpaul Lin	beqz	$p0, end_flush_icache
34637e5708aSMacpaul Lin
34737e5708aSMacpaul Lin	! get $p0 the index of I$ block
34837e5708aSMacpaul Lin	srli	$p0, $p0, 6
34937e5708aSMacpaul Lin
35037e5708aSMacpaul Lin	! $t1= bit width of I cache line size(ISZ)
35137e5708aSMacpaul Lin	addi	$t1, $p0, 2
35237e5708aSMacpaul Lin
35337e5708aSMacpaul Lin	li	$t4, 1
35437e5708aSMacpaul Lin	sll	$t5, $t4, $t1			! get $t5 cache line size
35537e5708aSMacpaul Lin	andi	$p1, $t0, ICAC_MEM_KBF_ISET	! get the ISET field
35637e5708aSMacpaul Lin	addi	$t2, $p1, 6			! $t2= bit width of ISET
35737e5708aSMacpaul Lin	andi	$p1, $t0, ICAC_MEM_KBF_IWAY	! get bitfield of Iway
35837e5708aSMacpaul Lin	srli	$p1, $p1, 3
35937e5708aSMacpaul Lin	addi	$p1, $p1, 1			! then $p1 is I way number
36037e5708aSMacpaul Lin	add	$t3, $t2, $t1			! SHIFT
36137e5708aSMacpaul Lin	sll	$p1, $p1, $t3			! GET the total cache size
36237e5708aSMacpaul LinICAC_LOOP:
36337e5708aSMacpaul Lin	sub	$p1, $p1, $t5
36437e5708aSMacpaul Lin	cctl	$p1, L1I_IX_INVAL
36537e5708aSMacpaul Lin	bnez	$p1, ICAC_LOOP
36637e5708aSMacpaul Linend_flush_icache:
36737e5708aSMacpaul Lin	ret
36837e5708aSMacpaul Lin
36937e5708aSMacpaul Lin/*
37037e5708aSMacpaul Lin * Invalidate D$
37137e5708aSMacpaul Lin */
37237e5708aSMacpaul Lininvalidate_dcac:
37337e5708aSMacpaul Lin	! read $cr2(D CAC/MEM cfg. reg.) configuration
37437e5708aSMacpaul Lin	mfsr	$t0, CR_DCAC_MEM
37537e5708aSMacpaul Lin
37637e5708aSMacpaul Lin	! Get the DSZ field
37737e5708aSMacpaul Lin	andi	$p0, $t0, DCAC_MEM_KBF_DSZ
37837e5708aSMacpaul Lin
37937e5708aSMacpaul Lin	! if $p0=0, then no D CAC existed
38037e5708aSMacpaul Lin	beqz	$p0, end_flush_dcache
38137e5708aSMacpaul Lin
38237e5708aSMacpaul Lin	! get $p0 the index of D$ block
38337e5708aSMacpaul Lin	srli	$p0, $p0, 6
38437e5708aSMacpaul Lin
38537e5708aSMacpaul Lin	! $t1= bit width of D cache line size(DSZ)
38637e5708aSMacpaul Lin	addi	$t1, $p0, 2
38737e5708aSMacpaul Lin
38837e5708aSMacpaul Lin	li	$t4, 1
38937e5708aSMacpaul Lin	sll	$t5, $t4, $t1			! get $t5 cache line size
39037e5708aSMacpaul Lin	andi	$p1, $t0, DCAC_MEM_KBF_DSET	! get the DSET field
39137e5708aSMacpaul Lin	addi	$t2, $p1, 6			! $t2= bit width of DSET
39237e5708aSMacpaul Lin	andi	$p1, $t0, DCAC_MEM_KBF_DWAY	! get bitfield of D way
39337e5708aSMacpaul Lin	srli	$p1, $p1, 3
39437e5708aSMacpaul Lin	addi	$p1, $p1, 1			! then $p1 is D way number
39537e5708aSMacpaul Lin	add	$t3, $t2, $t1			! SHIFT
39637e5708aSMacpaul Lin	sll	$p1, $p1, $t3			! GET the total cache size
39737e5708aSMacpaul LinDCAC_LOOP:
39837e5708aSMacpaul Lin	sub	$p1, $p1, $t5
39937e5708aSMacpaul Lin	cctl	$p1, L1D_IX_INVAL
40037e5708aSMacpaul Lin	bnez	$p1, DCAC_LOOP
40137e5708aSMacpaul Linend_flush_dcache:
40237e5708aSMacpaul Lin	ret
40337e5708aSMacpaul Lin
40437e5708aSMacpaul Lin/*
40537e5708aSMacpaul Lin * Interrupt handling
40637e5708aSMacpaul Lin */
40737e5708aSMacpaul Lin
40837e5708aSMacpaul Lin/*
40937e5708aSMacpaul Lin * exception handlers
41037e5708aSMacpaul Lin */
41137e5708aSMacpaul Lin	.align	5
41237e5708aSMacpaul Lin
41337e5708aSMacpaul Lin.macro	SAVE_ALL
41437e5708aSMacpaul Lin	! FIXME: Other way to get PC?
41537e5708aSMacpaul Lin	! FIXME: Update according to the newest spec!!
41637e5708aSMacpaul Lin1:
41737e5708aSMacpaul Lin	la	 $r28, 1
41837e5708aSMacpaul Lin	push $r28
41937e5708aSMacpaul Lin	mfsr $r28, PSW			! $PSW
42037e5708aSMacpaul Lin	push $r28
42137e5708aSMacpaul Lin	mfsr $r28, EIT_EVA		! $ir1 $EVA
42237e5708aSMacpaul Lin	push $r28
42337e5708aSMacpaul Lin	mfsr $r28, EIT_ITYPE		! $ir2 $ITYPE
42437e5708aSMacpaul Lin	push $r28
42537e5708aSMacpaul Lin	mfsr $r28, EIT_MACH_ERR		! $ir3 Mach Error
42637e5708aSMacpaul Lin	push $r28
42737e5708aSMacpaul Lin	mfsr $r28, EIT_INTR_PSW		! $ir5 $IPSW
42837e5708aSMacpaul Lin	push $r28
42937e5708aSMacpaul Lin	mfsr $r28, EIT_PREV_IPSW	! $ir6 prev $IPSW
43037e5708aSMacpaul Lin	push $r28
43137e5708aSMacpaul Lin	mfsr $r28, EIT_PREV_EVA		! $ir7 prev $EVA
43237e5708aSMacpaul Lin	push $r28
43337e5708aSMacpaul Lin	mfsr $r28, EIT_PREV_ITYPE	! $ir8 prev $ITYPE
43437e5708aSMacpaul Lin	push $r28
43537e5708aSMacpaul Lin	mfsr $r28, EIT_INTR_PC		! $ir9 Interruption PC
43637e5708aSMacpaul Lin	push $r28
43737e5708aSMacpaul Lin	mfsr $r28, EIT_PREV_IPC		! $ir10 prev INTR_PC
43837e5708aSMacpaul Lin	push $r28
43937e5708aSMacpaul Lin	mfsr $r28, EIT_OVL_INTR_PC	! $ir11 Overflowed INTR_PC
44037e5708aSMacpaul Lin	push $r28
44137e5708aSMacpaul Lin	mfusr $r28, $d1.lo
44237e5708aSMacpaul Lin	push $r28
44337e5708aSMacpaul Lin	mfusr $r28, $d1.hi
44437e5708aSMacpaul Lin	push $r28
44537e5708aSMacpaul Lin	mfusr $r28, $d0.lo
44637e5708aSMacpaul Lin	push $r28
44737e5708aSMacpaul Lin	mfusr $r28, $d0.hi
44837e5708aSMacpaul Lin	push $r28
44937e5708aSMacpaul Lin	pushm $r0, $r30		! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp
45037e5708aSMacpaul Lin	addi	$sp, $sp, -4	! make room for implicit pt_regs parameters
45137e5708aSMacpaul Lin.endm
45237e5708aSMacpaul Lin
45337e5708aSMacpaul Lin	.align	5
45437e5708aSMacpaul Lintlb_fill:
45537e5708aSMacpaul Lin	SAVE_ALL
45637e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
45737e5708aSMacpaul Lin	li	$r1, 1				! Determine interruption type
45837e5708aSMacpaul Lin	bal 	do_interruption
45937e5708aSMacpaul Lin
46037e5708aSMacpaul Lin	.align	5
46137e5708aSMacpaul Lintlb_not_present:
46237e5708aSMacpaul Lin	SAVE_ALL
46337e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
46437e5708aSMacpaul Lin	li	$r1, 2				! Determine interruption type
46537e5708aSMacpaul Lin	bal 	do_interruption
46637e5708aSMacpaul Lin
46737e5708aSMacpaul Lin	.align	5
46837e5708aSMacpaul Lintlb_misc:
46937e5708aSMacpaul Lin	SAVE_ALL
47037e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
47137e5708aSMacpaul Lin	li	$r1, 3				! Determine interruption type
47237e5708aSMacpaul Lin	bal 	do_interruption
47337e5708aSMacpaul Lin
47437e5708aSMacpaul Lin	.align	5
47537e5708aSMacpaul Lintlb_vlpt_miss:
47637e5708aSMacpaul Lin	SAVE_ALL
47737e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
47837e5708aSMacpaul Lin	li	$r1, 4				! Determine interruption type
47937e5708aSMacpaul Lin	bal	do_interruption
48037e5708aSMacpaul Lin
48137e5708aSMacpaul Lin	.align	5
482*1a05bb3cSMacpaul Linmachine_error:
48337e5708aSMacpaul Lin	SAVE_ALL
48437e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
48537e5708aSMacpaul Lin	li	$r1, 5				! Determine interruption type
48637e5708aSMacpaul Lin	bal	do_interruption
48737e5708aSMacpaul Lin
48837e5708aSMacpaul Lin	.align	5
48937e5708aSMacpaul Lindebug:
49037e5708aSMacpaul Lin	SAVE_ALL
49137e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
49237e5708aSMacpaul Lin	li	$r1, 6				! Determine interruption type
49337e5708aSMacpaul Lin	bal	do_interruption
49437e5708aSMacpaul Lin
49537e5708aSMacpaul Lin	.align	5
49637e5708aSMacpaul Lingeneral_exception:
49737e5708aSMacpaul Lin	SAVE_ALL
49837e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
49937e5708aSMacpaul Lin	li	$r1, 7				! Determine interruption type
50037e5708aSMacpaul Lin	bal	do_interruption
50137e5708aSMacpaul Lin
50237e5708aSMacpaul Lin	.align	5
503*1a05bb3cSMacpaul Linsyscall:
50437e5708aSMacpaul Lin	SAVE_ALL
50537e5708aSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
50637e5708aSMacpaul Lin	li	$r1, 8				! Determine interruption type
50737e5708aSMacpaul Lin	bal	do_interruption
50837e5708aSMacpaul Lin
50937e5708aSMacpaul Lin	.align	5
510*1a05bb3cSMacpaul Lininternal_interrupt:
511*1a05bb3cSMacpaul Lin	SAVE_ALL
512*1a05bb3cSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
513*1a05bb3cSMacpaul Lin	li	$r1, 9				! Determine interruption type
514*1a05bb3cSMacpaul Lin	bal	do_interruption
515*1a05bb3cSMacpaul Lin
516*1a05bb3cSMacpaul Lin	.align	5
517*1a05bb3cSMacpaul Linsoftware_interrupt:
518*1a05bb3cSMacpaul Lin	SAVE_ALL
519*1a05bb3cSMacpaul Lin	move	$r0, $sp			! To get the kernel stack
520*1a05bb3cSMacpaul Lin	li	$r1, 10				! Determine interruption type
521*1a05bb3cSMacpaul Lin	bal	do_interruption
522*1a05bb3cSMacpaul Lin
523*1a05bb3cSMacpaul Lin	.align	5
52437e5708aSMacpaul Lin
52537e5708aSMacpaul Lin/*
52637e5708aSMacpaul Lin * void reset_cpu(ulong addr);
52737e5708aSMacpaul Lin * $r0: input address to jump to
52837e5708aSMacpaul Lin */
52937e5708aSMacpaul Lin.globl reset_cpu
53037e5708aSMacpaul Linreset_cpu:
53137e5708aSMacpaul Lin/* No need to disable MMU because we never enable it */
53237e5708aSMacpaul Lin
53337e5708aSMacpaul Lin	bal	invalidate_icac
53437e5708aSMacpaul Lin	bal	invalidate_dcac
53537e5708aSMacpaul Lin	mfsr	$p0, $MMU_CFG
53637e5708aSMacpaul Lin	andi	$p0, $p0, 0x3			! MMPS
53737e5708aSMacpaul Lin	li	$p1, 0x2			! TLB MMU
53837e5708aSMacpaul Lin	bne	$p0, $p1, 1f
53937e5708aSMacpaul Lin	tlbop	flushall			! Flush TLB
54037e5708aSMacpaul Lin1:
54137e5708aSMacpaul Lin	mfsr	$p0, MR_CAC_CTL			! Get the $CACHE_CTL reg
54237e5708aSMacpaul Lin	li	$p1, DIS_DCAC
54337e5708aSMacpaul Lin	and	$p0, $p0, $p1			! Clear the DC_EN bit
54437e5708aSMacpaul Lin	mtsr	$p0, MR_CAC_CTL			! Write back the $CACHE_CTL reg
54537e5708aSMacpaul Lin	br	$r0				! Jump to the input address
546