1/*2* This file is subject to the terms and conditions of the GNU General Public3* License. See the file "COPYING" in the main directory of this archive4* for more details.5*6* Copyright (C) 2011-2012 by Broadcom Corporation7*8* Init for bmips 5000.9* Used to init second core in dual core 5000's.10*/1112#include <linux/init.h>1314#include <asm/asm.h>15#include <asm/asmmacro.h>16#include <asm/cacheops.h>17#include <asm/regdef.h>18#include <asm/mipsregs.h>19#include <asm/stackframe.h>20#include <asm/addrspace.h>21#include <asm/hazards.h>22#include <asm/bmips.h>2324#ifdef CONFIG_CPU_BMIPS5000252627#define cacheop(kva, size, linesize, op) \28.set noreorder ; \29addu t1, kva, size ; \30subu t2, linesize, 1 ; \31not t2 ; \32and t0, kva, t2 ; \33addiu t1, t1, -1 ; \34and t1, t2 ; \359: cache op, 0(t0) ; \36bne t0, t1, 9b ; \37addu t0, linesize ; \38.set reorder ;39404142#define IS_SHIFT 2243#define IL_SHIFT 1944#define IA_SHIFT 1645#define DS_SHIFT 1346#define DL_SHIFT 1047#define DA_SHIFT 748#define IS_MASK 749#define IL_MASK 750#define IA_MASK 751#define DS_MASK 752#define DL_MASK 753#define DA_MASK 754#define ICE_MASK 0x8000000055#define DCE_MASK 0x400000005657#define CP0_BRCM_CONFIG0 $22, 058#define CP0_BRCM_MODE $22, 159#define CP0_CONFIG_K0_MASK 76061#define CP0_ICACHE_TAG_LO $2862#define CP0_ICACHE_DATA_LO $28, 163#define CP0_DCACHE_TAG_LO $28, 264#define CP0_D_SEC_CACHE_DATA_LO $28, 365#define CP0_ICACHE_TAG_HI $2966#define CP0_ICACHE_DATA_HI $29, 167#define CP0_DCACHE_TAG_HI $29, 26869#define CP0_BRCM_MODE_Luc_MASK (1 << 11)70#define CP0_BRCM_CONFIG0_CWF_MASK (1 << 20)71#define CP0_BRCM_CONFIG0_TSE_MASK (1 << 19)72#define CP0_BRCM_MODE_SET_MASK (1 << 7)73#define CP0_BRCM_MODE_ClkRATIO_MASK (7 << 4)74#define CP0_BRCM_MODE_BrPRED_MASK (3 << 24)75#define CP0_BRCM_MODE_BrPRED_SHIFT 2476#define CP0_BRCM_MODE_BrHIST_MASK (0x1f << 20)77#define CP0_BRCM_MODE_BrHIST_SHIFT 207879/* ZSC L2 Cache Register Access Register Definitions */80#define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 248182#define BRCM_ZSC_CONFIG_REG 0 << 383#define BRCM_ZSC_REQ_BUFFER_REG 2 << 384#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0 4 << 385#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1 6 << 386#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2 8 << 38788#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0 0xa << 389#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1 0xc << 39091#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0 0xe << 392#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1 0x10 << 39394#define BRCM_ZSC_CONFIG_LMB1En 1 << (15)95#define BRCM_ZSC_CONFIG_LMB0En 1 << (14)9697/* branch predition values */9899#define BRCM_BrPRED_ALL_TAKEN (0x0)100#define BRCM_BrPRED_ALL_NOT_TAKEN (0x1)101#define BRCM_BrPRED_BHT_ENABLE (0x2)102#define BRCM_BrPRED_PREDICT_BACKWARD (0x3)103104105106.align 2107/*108* Function: size_i_cache109* Arguments: None110* Returns: v0 = i cache size, v1 = I cache line size111* Description: compute the I-cache size and I-cache line size112* Trashes: v0, v1, a0, t0113*114* pseudo code:115*116*/117118LEAF(size_i_cache)119.set noreorder120121mfc0 a0, CP0_CONFIG, 1122move t0, a0123124/*125* Determine sets per way: IS126*127* This field contains the number of sets (i.e., indices) per way of128* the instruction cache:129* i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k130* vi) 0x5 - 0x7: Reserved.131*/132133srl a0, a0, IS_SHIFT134and a0, a0, IS_MASK135136/* sets per way = (64<<IS) */137138li v0, 0x40139sllv v0, v0, a0140141/*142* Determine line size143*144* This field contains the line size of the instruction cache:145* i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)146* 0x5: 64 bytes, iv) the rest: Reserved.147*/148149move a0, t0150151srl a0, a0, IL_SHIFT152and a0, a0, IL_MASK153154beqz a0, no_i_cache155nop156157/* line size = 2 ^ (IL+1) */158159addi a0, a0, 1160li v1, 1161sll v1, v1, a0162163/* v0 now have sets per way, multiply it by line size now164* that will give the set size165*/166167sll v0, v0, a0168169/*170* Determine set associativity171*172* This field contains the set associativity of the instruction cache.173* i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:174* 4-way, v) 0x4 - 0x7: Reserved.175*/176177move a0, t0178179srl a0, a0, IA_SHIFT180and a0, a0, IA_MASK181addi a0, a0, 0x1182183/* v0 has the set size, multiply it by184* set associativiy, to get the cache size185*/186187multu v0, a0 /*multu is interlocked, so no need to insert nops */188mflo v0189b 1f190nop191192no_i_cache:193move v0, zero194move v1, zero1951:196jr ra197nop198.set reorder199200END(size_i_cache)201202/*203* Function: size_d_cache204* Arguments: None205* Returns: v0 = d cache size, v1 = d cache line size206* Description: compute the D-cache size and D-cache line size.207* Trashes: v0, v1, a0, t0208*209*/210211LEAF(size_d_cache)212.set noreorder213214mfc0 a0, CP0_CONFIG, 1215move t0, a0216217/*218* Determine sets per way: IS219*220* This field contains the number of sets (i.e., indices) per way of221* the instruction cache:222* i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k223* vi) 0x5 - 0x7: Reserved.224*/225226srl a0, a0, DS_SHIFT227and a0, a0, DS_MASK228229/* sets per way = (64<<IS) */230231li v0, 0x40232sllv v0, v0, a0233234/*235* Determine line size236*237* This field contains the line size of the instruction cache:238* i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)239* 0x5: 64 bytes, iv) the rest: Reserved.240*/241move a0, t0242243srl a0, a0, DL_SHIFT244and a0, a0, DL_MASK245246beqz a0, no_d_cache247nop248249/* line size = 2 ^ (IL+1) */250251addi a0, a0, 1252li v1, 1253sll v1, v1, a0254255/* v0 now have sets per way, multiply it by line size now256* that will give the set size257*/258259sll v0, v0, a0260261/* determine set associativity262*263* This field contains the set associativity of the instruction cache.264* i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:265* 4-way, v) 0x4 - 0x7: Reserved.266*/267268move a0, t0269270srl a0, a0, DA_SHIFT271and a0, a0, DA_MASK272addi a0, a0, 0x1273274/* v0 has the set size, multiply it by275* set associativiy, to get the cache size276*/277278multu v0, a0 /*multu is interlocked, so no need to insert nops */279mflo v0280281b 1f282nop283284no_d_cache:285move v0, zero286move v1, zero2871:288jr ra289nop290.set reorder291292END(size_d_cache)293294295/*296* Function: enable_ID297* Arguments: None298* Returns: None299* Description: Enable I and D caches, initialize I and D-caches, also set300* hardware delay for d-cache (TP0).301* Trashes: t0302*303*/304.global enable_ID305.ent enable_ID306.set noreorder307enable_ID:308mfc0 t0, CP0_BRCM_CONFIG0309or t0, t0, (ICE_MASK | DCE_MASK)310mtc0 t0, CP0_BRCM_CONFIG0311jr ra312nop313314.end enable_ID315.set reorder316317318/*319* Function: l1_init320* Arguments: None321* Returns: None322* Description: Enable I and D caches, and initialize I and D-caches323* Trashes: a0, v0, v1, t0, t1, t2, t8324*325*/326.globl l1_init327.ent l1_init328.set noreorder329l1_init:330331/* save return address */332move t8, ra333334335/* initialize I and D cache Data and Tag registers. */336mtc0 zero, CP0_ICACHE_TAG_LO337mtc0 zero, CP0_ICACHE_TAG_HI338mtc0 zero, CP0_ICACHE_DATA_LO339mtc0 zero, CP0_ICACHE_DATA_HI340mtc0 zero, CP0_DCACHE_TAG_LO341mtc0 zero, CP0_DCACHE_TAG_HI342343/* Enable Caches before Clearing. If the caches are disabled344* then the cache operations to clear the cache will be ignored345*/346347jal enable_ID348nop349350jal size_i_cache /* v0 = i-cache size, v1 = i-cache line size */351nop352353/* run uncached in kseg 1 */354la k0, 1f355lui k1, 0x2000356or k0, k1, k0357jr k0358nop3591:360361/*362* set K0 cache mode363*/364365mfc0 t0, CP0_CONFIG366and t0, t0, ~CP0_CONFIG_K0_MASK367or t0, t0, 3 /* Write Back mode */368mtc0 t0, CP0_CONFIG369370/*371* Initialize instruction cache.372*/373374li a0, KSEG0375cacheop(a0, v0, v1, Index_Store_Tag_I)376377/*378* Now we can run from I-$, kseg 0379*/380la k0, 1f381lui k1, 0x2000382or k0, k1, k0383xor k0, k1, k0384jr k0385nop3861:387/*388* Initialize data cache.389*/390391jal size_d_cache /* v0 = d-cache size, v1 = d-cache line size */392nop393394395li a0, KSEG0396cacheop(a0, v0, v1, Index_Store_Tag_D)397398jr t8399nop400401.end l1_init402.set reorder403404405/*406* Function: set_other_config407* Arguments: none408* Returns: None409* Description: initialize other remainder configuration to defaults.410* Trashes: t0, t1411*412* pseudo code:413*414*/415LEAF(set_other_config)416.set noreorder417418/* enable Bus error for I-fetch */419mfc0 t0, CP0_CACHEERR, 0420li t1, 0x4421or t0, t1422mtc0 t0, CP0_CACHEERR, 0423424/* enable Bus error for Load */425mfc0 t0, CP0_CACHEERR, 1426li t1, 0x4427or t0, t1428mtc0 t0, CP0_CACHEERR, 1429430/* enable Bus Error for Store */431mfc0 t0, CP0_CACHEERR, 2432li t1, 0x4433or t0, t1434mtc0 t0, CP0_CACHEERR, 2435436jr ra437nop438.set reorder439END(set_other_config)440441/*442* Function: set_branch_pred443* Arguments: none444* Returns: None445* Description:446* Trashes: t0, t1447*448* pseudo code:449*450*/451452LEAF(set_branch_pred)453.set noreorder454mfc0 t0, CP0_BRCM_MODE455li t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK )456and t0, t0, t1457458/* enable Branch prediction */459li t1, BRCM_BrPRED_BHT_ENABLE460sll t1, CP0_BRCM_MODE_BrPRED_SHIFT461or t0, t0, t1462463/* set history count to 8 */464li t1, 8465sll t1, CP0_BRCM_MODE_BrHIST_SHIFT466or t0, t0, t1467468mtc0 t0, CP0_BRCM_MODE469jr ra470nop471.set reorder472END(set_branch_pred)473474475/*476* Function: set_luc477* Arguments: set link uncached.478* Returns: None479* Description:480* Trashes: t0, t1481*482*/483LEAF(set_luc)484.set noreorder485mfc0 t0, CP0_BRCM_MODE486li t1, ~(CP0_BRCM_MODE_Luc_MASK)487and t0, t0, t1488489/* set Luc */490ori t0, t0, CP0_BRCM_MODE_Luc_MASK491492mtc0 t0, CP0_BRCM_MODE493jr ra494nop495.set reorder496END(set_luc)497498/*499* Function: set_cwf_tse500* Arguments: set CWF and TSE bits501* Returns: None502* Description:503* Trashes: t0, t1504*505*/506LEAF(set_cwf_tse)507.set noreorder508mfc0 t0, CP0_BRCM_CONFIG0509li t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK)510or t0, t0, t1511512mtc0 t0, CP0_BRCM_CONFIG0513jr ra514nop515.set reorder516END(set_cwf_tse)517518/*519* Function: set_clock_ratio520* Arguments: set clock ratio specified by a0521* Returns: None522* Description:523* Trashes: v0, v1, a0, a1524*525* pseudo code:526*527*/528LEAF(set_clock_ratio)529.set noreorder530531mfc0 t0, CP0_BRCM_MODE532li t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK)533and t0, t0, t1534li t1, CP0_BRCM_MODE_SET_MASK535or t0, t0, t1536or t0, t0, a0537mtc0 t0, CP0_BRCM_MODE538jr ra539nop540.set reorder541END(set_clock_ratio)542/*543* Function: set_zephyr544* Arguments: None545* Returns: None546* Description: Set any zephyr bits547* Trashes: t0 & t1548*549*/550LEAF(set_zephyr)551.set noreorder552553/* enable read/write of CP0 #22 sel. 8 */554li t0, 0x5a455048555.word 0x4088b00f /* mtc0 t0, $22, 15 */556557.word 0x4008b008 /* mfc0 t0, $22, 8 */558li t1, 0x09008000 /* turn off pref, jtb */559or t0, t0, t1560.word 0x4088b008 /* mtc0 t0, $22, 8 */561sync562563/* disable read/write of CP0 #22 sel 8 */564li t0, 0x0565.word 0x4088b00f /* mtc0 t0, $22, 15 */566567568jr ra569nop570.set reorder571572END(set_zephyr)573574575/*576* Function: set_llmb577* Arguments: a0=0 disable llmb, a0=1 enables llmb578* Returns: None579* Description:580* Trashes: t0, t1, t2581*582* pseudo code:583*584*/585LEAF(set_llmb)586.set noreorder587588li t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG589sync590cache 0x7, 0x0(t2)591sync592mfc0 t0, CP0_D_SEC_CACHE_DATA_LO593li t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)594and t0, t0, t1595596beqz a0, svlmb597nop598599enable_lmb:600li t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)601or t0, t0, t1602603svlmb:604mtc0 t0, CP0_D_SEC_CACHE_DATA_LO605sync606cache 0xb, 0x0(t2)607sync608609jr ra610nop611.set reorder612613END(set_llmb)614/*615* Function: core_init616* Arguments: none617* Returns: None618* Description: initialize core related configuration619* Trashes: v0,v1,a0,a1,t8620*621* pseudo code:622*623*/624.globl core_init625.ent core_init626.set noreorder627core_init:628move t8, ra629630/* set Zephyr bits. */631bal set_zephyr632nop633634/* set low latency memory bus */635li a0, 1636bal set_llmb637nop638639/* set branch prediction (TP0 only) */640bal set_branch_pred641nop642643/* set link uncached */644bal set_luc645nop646647/* set CWF and TSE */648bal set_cwf_tse649nop650651/*652*set clock ratio by setting 1 to 'set'653* and 0 to ClkRatio, (TP0 only)654*/655li a0, 0656bal set_clock_ratio657nop658659/* set other configuration to defaults */660bal set_other_config661nop662663move ra, t8664jr ra665nop666667.set reorder668.end core_init669670/*671* Function: clear_jump_target_buffer672* Arguments: None673* Returns: None674* Description:675* Trashes: t0, t1, t2676*677*/678#define RESET_CALL_RETURN_STACK_THIS_THREAD (0x06<<16)679#define RESET_JUMP_TARGET_BUFFER_THIS_THREAD (0x04<<16)680#define JTB_CS_CNTL_MASK (0xFF<<16)681682.globl clear_jump_target_buffer683.ent clear_jump_target_buffer684.set noreorder685clear_jump_target_buffer:686687mfc0 t0, $22, 2688nop689nop690691li t1, ~JTB_CS_CNTL_MASK692and t0, t0, t1693li t2, RESET_CALL_RETURN_STACK_THIS_THREAD694or t0, t0, t2695mtc0 t0, $22, 2696nop697nop698699and t0, t0, t1700li t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD701or t0, t0, t2702mtc0 t0, $22, 2703nop704nop705jr ra706nop707708.end clear_jump_target_buffer709.set reorder710/*711* Function: bmips_cache_init712* Arguments: None713* Returns: None714* Description: Enable I and D caches, and initialize I and D-caches715* Trashes: v0, v1, t0, t1, t2, t5, t7, t8716*717*/718.globl bmips_5xxx_init719.ent bmips_5xxx_init720.set noreorder721bmips_5xxx_init:722723/* save return address and A0 */724move t7, ra725move t5, a0726727jal l1_init728nop729730jal core_init731nop732733jal clear_jump_target_buffer734nop735736mtc0 zero, CP0_CAUSE737738move a0, t5739jr t7740nop741742.end bmips_5xxx_init743.set reorder744745746#endif747748749