Back to home page

OSCL-LXR

 
 

    


0001 
0002 /*
0003  * This file is subject to the terms and conditions of the GNU General Public
0004  * License.  See the file "COPYING" in the main directory of this archive
0005  * for more details.
0006  *
0007  * Copyright (C) 2011-2012 by Broadcom Corporation
0008  *
0009  * Init for bmips 5000.
0010  * Used to init second core in dual core 5000's.
0011  */
0012 
0013 #include <linux/init.h>
0014 
0015 #include <asm/asm.h>
0016 #include <asm/asmmacro.h>
0017 #include <asm/cacheops.h>
0018 #include <asm/regdef.h>
0019 #include <asm/mipsregs.h>
0020 #include <asm/stackframe.h>
0021 #include <asm/addrspace.h>
0022 #include <asm/hazards.h>
0023 #include <asm/bmips.h>
0024 
0025 #ifdef CONFIG_CPU_BMIPS5000
0026 
0027 
0028 #define cacheop(kva, size, linesize, op)    \
0029     .set noreorder          ;   \
0030     addu        t1, kva, size   ;   \
0031     subu        t2, linesize, 1 ;   \
0032     not     t2      ;   \
0033     and     t0, kva, t2 ;   \
0034     addiu       t1, t1, -1  ;   \
0035     and     t1, t2      ;   \
0036 9:  cache       op, 0(t0)   ;   \
0037     bne     t0, t1, 9b  ;   \
0038      addu       t0, linesize    ;   \
0039     .set reorder            ;
0040 
0041 
0042 
0043 #define IS_SHIFT    22
0044 #define IL_SHIFT    19
0045 #define IA_SHIFT    16
0046 #define DS_SHIFT    13
0047 #define DL_SHIFT    10
0048 #define DA_SHIFT     7
0049 #define IS_MASK      7
0050 #define IL_MASK      7
0051 #define IA_MASK      7
0052 #define DS_MASK      7
0053 #define DL_MASK      7
0054 #define DA_MASK      7
0055 #define ICE_MASK    0x80000000
0056 #define DCE_MASK    0x40000000
0057 
0058 #define CP0_BRCM_CONFIG0    $22, 0
0059 #define CP0_BRCM_MODE       $22, 1
0060 #define CP0_CONFIG_K0_MASK  7
0061 
0062 #define CP0_ICACHE_TAG_LO   $28
0063 #define CP0_ICACHE_DATA_LO  $28, 1
0064 #define CP0_DCACHE_TAG_LO   $28, 2
0065 #define CP0_D_SEC_CACHE_DATA_LO $28, 3
0066 #define CP0_ICACHE_TAG_HI   $29
0067 #define CP0_ICACHE_DATA_HI  $29, 1
0068 #define CP0_DCACHE_TAG_HI   $29, 2
0069 
0070 #define CP0_BRCM_MODE_Luc_MASK      (1 << 11)
0071 #define CP0_BRCM_CONFIG0_CWF_MASK   (1 << 20)
0072 #define CP0_BRCM_CONFIG0_TSE_MASK   (1 << 19)
0073 #define CP0_BRCM_MODE_SET_MASK      (1 << 7)
0074 #define CP0_BRCM_MODE_ClkRATIO_MASK (7 << 4)
0075 #define CP0_BRCM_MODE_BrPRED_MASK   (3 << 24)
0076 #define CP0_BRCM_MODE_BrPRED_SHIFT  24
0077 #define CP0_BRCM_MODE_BrHIST_MASK   (0x1f << 20)
0078 #define CP0_BRCM_MODE_BrHIST_SHIFT  20
0079 
0080 /* ZSC L2 Cache Register Access Register Definitions */
0081 #define BRCM_ZSC_ALL_REGS_SELECT        0x7 << 24
0082 
0083 #define BRCM_ZSC_CONFIG_REG         0 << 3
0084 #define BRCM_ZSC_REQ_BUFFER_REG         2 << 3
0085 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0     4 << 3
0086 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1     6 << 3
0087 #define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2     8 << 3
0088 
0089 #define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0     0xa << 3
0090 #define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1     0xc << 3
0091 
0092 #define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0     0xe << 3
0093 #define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1     0x10 << 3
0094 
0095 #define BRCM_ZSC_CONFIG_LMB1En          1 << (15)
0096 #define BRCM_ZSC_CONFIG_LMB0En          1 << (14)
0097 
0098 /* branch predition values */
0099 
0100 #define BRCM_BrPRED_ALL_TAKEN       (0x0)
0101 #define BRCM_BrPRED_ALL_NOT_TAKEN   (0x1)
0102 #define BRCM_BrPRED_BHT_ENABLE      (0x2)
0103 #define BRCM_BrPRED_PREDICT_BACKWARD    (0x3)
0104 
0105 
0106 
0107 .align 2
0108 /*
0109  * Function:    size_i_cache
0110  * Arguments:   None
0111  * Returns: v0 = i cache size, v1 = I cache line size
0112  * Description: compute the I-cache size and I-cache line size
0113  * Trashes: v0, v1, a0, t0
0114  *
0115  *  pseudo code:
0116  *
0117  */
0118 
0119 LEAF(size_i_cache)
0120     .set    noreorder
0121 
0122     mfc0    a0, CP0_CONFIG, 1
0123     move    t0, a0
0124 
0125     /*
0126      * Determine sets per way: IS
0127      *
0128      * This field contains the number of sets (i.e., indices) per way of
0129      * the instruction cache:
0130      * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
0131      * vi) 0x5 - 0x7: Reserved.
0132      */
0133 
0134     srl a0, a0, IS_SHIFT
0135     and a0, a0, IS_MASK
0136 
0137     /* sets per way = (64<<IS) */
0138 
0139     li  v0, 0x40
0140     sllv    v0, v0, a0
0141 
0142     /*
0143      * Determine line size
0144      *
0145      * This field contains the line size of the instruction cache:
0146      * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
0147      * 0x5: 64 bytes, iv) the rest: Reserved.
0148      */
0149 
0150     move    a0, t0
0151 
0152     srl a0, a0, IL_SHIFT
0153     and a0, a0, IL_MASK
0154 
0155     beqz    a0, no_i_cache
0156     nop
0157 
0158     /* line size = 2 ^ (IL+1) */
0159 
0160     addi    a0, a0, 1
0161     li  v1, 1
0162     sll v1, v1, a0
0163 
0164     /* v0 now have sets per way, multiply it by line size now
0165      * that will give the set size
0166      */
0167 
0168     sll v0, v0, a0
0169 
0170     /*
0171      * Determine set associativity
0172      *
0173      * This field contains the set associativity of the instruction cache.
0174      * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
0175      * 4-way, v) 0x4 - 0x7: Reserved.
0176      */
0177 
0178     move    a0, t0
0179 
0180     srl a0, a0, IA_SHIFT
0181     and a0, a0, IA_MASK
0182     addi    a0, a0, 0x1
0183 
0184     /* v0 has the set size, multiply it by
0185      * set associativiy, to get the cache size
0186      */
0187 
0188     multu   v0, a0  /*multu is interlocked, so no need to insert nops */
0189     mflo    v0
0190     b   1f
0191     nop
0192 
0193 no_i_cache:
0194     move    v0, zero
0195     move    v1, zero
0196 1:
0197     jr  ra
0198     nop
0199     .set    reorder
0200 
0201 END(size_i_cache)
0202 
0203 /*
0204  * Function:    size_d_cache
0205  * Arguments:   None
0206  * Returns: v0 = d cache size, v1 = d cache line size
0207  * Description: compute the D-cache size and D-cache line size.
0208  * Trashes: v0, v1, a0, t0
0209  *
0210  */
0211 
0212 LEAF(size_d_cache)
0213     .set    noreorder
0214 
0215     mfc0    a0, CP0_CONFIG, 1
0216     move    t0, a0
0217 
0218     /*
0219      * Determine sets per way: IS
0220      *
0221      * This field contains the number of sets (i.e., indices) per way of
0222      * the instruction cache:
0223      * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
0224      * vi) 0x5 - 0x7: Reserved.
0225      */
0226 
0227     srl a0, a0, DS_SHIFT
0228     and a0, a0, DS_MASK
0229 
0230     /* sets per way = (64<<IS) */
0231 
0232     li  v0, 0x40
0233     sllv    v0, v0, a0
0234 
0235     /*
0236      * Determine line size
0237      *
0238      * This field contains the line size of the instruction cache:
0239      * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
0240      * 0x5: 64 bytes, iv) the rest: Reserved.
0241      */
0242     move    a0, t0
0243 
0244     srl a0, a0, DL_SHIFT
0245     and a0, a0, DL_MASK
0246 
0247     beqz    a0, no_d_cache
0248     nop
0249 
0250     /* line size = 2 ^ (IL+1) */
0251 
0252     addi    a0, a0, 1
0253     li  v1, 1
0254     sll v1, v1, a0
0255 
0256     /* v0 now have sets per way, multiply it by line size now
0257      * that will give the set size
0258      */
0259 
0260     sll v0, v0, a0
0261 
0262     /* determine set associativity
0263      *
0264      * This field contains the set associativity of the instruction cache.
0265      * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
0266      * 4-way, v) 0x4 - 0x7: Reserved.
0267      */
0268 
0269     move    a0, t0
0270 
0271     srl a0, a0, DA_SHIFT
0272     and a0, a0, DA_MASK
0273     addi    a0, a0, 0x1
0274 
0275     /* v0 has the set size, multiply it by
0276      * set associativiy, to get the cache size
0277      */
0278 
0279     multu   v0, a0  /*multu is interlocked, so no need to insert nops */
0280     mflo    v0
0281 
0282     b   1f
0283     nop
0284 
0285 no_d_cache:
0286     move    v0, zero
0287     move    v1, zero
0288 1:
0289     jr  ra
0290     nop
0291     .set    reorder
0292 
0293 END(size_d_cache)
0294 
0295 
0296 /*
0297  * Function: enable_ID
0298  * Arguments:   None
0299  * Returns: None
0300  * Description: Enable I and D caches, initialize I and D-caches, also set
0301  *      hardware delay for d-cache (TP0).
0302  * Trashes: t0
0303  *
0304  */
0305     .global enable_ID
0306     .ent    enable_ID
0307     .set    noreorder
0308 enable_ID:
0309     mfc0    t0, CP0_BRCM_CONFIG0
0310     or  t0, t0, (ICE_MASK | DCE_MASK)
0311     mtc0    t0, CP0_BRCM_CONFIG0
0312     jr  ra
0313     nop
0314 
0315     .end    enable_ID
0316     .set    reorder
0317 
0318 
0319 /*
0320  * Function: l1_init
0321  * Arguments:   None
0322  * Returns: None
0323  * Description: Enable I and D caches, and initialize I and D-caches
0324  * Trashes: a0, v0, v1, t0, t1, t2, t8
0325  *
0326  */
0327     .globl  l1_init
0328     .ent    l1_init
0329     .set    noreorder
0330 l1_init:
0331 
0332     /* save return address */
0333     move    t8, ra
0334 
0335 
0336     /* initialize I and D cache Data and Tag registers.  */
0337     mtc0    zero, CP0_ICACHE_TAG_LO
0338     mtc0    zero, CP0_ICACHE_TAG_HI
0339     mtc0    zero, CP0_ICACHE_DATA_LO
0340     mtc0    zero, CP0_ICACHE_DATA_HI
0341     mtc0    zero, CP0_DCACHE_TAG_LO
0342     mtc0    zero, CP0_DCACHE_TAG_HI
0343 
0344     /* Enable Caches before Clearing. If the caches are disabled
0345      * then the cache operations to clear the cache will be ignored
0346      */
0347 
0348     jal enable_ID
0349     nop
0350 
0351     jal size_i_cache    /* v0 = i-cache size, v1 = i-cache line size */
0352     nop
0353 
0354     /* run uncached in kseg 1 */
0355     la  k0, 1f
0356     lui k1, 0x2000
0357     or  k0, k1, k0
0358     jr  k0
0359     nop
0360 1:
0361 
0362     /*
0363      * set K0 cache mode
0364      */
0365 
0366     mfc0    t0, CP0_CONFIG
0367     and t0, t0, ~CP0_CONFIG_K0_MASK
0368     or  t0, t0, 3   /* Write Back mode */
0369     mtc0    t0, CP0_CONFIG
0370 
0371     /*
0372      * Initialize instruction cache.
0373      */
0374 
0375     li  a0, KSEG0
0376     cacheop(a0, v0, v1, Index_Store_Tag_I)
0377 
0378     /*
0379      * Now we can run from I-$, kseg 0
0380      */
0381     la  k0, 1f
0382     lui k1, 0x2000
0383     or  k0, k1, k0
0384     xor k0, k1, k0
0385     jr  k0
0386     nop
0387 1:
0388     /*
0389      * Initialize data cache.
0390      */
0391 
0392     jal size_d_cache    /* v0 = d-cache size, v1 = d-cache line size */
0393     nop
0394 
0395 
0396     li  a0, KSEG0
0397     cacheop(a0, v0, v1, Index_Store_Tag_D)
0398 
0399     jr  t8
0400     nop
0401 
0402     .end    l1_init
0403     .set    reorder
0404 
0405 
0406 /*
0407  * Function:    set_other_config
0408  * Arguments:   none
0409  * Returns: None
0410  * Description: initialize other remainder configuration to defaults.
0411  * Trashes: t0, t1
0412  *
0413  *  pseudo code:
0414  *
0415  */
0416 LEAF(set_other_config)
0417     .set noreorder
0418 
0419     /* enable Bus error for I-fetch */
0420     mfc0    t0, CP0_CACHEERR, 0
0421     li  t1, 0x4
0422     or  t0, t1
0423     mtc0    t0, CP0_CACHEERR, 0
0424 
0425     /* enable Bus error for Load */
0426     mfc0    t0, CP0_CACHEERR, 1
0427     li  t1, 0x4
0428     or  t0, t1
0429     mtc0    t0, CP0_CACHEERR, 1
0430 
0431     /* enable Bus Error for Store */
0432     mfc0    t0, CP0_CACHEERR, 2
0433     li  t1, 0x4
0434     or  t0, t1
0435     mtc0    t0, CP0_CACHEERR, 2
0436 
0437     jr  ra
0438     nop
0439     .set reorder
0440 END(set_other_config)
0441 
0442 /*
0443  * Function:    set_branch_pred
0444  * Arguments:   none
0445  * Returns: None
0446  * Description:
0447  * Trashes: t0, t1
0448  *
0449  *  pseudo code:
0450  *
0451  */
0452 
0453 LEAF(set_branch_pred)
0454     .set noreorder
0455     mfc0    t0, CP0_BRCM_MODE
0456     li  t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK )
0457     and t0, t0, t1
0458 
0459     /* enable Branch prediction */
0460     li  t1, BRCM_BrPRED_BHT_ENABLE
0461     sll t1, CP0_BRCM_MODE_BrPRED_SHIFT
0462     or  t0, t0, t1
0463 
0464     /* set history count to 8 */
0465     li  t1, 8
0466     sll t1, CP0_BRCM_MODE_BrHIST_SHIFT
0467     or  t0, t0, t1
0468 
0469     mtc0    t0, CP0_BRCM_MODE
0470     jr  ra
0471     nop
0472     .set    reorder
0473 END(set_branch_pred)
0474 
0475 
0476 /*
0477  * Function:    set_luc
0478  * Arguments:   set link uncached.
0479  * Returns: None
0480  * Description:
0481  * Trashes: t0, t1
0482  *
0483  */
0484 LEAF(set_luc)
0485     .set noreorder
0486     mfc0    t0, CP0_BRCM_MODE
0487     li  t1, ~(CP0_BRCM_MODE_Luc_MASK)
0488     and t0, t0, t1
0489 
0490     /* set Luc */
0491     ori t0, t0, CP0_BRCM_MODE_Luc_MASK
0492 
0493     mtc0    t0, CP0_BRCM_MODE
0494     jr  ra
0495     nop
0496     .set    reorder
0497 END(set_luc)
0498 
0499 /*
0500  * Function:    set_cwf_tse
0501  * Arguments:   set CWF and TSE bits
0502  * Returns: None
0503  * Description:
0504  * Trashes: t0, t1
0505  *
0506  */
0507 LEAF(set_cwf_tse)
0508     .set noreorder
0509     mfc0    t0, CP0_BRCM_CONFIG0
0510     li  t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK)
0511     or  t0, t0, t1
0512 
0513     mtc0    t0, CP0_BRCM_CONFIG0
0514     jr  ra
0515     nop
0516     .set    reorder
0517 END(set_cwf_tse)
0518 
0519 /*
0520  * Function:    set_clock_ratio
0521  * Arguments:   set clock ratio specified by a0
0522  * Returns: None
0523  * Description:
0524  * Trashes: v0, v1, a0, a1
0525  *
0526  *  pseudo code:
0527  *
0528  */
0529 LEAF(set_clock_ratio)
0530     .set noreorder
0531 
0532     mfc0    t0, CP0_BRCM_MODE
0533     li  t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK)
0534     and t0, t0, t1
0535     li  t1, CP0_BRCM_MODE_SET_MASK
0536     or  t0, t0, t1
0537     or  t0, t0, a0
0538     mtc0    t0, CP0_BRCM_MODE
0539     jr  ra
0540     nop
0541     .set    reorder
0542 END(set_clock_ratio)
0543 /*
0544  * Function: set_zephyr
0545  * Arguments:   None
0546  * Returns: None
0547  * Description: Set any zephyr bits
0548  * Trashes: t0 & t1
0549  *
0550  */
0551 LEAF(set_zephyr)
0552     .set    noreorder
0553 
0554     /* enable read/write of CP0 #22 sel. 8 */
0555     li  t0, 0x5a455048
0556     .word   0x4088b00f  /* mtc0    t0, $22, 15 */
0557 
0558     .word   0x4008b008  /* mfc0    t0, $22, 8 */
0559     li  t1, 0x09008000  /* turn off pref, jtb */
0560     or  t0, t0, t1
0561     .word   0x4088b008  /* mtc0    t0, $22, 8 */
0562     sync
0563 
0564     /* disable read/write of CP0 #22 sel 8 */
0565     li  t0, 0x0
0566     .word   0x4088b00f  /* mtc0    t0, $22, 15 */
0567 
0568 
0569     jr  ra
0570     nop
0571     .set reorder
0572 
0573 END(set_zephyr)
0574 
0575 
0576 /*
0577  * Function:    set_llmb
0578  * Arguments:   a0=0 disable llmb, a0=1 enables llmb
0579  * Returns: None
0580  * Description:
0581  * Trashes: t0, t1, t2
0582  *
0583  *      pseudo code:
0584  *
0585  */
0586 LEAF(set_llmb)
0587     .set noreorder
0588 
0589     li  t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG
0590     sync
0591     cache   0x7, 0x0(t2)
0592     sync
0593     mfc0    t0, CP0_D_SEC_CACHE_DATA_LO
0594     li  t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
0595     and t0, t0, t1
0596 
0597     beqz    a0, svlmb
0598     nop
0599 
0600 enable_lmb:
0601     li  t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
0602     or  t0, t0, t1
0603 
0604 svlmb:
0605     mtc0    t0, CP0_D_SEC_CACHE_DATA_LO
0606     sync
0607     cache   0xb, 0x0(t2)
0608     sync
0609 
0610     jr  ra
0611     nop
0612     .set reorder
0613 
0614 END(set_llmb)
0615 /*
0616  * Function:    core_init
0617  * Arguments:   none
0618  * Returns: None
0619  * Description: initialize core related configuration
0620  * Trashes: v0,v1,a0,a1,t8
0621  *
0622  *  pseudo code:
0623  *
0624  */
0625     .globl  core_init
0626     .ent    core_init
0627     .set    noreorder
0628 core_init:
0629     move    t8, ra
0630 
0631     /* set Zephyr bits. */
0632     bal set_zephyr
0633     nop
0634 
0635     /* set low latency memory bus */
0636     li  a0, 1
0637     bal set_llmb
0638     nop
0639 
0640     /* set branch prediction (TP0 only) */
0641     bal set_branch_pred
0642     nop
0643 
0644     /* set link uncached */
0645     bal set_luc
0646     nop
0647 
0648     /* set CWF and TSE */
0649     bal set_cwf_tse
0650     nop
0651 
0652     /*
0653      *set clock ratio by setting 1 to 'set'
0654      * and 0 to ClkRatio, (TP0 only)
0655      */
0656     li  a0, 0
0657     bal set_clock_ratio
0658     nop
0659 
0660     /* set other configuration to defaults */
0661     bal set_other_config
0662     nop
0663 
0664     move    ra, t8
0665     jr  ra
0666     nop
0667 
0668     .set reorder
0669     .end    core_init
0670 
0671 /*
0672  * Function:    clear_jump_target_buffer
0673  * Arguments:   None
0674  * Returns: None
0675  * Description:
0676  * Trashes: t0, t1, t2
0677  *
0678  */
0679 #define RESET_CALL_RETURN_STACK_THIS_THREAD     (0x06<<16)
0680 #define RESET_JUMP_TARGET_BUFFER_THIS_THREAD        (0x04<<16)
0681 #define JTB_CS_CNTL_MASK                (0xFF<<16)
0682 
0683     .globl  clear_jump_target_buffer
0684     .ent    clear_jump_target_buffer
0685     .set    noreorder
0686 clear_jump_target_buffer:
0687 
0688     mfc0    t0, $22, 2
0689     nop
0690     nop
0691 
0692     li  t1, ~JTB_CS_CNTL_MASK
0693     and t0, t0, t1
0694     li  t2, RESET_CALL_RETURN_STACK_THIS_THREAD
0695     or  t0, t0, t2
0696     mtc0    t0, $22, 2
0697     nop
0698     nop
0699 
0700     and t0, t0, t1
0701     li  t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD
0702     or  t0, t0, t2
0703     mtc0    t0, $22, 2
0704     nop
0705     nop
0706     jr  ra
0707     nop
0708 
0709     .end    clear_jump_target_buffer
0710     .set    reorder
0711 /*
0712  * Function:    bmips_cache_init
0713  * Arguments:   None
0714  * Returns: None
0715  * Description: Enable I and D caches, and initialize I and D-caches
0716  * Trashes: v0, v1, t0, t1, t2, t5, t7, t8
0717  *
0718  */
0719     .globl  bmips_5xxx_init
0720     .ent    bmips_5xxx_init
0721     .set    noreorder
0722 bmips_5xxx_init:
0723 
0724     /* save return address and A0 */
0725     move    t7, ra
0726     move    t5, a0
0727 
0728     jal l1_init
0729     nop
0730 
0731     jal core_init
0732     nop
0733 
0734     jal clear_jump_target_buffer
0735     nop
0736 
0737     mtc0    zero, CP0_CAUSE
0738 
0739     move    a0, t5
0740     jr  t7
0741     nop
0742 
0743     .end    bmips_5xxx_init
0744     .set    reorder
0745 
0746 
0747 #endif