322 lines · 7.0 KB · Assembly
RawDownload
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2011 by Kevin Cernekee (cernekee@gmail.com) * * Reset/NMI/re-entry vectors for BMIPS processors */  #include <asm/asm.h>#include <asm/asmmacro.h>#include <asm/cacheops.h>#include <asm/cpu.h>#include <asm/regdef.h>#include <asm/mipsregs.h>#include <asm/stackframe.h>#include <asm/addrspace.h>#include <asm/hazards.h>#include <asm/bmips.h> 	.macro	BARRIER	.set	mips32	_ssnop	_ssnop	_ssnop	.set	mips0	.endm /*********************************************************************** * Alternate CPU1 startup vector for BMIPS4350 * * On some systems the bootloader has already started CPU1 and configured * it to resume execution at 0x8000_0200 (!BEV IV vector) when it is * triggered by the SW1 interrupt.  If that is the case we try to move * it to a more convenient place: BMIPS_WARM_RESTART_VEC @ 0x8000_0380. ***********************************************************************/ LEAF(bmips_smp_movevec)	la	k0, 1f	li	k1, CKSEG1	or	k0, k1	jr	k0 1:	/* clear IV, pending IPIs */	mtc0	zero, CP0_CAUSE 	/* re-enable IRQs to wait for SW1 */	li	k0, ST0_IE | ST0_BEV | STATUSF_IP1	mtc0	k0, CP0_STATUS 	/* set up CPU1 CBR; move BASE to 0xa000_0000 */	li	k0, 0xff400000	mtc0	k0, $22, 6	/* set up relocation vector address based on thread ID */	mfc0	k1, $22, 3	srl	k1, 16	andi	k1, 0x8000	or	k1, CKSEG1 | BMIPS_RELO_VECTOR_CONTROL_0	or	k0, k1	li	k1, 0xa0080000	sw	k1, 0(k0) 	/* wait here for SW1 interrupt from bmips_boot_secondary() */	wait 	la	k0, bmips_reset_nmi_vec	li	k1, CKSEG1	or	k0, k1	jr	k0END(bmips_smp_movevec) /*********************************************************************** * Reset/NMI vector * For BMIPS processors that can relocate their exception vectors, this * entire function gets copied to 0x8000_0000. ***********************************************************************/ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)	.set	push	.set	noat	.align	4 #ifdef CONFIG_SMP	/* if the NMI bit is clear, assume this is a CPU1 reset instead */	li	k1, (1 << 19)	mfc0	k0, CP0_STATUS	and	k0, k1	beqz	k0, soft_reset #if defined(CONFIG_CPU_BMIPS5000)	mfc0	k0, CP0_PRID	li	k1, PRID_IMP_BMIPS5000	/* mask with PRID_IMP_BMIPS5000 to cover both variants */	andi	k0, PRID_IMP_BMIPS5000	bne	k0, k1, 1f 	/* if we're not on core 0, this must be the SMP boot signal */	li	k1, (3 << 25)	mfc0	k0, $22	and	k0, k1	bnez	k0, bmips_smp_entry1:#endif /* CONFIG_CPU_BMIPS5000 */#endif /* CONFIG_SMP */ 	/* nope, it's just a regular NMI */	SAVE_ALL	move	a0, sp 	/* clear EXL, ERL, BEV so that TLB refills still work */	mfc0	k0, CP0_STATUS	li	k1, ST0_ERL | ST0_EXL | ST0_BEV | ST0_IE	or	k0, k1	xor	k0, k1	mtc0	k0, CP0_STATUS	BARRIER 	/* jump to the NMI handler function */	la	k0, nmi_handler	jr	k0 	RESTORE_ALL	.set	arch=r4000	eret #ifdef CONFIG_SMPsoft_reset: #if defined(CONFIG_CPU_BMIPS5000)	mfc0	k0, CP0_PRID	andi	k0, 0xff00	li	k1, PRID_IMP_BMIPS5200	bne	k0, k1, bmips_smp_entry         /* if running on TP 1, jump  to  bmips_smp_entry */        mfc0    k0, $22        li      k1, (1 << 24)        and     k1, k0        bnez    k1, bmips_smp_entry        nop         /*         * running on TP0, can not be core 0 (the boot core).         * Check for soft reset.  Indicates a warm boot         */        mfc0    k0, $12        li      k1, (1 << 20)        and     k0, k1        beqz    k0, bmips_smp_entry         /*         * Warm boot.         * Cache init is only done on TP0         */        la      k0, bmips_5xxx_init        jalr    k0        nop         b       bmips_smp_entry        nop#endif /*********************************************************************** * CPU1 reset vector (used for the initial boot only) * This is still part of bmips_reset_nmi_vec(). ***********************************************************************/ bmips_smp_entry: 	/* set up CP0 STATUS; enable FPU */	li	k0, 0x30000000	mtc0	k0, CP0_STATUS	BARRIER 	/* set local CP0 CONFIG to make kseg0 cacheable, write-back */	mfc0	k0, CP0_CONFIG	ori	k0, 0x07	xori	k0, 0x04	mtc0	k0, CP0_CONFIG 	mfc0	k0, CP0_PRID	andi	k0, 0xff00#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)	li	k1, PRID_IMP_BMIPS43XX	bne	k0, k1, 2f 	/* initialize CPU1's local I-cache */	li	k0, 0x80000000	li	k1, 0x80010000	mtc0	zero, $28	mtc0	zero, $28, 1	BARRIER 1:	cache	Index_Store_Tag_I, 0(k0)	addiu	k0, 16	bne	k0, k1, 1b 	b	3f2:#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */#if defined(CONFIG_CPU_BMIPS5000)	/* mask with PRID_IMP_BMIPS5000 to cover both variants */	li	k1, PRID_IMP_BMIPS5000	andi	k0, PRID_IMP_BMIPS5000	bne	k0, k1, 3f 	/* set exception vector base */	la	k0, ebase	lw	k0, 0(k0)	mtc0	k0, $15, 1	BARRIER#endif /* CONFIG_CPU_BMIPS5000 */3:	/* jump back to kseg0 in case we need to remap the kseg1 area */	la	k0, 1f	jr	k01:	la	k0, bmips_enable_xks01	jalr	k0 	/* use temporary stack to set up upper memory TLB */	li	sp, BMIPS_WARM_RESTART_VEC	la	k0, plat_wired_tlb_setup	jalr	k0 	/* switch to permanent stack and continue booting */ 	.global bmips_secondary_reentrybmips_secondary_reentry:	la	k0, bmips_smp_boot_sp	lw	sp, 0(k0)	la	k0, bmips_smp_boot_gp	lw	gp, 0(k0)	la	k0, start_secondary	jr	k0 #endif /* CONFIG_SMP */ 	.align	4	.global bmips_reset_nmi_vec_endbmips_reset_nmi_vec_end: END(bmips_reset_nmi_vec) 	.set	pop /*********************************************************************** * CPU1 warm restart vector (used for second and subsequent boots). * Also used for S2 standby recovery (PM). * This entire function gets copied to (BMIPS_WARM_RESTART_VEC) ***********************************************************************/ LEAF(bmips_smp_int_vec) 	.align	4	mfc0	k0, CP0_STATUS	ori	k0, 0x01	xori	k0, 0x01	mtc0	k0, CP0_STATUS	eret 	.align	4	.global bmips_smp_int_vec_endbmips_smp_int_vec_end: END(bmips_smp_int_vec) /*********************************************************************** * XKS01 support * Certain CPUs support extending kseg0 to 1024MB. ***********************************************************************/ LEAF(bmips_enable_xks01) #if defined(CONFIG_XKS01)	mfc0	t0, CP0_PRID	andi	t2, t0, 0xff00#if defined(CONFIG_CPU_BMIPS4380)	li	t1, PRID_IMP_BMIPS43XX	bne	t2, t1, 1f 	andi	t0, 0xff	addiu	t1, t0, -PRID_REV_BMIPS4380_HI	bgtz	t1, 2f	addiu	t0, -PRID_REV_BMIPS4380_LO	bltz	t0, 2f 	mfc0	t0, $22, 3	li	t1, 0x1ff0	li	t2, (1 << 12) | (1 << 9)	or	t0, t1	xor	t0, t1	or	t0, t2	mtc0	t0, $22, 3	BARRIER	b	2f1:#endif /* CONFIG_CPU_BMIPS4380 */#if defined(CONFIG_CPU_BMIPS5000)	li	t1, PRID_IMP_BMIPS5000	/* mask with PRID_IMP_BMIPS5000 to cover both variants */	andi	t2, PRID_IMP_BMIPS5000	bne	t2, t1, 2f 	mfc0	t0, $22, 5	li	t1, 0x01ff	li	t2, (1 << 8) | (1 << 5)	or	t0, t1	xor	t0, t1	or	t0, t2	mtc0	t0, $22, 5	BARRIER#endif /* CONFIG_CPU_BMIPS5000 */2:#endif /* defined(CONFIG_XKS01) */ 	jr	ra END(bmips_enable_xks01)