linux-zen-desktop/arch/mips/kernel/bmips_5xxx_init.S

748 lines
13 KiB
ArmAsm

/*
* 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