1df0ac8a4SKevin Cernekee/* 2df0ac8a4SKevin Cernekee * This file is subject to the terms and conditions of the GNU General Public 3df0ac8a4SKevin Cernekee * License. See the file "COPYING" in the main directory of this archive 4df0ac8a4SKevin Cernekee * for more details. 5df0ac8a4SKevin Cernekee * 6df0ac8a4SKevin Cernekee * Copyright (C) 2011 by Kevin Cernekee (cernekee@gmail.com) 7df0ac8a4SKevin Cernekee * 8df0ac8a4SKevin Cernekee * Reset/NMI/re-entry vectors for BMIPS processors 9df0ac8a4SKevin Cernekee */ 10df0ac8a4SKevin Cernekee 11df0ac8a4SKevin Cernekee 12df0ac8a4SKevin Cernekee#include <asm/asm.h> 13df0ac8a4SKevin Cernekee#include <asm/asmmacro.h> 14df0ac8a4SKevin Cernekee#include <asm/cacheops.h> 156465460cSJonas Gorski#include <asm/cpu.h> 16df0ac8a4SKevin Cernekee#include <asm/regdef.h> 17df0ac8a4SKevin Cernekee#include <asm/mipsregs.h> 18df0ac8a4SKevin Cernekee#include <asm/stackframe.h> 19df0ac8a4SKevin Cernekee#include <asm/addrspace.h> 20df0ac8a4SKevin Cernekee#include <asm/hazards.h> 21df0ac8a4SKevin Cernekee#include <asm/bmips.h> 22df0ac8a4SKevin Cernekee 23df0ac8a4SKevin Cernekee .macro BARRIER 24df0ac8a4SKevin Cernekee .set mips32 25df0ac8a4SKevin Cernekee _ssnop 26df0ac8a4SKevin Cernekee _ssnop 27df0ac8a4SKevin Cernekee _ssnop 28df0ac8a4SKevin Cernekee .set mips0 29df0ac8a4SKevin Cernekee .endm 30df0ac8a4SKevin Cernekee 31df0ac8a4SKevin Cernekee/*********************************************************************** 32df0ac8a4SKevin Cernekee * Alternate CPU1 startup vector for BMIPS4350 33df0ac8a4SKevin Cernekee * 34df0ac8a4SKevin Cernekee * On some systems the bootloader has already started CPU1 and configured 35df0ac8a4SKevin Cernekee * it to resume execution at 0x8000_0200 (!BEV IV vector) when it is 36df0ac8a4SKevin Cernekee * triggered by the SW1 interrupt. If that is the case we try to move 37df0ac8a4SKevin Cernekee * it to a more convenient place: BMIPS_WARM_RESTART_VEC @ 0x8000_0380. 38df0ac8a4SKevin Cernekee ***********************************************************************/ 39df0ac8a4SKevin Cernekee 40df0ac8a4SKevin CernekeeLEAF(bmips_smp_movevec) 41df0ac8a4SKevin Cernekee la k0, 1f 42df0ac8a4SKevin Cernekee li k1, CKSEG1 43df0ac8a4SKevin Cernekee or k0, k1 44df0ac8a4SKevin Cernekee jr k0 45df0ac8a4SKevin Cernekee 46df0ac8a4SKevin Cernekee1: 47df0ac8a4SKevin Cernekee /* clear IV, pending IPIs */ 48df0ac8a4SKevin Cernekee mtc0 zero, CP0_CAUSE 49df0ac8a4SKevin Cernekee 50df0ac8a4SKevin Cernekee /* re-enable IRQs to wait for SW1 */ 51df0ac8a4SKevin Cernekee li k0, ST0_IE | ST0_BEV | STATUSF_IP1 52df0ac8a4SKevin Cernekee mtc0 k0, CP0_STATUS 53df0ac8a4SKevin Cernekee 54df0ac8a4SKevin Cernekee /* set up CPU1 CBR; move BASE to 0xa000_0000 */ 55df0ac8a4SKevin Cernekee li k0, 0xff400000 56df0ac8a4SKevin Cernekee mtc0 k0, $22, 6 57ff5fadafSFlorian Fainelli /* set up relocation vector address based on thread ID */ 58ff5fadafSFlorian Fainelli mfc0 k1, $22, 3 59ff5fadafSFlorian Fainelli srl k1, 16 60ff5fadafSFlorian Fainelli andi k1, 0x8000 61ff5fadafSFlorian Fainelli or k1, CKSEG1 | BMIPS_RELO_VECTOR_CONTROL_0 62df0ac8a4SKevin Cernekee or k0, k1 63df0ac8a4SKevin Cernekee li k1, 0xa0080000 64df0ac8a4SKevin Cernekee sw k1, 0(k0) 65df0ac8a4SKevin Cernekee 66df0ac8a4SKevin Cernekee /* wait here for SW1 interrupt from bmips_boot_secondary() */ 67df0ac8a4SKevin Cernekee wait 68df0ac8a4SKevin Cernekee 69df0ac8a4SKevin Cernekee la k0, bmips_reset_nmi_vec 70df0ac8a4SKevin Cernekee li k1, CKSEG1 71df0ac8a4SKevin Cernekee or k0, k1 72df0ac8a4SKevin Cernekee jr k0 73df0ac8a4SKevin CernekeeEND(bmips_smp_movevec) 74df0ac8a4SKevin Cernekee 75df0ac8a4SKevin Cernekee/*********************************************************************** 76df0ac8a4SKevin Cernekee * Reset/NMI vector 77df0ac8a4SKevin Cernekee * For BMIPS processors that can relocate their exception vectors, this 78df0ac8a4SKevin Cernekee * entire function gets copied to 0x8000_0000. 79df0ac8a4SKevin Cernekee ***********************************************************************/ 80df0ac8a4SKevin Cernekee 81df0ac8a4SKevin CernekeeNESTED(bmips_reset_nmi_vec, PT_SIZE, sp) 82df0ac8a4SKevin Cernekee .set push 83df0ac8a4SKevin Cernekee .set noat 84df0ac8a4SKevin Cernekee .align 4 85df0ac8a4SKevin Cernekee 86df0ac8a4SKevin Cernekee#ifdef CONFIG_SMP 87df0ac8a4SKevin Cernekee /* if the NMI bit is clear, assume this is a CPU1 reset instead */ 88df0ac8a4SKevin Cernekee li k1, (1 << 19) 89df0ac8a4SKevin Cernekee mfc0 k0, CP0_STATUS 90df0ac8a4SKevin Cernekee and k0, k1 91df0ac8a4SKevin Cernekee beqz k0, bmips_smp_entry 92df0ac8a4SKevin Cernekee 93df0ac8a4SKevin Cernekee#if defined(CONFIG_CPU_BMIPS5000) 946465460cSJonas Gorski mfc0 k0, CP0_PRID 956465460cSJonas Gorski li k1, PRID_IMP_BMIPS5000 966465460cSJonas Gorski andi k0, 0xff00 976465460cSJonas Gorski bne k0, k1, 1f 986465460cSJonas Gorski 99df0ac8a4SKevin Cernekee /* if we're not on core 0, this must be the SMP boot signal */ 100df0ac8a4SKevin Cernekee li k1, (3 << 25) 101df0ac8a4SKevin Cernekee mfc0 k0, $22 102df0ac8a4SKevin Cernekee and k0, k1 103df0ac8a4SKevin Cernekee bnez k0, bmips_smp_entry 1046465460cSJonas Gorski1: 1056465460cSJonas Gorski#endif /* CONFIG_CPU_BMIPS5000 */ 106df0ac8a4SKevin Cernekee#endif /* CONFIG_SMP */ 107df0ac8a4SKevin Cernekee 108df0ac8a4SKevin Cernekee /* nope, it's just a regular NMI */ 109df0ac8a4SKevin Cernekee SAVE_ALL 110df0ac8a4SKevin Cernekee move a0, sp 111df0ac8a4SKevin Cernekee 112df0ac8a4SKevin Cernekee /* clear EXL, ERL, BEV so that TLB refills still work */ 113df0ac8a4SKevin Cernekee mfc0 k0, CP0_STATUS 114df0ac8a4SKevin Cernekee li k1, ST0_ERL | ST0_EXL | ST0_BEV | ST0_IE 115df0ac8a4SKevin Cernekee or k0, k1 116df0ac8a4SKevin Cernekee xor k0, k1 117df0ac8a4SKevin Cernekee mtc0 k0, CP0_STATUS 118df0ac8a4SKevin Cernekee BARRIER 119df0ac8a4SKevin Cernekee 120df0ac8a4SKevin Cernekee /* jump to the NMI handler function */ 121df0ac8a4SKevin Cernekee la k0, nmi_handler 122df0ac8a4SKevin Cernekee jr k0 123df0ac8a4SKevin Cernekee 124df0ac8a4SKevin Cernekee RESTORE_ALL 125*a809d460SRalf Baechle .set arch=r4000 126df0ac8a4SKevin Cernekee eret 127df0ac8a4SKevin Cernekee 128df0ac8a4SKevin Cernekee/*********************************************************************** 129df0ac8a4SKevin Cernekee * CPU1 reset vector (used for the initial boot only) 130df0ac8a4SKevin Cernekee * This is still part of bmips_reset_nmi_vec(). 131df0ac8a4SKevin Cernekee ***********************************************************************/ 132df0ac8a4SKevin Cernekee 133df0ac8a4SKevin Cernekee#ifdef CONFIG_SMP 134df0ac8a4SKevin Cernekee 135df0ac8a4SKevin Cernekeebmips_smp_entry: 136df0ac8a4SKevin Cernekee 137df0ac8a4SKevin Cernekee /* set up CP0 STATUS; enable FPU */ 138df0ac8a4SKevin Cernekee li k0, 0x30000000 139df0ac8a4SKevin Cernekee mtc0 k0, CP0_STATUS 140df0ac8a4SKevin Cernekee BARRIER 141df0ac8a4SKevin Cernekee 142df0ac8a4SKevin Cernekee /* set local CP0 CONFIG to make kseg0 cacheable, write-back */ 143df0ac8a4SKevin Cernekee mfc0 k0, CP0_CONFIG 144df0ac8a4SKevin Cernekee ori k0, 0x07 145df0ac8a4SKevin Cernekee xori k0, 0x04 146df0ac8a4SKevin Cernekee mtc0 k0, CP0_CONFIG 147df0ac8a4SKevin Cernekee 1486465460cSJonas Gorski mfc0 k0, CP0_PRID 1496465460cSJonas Gorski andi k0, 0xff00 150df0ac8a4SKevin Cernekee#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) 1516465460cSJonas Gorski li k1, PRID_IMP_BMIPS43XX 1526465460cSJonas Gorski bne k0, k1, 2f 1536465460cSJonas Gorski 154df0ac8a4SKevin Cernekee /* initialize CPU1's local I-cache */ 155df0ac8a4SKevin Cernekee li k0, 0x80000000 156df0ac8a4SKevin Cernekee li k1, 0x80010000 157df0ac8a4SKevin Cernekee mtc0 zero, $28 158df0ac8a4SKevin Cernekee mtc0 zero, $28, 1 159df0ac8a4SKevin Cernekee BARRIER 160df0ac8a4SKevin Cernekee 161df0ac8a4SKevin Cernekee1: cache Index_Store_Tag_I, 0(k0) 162df0ac8a4SKevin Cernekee addiu k0, 16 163df0ac8a4SKevin Cernekee bne k0, k1, 1b 1646465460cSJonas Gorski 1656465460cSJonas Gorski b 3f 1666465460cSJonas Gorski2: 1676465460cSJonas Gorski#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */ 1686465460cSJonas Gorski#if defined(CONFIG_CPU_BMIPS5000) 169df0ac8a4SKevin Cernekee /* set exception vector base */ 1706465460cSJonas Gorski li k1, PRID_IMP_BMIPS5000 1716465460cSJonas Gorski bne k0, k1, 3f 1726465460cSJonas Gorski 173df0ac8a4SKevin Cernekee la k0, ebase 174df0ac8a4SKevin Cernekee lw k0, 0(k0) 175df0ac8a4SKevin Cernekee mtc0 k0, $15, 1 176df0ac8a4SKevin Cernekee BARRIER 1776465460cSJonas Gorski#endif /* CONFIG_CPU_BMIPS5000 */ 1786465460cSJonas Gorski3: 179df0ac8a4SKevin Cernekee /* jump back to kseg0 in case we need to remap the kseg1 area */ 180df0ac8a4SKevin Cernekee la k0, 1f 181df0ac8a4SKevin Cernekee jr k0 182df0ac8a4SKevin Cernekee1: 183df0ac8a4SKevin Cernekee la k0, bmips_enable_xks01 184df0ac8a4SKevin Cernekee jalr k0 185df0ac8a4SKevin Cernekee 186df0ac8a4SKevin Cernekee /* use temporary stack to set up upper memory TLB */ 187df0ac8a4SKevin Cernekee li sp, BMIPS_WARM_RESTART_VEC 188df0ac8a4SKevin Cernekee la k0, plat_wired_tlb_setup 189df0ac8a4SKevin Cernekee jalr k0 190df0ac8a4SKevin Cernekee 191df0ac8a4SKevin Cernekee /* switch to permanent stack and continue booting */ 192df0ac8a4SKevin Cernekee 193df0ac8a4SKevin Cernekee .global bmips_secondary_reentry 194df0ac8a4SKevin Cernekeebmips_secondary_reentry: 195df0ac8a4SKevin Cernekee la k0, bmips_smp_boot_sp 196df0ac8a4SKevin Cernekee lw sp, 0(k0) 197df0ac8a4SKevin Cernekee la k0, bmips_smp_boot_gp 198df0ac8a4SKevin Cernekee lw gp, 0(k0) 199df0ac8a4SKevin Cernekee la k0, start_secondary 200df0ac8a4SKevin Cernekee jr k0 201df0ac8a4SKevin Cernekee 202df0ac8a4SKevin Cernekee#endif /* CONFIG_SMP */ 203df0ac8a4SKevin Cernekee 204df0ac8a4SKevin Cernekee .align 4 205df0ac8a4SKevin Cernekee .global bmips_reset_nmi_vec_end 206df0ac8a4SKevin Cernekeebmips_reset_nmi_vec_end: 207df0ac8a4SKevin Cernekee 208df0ac8a4SKevin CernekeeEND(bmips_reset_nmi_vec) 209df0ac8a4SKevin Cernekee 210df0ac8a4SKevin Cernekee .set pop 211df0ac8a4SKevin Cernekee .previous 212df0ac8a4SKevin Cernekee 213df0ac8a4SKevin Cernekee/*********************************************************************** 214df0ac8a4SKevin Cernekee * CPU1 warm restart vector (used for second and subsequent boots). 215df0ac8a4SKevin Cernekee * Also used for S2 standby recovery (PM). 216df0ac8a4SKevin Cernekee * This entire function gets copied to (BMIPS_WARM_RESTART_VEC) 217df0ac8a4SKevin Cernekee ***********************************************************************/ 218df0ac8a4SKevin Cernekee 219df0ac8a4SKevin CernekeeLEAF(bmips_smp_int_vec) 220df0ac8a4SKevin Cernekee 221df0ac8a4SKevin Cernekee .align 4 222df0ac8a4SKevin Cernekee mfc0 k0, CP0_STATUS 223df0ac8a4SKevin Cernekee ori k0, 0x01 224df0ac8a4SKevin Cernekee xori k0, 0x01 225df0ac8a4SKevin Cernekee mtc0 k0, CP0_STATUS 226df0ac8a4SKevin Cernekee eret 227df0ac8a4SKevin Cernekee 228df0ac8a4SKevin Cernekee .align 4 229df0ac8a4SKevin Cernekee .global bmips_smp_int_vec_end 230df0ac8a4SKevin Cernekeebmips_smp_int_vec_end: 231df0ac8a4SKevin Cernekee 232df0ac8a4SKevin CernekeeEND(bmips_smp_int_vec) 233df0ac8a4SKevin Cernekee 234df0ac8a4SKevin Cernekee/*********************************************************************** 235df0ac8a4SKevin Cernekee * XKS01 support 236df0ac8a4SKevin Cernekee * Certain CPUs support extending kseg0 to 1024MB. 237df0ac8a4SKevin Cernekee ***********************************************************************/ 238df0ac8a4SKevin Cernekee 239df0ac8a4SKevin CernekeeLEAF(bmips_enable_xks01) 240df0ac8a4SKevin Cernekee 241df0ac8a4SKevin Cernekee#if defined(CONFIG_XKS01) 2426465460cSJonas Gorski mfc0 t0, CP0_PRID 2436465460cSJonas Gorski andi t2, t0, 0xff00 244df0ac8a4SKevin Cernekee#if defined(CONFIG_CPU_BMIPS4380) 2456465460cSJonas Gorski li t1, PRID_IMP_BMIPS43XX 2466465460cSJonas Gorski bne t2, t1, 1f 2476465460cSJonas Gorski 2486465460cSJonas Gorski andi t0, 0xff 2496465460cSJonas Gorski addiu t1, t0, -PRID_REV_BMIPS4380_HI 2506465460cSJonas Gorski bgtz t1, 2f 2516465460cSJonas Gorski addiu t0, -PRID_REV_BMIPS4380_LO 2526465460cSJonas Gorski bltz t0, 2f 2536465460cSJonas Gorski 254df0ac8a4SKevin Cernekee mfc0 t0, $22, 3 255df0ac8a4SKevin Cernekee li t1, 0x1ff0 256df0ac8a4SKevin Cernekee li t2, (1 << 12) | (1 << 9) 257df0ac8a4SKevin Cernekee or t0, t1 258df0ac8a4SKevin Cernekee xor t0, t1 259df0ac8a4SKevin Cernekee or t0, t2 260df0ac8a4SKevin Cernekee mtc0 t0, $22, 3 261df0ac8a4SKevin Cernekee BARRIER 2626465460cSJonas Gorski b 2f 2636465460cSJonas Gorski1: 2646465460cSJonas Gorski#endif /* CONFIG_CPU_BMIPS4380 */ 2656465460cSJonas Gorski#if defined(CONFIG_CPU_BMIPS5000) 2666465460cSJonas Gorski li t1, PRID_IMP_BMIPS5000 2676465460cSJonas Gorski bne t2, t1, 2f 2686465460cSJonas Gorski 269df0ac8a4SKevin Cernekee mfc0 t0, $22, 5 270df0ac8a4SKevin Cernekee li t1, 0x01ff 271df0ac8a4SKevin Cernekee li t2, (1 << 8) | (1 << 5) 272df0ac8a4SKevin Cernekee or t0, t1 273df0ac8a4SKevin Cernekee xor t0, t1 274df0ac8a4SKevin Cernekee or t0, t2 275df0ac8a4SKevin Cernekee mtc0 t0, $22, 5 276df0ac8a4SKevin Cernekee BARRIER 2776465460cSJonas Gorski#endif /* CONFIG_CPU_BMIPS5000 */ 2786465460cSJonas Gorski2: 279df0ac8a4SKevin Cernekee#endif /* defined(CONFIG_XKS01) */ 280df0ac8a4SKevin Cernekee 281df0ac8a4SKevin Cernekee jr ra 282df0ac8a4SKevin Cernekee 283df0ac8a4SKevin CernekeeEND(bmips_enable_xks01) 284df0ac8a4SKevin Cernekee 285df0ac8a4SKevin Cernekee .previous 286