/****************************************************************************
* arch/mips/src/mips32/mips_cache.S
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/cache.h>
#include <arch/mips32/registers.h>
#include <arch/mips32/cp0.h>
#include "mips_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Cache algorithm.
* When the cache is enabled the write-back write-allocate algorithm is used.
*/
#define CACHE_ENABLE CP0_CONFIG_K0_CACHEABLE
#define CACHE_DISABLE CP0_CONFIG_K0_UNCACHED
/* Cache Operations ********************************************************/
#define INDEX_INVALIDATE_I 0x00
#define INDEX_INVALIDATE_D 0x01
#define INDEX_STORE_TAG_I 0x08
#define INDEX_STORE_TAG_D 0x09
#define HIT_INVALIDATE_I 0x10
#define HIT_INVALIDATE_D 0x11
#define HIT_WRITEBACK_D 0x15
/****************************************************************************
* Public Symbols
****************************************************************************/
.file "mips_cache.S"
/****************************************************************************
* Assembly Language Macros
****************************************************************************/
/****************************************************************************
* Name: CACHE_OP
* Description:
* Performs cache operation on an address range.
*
****************************************************************************/
.macro CACHE_OP op, start, end, lsize
1:
cache \op, 0(\start)
addu \start, \start, \lsize
bne \start, \end, 1b
.endm
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: icache_linesize
*
* Description:
* Get I-Cache line size.
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = Size of I-Cache line
*
****************************************************************************/
.text
.set nomips16
.globl icache_linesize
.ent icache_linesize
icache_linesize:
#ifndef CONFIG_MIPS32_CACHE_AUTOINFO
li v0, CONFIG_MIPS32_ILINE_SIZE
#else
li v0, 0
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get the I-Cache line size */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_IL_MASK
beqz t1, 1f /* No I-Cache implemented, leave. */
srl t1, t1, CP0_CONFIG1_IL_SHIFT
li t2, 2
srl v0, t2, t1 /* Cache line size = 2 << IL_VALUE */
#endif
1:
jr ra
nop
.size icache_linesize,.-icache_linesize
.end icache_linesize
/****************************************************************************
* Name: icache_associativity
*
* Description:
* Get I-Cache associativity
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = I-Cache associativity.
*
****************************************************************************/
.text
.set nomips16
.globl icache_associativity
.ent icache_associativity
icache_associativity:
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get I-Cache associativity. */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_IA_MASK
srl t1, t1, CP0_CONFIG1_IA_SHIFT
addu v0, t1, 1 /* Cache associativity = IA_VALUE + 1 */
1:
jr ra
nop
.size icache_associativity,.-icache_associativity
.end icache_associativity
/****************************************************************************
* Name: icache_sets
*
* Description:
* Get I-Cache sets
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = I-Cache sets.
*
****************************************************************************/
.text
.set nomips16
.globl icache_sets
.ent icache_sets
icache_sets:
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get I-Cache sets. */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_IS_MASK
srl t1, t1, CP0_CONFIG1_IS_SHIFT
addu t1, 6 /* Cache sets = 1 << IS_VALUE + 6 */
li t2, 1
sll v0, t2, t1
1:
jr ra
nop
.size icache_sets,.-icache_sets
.end icache_sets
/****************************************************************************
* Name: icache_size
*
* Description:
* Get I-Cache size.
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = Size of I-Cache.
*
****************************************************************************/
.text
.set nomips16
.globl icache_size
.ent icache_size
icache_size:
#ifndef CONFIG_MIPS32_CACHE_AUTOINFO
li v0, CONFIG_MIPS32_ICACHE_SIZE
#else
addiu sp, sp, -16
sw s0, 0(sp)
sw s1, 4(sp)
sw s2, 8(sp)
sw ra, 12(sp)
/* Get I-Cache line size */
jal icache_linesize
nop
move s0, v0
/* Get I-Cache associativity */
jal icache_associativity
nop
move s1, v0
/* Get I-Cache sets per way */
jal icache_sets
nop
move s2, v0
/* Cache size = line size * associativity * sets per way */
multu s0, s1
mflo t0
multu s2, t0
mflo v0
lw s0, 0(sp)
lw s1, 4(sp)
lw s2, 8(sp)
lw ra, 12(sp)
addiu sp, sp, 16
#endif
1:
jr ra
nop
.size icache_size,.-icache_size
.end icache_size
/****************************************************************************
* Name: dcache_linesize
*
* Description:
* Get D-Cache line size.
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = Size of D-Cache line
*
****************************************************************************/
.text
.set nomips16
.globl dcache_linesize
.ent dcache_linesize
dcache_linesize:
#ifndef CONFIG_MIPS32_CACHE_AUTOINFO
li v0, CONFIG_MIPS32_DLINE_SIZE
#else
li v0, 0
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get D-Cache line size */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_DL_MASK
beqz t1, 1f /* No D-Cache implemented, leave. */
srl t1, t1, CP0_CONFIG1_DL_SHIFT
li t2, 2
srl v0, t2, t1 /* Cache line size = 2 << DL_VALUE */
#endif
1:
jr ra
nop
.size dcache_linesize,.-dcache_linesize
.end dcache_linesize
/****************************************************************************
* Name: dcache_associativity
*
* Description:
* Get D-Cache associativity
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = D-Cache associativity.
*
****************************************************************************/
.text
.set nomips16
.globl dcache_associativity
.ent dcache_associativity
dcache_associativity:
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get D-Cache associativity. */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_DA_MASK
srl t1, t1, CP0_CONFIG1_DA_SHIFT
addu v0, t1, 1 /* Cache associativity = DA_VALUE + 1 */
1:
jr ra
nop
.size dcache_associativity,.-dcache_associativity
.end dcache_associativity
/****************************************************************************
* Name: dcache_sets
*
* Description:
* Get D-Cache sets
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = D-Cache sets.
*
****************************************************************************/
.text
.set nomips16
.globl dcache_sets
.ent dcache_sets
dcache_sets:
/* Is a cache implemented? */
mfc0 t0, MIPS32_CP0_CONFIG
and t1, t0, CP0_CONFIG_M_MASK
beqz t1, 1f /* No cache implemented, leave. */
/* Get D-Cache sets. */
mfc0 t0, MIPS32_CP0_CONFIG1
and t1, t0, CP0_CONFIG1_DS_MASK
srl t1, t1, CP0_CONFIG1_DS_SHIFT
addu t1, 6 /* Cache sets = 1 << DS_VALUE + 6 */
li t2, 1
sll v0, t2, t1
1:
jr ra
nop
.size dcache_sets,.-dcache_sets
.end dcache_sets
/****************************************************************************
* Name: dcache_size
*
* Description:
* Get D-Cache size.
*
* Input Parameters:
* None
*
* Returned Value:
* V0 = Size of D-Cache.
*
****************************************************************************/
.text
.set nomips16
.globl dcache_size
.ent dcache_size
dcache_size:
#ifndef CONFIG_MIPS32_CACHE_AUTOINFO
li v0, CONFIG_MIPS32_DCACHE_SIZE
#else
addiu sp, sp, -16
sw s0, 0(sp)
sw s1, 4(sp)
sw s2, 8(sp)
sw ra, 12(sp)
/* Get D-Cache line size */
jal dcache_linesize
nop
move s0, v0
/* Get D-Cache associativity */
jal dcache_associativity
nop
move s1, v0
/* Get D-Cache sets per way */
jal dcache_sets
nop
move s2, v0
/* Cache size = line size * associativity * sets per way */
multu s0, s1
mflo t0
multu s2, t0
mflo v0
lw s0, 0(sp)
lw s1, 4(sp)
lw s2, 8(sp)
lw ra, 12(sp)
addiu sp, sp, 16
#endif
1:
jr ra
nop
.size dcache_size,.-dcache_size
.end dcache_size
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_enable_icache
*
* Description:
* Enable the I-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Caution:
* The writable global variables aren't initialized yet.
*
****************************************************************************/
#ifdef CONFIG_MIPS32_ICACHE
.text
.set nomips16
.globl up_enable_icache
.ent up_enable_icache
up_enable_icache:
/* Disable interrupts */
di
/* Enable both I & D Caches */
mfc0 t1, MIPS32_CP0_CONFIG
ori t1, CP0_CONFIG_K0_MASK
xori t1, CP0_CONFIG_K0_MASK
ori t1, CACHE_ENABLE
mtc0 t1, MIPS32_CP0_CONFIG
/* Restore interrupts */
ei
jr ra
nop
.size up_enable_icache,.-up_enable_icache
.end up_enable_icache
#endif
/****************************************************************************
* Name: up_disable_icache
*
* Description:
* Disable the I-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_ICACHE
.text
.set nomips16
.globl up_disable_icache
.ent up_disable_icache
up_disable_icache:
/* Disable interrupts */
di
/* Disable both I & D Caches */
mfc0 t1, MIPS32_CP0_CONFIG
ori t1, CP0_CONFIG_K0_MASK
xori t1, CP0_CONFIG_K0_MASK
ori t1, CACHE_DISABLE
mtc0 t1, MIPS32_CP0_CONFIG
/* Restore interrupts */
ei
jr ra
nop
.size up_disable_icache,.-up_disable_icache
.end up_disable_icache
#endif
/****************************************************************************
* Name: up_invalidate_icache
*
* Description:
* Invalidate the instruction cache within the specified region.
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_ICACHE
.text
.set nomips16
.globl up_invalidate_icache
.ent up_invalidate_icache
up_invalidate_icache:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get I-Cache line size */
jal icache_linesize
nop
move t2, v0
beqz t2, 1f /* No I-Cache, nothing to do here. */
/* Align start and end addresses to cache line size */
.set noreorder
subu t3, t2, 1
not t3
and t0, a0, t3
subu t1, a1, 1
and t1, t1, t3
/* Perform the cache operation */
CACHE_OP HIT_INVALIDATE_I, t0, t1, t2
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_invalidate_icache,.-up_invalidate_icache
.end up_invalidate_icache
#endif
/****************************************************************************
* Name: up_invalidate_icache_all
*
* Description:
* Invalidate the entire contents of I cache.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_ICACHE
.text
.set nomips16
.globl up_invalidate_icache_all
.ent up_invalidate_icache_all
up_invalidate_icache_all:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get I-Cache size */
jal icache_size
nop
move t0, v0
beqz t0, 1f /* No I-Cache, nothing to do here. */
/* Get I-Cache line size */
jal icache_linesize
nop
move t1, v0
beqz t1, 1f /* No I-Cache, nothing to do here. */
/* Start address is IBASE, end address is IBASE + Cache Size */
.set noreorder
li t3, CONFIG_MIPS32_KSEG0_IBASE
addu t4, t3, t0
/* Perform the cache operation */
CACHE_OP HIT_INVALIDATE_I, t3, t4, t1
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_invalidate_icache_all,.-up_invalidate_icache_all
.end up_invalidate_icache_all
#endif
/****************************************************************************
* Name: up_enable_dcache
*
* Description:
* Enable the D-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Caution:
* The writable global variables aren't initialized yet.
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_enable_dcache
.ent up_enable_dcache
up_enable_dcache:
/* Disable interrupts */
di
.set noreorder
/* Enable both I & D Caches */
mfc0 t1, MIPS32_CP0_CONFIG
ori t1, CP0_CONFIG_K0_MASK
xori t1, CP0_CONFIG_K0_MASK
ori t1, CACHE_ENABLE
mtc0 t1, MIPS32_CP0_CONFIG
/* Restore interrupts */
.set reorder
ei
jr ra
nop
.size up_enable_dcache,.-up_enable_dcache
.end up_enable_dcache
#endif
/****************************************************************************
* Name: up_disable_dcache
*
* Description:
* Disable the D-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_disable_dcache
.ent up_disable_dcache
up_disable_dcache:
/* Disable interrupts */
di
.set noreorder
/* Disable both I & D Caches */
mfc0 t1, MIPS32_CP0_CONFIG
ori t1, CP0_CONFIG_K0_MASK
xori t1, CP0_CONFIG_K0_MASK
ori t1, CACHE_DISABLE
mtc0 t1, MIPS32_CP0_CONFIG
/* Restore interrupts */
.set reorder
ei
jr ra
nop
.size up_disable_dcache,.-up_disable_dcache
.end up_disable_dcache
#endif
/****************************************************************************
* Name: up_invalidate_dcache
*
* Description:
* Invalidate the data cache within the specified region; we will be
* performing a DMA operation in this region and we want to purge old data
* in the cache.
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_invalidate_dcache
.ent up_invalidate_dcache
up_invalidate_dcache:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache line size */
jal dcache_linesize
nop
move t2, v0
beqz t2, 1f /* No D-Cache, nothing to do here. */
/* Align start and end addresses to cache line size */
.set noreorder
subu t3, t2, 1
not t3
and t0, a0, t3
subu t1, a1, 1
and t1, t1, t3
/* Perform the cache operation */
CACHE_OP HIT_INVALIDATE_D, t0, t1, t2
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0( sp)
addiu sp, sp, 8
jr ra
nop
.size up_invalidate_dcache,.-up_invalidate_dcache
.end up_invalidate_dcache
#endif
/****************************************************************************
* Name: up_invalidate_dcache_all
*
* Description:
* Invalidate the entire contents of D cache.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_invalidate_dcache_all
.ent up_invalidate_dcache_all
up_invalidate_dcache_all:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache size */
jal dcache_size
nop
move t0, v0
beqz t0, 1f /* No D-Cache, nothing to do here. */
/* Get D-Cache line size */
jal dcache_linesize
nop
move t1, v0
beqz t1, 1f /* No D-Cache, nothing to do here. */
/* Start address is DBASE, end address is DBASE + Cache Size */
.set noreorder
li t3, CONFIG_MIPS32_KSEG0_DBASE
addu t4, t3, t0
/* Perform the cache operation */
CACHE_OP HIT_INVALIDATE_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_invalidate_dcache_all,.-up_invalidate_dcache_all
.end up_invalidate_dcache_all
#endif
/****************************************************************************
* Name: up_clean_dcache
*
* Description:
* Clean the data cache within the specified region by flushing the
* contents of the data cache to memory.
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_clean_dcache
.ent up_clean_dcache
up_clean_dcache:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache line size */
jal dcache_linesize
nop
move t2, v0
beqz t2, 1f /* No D-Cache, nothing to do here. */
/* Align start and end addresses to cache size */
.set noreorder
subu t3, t2, 1
not t3
and t0, a0, t3
subu t1, a1, 1
and t1, t1, t3
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t0, t1, t2
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0( sp)
addiu sp, sp, 8
jr ra
nop
.size up_clean_dcache,.-up_clean_dcache
.end up_clean_dcache
#endif
/****************************************************************************
* Name: up_clean_dcache_all
*
* Description:
* Clean the entire data cache within the specified region by flushing the
* contents of the data cache to memory.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_clean_dcache_all
.ent up_clean_dcache_all
up_clean_dcache_all:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache size */
jal dcache_size
nop
move t0, v0
beqz t0, 1f /* No D-Cache, nothing to do here. */
/* Get D-Cache line size */
jal dcache_linesize
nop
move t1, v0
beqz t1, 1f /* No D-Cache, nothing to do here. */
/* Start address is DBASE, end address is DBASE + Cache Size */
.set noreorder
li t3, CONFIG_MIPS32_KSEG0_DBASE
addu t4, t3, t0
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_clean_dcache_all,.-up_clean_dcache_all
.end up_clean_dcache_all
#endif
/****************************************************************************
* Name: up_flush_dcache
*
* Description:
* Flush the data cache within the specified region by cleaning and
* invalidating the D cache.
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_flush_dcache
.ent up_flush_dcache
up_flush_dcache:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache line size */
jal dcache_linesize
nop
move t2, v0
beqz t2, 1f /* No D-Cache, nothing to do here. */
/* Align start and end addresses to cache size */
.set noreorder
subu t3, t2, 1
not t3
and t0, a0, t3
subu t1, a1, 1
and t1, t1, t3
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t0, t1, t2
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_flush_dcache,.-up_flush_dcache
.end up_flush_dcache
#endif
/****************************************************************************
* Name: up_flush_dcache_all
*
* Description:
* Flush the entire data cache by cleaning and invalidating the D cache.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_flush_dcache_all
.ent up_flush_dcache_all
up_flush_dcache_all:
addiu sp, sp, -8
sw ra, 0(sp)
/* Get D-Cache size */
jal dcache_size
nop
move t0, v0
beqz t0, 1f /* No D-Cache, nothing to do here. */
/* Get D-Cache line size */
jal dcache_linesize
nop
move t1, v0
beqz t1, 1f /* No D-Cache, nothing to do here. */
/* Start address is DBASE, end address is DBASE + Cache Size */
.set noreorder
li t3, CONFIG_MIPS32_KSEG0_DBASE
addu t4, t3, t0
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
sync
1:
.set reorder
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_flush_dcache_all,.-up_flush_dcache_all
.end up_flush_dcache_all
#endif
/****************************************************************************
* Name: up_coherent_dcache
*
* Description:
* Ensure that the I and D caches are coherent within specified region
* by cleaning the D cache (i.e., flushing the D cache contents to memory
* and invalidating the I cache. This is typically used when code has been
* written to a memory region, and will be executed.
*
* Input Parameters:
* addr - virtual start address of region
* len - Size of the address region in bytes
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_MIPS32_DCACHE
.text
.set nomips16
.globl up_coherent_dcache
.ent up_coherent_dcache
up_coherent_dcache:
addiu sp, sp, -8
sw ra, 0(sp)
/* If size is null, nothing to do here. */
beqz a1, 1f
/* End address = addr + len*/
addu a1, a0
/* Flush any dirty D-Cache lines */
jal up_flush_dcache
nop
/* Invalidate the entire I-Cache */
jal up_invalidate_icache_all
nop
1:
lw ra, 0(sp)
addiu sp, sp, 8
jr ra
nop
.size up_coherent_dcache,.-up_coherent_dcache
.end up_coherent_dcache
#endif