blob: af7cd681a8cad3e4899f126186b1dcba68bf4617 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* Copyright (c) 2014, Microchip Technology Inc. and its subsidiaries ("Microchip")
* All rights reserved.
*
* This software is developed by Microchip Technology Inc. and its
* subsidiaries ("Microchip").
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. Microchip's name may not be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY MICROCHIP "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL MICROCHIP BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT LIMITED TO
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWSOEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*-------------------------------------------------------------------------*/
#include <xc.h>
#include <cp0defs.h>
/* Symbols defined in linker script */
.weak __pic32_init_cache_program_base_addr
.weak __pic32_init_cache_data_base_addr
/* Cache Coherency Attributes */
#define _CACHE_WRITEBACK_WRITEALLOCATE 3
#define _CACHE_WRITETHROUGH_WRITEALLOCATE 1
#define _CACHE_WRITETHROUGH_NOWRITEALLOCATE 0
#define _CACHE_DISABLE 2
#ifndef _CP0_ERRCTL
#define _CP0_ERRCTL $26, 0
#endif
#ifndef _CP0_TAGLO
#define _CP0_TAGLO $28, 0
#endif
/* Set __PIC32_CACHE_MODE to the desired coherency attribute */
#define __PIC32_CACHE_MODE _CACHE_WRITEBACK_WRITEALLOCATE
/* ==================================== */
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
#define tmp t0
#define cfg t1
#define icachesize t2
#define ilinesize t3
#define iways t4
#define dcachesize t5
#define dlinesize t6
#define dways t7
#define save_ra v1
#define INIT_L1_CACHE
#if defined(INIT_L1_CACHE)
.sdata; .globl __pic32_icache_size; .type __pic32_icache_size,@object; .size __pic32_icache_size,4; __pic32_icache_size:; .word -1
.sdata; .globl __pic32_icache_linesize; .type __pic32_icache_linesize,@object; .size __pic32_icache_linesize,4; __pic32_icache_linesize:; .word -1
.sdata; .globl __pic32_icache_ways; .type __pic32_icache_ways,@object; .size __pic32_icache_ways,4; __pic32_icache_ways:; .word 1
.sdata; .globl __pic32_dcache_size; .type __pic32_dcache_size,@object; .size __pic32_dcache_size,4; __pic32_dcache_size:; .word -1
.sdata; .globl __pic32_dcache_linesize; .type __pic32_dcache_linesize,@object; .size __pic32_dcache_linesize,4; __pic32_dcache_linesize:; .word -1
.sdata; .globl __pic32_dcache_ways; .type __pic32_dcache_ways,@object; .size __pic32_dcache_ways,4; __pic32_dcache_ways:; .word 1
.sdata; .globl __pic32_scache_size; .type __pic32_scache_size,@object; .size __pic32_scache_size,4; __pic32_scache_size:; .word -1
.sdata; .globl __pic32_scache_linesize; .type __pic32_scache_linesize,@object; .size __pic32_scache_linesize,4; __pic32_scache_linesize:; .word -1
.sdata; .globl __pic32_scache_ways; .type __pic32_scache_ways,@object; .size __pic32_scache_ways,4; __pic32_scache_ways:; .word 1
.section .cache_init.cache, code
.set nomips16
.ent __size_cache; __size_cache:
mfc0 cfg,_CP0_CONFIG
li icachesize,0
li ilinesize,0
li dcachesize,0
li dlinesize,0
/* Check that we have Config1 */
and tmp,cfg,_CP0_CONFIG_M_MASK
mfc0 cfg,_CP0_CONFIG1
beqz tmp,9f
nop
/* Get icache line size (log2) */
and tmp,cfg,_CP0_CONFIG1_IL_MASK
srl tmp,_CP0_CONFIG1_IL_POSITION
beqz tmp,8f # no i-cache
addu tmp,1
/* Get number of icache ways */
and iways,cfg,_CP0_CONFIG1_IA_MASK
srl iways,_CP0_CONFIG1_IA_POSITION
addu iways,1
move icachesize,iways
/* total icache size = lines/way * linesize *ways */
li ilinesize,1
sll ilinesize,tmp
sll icachesize,tmp
/* get icache lines per way */
and tmp,cfg,_CP0_CONFIG1_IS_MASK
srl tmp,_CP0_CONFIG1_IS_POSITION
addu tmp,6
sll icachesize,tmp
/* Get dcache line size (log2) */
8: and tmp,cfg,_CP0_CONFIG1_DL_MASK
srl tmp,_CP0_CONFIG1_DL_POSITION
beqz tmp,8f # no d-cache
addu tmp,1
/* Get number of dcache ways */
and dways,cfg,_CP0_CONFIG1_DA_MASK
srl dways,_CP0_CONFIG1_DA_POSITION
addu dways,1
move dcachesize,dways
/* Total dcache size = lines/way * linesize * ways */
li dlinesize,1
sll dlinesize,tmp
sll dcachesize,tmp
and tmp,cfg,_CP0_CONFIG1_DS_MASK
srl tmp,_CP0_CONFIG1_DS_POSITION
addu tmp,6
sll dcachesize,tmp
#undef cfg
#undef tmp
8:
9: j ra
nop
.size __size_cache,.-__size_cache; .end __size_cache;
/*
* void __pic32_size_cache()
*
* Work out size of I & D caches (assume already initialized)
*/
.section .cache_init.pic32_size_cache, code
.set nomips16
.globl __pic32_size_cache; .ent __pic32_size_cache;
__pic32_size_cache:
lw t0,__pic32_icache_size
move a3,ra
bgtz t0,8f # already known?
bal __size_cache
move ra,a3
..savesize:
sw icachesize,__pic32_icache_size
sw dcachesize,__pic32_dcache_size
sw ilinesize,__pic32_icache_linesize
sw dlinesize,__pic32_dcache_linesize
sw iways,__pic32_icache_ways
sw dways,__pic32_dcache_ways
8: j ra
nop
.size __pic32_size_cache,.-__pic32_size_cache; .end __pic32_size_cache
/*
* void __pic32_init_cache()
*
* Work out size and initialize I & D caches.
*/
.section .cache_init.pic32_init_cache, code
.set nomips16
.globl __pic32_init_cache; .ent __pic32_init_cache;
__pic32_init_cache:
move save_ra,ra
bal __size_cache
/* Run uncached */
.set noreorder
.set nomacro
#if 0
bal 1f
#
li cfg,0xa0000000
1: or cfg,ra
addu cfg,16
jr cfg
move ra,v1
#endif
/*
* The caches may be in an indeterminate state, so we force an
* invalidate, load/fill, and invalidate for each line.
*/
/* Disable all i/u and cache exceptions */
.set macro
.set noreorder
# Disable interrupts and set UM=1
# Save current status in tmp
mfc0 t0,_CP0_STATUS
li t1,~_CP0_STATUS_IE_MASK
and t1,t0
or t1,_CP0_STATUS_ERL_MASK
mtc0 t1,_CP0_STATUS
ehb
mtc0 zero,_CP0_ERRCTL
mtc0 zero,_CP0_TAGLO # 4K taglo / 2*K itaglo
ehb
/* Initialize primary instruction cache */
.set noreorder
4: la a0,__pic32_init_cache_program_base_addr
bne a0,zero,0f
/* Use a default if the symbol is not defined */
li a0,0x9D000000 /* KSEG0_PROGRAM_BASE */
0: beqz icachesize,8f # icachesize
addu a1,a0,icachesize # limit = base + icachesize
1: addu a0,ilinesize # line size
bne a0,a1,1b
cache Index_Store_Tag_I,-4(a0) # BDSLOT: clear tag
/* Initialize primary data cache */
.set noreorder
8: la a0,__pic32_init_cache_data_base_addr
bne a0,zero,0f
/* Use a default if the symbol is not defined */
li a0,0x80000000 /* KSEG_DATA_BASE */
0: beqz dcachesize,8f
addu a1,a0,dcachesize # limit = base + dcachesize
1: addu a0,dlinesize
bne a0,a1,1b
cache Index_Store_Tag_D,-4(a0) # BDSLOT: clear tag
.set reorder
8: sync
/* Store the sizes only after the caches are initialized */
4: sw icachesize,__pic32_icache_size
sw dcachesize,__pic32_dcache_size
sw ilinesize,__pic32_icache_linesize
sw dlinesize,__pic32_dcache_linesize
sw iways,__pic32_icache_ways
sw dways,__pic32_dcache_ways
.set noreorder
# restore status
mtc0 t0,_CP0_STATUS
ehb
# Configure Cache Mode
mfc0 t1, _CP0_CONFIG
ori t1, _CP0_CONFIG_K0_MASK
xori t1, _CP0_CONFIG_K0_MASK
ori t1, __PIC32_CACHE_MODE
mtc0 t1, _CP0_CONFIG
ehb
.set reorder
move ra, save_ra
jr ra
nop
.size __pic32_init_cache,.-__pic32_init_cache; .end __pic32_init_cache;
#endif /* INIT_L1_CACHE */
#undef _CACHE_WRITEBACK_WRITEALLOCATE
#undef _CACHE_WRITETHROUGH_WRITEALLOCATE
#undef _CACHE_WRITETHROUGH_NOWRITEALLOCATE
#undef _CACHE_DISABLE
#undef _CP0_ERRCTL
#undef _CP0_TAGLO