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