diff options
Diffstat (limited to 'arch/mips/kernel/cps-vec.S')
-rw-r--r-- | arch/mips/kernel/cps-vec.S | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S new file mode 100644 index 0000000..f7a46db --- /dev/null +++ b/arch/mips/kernel/cps-vec.S @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2013 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <asm/addrspace.h> +#include <asm/asm.h> +#include <asm/asm-offsets.h> +#include <asm/asmmacro.h> +#include <asm/cacheops.h> +#include <asm/mipsregs.h> + +#define GCR_CL_COHERENCE_OFS 0x2008 + +.section .text.cps-vec +.balign 0x1000 +.set noreorder + +LEAF(mips_cps_core_entry) + /* + * These first 8 bytes will be patched by cps_smp_setup to load the + * base address of the CM GCRs into register v1. + */ + .quad 0 + + /* Check whether we're here due to an NMI */ + mfc0 k0, CP0_STATUS + and k0, k0, ST0_NMI + beqz k0, not_nmi + nop + + /* This is an NMI */ + la k0, nmi_handler + jr k0 + nop + +not_nmi: + /* Setup Cause */ + li t0, CAUSEF_IV + mtc0 t0, CP0_CAUSE + + /* Setup Status */ + li t0, ST0_CU1 | ST0_CU0 + mtc0 t0, CP0_STATUS + + /* + * Clear the bits used to index the caches. Note that the architecture + * dictates that writing to any of TagLo or TagHi selects 0 or 2 should + * be valid for all MIPS32 CPUs, even those for which said writes are + * unnecessary. + */ + mtc0 zero, CP0_TAGLO, 0 + mtc0 zero, CP0_TAGHI, 0 + mtc0 zero, CP0_TAGLO, 2 + mtc0 zero, CP0_TAGHI, 2 + ehb + + /* Primary cache configuration is indicated by Config1 */ + mfc0 v0, CP0_CONFIG, 1 + + /* Detect I-cache line size */ + _EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ + beqz t0, icache_done + li t1, 2 + sllv t0, t1, t0 + + /* Detect I-cache size */ + _EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ + xori t2, t1, 0x7 + beqz t2, 1f + li t3, 32 + addi t1, t1, 1 + sllv t1, t3, t1 +1: /* At this point t1 == I-cache sets per way */ + _EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ + addi t2, t2, 1 + mul t1, t1, t0 + mul t1, t1, t2 + + li a0, KSEG0 + add a1, a0, t1 +1: cache Index_Store_Tag_I, 0(a0) + add a0, a0, t0 + bne a0, a1, 1b + nop +icache_done: + + /* Detect D-cache line size */ + _EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ + beqz t0, dcache_done + li t1, 2 + sllv t0, t1, t0 + + /* Detect D-cache size */ + _EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ + xori t2, t1, 0x7 + beqz t2, 1f + li t3, 32 + addi t1, t1, 1 + sllv t1, t3, t1 +1: /* At this point t1 == D-cache sets per way */ + _EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ + addi t2, t2, 1 + mul t1, t1, t0 + mul t1, t1, t2 + + li a0, KSEG0 + addu a1, a0, t1 + subu a1, a1, t0 +1: cache Index_Store_Tag_D, 0(a0) + bne a0, a1, 1b + add a0, a0, t0 +dcache_done: + + /* Set Kseg0 cacheable, coherent, write-back, write-allocate */ + mfc0 t0, CP0_CONFIG + ori t0, 0x7 + xori t0, 0x2 + mtc0 t0, CP0_CONFIG + ehb + + /* Enter the coherent domain */ + li t0, 0xff + sw t0, GCR_CL_COHERENCE_OFS(v1) + ehb + + /* Jump to kseg0 */ + la t0, 1f + jr t0 + nop + +1: /* We're up, cached & coherent */ + + /* + * TODO: We should check the VPE number we intended to boot here, and + * if non-zero we should start that VPE and stop this one. For + * the moment this doesn't matter since CPUs are brought up + * sequentially and in order, but once hotplug is implemented + * this will need revisiting. + */ + + /* Off we go! */ + la t0, mips_cps_bootcfg + lw t1, BOOTCFG_PC(t0) + lw gp, BOOTCFG_GP(t0) + lw sp, BOOTCFG_SP(t0) + jr t1 + nop + END(mips_cps_core_entry) + +.org 0x200 +LEAF(excep_tlbfill) + b . + nop + END(excep_tlbfill) + +.org 0x280 +LEAF(excep_xtlbfill) + b . + nop + END(excep_xtlbfill) + +.org 0x300 +LEAF(excep_cache) + b . + nop + END(excep_cache) + +.org 0x380 +LEAF(excep_genex) + b . + nop + END(excep_genex) + +.org 0x400 +LEAF(excep_intex) + b . + nop + END(excep_intex) + +.org 0x480 +LEAF(excep_ejtag) + la k0, ejtag_debug_handler + jr k0 + nop + END(excep_ejtag) |