/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2011-2012 by Broadcom Corporation * * Init for bmips 5000. * Used to init second core in dual core 5000's. */ #include <linux/init.h> #include <asm/asm.h> #include <asm/asmmacro.h> #include <asm/cacheops.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> #include <asm/addrspace.h> #include <asm/hazards.h> #include <asm/bmips.h> #ifdef CONFIG_CPU_BMIPS5000 #define cacheop(kva, size, linesize, op) \ .set noreorder ; \ addu t1, kva, size ; \ subu t2, linesize, 1 ; \ not t2 ; \ and t0, kva, t2 ; \ addiu t1, t1, -1 ; \ and t1, t2 ; \ 9: cache op, 0(t0) ; \ bne t0, t1, 9b ; \ addu t0, linesize ; \ .set reorder ; #define IS_SHIFT 22 #define IL_SHIFT 19 #define IA_SHIFT 16 #define DS_SHIFT 13 #define DL_SHIFT 10 #define DA_SHIFT 7 #define IS_MASK 7 #define IL_MASK 7 #define IA_MASK 7 #define DS_MASK 7 #define DL_MASK 7 #define DA_MASK 7 #define ICE_MASK 0x80000000 #define DCE_MASK 0x40000000 #define CP0_BRCM_CONFIG0 $22, 0 #define CP0_BRCM_MODE $22, 1 #define CP0_CONFIG_K0_MASK 7 #define CP0_ICACHE_TAG_LO $28 #define CP0_ICACHE_DATA_LO $28, 1 #define CP0_DCACHE_TAG_LO $28, 2 #define CP0_D_SEC_CACHE_DATA_LO $28, 3 #define CP0_ICACHE_TAG_HI $29 #define CP0_ICACHE_DATA_HI $29, 1 #define CP0_DCACHE_TAG_HI $29, 2 #define CP0_BRCM_MODE_Luc_MASK (1 << 11) #define CP0_BRCM_CONFIG0_CWF_MASK (1 << 20) #define CP0_BRCM_CONFIG0_TSE_MASK (1 << 19) #define CP0_BRCM_MODE_SET_MASK (1 << 7) #define CP0_BRCM_MODE_ClkRATIO_MASK (7 << 4) #define CP0_BRCM_MODE_BrPRED_MASK (3 << 24) #define CP0_BRCM_MODE_BrPRED_SHIFT 24 #define CP0_BRCM_MODE_BrHIST_MASK (0x1f << 20) #define CP0_BRCM_MODE_BrHIST_SHIFT 20 /* ZSC L2 Cache Register Access Register Definitions */ #define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 24 #define BRCM_ZSC_CONFIG_REG 0 << 3 #define BRCM_ZSC_REQ_BUFFER_REG 2 << 3 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0 4 << 3 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1 6 << 3 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2 8 << 3 #define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0 0xa << 3 #define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1 0xc << 3 #define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0 0xe << 3 #define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1 0x10 << 3 #define BRCM_ZSC_CONFIG_LMB1En 1 << (15) #define BRCM_ZSC_CONFIG_LMB0En 1 << (14) /* branch predition values */ #define BRCM_BrPRED_ALL_TAKEN (0x0) #define BRCM_BrPRED_ALL_NOT_TAKEN (0x1) #define BRCM_BrPRED_BHT_ENABLE (0x2) #define BRCM_BrPRED_PREDICT_BACKWARD (0x3) .align 2 /* * Function: size_i_cache * Arguments: None * Returns: v0 = i cache size, v1 = I cache line size * Description: compute the I-cache size and I-cache line size * Trashes: v0, v1, a0, t0 * * pseudo code: * */ LEAF(size_i_cache) .set noreorder mfc0 a0, CP0_CONFIG, 1 move t0, a0 /* * Determine sets per way: IS * * This field contains the number of sets (i.e., indices) per way of * the instruction cache: * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k * vi) 0x5 - 0x7: Reserved. */ srl a0, a0, IS_SHIFT and a0, a0, IS_MASK /* sets per way = (64<<IS) */ li v0, 0x40 sllv v0, v0, a0 /* * Determine line size * * This field contains the line size of the instruction cache: * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii) * 0x5: 64 bytes, iv) the rest: Reserved. */ move a0, t0 srl a0, a0, IL_SHIFT and a0, a0, IL_MASK beqz a0, no_i_cache nop /* line size = 2 ^ (IL+1) */ addi a0, a0, 1 li v1, 1 sll v1, v1, a0 /* v0 now have sets per way, multiply it by line size now * that will give the set size */ sll v0, v0, a0 /* * Determine set associativity * * This field contains the set associativity of the instruction cache. * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3: * 4-way, v) 0x4 - 0x7: Reserved. */ move a0, t0 srl a0, a0, IA_SHIFT and a0, a0, IA_MASK addi a0, a0, 0x1 /* v0 has the set size, multiply it by * set associativiy, to get the cache size */ multu v0, a0 /*multu is interlocked, so no need to insert nops */ mflo v0 b 1f nop no_i_cache: move v0, zero move v1, zero 1: jr ra nop .set reorder END(size_i_cache) /* * Function: size_d_cache * Arguments: None * Returns: v0 = d cache size, v1 = d cache line size * Description: compute the D-cache size and D-cache line size. * Trashes: v0, v1, a0, t0 * */ LEAF(size_d_cache) .set noreorder mfc0 a0, CP0_CONFIG, 1 move t0, a0 /* * Determine sets per way: IS * * This field contains the number of sets (i.e., indices) per way of * the instruction cache: * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k * vi) 0x5 - 0x7: Reserved. */ srl a0, a0, DS_SHIFT and a0, a0, DS_MASK /* sets per way = (64<<IS) */ li v0, 0x40 sllv v0, v0, a0 /* * Determine line size * * This field contains the line size of the instruction cache: * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii) * 0x5: 64 bytes, iv) the rest: Reserved. */ move a0, t0 srl a0, a0, DL_SHIFT and a0, a0, DL_MASK beqz a0, no_d_cache nop /* line size = 2 ^ (IL+1) */ addi a0, a0, 1 li v1, 1 sll v1, v1, a0 /* v0 now have sets per way, multiply it by line size now * that will give the set size */ sll v0, v0, a0 /* determine set associativity * * This field contains the set associativity of the instruction cache. * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3: * 4-way, v) 0x4 - 0x7: Reserved. */ move a0, t0 srl a0, a0, DA_SHIFT and a0, a0, DA_MASK addi a0, a0, 0x1 /* v0 has the set size, multiply it by * set associativiy, to get the cache size */ multu v0, a0 /*multu is interlocked, so no need to insert nops */ mflo v0 b 1f nop no_d_cache: move v0, zero move v1, zero 1: jr ra nop .set reorder END(size_d_cache) /* * Function: enable_ID * Arguments: None * Returns: None * Description: Enable I and D caches, initialize I and D-caches, also set * hardware delay for d-cache (TP0). * Trashes: t0 * */ .global enable_ID .ent enable_ID .set noreorder enable_ID: mfc0 t0, CP0_BRCM_CONFIG0 or t0, t0, (ICE_MASK | DCE_MASK) mtc0 t0, CP0_BRCM_CONFIG0 jr ra nop .end enable_ID .set reorder /* * Function: l1_init * Arguments: None * Returns: None * Description: Enable I and D caches, and initialize I and D-caches * Trashes: a0, v0, v1, t0, t1, t2, t8 * */ .globl l1_init .ent l1_init .set noreorder l1_init: /* save return address */ move t8, ra /* initialize I and D cache Data and Tag registers. */ mtc0 zero, CP0_ICACHE_TAG_LO mtc0 zero, CP0_ICACHE_TAG_HI mtc0 zero, CP0_ICACHE_DATA_LO mtc0 zero, CP0_ICACHE_DATA_HI mtc0 zero, CP0_DCACHE_TAG_LO mtc0 zero, CP0_DCACHE_TAG_HI /* Enable Caches before Clearing. If the caches are disabled * then the cache operations to clear the cache will be ignored */ jal enable_ID nop jal size_i_cache /* v0 = i-cache size, v1 = i-cache line size */ nop /* run uncached in kseg 1 */ la k0, 1f lui k1, 0x2000 or k0, k1, k0 jr k0 nop 1: /* * set K0 cache mode */ mfc0 t0, CP0_CONFIG and t0, t0, ~CP0_CONFIG_K0_MASK or t0, t0, 3 /* Write Back mode */ mtc0 t0, CP0_CONFIG /* * Initialize instruction cache. */ li a0, KSEG0 cacheop(a0, v0, v1, Index_Store_Tag_I) /* * Now we can run from I-$, kseg 0 */ la k0, 1f lui k1, 0x2000 or k0, k1, k0 xor k0, k1, k0 jr k0 nop 1: /* * Initialize data cache. */ jal size_d_cache /* v0 = d-cache size, v1 = d-cache line size */ nop li a0, KSEG0 cacheop(a0, v0, v1, Index_Store_Tag_D) jr t8 nop .end l1_init .set reorder /* * Function: set_other_config * Arguments: none * Returns: None * Description: initialize other remainder configuration to defaults. * Trashes: t0, t1 * * pseudo code: * */ LEAF(set_other_config) .set noreorder /* enable Bus error for I-fetch */ mfc0 t0, CP0_CACHEERR, 0 li t1, 0x4 or t0, t1 mtc0 t0, CP0_CACHEERR, 0 /* enable Bus error for Load */ mfc0 t0, CP0_CACHEERR, 1 li t1, 0x4 or t0, t1 mtc0 t0, CP0_CACHEERR, 1 /* enable Bus Error for Store */ mfc0 t0, CP0_CACHEERR, 2 li t1, 0x4 or t0, t1 mtc0 t0, CP0_CACHEERR, 2 jr ra nop .set reorder END(set_other_config) /* * Function: set_branch_pred * Arguments: none * Returns: None * Description: * Trashes: t0, t1 * * pseudo code: * */ LEAF(set_branch_pred) .set noreorder mfc0 t0, CP0_BRCM_MODE li t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK ) and t0, t0, t1 /* enable Branch prediction */ li t1, BRCM_BrPRED_BHT_ENABLE sll t1, CP0_BRCM_MODE_BrPRED_SHIFT or t0, t0, t1 /* set history count to 8 */ li t1, 8 sll t1, CP0_BRCM_MODE_BrHIST_SHIFT or t0, t0, t1 mtc0 t0, CP0_BRCM_MODE jr ra nop .set reorder END(set_branch_pred) /* * Function: set_luc * Arguments: set link uncached. * Returns: None * Description: * Trashes: t0, t1 * */ LEAF(set_luc) .set noreorder mfc0 t0, CP0_BRCM_MODE li t1, ~(CP0_BRCM_MODE_Luc_MASK) and t0, t0, t1 /* set Luc */ ori t0, t0, CP0_BRCM_MODE_Luc_MASK mtc0 t0, CP0_BRCM_MODE jr ra nop .set reorder END(set_luc) /* * Function: set_cwf_tse * Arguments: set CWF and TSE bits * Returns: None * Description: * Trashes: t0, t1 * */ LEAF(set_cwf_tse) .set noreorder mfc0 t0, CP0_BRCM_CONFIG0 li t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK) or t0, t0, t1 mtc0 t0, CP0_BRCM_CONFIG0 jr ra nop .set reorder END(set_cwf_tse) /* * Function: set_clock_ratio * Arguments: set clock ratio specified by a0 * Returns: None * Description: * Trashes: v0, v1, a0, a1 * * pseudo code: * */ LEAF(set_clock_ratio) .set noreorder mfc0 t0, CP0_BRCM_MODE li t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK) and t0, t0, t1 li t1, CP0_BRCM_MODE_SET_MASK or t0, t0, t1 or t0, t0, a0 mtc0 t0, CP0_BRCM_MODE jr ra nop .set reorder END(set_clock_ratio) /* * Function: set_zephyr * Arguments: None * Returns: None * Description: Set any zephyr bits * Trashes: t0 & t1 * */ LEAF(set_zephyr) .set noreorder /* enable read/write of CP0 #22 sel. 8 */ li t0, 0x5a455048 .word 0x4088b00f /* mtc0 t0, $22, 15 */ .word 0x4008b008 /* mfc0 t0, $22, 8 */ li t1, 0x09008000 /* turn off pref, jtb */ or t0, t0, t1 .word 0x4088b008 /* mtc0 t0, $22, 8 */ sync /* disable read/write of CP0 #22 sel 8 */ li t0, 0x0 .word 0x4088b00f /* mtc0 t0, $22, 15 */ jr ra nop .set reorder END(set_zephyr) /* * Function: set_llmb * Arguments: a0=0 disable llmb, a0=1 enables llmb * Returns: None * Description: * Trashes: t0, t1, t2 * * pseudo code: * */ LEAF(set_llmb) .set noreorder li t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG sync cache 0x7, 0x0(t2) sync mfc0 t0, CP0_D_SEC_CACHE_DATA_LO li t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En) and t0, t0, t1 beqz a0, svlmb nop enable_lmb: li t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En) or t0, t0, t1 svlmb: mtc0 t0, CP0_D_SEC_CACHE_DATA_LO sync cache 0xb, 0x0(t2) sync jr ra nop .set reorder END(set_llmb) /* * Function: core_init * Arguments: none * Returns: None * Description: initialize core related configuration * Trashes: v0,v1,a0,a1,t8 * * pseudo code: * */ .globl core_init .ent core_init .set noreorder core_init: move t8, ra /* set Zephyr bits. */ bal set_zephyr nop /* set low latency memory bus */ li a0, 1 bal set_llmb nop /* set branch prediction (TP0 only) */ bal set_branch_pred nop /* set link uncached */ bal set_luc nop /* set CWF and TSE */ bal set_cwf_tse nop /* *set clock ratio by setting 1 to 'set' * and 0 to ClkRatio, (TP0 only) */ li a0, 0 bal set_clock_ratio nop /* set other configuration to defaults */ bal set_other_config nop move ra, t8 jr ra nop .set reorder .end core_init /* * Function: clear_jump_target_buffer * Arguments: None * Returns: None * Description: * Trashes: t0, t1, t2 * */ #define RESET_CALL_RETURN_STACK_THIS_THREAD (0x06<<16) #define RESET_JUMP_TARGET_BUFFER_THIS_THREAD (0x04<<16) #define JTB_CS_CNTL_MASK (0xFF<<16) .globl clear_jump_target_buffer .ent clear_jump_target_buffer .set noreorder clear_jump_target_buffer: mfc0 t0, $22, 2 nop nop li t1, ~JTB_CS_CNTL_MASK and t0, t0, t1 li t2, RESET_CALL_RETURN_STACK_THIS_THREAD or t0, t0, t2 mtc0 t0, $22, 2 nop nop and t0, t0, t1 li t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD or t0, t0, t2 mtc0 t0, $22, 2 nop nop jr ra nop .end clear_jump_target_buffer .set reorder /* * Function: bmips_cache_init * Arguments: None * Returns: None * Description: Enable I and D caches, and initialize I and D-caches * Trashes: v0, v1, t0, t1, t2, t5, t7, t8 * */ .globl bmips_5xxx_init .ent bmips_5xxx_init .set noreorder bmips_5xxx_init: /* save return address and A0 */ move t7, ra move t5, a0 jal l1_init nop jal core_init nop jal clear_jump_target_buffer nop mtc0 zero, CP0_CAUSE move a0, t5 jr t7 nop .end bmips_5xxx_init .set reorder #endif