| |
| /* |
| * 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 |
| |
| #if ENABLE_FPU==1 |
| /* initialize the Floating point unit (both TPs) */ |
| bal init_fpu |
| nop |
| #endif |
| |
| /* 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 |