/*1* This file is subject to the terms and conditions of the GNU General Public2* License. See the file "COPYING" in the main directory of this archive3* for more details.4*5* Copyright (C) 2011 by Kevin Cernekee ([email protected])6*7* Reset/NMI/re-entry vectors for BMIPS processors8*/91011#include <asm/asm.h>12#include <asm/asmmacro.h>13#include <asm/cacheops.h>14#include <asm/cpu.h>15#include <asm/regdef.h>16#include <asm/mipsregs.h>17#include <asm/stackframe.h>18#include <asm/addrspace.h>19#include <asm/hazards.h>20#include <asm/bmips.h>2122.macro BARRIER23.set mips3224_ssnop25_ssnop26_ssnop27.set mips028.endm2930/***********************************************************************31* Alternate CPU1 startup vector for BMIPS435032*33* On some systems the bootloader has already started CPU1 and configured34* it to resume execution at 0x8000_0200 (!BEV IV vector) when it is35* triggered by the SW1 interrupt. If that is the case we try to move36* it to a more convenient place: BMIPS_WARM_RESTART_VEC @ 0x8000_0380.37***********************************************************************/3839LEAF(bmips_smp_movevec)40la k0, 1f41li k1, CKSEG142or k0, k143jr k044451:46/* clear IV, pending IPIs */47mtc0 zero, CP0_CAUSE4849/* re-enable IRQs to wait for SW1 */50li k0, ST0_IE | ST0_BEV | STATUSF_IP151mtc0 k0, CP0_STATUS5253/* set up CPU1 CBR; move BASE to 0xa000_0000 */54li k0, 0xff40000055mtc0 k0, $22, 656/* set up relocation vector address based on thread ID */57mfc0 k1, $22, 358srl k1, 1659andi k1, 0x800060or k1, CKSEG1 | BMIPS_RELO_VECTOR_CONTROL_061or k0, k162li k1, 0xa008000063sw k1, 0(k0)6465/* wait here for SW1 interrupt from bmips_boot_secondary() */66wait6768la k0, bmips_reset_nmi_vec69li k1, CKSEG170or k0, k171jr k072END(bmips_smp_movevec)7374/***********************************************************************75* Reset/NMI vector76* For BMIPS processors that can relocate their exception vectors, this77* entire function gets copied to 0x8000_0000.78***********************************************************************/7980NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)81.set push82.set noat83.align 48485#ifdef CONFIG_SMP86/* if the NMI bit is clear, assume this is a CPU1 reset instead */87li k1, (1 << 19)88mfc0 k0, CP0_STATUS89and k0, k190beqz k0, soft_reset9192#if defined(CONFIG_CPU_BMIPS5000)93mfc0 k0, CP0_PRID94li k1, PRID_IMP_BMIPS500095/* mask with PRID_IMP_BMIPS5000 to cover both variants */96andi k0, PRID_IMP_BMIPS500097bne k0, k1, 1f9899/* if we're not on core 0, this must be the SMP boot signal */100li k1, (3 << 25)101mfc0 k0, $22102and k0, k1103bnez k0, bmips_smp_entry1041:105#endif /* CONFIG_CPU_BMIPS5000 */106#endif /* CONFIG_SMP */107108/* nope, it's just a regular NMI */109SAVE_ALL110move a0, sp111112/* clear EXL, ERL, BEV so that TLB refills still work */113mfc0 k0, CP0_STATUS114li k1, ST0_ERL | ST0_EXL | ST0_BEV | ST0_IE115or k0, k1116xor k0, k1117mtc0 k0, CP0_STATUS118BARRIER119120/* jump to the NMI handler function */121la k0, nmi_handler122jr k0123124RESTORE_ALL125.set arch=r4000126eret127128#ifdef CONFIG_SMP129soft_reset:130131#if defined(CONFIG_CPU_BMIPS5000)132mfc0 k0, CP0_PRID133andi k0, 0xff00134li k1, PRID_IMP_BMIPS5200135bne k0, k1, bmips_smp_entry136137/* if running on TP 1, jump to bmips_smp_entry */138mfc0 k0, $22139li k1, (1 << 24)140and k1, k0141bnez k1, bmips_smp_entry142nop143144/*145* running on TP0, can not be core 0 (the boot core).146* Check for soft reset. Indicates a warm boot147*/148mfc0 k0, $12149li k1, (1 << 20)150and k0, k1151beqz k0, bmips_smp_entry152153/*154* Warm boot.155* Cache init is only done on TP0156*/157la k0, bmips_5xxx_init158jalr k0159nop160161b bmips_smp_entry162nop163#endif164165/***********************************************************************166* CPU1 reset vector (used for the initial boot only)167* This is still part of bmips_reset_nmi_vec().168***********************************************************************/169170bmips_smp_entry:171172/* set up CP0 STATUS; enable FPU */173li k0, 0x30000000174mtc0 k0, CP0_STATUS175BARRIER176177/* set local CP0 CONFIG to make kseg0 cacheable, write-back */178mfc0 k0, CP0_CONFIG179ori k0, 0x07180xori k0, 0x04181mtc0 k0, CP0_CONFIG182183mfc0 k0, CP0_PRID184andi k0, 0xff00185#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)186li k1, PRID_IMP_BMIPS43XX187bne k0, k1, 2f188189/* initialize CPU1's local I-cache */190li k0, 0x80000000191li k1, 0x80010000192mtc0 zero, $28193mtc0 zero, $28, 1194BARRIER1951961: cache Index_Store_Tag_I, 0(k0)197addiu k0, 16198bne k0, k1, 1b199200b 3f2012:202#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */203#if defined(CONFIG_CPU_BMIPS5000)204/* mask with PRID_IMP_BMIPS5000 to cover both variants */205li k1, PRID_IMP_BMIPS5000206andi k0, PRID_IMP_BMIPS5000207bne k0, k1, 3f208209/* set exception vector base */210la k0, ebase211lw k0, 0(k0)212mtc0 k0, $15, 1213BARRIER214#endif /* CONFIG_CPU_BMIPS5000 */2153:216/* jump back to kseg0 in case we need to remap the kseg1 area */217la k0, 1f218jr k02191:220la k0, bmips_enable_xks01221jalr k0222223/* use temporary stack to set up upper memory TLB */224li sp, BMIPS_WARM_RESTART_VEC225la k0, plat_wired_tlb_setup226jalr k0227228/* switch to permanent stack and continue booting */229230.global bmips_secondary_reentry231bmips_secondary_reentry:232la k0, bmips_smp_boot_sp233lw sp, 0(k0)234la k0, bmips_smp_boot_gp235lw gp, 0(k0)236la k0, start_secondary237jr k0238239#endif /* CONFIG_SMP */240241.align 4242.global bmips_reset_nmi_vec_end243bmips_reset_nmi_vec_end:244245END(bmips_reset_nmi_vec)246247.set pop248249/***********************************************************************250* CPU1 warm restart vector (used for second and subsequent boots).251* Also used for S2 standby recovery (PM).252* This entire function gets copied to (BMIPS_WARM_RESTART_VEC)253***********************************************************************/254255LEAF(bmips_smp_int_vec)256257.align 4258mfc0 k0, CP0_STATUS259ori k0, 0x01260xori k0, 0x01261mtc0 k0, CP0_STATUS262eret263264.align 4265.global bmips_smp_int_vec_end266bmips_smp_int_vec_end:267268END(bmips_smp_int_vec)269270/***********************************************************************271* XKS01 support272* Certain CPUs support extending kseg0 to 1024MB.273***********************************************************************/274275LEAF(bmips_enable_xks01)276277#if defined(CONFIG_XKS01)278mfc0 t0, CP0_PRID279andi t2, t0, 0xff00280#if defined(CONFIG_CPU_BMIPS4380)281li t1, PRID_IMP_BMIPS43XX282bne t2, t1, 1f283284andi t0, 0xff285addiu t1, t0, -PRID_REV_BMIPS4380_HI286bgtz t1, 2f287addiu t0, -PRID_REV_BMIPS4380_LO288bltz t0, 2f289290mfc0 t0, $22, 3291li t1, 0x1ff0292li t2, (1 << 12) | (1 << 9)293or t0, t1294xor t0, t1295or t0, t2296mtc0 t0, $22, 3297BARRIER298b 2f2991:300#endif /* CONFIG_CPU_BMIPS4380 */301#if defined(CONFIG_CPU_BMIPS5000)302li t1, PRID_IMP_BMIPS5000303/* mask with PRID_IMP_BMIPS5000 to cover both variants */304andi t2, PRID_IMP_BMIPS5000305bne t2, t1, 2f306307mfc0 t0, $22, 5308li t1, 0x01ff309li t2, (1 << 8) | (1 << 5)310or t0, t1311xor t0, t1312or t0, t2313mtc0 t0, $22, 5314BARRIER315#endif /* CONFIG_CPU_BMIPS5000 */3162:317#endif /* defined(CONFIG_XKS01) */318319jr ra320321END(bmips_enable_xks01)322323324