Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2011 by Kevin Cernekee (cernekee@gmail.com)
0007  *
0008  * Reset/NMI/re-entry vectors for BMIPS processors
0009  */
0010 
0011 
0012 #include <asm/asm.h>
0013 #include <asm/asmmacro.h>
0014 #include <asm/cacheops.h>
0015 #include <asm/cpu.h>
0016 #include <asm/regdef.h>
0017 #include <asm/mipsregs.h>
0018 #include <asm/stackframe.h>
0019 #include <asm/addrspace.h>
0020 #include <asm/hazards.h>
0021 #include <asm/bmips.h>
0022 
0023     .macro  BARRIER
0024     .set    mips32
0025     _ssnop
0026     _ssnop
0027     _ssnop
0028     .set    mips0
0029     .endm
0030 
0031 /***********************************************************************
0032  * Alternate CPU1 startup vector for BMIPS4350
0033  *
0034  * On some systems the bootloader has already started CPU1 and configured
0035  * it to resume execution at 0x8000_0200 (!BEV IV vector) when it is
0036  * triggered by the SW1 interrupt.  If that is the case we try to move
0037  * it to a more convenient place: BMIPS_WARM_RESTART_VEC @ 0x8000_0380.
0038  ***********************************************************************/
0039 
0040 LEAF(bmips_smp_movevec)
0041     la  k0, 1f
0042     li  k1, CKSEG1
0043     or  k0, k1
0044     jr  k0
0045 
0046 1:
0047     /* clear IV, pending IPIs */
0048     mtc0    zero, CP0_CAUSE
0049 
0050     /* re-enable IRQs to wait for SW1 */
0051     li  k0, ST0_IE | ST0_BEV | STATUSF_IP1
0052     mtc0    k0, CP0_STATUS
0053 
0054     /* set up CPU1 CBR; move BASE to 0xa000_0000 */
0055     li  k0, 0xff400000
0056     mtc0    k0, $22, 6
0057     /* set up relocation vector address based on thread ID */
0058     mfc0    k1, $22, 3
0059     srl k1, 16
0060     andi    k1, 0x8000
0061     or  k1, CKSEG1 | BMIPS_RELO_VECTOR_CONTROL_0
0062     or  k0, k1
0063     li  k1, 0xa0080000
0064     sw  k1, 0(k0)
0065 
0066     /* wait here for SW1 interrupt from bmips_boot_secondary() */
0067     wait
0068 
0069     la  k0, bmips_reset_nmi_vec
0070     li  k1, CKSEG1
0071     or  k0, k1
0072     jr  k0
0073 END(bmips_smp_movevec)
0074 
0075 /***********************************************************************
0076  * Reset/NMI vector
0077  * For BMIPS processors that can relocate their exception vectors, this
0078  * entire function gets copied to 0x8000_0000.
0079  ***********************************************************************/
0080 
0081 NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
0082     .set    push
0083     .set    noat
0084     .align  4
0085 
0086 #ifdef CONFIG_SMP
0087     /* if the NMI bit is clear, assume this is a CPU1 reset instead */
0088     li  k1, (1 << 19)
0089     mfc0    k0, CP0_STATUS
0090     and k0, k1
0091     beqz    k0, soft_reset
0092 
0093 #if defined(CONFIG_CPU_BMIPS5000)
0094     mfc0    k0, CP0_PRID
0095     li  k1, PRID_IMP_BMIPS5000
0096     /* mask with PRID_IMP_BMIPS5000 to cover both variants */
0097     andi    k0, PRID_IMP_BMIPS5000
0098     bne k0, k1, 1f
0099 
0100     /* if we're not on core 0, this must be the SMP boot signal */
0101     li  k1, (3 << 25)
0102     mfc0    k0, $22
0103     and k0, k1
0104     bnez    k0, bmips_smp_entry
0105 1:
0106 #endif /* CONFIG_CPU_BMIPS5000 */
0107 #endif /* CONFIG_SMP */
0108 
0109     /* nope, it's just a regular NMI */
0110     SAVE_ALL
0111     move    a0, sp
0112 
0113     /* clear EXL, ERL, BEV so that TLB refills still work */
0114     mfc0    k0, CP0_STATUS
0115     li  k1, ST0_ERL | ST0_EXL | ST0_BEV | ST0_IE
0116     or  k0, k1
0117     xor k0, k1
0118     mtc0    k0, CP0_STATUS
0119     BARRIER
0120 
0121     /* jump to the NMI handler function */
0122     la  k0, nmi_handler
0123     jr  k0
0124 
0125     RESTORE_ALL
0126     .set    arch=r4000
0127     eret
0128 
0129 #ifdef CONFIG_SMP
0130 soft_reset:
0131 
0132 #if defined(CONFIG_CPU_BMIPS5000)
0133     mfc0    k0, CP0_PRID
0134     andi    k0, 0xff00
0135     li  k1, PRID_IMP_BMIPS5200
0136     bne k0, k1, bmips_smp_entry
0137 
0138         /* if running on TP 1, jump  to  bmips_smp_entry */
0139         mfc0    k0, $22
0140         li      k1, (1 << 24)
0141         and     k1, k0
0142         bnez    k1, bmips_smp_entry
0143         nop
0144 
0145         /*
0146          * running on TP0, can not be core 0 (the boot core).
0147          * Check for soft reset.  Indicates a warm boot
0148          */
0149         mfc0    k0, $12
0150         li      k1, (1 << 20)
0151         and     k0, k1
0152         beqz    k0, bmips_smp_entry
0153 
0154         /*
0155          * Warm boot.
0156          * Cache init is only done on TP0
0157          */
0158         la      k0, bmips_5xxx_init
0159         jalr    k0
0160         nop
0161 
0162         b       bmips_smp_entry
0163         nop
0164 #endif
0165 
0166 /***********************************************************************
0167  * CPU1 reset vector (used for the initial boot only)
0168  * This is still part of bmips_reset_nmi_vec().
0169  ***********************************************************************/
0170 
0171 bmips_smp_entry:
0172 
0173     /* set up CP0 STATUS; enable FPU */
0174     li  k0, 0x30000000
0175     mtc0    k0, CP0_STATUS
0176     BARRIER
0177 
0178     /* set local CP0 CONFIG to make kseg0 cacheable, write-back */
0179     mfc0    k0, CP0_CONFIG
0180     ori k0, 0x07
0181     xori    k0, 0x04
0182     mtc0    k0, CP0_CONFIG
0183 
0184     mfc0    k0, CP0_PRID
0185     andi    k0, 0xff00
0186 #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
0187     li  k1, PRID_IMP_BMIPS43XX
0188     bne k0, k1, 2f
0189 
0190     /* initialize CPU1's local I-cache */
0191     li  k0, 0x80000000
0192     li  k1, 0x80010000
0193     mtc0    zero, $28
0194     mtc0    zero, $28, 1
0195     BARRIER
0196 
0197 1:  cache   Index_Store_Tag_I, 0(k0)
0198     addiu   k0, 16
0199     bne k0, k1, 1b
0200 
0201     b   3f
0202 2:
0203 #endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
0204 #if defined(CONFIG_CPU_BMIPS5000)
0205     /* mask with PRID_IMP_BMIPS5000 to cover both variants */
0206     li  k1, PRID_IMP_BMIPS5000
0207     andi    k0, PRID_IMP_BMIPS5000
0208     bne k0, k1, 3f
0209 
0210     /* set exception vector base */
0211     la  k0, ebase
0212     lw  k0, 0(k0)
0213     mtc0    k0, $15, 1
0214     BARRIER
0215 #endif /* CONFIG_CPU_BMIPS5000 */
0216 3:
0217     /* jump back to kseg0 in case we need to remap the kseg1 area */
0218     la  k0, 1f
0219     jr  k0
0220 1:
0221     la  k0, bmips_enable_xks01
0222     jalr    k0
0223 
0224     /* use temporary stack to set up upper memory TLB */
0225     li  sp, BMIPS_WARM_RESTART_VEC
0226     la  k0, plat_wired_tlb_setup
0227     jalr    k0
0228 
0229     /* switch to permanent stack and continue booting */
0230 
0231     .global bmips_secondary_reentry
0232 bmips_secondary_reentry:
0233     la  k0, bmips_smp_boot_sp
0234     lw  sp, 0(k0)
0235     la  k0, bmips_smp_boot_gp
0236     lw  gp, 0(k0)
0237     la  k0, start_secondary
0238     jr  k0
0239 
0240 #endif /* CONFIG_SMP */
0241 
0242     .align  4
0243     .global bmips_reset_nmi_vec_end
0244 bmips_reset_nmi_vec_end:
0245 
0246 END(bmips_reset_nmi_vec)
0247 
0248     .set    pop
0249 
0250 /***********************************************************************
0251  * CPU1 warm restart vector (used for second and subsequent boots).
0252  * Also used for S2 standby recovery (PM).
0253  * This entire function gets copied to (BMIPS_WARM_RESTART_VEC)
0254  ***********************************************************************/
0255 
0256 LEAF(bmips_smp_int_vec)
0257 
0258     .align  4
0259     mfc0    k0, CP0_STATUS
0260     ori k0, 0x01
0261     xori    k0, 0x01
0262     mtc0    k0, CP0_STATUS
0263     eret
0264 
0265     .align  4
0266     .global bmips_smp_int_vec_end
0267 bmips_smp_int_vec_end:
0268 
0269 END(bmips_smp_int_vec)
0270 
0271 /***********************************************************************
0272  * XKS01 support
0273  * Certain CPUs support extending kseg0 to 1024MB.
0274  ***********************************************************************/
0275 
0276 LEAF(bmips_enable_xks01)
0277 
0278 #if defined(CONFIG_XKS01)
0279     mfc0    t0, CP0_PRID
0280     andi    t2, t0, 0xff00
0281 #if defined(CONFIG_CPU_BMIPS4380)
0282     li  t1, PRID_IMP_BMIPS43XX
0283     bne t2, t1, 1f
0284 
0285     andi    t0, 0xff
0286     addiu   t1, t0, -PRID_REV_BMIPS4380_HI
0287     bgtz    t1, 2f
0288     addiu   t0, -PRID_REV_BMIPS4380_LO
0289     bltz    t0, 2f
0290 
0291     mfc0    t0, $22, 3
0292     li  t1, 0x1ff0
0293     li  t2, (1 << 12) | (1 << 9)
0294     or  t0, t1
0295     xor t0, t1
0296     or  t0, t2
0297     mtc0    t0, $22, 3
0298     BARRIER
0299     b   2f
0300 1:
0301 #endif /* CONFIG_CPU_BMIPS4380 */
0302 #if defined(CONFIG_CPU_BMIPS5000)
0303     li  t1, PRID_IMP_BMIPS5000
0304     /* mask with PRID_IMP_BMIPS5000 to cover both variants */
0305     andi    t2, PRID_IMP_BMIPS5000
0306     bne t2, t1, 2f
0307 
0308     mfc0    t0, $22, 5
0309     li  t1, 0x01ff
0310     li  t2, (1 << 8) | (1 << 5)
0311     or  t0, t1
0312     xor t0, t1
0313     or  t0, t2
0314     mtc0    t0, $22, 5
0315     BARRIER
0316 #endif /* CONFIG_CPU_BMIPS5000 */
0317 2:
0318 #endif /* defined(CONFIG_XKS01) */
0319 
0320     jr  ra
0321 
0322 END(bmips_enable_xks01)