arch/mips/jz4780: Add support for L2 cache operations

The common mips_cache.S only handles generic L1 cache operations and
does not support L2 (secondary) cache operations required for the
JZ4780 target.

This commit introduces mti_cache.S to support both L1 and L2 cache
operations.

The mti_cache.S implementation is BSD licensed from Imagination
Technologies.

Signed-off-by: Lwazi Dube <lwazeh@gmail.com>
This commit is contained in:
Lwazi Dube 2026-07-20 19:00:19 -04:00 committed by Xiang Xiao
parent c0e796e55d
commit 784035a3e9
10 changed files with 1213 additions and 19 deletions

View file

@ -34,12 +34,12 @@ config ARCH_CHIP_JZ4780
bool "JZ4780"
select ARCH_MIPS32
select ARCH_MIPS_XBURST1
select ARCH_DCACHE
select ARCH_ICACHE
select ARCH_HAVE_IRQPRIO
select ARCH_VECNOTIRQ
select ARCH_HAVE_RESET
select ARCH_HAVE_SERIAL_TERMIOS
select MIPS32_HAVE_DCACHE
select MIPS32_HAVE_ICACHE
select MIPS32_USE_WAIT_INSTRUCTION
select MIPS32_USE_SYSCALL_INSTRUCTION
---help---

View file

@ -26,7 +26,7 @@ HEAD_ASRC = jz4780_head.S
# Common MIPS files
CMN_ASRCS = mips_syscall0.S fork.S mips_cache.S
CMN_ASRCS = mips_syscall0.S fork.S
CMN_CSRCS += mips_allocateheap.c mips_copystate.c mips_createstack.c
CMN_CSRCS += mips_doirq.c mips_exit.c mips_getintstack.c mips_initialize.c
CMN_CSRCS += mips_initialstate.c mips_irq.c mips_lowputs.c
@ -44,6 +44,10 @@ endif
# Required JZ4780 files
CHIP_ASRCS =
ifeq ($(CONFIG_ALLOW_BSD_COMPONENTS),y)
CHIP_ASRCS = mti_cache.S
endif
CHIP_CSRCS = jz4780_lowinit.c jz4780_exception.c jz4780_decodeirq.c
CHIP_CSRCS += jz4780_irq.c jz4780_timerisr.c jz4780_gpio.c
CHIP_CSRCS += jz4780_cache.c

View file

@ -34,6 +34,8 @@
* Pre-processor Definitions
****************************************************************************/
#define JZ4780_DCACHE_LINESIZE 32
/****************************************************************************
* Public Types
****************************************************************************/

View file

@ -0,0 +1,442 @@
/****************************************************************************
* arch/mips/src/jz4780/jz4780_cache.c
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 <assert.h>
#include <stdint.h>
#include <nuttx/cache.h>
#include <nuttx/debug.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "jz4780_cache.h"
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_cache_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_ARCH_ICACHE
/****************************************************************************
* Name: up_get_icache_linesize
*
* Description:
* Get icache linesize
*
* Input Parameters:
* None
*
* Returned Value:
* Cache line size
*
****************************************************************************/
size_t up_get_icache_linesize(void)
{
return mips_icache_linesize;
}
/****************************************************************************
* Name: up_get_icache_size
*
* Description:
* Get icache size
*
* Input Parameters:
* None
*
* Returned Value:
* Cache size
*
****************************************************************************/
size_t up_get_icache_size(void)
{
return mips_icache_size;
}
/****************************************************************************
* Name: up_invalidate_icache_all
*
* Description:
* Invalidate all instruction caches to PoU, also flushes branch target
* cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_invalidate_icache_all(void)
{
}
/****************************************************************************
* Name: up_invalidate_icache
*
* Description:
* Validate the specified range instruction cache as PoU,
* and flush the branch target cache
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
void up_invalidate_icache(uintptr_t start, uintptr_t end)
{
}
/****************************************************************************
* Name: up_enable_icache
*
* Description:
* Enable the I-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_enable_icache(void)
{
}
/****************************************************************************
* Name: up_disable_icache
*
* Description:
* Disable the I-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_disable_icache(void)
{
}
#endif /* CONFIG_ARCH_ICACHE */
#ifdef CONFIG_ARCH_DCACHE
/****************************************************************************
* Name: up_get_dcache_linesize
*
* Description:
* Get dcache linesize
*
* Input Parameters:
* None
*
* Returned Value:
* Cache line size
*
****************************************************************************/
size_t up_get_dcache_linesize(void)
{
return mips_dcache_linesize;
}
/****************************************************************************
* Name: up_get_dcache_size
*
* Description:
* Get dcache size
*
* Input Parameters:
* None
*
* Returned Value:
* Cache size
*
****************************************************************************/
size_t up_get_dcache_size(void)
{
return mips_dcache_size;
}
/****************************************************************************
* 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
*
* Assumptions:
* This operation is not atomic. This function assumes that the caller
* has exclusive access to the address range so that no harm is done if
* the operation is preempted.
*
****************************************************************************/
void up_invalidate_dcache(uintptr_t start, uintptr_t end)
{
if (end > start)
{
if ((end - start) % mips_dcache_linesize == 0)
{
m32_dcache_invalidate(start, end - start);
}
else
{
m32_dcache_clean_invalidate(start, end - start);
}
}
}
/****************************************************************************
* Name: up_invalidate_dcache_all
*
* Description:
* Invalidate the entire contents of D cache.
*
* NOTE: This function forces L1 and L2 cache operations to be atomic
* by disabling interrupts.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_invalidate_dcache_all(void)
{
}
/****************************************************************************
* 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
*
* Assumptions:
* This operation is not atomic. This function assumes that the caller
* has exclusive access to the address range so that no harm is done if
* the operation is preempted.
*
****************************************************************************/
void up_clean_dcache(uintptr_t start, uintptr_t end)
{
if (end > start)
{
m32_dcache_clean(start, end - start);
}
}
/****************************************************************************
* 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.
*
* NOTE: This operation is un-necessary if the DCACHE is configured in
* write-through mode.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* This operation is not atomic. This function assumes that the caller
* has exclusive access to the address range so that no harm is done if
* the operation is preempted.
*
****************************************************************************/
void up_clean_dcache_all(void)
{
}
/****************************************************************************
* 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
*
* Assumptions:
* This operation is not atomic. This function assumes that the caller
* has exclusive access to the address range so that no harm is done if
* the operation is preempted.
*
****************************************************************************/
void up_flush_dcache(uintptr_t start, uintptr_t end)
{
if (start % mips_dcache_linesize != 0)
{
start = start - start % mips_dcache_linesize;
}
if (end > start)
{
m32_dcache_clean_invalidate(start, end - start);
}
}
/****************************************************************************
* Name: up_flush_dcache_all
*
* Description:
* Flush the entire data cache by cleaning and invalidating the D cache.
*
* NOTE: If DCACHE write-through is configured, then this operation is the
* same as up_invalidate_cache_all().
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* This operation is not atomic. This function assumes that the caller
* has exclusive access to the address range so that no harm is done if
* the operation is preempted.
*
****************************************************************************/
void up_flush_dcache_all(void)
{
irqstate_t flags;
flags = spin_lock_irqsave(&g_cache_lock);
m32_flush_dcache();
spin_unlock_irqrestore(&g_cache_lock, flags);
}
/****************************************************************************
* Name: up_enable_dcache
*
* Description:
* Enable the D-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_enable_dcache(void)
{
}
/****************************************************************************
* Name: up_disable_dcache
*
* Description:
* Disable the D-Cache
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void up_disable_dcache(void)
{
}
/****************************************************************************
* 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
*
****************************************************************************/
void up_coherent_dcache(uintptr_t addr, size_t len)
{
}
#endif /* CONFIG_ARCH_DCACHE */

View file

@ -0,0 +1,91 @@
/****************************************************************************
* arch/mips/src/jz4780/jz4780_cache.h
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 <assert.h>
#include <stdint.h>
#include <nuttx/cache.h>
#include <nuttx/debug.h>
#include <arch/board/board.h>
#ifndef __ARCH_MIPS_SRC_JZ4780_JZ4780_CACHE_H
#define __ARCH_MIPS_SRC_JZ4780_JZ4780_CACHE_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************
* Inline Functions
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
void m32_size_cache(void);
void m32_flush_dcache(void);
void m32_flush_icache(void);
void m32_clean_cache(uint32_t kva, size_t n);
void m32_sync_icache(uint32_t kva, size_t n);
void m32_dcache_clean_invalidate(uint32_t kva, size_t n);
void m32_dcache_invalidate(uint32_t kva, size_t n);
void m32_dcache_clean(unsigned kva, size_t n);
extern int mips_icache_size;
extern int mips_icache_linesize;
extern int mips_icache_ways;
extern int mips_dcache_size;
extern int mips_dcache_linesize;
extern int mips_dcache_ways;
extern int mips_scache_size;
extern int mips_scache_linesize;
extern int mips_scache_ways;
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_MIPS_SRC_JZ4780_JZ4780_CACHE_H */

View file

@ -37,6 +37,7 @@
#include "mips_internal.h"
#include "jz4780_lowinit.h"
#include "jz4780_cache.h"
/****************************************************************************
* Pre-processor Definitions
@ -95,6 +96,8 @@ static inline void jz4780_pbclk(void)
void jz4780_lowinit(void)
{
m32_size_cache();
/* Configure peripheral clocking */
jz4780_pbclk();

View file

@ -61,7 +61,7 @@ static void reboot_s(int sec)
}
/****************************************************************************
* Function: jzjz_timerisr
* Function: jz_timerisr
*
* Description:
* The timer ISR will perform a variety of services for various portions

View file

@ -0,0 +1,664 @@
/****************************************************************************
* arch/mips/src/jz4780/mti_cache.S
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2014-2015, Imagination Technologies Limited and/or its
* affiliated group companies.
* All rights reserved.
*
* 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. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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) HOWEVER 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "mips32-memorymap.h"
#ifdef CONFIG_ALLOW_BSD_COMPONENTS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define FUNCTION(x) .global x; .type x, STT_FUNC; x:
#define DATA(x) .global x; .type x, STT_OBJECT; x:
/* Cache operations */
#define Index_Invalidate_I 0x00 /* 0 0 */
#define Index_Writeback_Inv_D 0x01 /* 0 1 */
#define Index_Writeback_Inv_T 0x02 /* 0 2 */
#define Index_Writeback_Inv_S 0x03 /* 0 3 */
#define Index_Load_Tag_I 0x04 /* 1 0 */
#define Index_Load_Tag_D 0x05 /* 1 1 */
#define Index_Load_Tag_T 0x06 /* 1 2 */
#define Index_Load_Tag_S 0x07 /* 1 3 */
#define Index_Store_Tag_I 0x08 /* 2 0 */
#define Index_Store_Tag_D 0x09 /* 2 1 */
#define Index_Store_Tag_T 0x0A /* 2 2 */
#define Index_Store_Tag_S 0x0B /* 2 3 */
#define Hit_Invalidate_I 0x10 /* 4 0 */
#define Hit_Invalidate_D 0x11 /* 4 1 */
#define Hit_Invalidate_T 0x12 /* 4 2 */
#define Hit_Invalidate_S 0x13 /* 4 3 */
#define Fill_I 0x14 /* 5 0 */
#define Hit_Writeback_Inv_D 0x15 /* 5 1 */
#define Hit_Writeback_Inv_T 0x16 /* 5 2 */
#define Hit_Writeback_Inv_S 0x17 /* 5 3 */
#define Hit_Writeback_D 0x19 /* 6 1 */
#define Hit_Writeback_T 0x1A /* 6 2 */
#define Hit_Writeback_S 0x1B /* 6 3 */
#define Fetch_Lock_I 0x1C /* 7 0 */
#define Fetch_Lock_D 0x1D /* 7 1 */
#define Fetch_Lock_S 0x1F /* 7 3 */
#define C0_CONFIG $16
#define C0_CONFIG0 $16, 0
#define C0_CONFIG1 $16, 1
#define C0_CONFIG2 $16, 2
#define C0_CONFIG3 $16, 3
#define C0_CONFIG4 $16, 4
#define C0_CONFIG5 $16, 5
#define CFG1_IL_SHIFT 19
#define CFG1_IL_BITS 3
#define CFG1_IS_SHIFT 22 /* Unless n==7, then 32 */
#define CFG1_IS_BITS 3
#define CFG1_IA_SHIFT 16
#define CFG1_IA_BITS 3
#define CFG1_DS_SHIFT 13
#define CFG1_DS_BITS 3
#define CFG1_DL_SHIFT 10
#define CFG1_DL_BITS 3
#define CFG1_DA_SHIFT 7
#define CFG1_DA_BITS 3
#define CFG2_SS_SHIFT 8
#define CFG2_SS_BITS 4
#define CFG2_SL_SHIFT 4
#define CFG2_SL_BITS 4
#define CFG2_SA_SHIFT 0
#define CFG2_SA_BITS 4
#define CFG3_M_SHIFT 31
#define CFG4_M_SHIFT 31
#define CFG5_L2C_SHIFT 10
/* Global data declaration with size. */
#define EXPORTS(name, sz) \
.globl name; \
.type name, @object; \
.size name, sz; \
name:
#define DECL(x, val) \
EXPORTS(x, 4); \
.word val
#define PTR_SUBU subu /* decrement pointer (SGI uses sub) */
#define PTR_ADDU addu /* increment pointer (SGI uses add) */
#define PTR_MFC0 mfc0 /* access CP0 pointer width register */
#define PTR_MTC0 mtc0 /* access CP0 pointer width register */
/* Macros to automate cache operations */
#define addr $t0
#define maxaddr $t1
#define mask $t2
#define cacheop(kva, n, linesize, op) \
/* check for bad size */ \
blez n, 11f ; \
PTR_ADDU maxaddr, kva, n ; \
/* align to line boundaries */ \
PTR_SUBU mask, linesize, 1 ; \
not mask ; \
and addr, kva, mask ; \
PTR_SUBU addr, linesize ; \
PTR_ADDU maxaddr, -1 ; \
and maxaddr, mask ; \
/* the cacheop loop */ \
10: PTR_ADDU addr, linesize ; \
cache op, 0(addr) ; \
bne addr, maxaddr, 10b ; \
11:
/* virtual cache op: no limit on size of region */
#define vcacheop(kva, n, linesize, op) \
cacheop(kva, n, linesize, op)
/* indexed cache op: region limited to cache size */
#define icacheop(kva, n, linesize, size, op) \
move $t3, n; \
bltu n, size, 12f; \
move $t3, size; \
12: cacheop(kva, $t3, linesize, op)
/* caches may not have been sized yet */
#define SIZE_CACHE(reg, which) \
lw reg, which; \
9: blez reg, 9f; \
sync
#define tmp $t0
#define cfg $t1
#define icachesize $t2
#define ilinesize $t3
#define iways $ta0
#define dcachesize $ta1
#define dlinesize $ta2
#define dways $ta3
#define scachesize $t8
#define slinesize $t9
#define sways $v0
#define tmp1 $v1
#define tmp2 $a0
#define tmp3 $a1
#define tmp4 $a2
#define tmp5 $a3
.set nomips16
DECL(mips_icache_size, -1)
DECL(mips_icache_linesize, -1)
DECL(mips_icache_ways, 1)
DECL(mips_dcache_size, -1)
DECL(mips_dcache_linesize, -1)
DECL(mips_dcache_ways, 1)
DECL(mips_scache_size, -1)
DECL(mips_scache_linesize, -1)
DECL(mips_scache_ways, 1)
/****************************************************************************
*
* void m32_size_cache()
*
* Work out size of I, D & S caches (assume already initialised)
*
****************************************************************************/
FUNCTION(m32_size_cache)
lw $t0, mips_icache_size
move tmp3, $ra
bgtz $t0, 8f # already known?
bal _size_cache
move $ra, tmp3
8: # Return
jr $ra
/****************************************************************************
*
* void m32_clean_icache (unsigned kva, size_t n)
*
* Writeback and invalidate address range in instruction caches
*
****************************************************************************/
FUNCTION(m32_clean_icache)
SIZE_CACHE($a2, mips_icache_linesize)
vcacheop($a0, $a1, $a2, Hit_Invalidate_I)
lw $a2, mips_scache_linesize
blez $a2, 9f
vcacheop($a0, $a1, $a2, Hit_Writeback_Inv_S)
sync
9: jr.hb $ra
/****************************************************************************
*
* static void _size_cache()
*
* Internal routine to determine cache sizes by looking at config
* registers. Sizes are returned in registers, as follows:
*
* Do not use tmp3 (reg a1) and tmp1 (reg v1) in this function.
*
****************************************************************************/
FUNCTION(_size_cache)
# Read $config, 0 to check presence of $config, 1
mfc0 cfg, C0_CONFIG
# Read Configuration register, select 1
mfc0 cfg, C0_CONFIG1
# Get I-cache line size
ext tmp, cfg, CFG1_IL_SHIFT, CFG1_IL_BITS
beqz tmp, 8f # No I-cache
# Get number of I-cache ways
ext iways, cfg, CFG1_IA_SHIFT, CFG1_IA_BITS
addiu iways, iways, 1
move icachesize, iways
# Total icache size = lines/way * linesize * ways
li ilinesize, 1
addiu tmp, tmp, 1
sllv ilinesize, ilinesize, tmp
sllv icachesize, icachesize, tmp
# Get I-cache lines per way
ext tmp, cfg, CFG1_IS_SHIFT, CFG1_IS_BITS
addiu tmp, tmp, 1
andi tmp, tmp, 7
addiu tmp, tmp, 5
sllv icachesize, icachesize, tmp
# Store icache config
sw icachesize, mips_icache_size
sw ilinesize, mips_icache_linesize
sw iways, mips_icache_ways
8: # No I-cache, check for D-cache
ext tmp, cfg, CFG1_DL_SHIFT, CFG1_DL_BITS
beqz tmp, 9f # No D-cache
# Get number of dcache ways
ext dways, cfg, CFG1_DA_SHIFT, CFG1_DA_BITS
addiu dways, dways, 1
move dcachesize, dways
# Total dcache size = lines/way * linesize * ways
li dlinesize, 1
addiu tmp, tmp, 1
sllv dlinesize, dlinesize, tmp
sllv dcachesize, dcachesize, tmp
# Get dcache lines per way
ext tmp, cfg, CFG1_DS_SHIFT, CFG1_DS_BITS
addiu tmp, tmp, 1
andi tmp, tmp, 7
addiu tmp, tmp, 5
sllv dcachesize, dcachesize, tmp
# Store dcache config
sw dcachesize, mips_dcache_size
sw dlinesize, mips_dcache_linesize
sw dways, mips_dcache_ways
9:
LA tmp, __cache_size_hook
move tmp4, $ra
jal tmp
move $ra, tmp4
# Return
jr $ra
/****************************************************************************
*
* static void __cache_size_hook()
*
* Internal routine to determine cache sizes by looking at config
* registers. Sizing information is stored directly to memory.
*
* Do not use tmp3 (reg a1), tmp1 (reg v1) or tmp4 (a2) in this function.
*
****************************************************************************/
FUNCTION(__cache_size_hook)
# If we are operating with a coherency manager, abort.
# Check if we have config 5 register present
mfc0 tmp, C0_CONFIG3
ext tmp, tmp, CFG3_M_SHIFT, 1
beqz tmp, 2f
mfc0 tmp, C0_CONFIG4
ext tmp, tmp, CFG4_M_SHIFT, 1
beqz tmp, 2f
# Do we have a memory mapped L2 cache config?
mfc0 tmp, C0_CONFIG5
ext tmp, tmp, CFG5_L2C_SHIFT, 1
beqz tmp, 2f
# No CM3 code supplied but we have a memory mapped L2 config
# Report a Boot failure through UHI
li $t9, 23
# Reason - L2 cache config
li $a0, 1
# Syscall number
li $v0, 1
# Trigger the UHI operation
syscall 1
# Should never return
1:
b 1b
2: mfc0 cfg, C0_CONFIG2
# Get scache line size (log2)
ext tmp, cfg, CFG2_SL_SHIFT, CFG2_SL_BITS
beqz tmp, 3f # no s-cache
addiu tmp, tmp, 1
# Get number of scache ways
ext sways, cfg, CFG2_SA_SHIFT, CFG2_SA_BITS
addiu sways, sways, 1
move scachesize, sways
# Total scache size = lines/way * linesize * ways
li slinesize, 1
sllv slinesize, slinesize, tmp
sllv scachesize, scachesize, tmp
# Get scache lines per way
ext tmp, cfg, CFG2_SS_SHIFT, CFG2_SS_BITS
addiu tmp, tmp, 6
sllv scachesize, scachesize, tmp
sw scachesize, mips_scache_size
sw slinesize, mips_scache_linesize
sw sways, mips_scache_ways
3:
# Return
jr $ra
/****************************************************************************
*
* void m32_flush_cache (void)
*
* Writeback and invalidate all caches
*
****************************************************************************/
FUNCTION(m32_flush_cache)
SIZE_CACHE($a1, mips_dcache_size)
/* writeback and invalidate primary caches individually */
lw $a2, mips_dcache_linesize
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Writeback_Inv_D)
9: lw $a1, mips_icache_size
lw $a2, mips_icache_linesize
blez $a1, 9f
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Invalidate_I)
9: lw $a1, mips_scache_size
lw $a2, mips_scache_linesize
blez $a1, 9f
sync
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Writeback_Inv_S)
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_flush_dcache (void)
*
* Writeback and invalidate data caches only
*
****************************************************************************/
FUNCTION(m32_flush_dcache)
SIZE_CACHE($a1, mips_dcache_size)
/* writeback and invalidate primary data cache */
lw $a2, mips_dcache_linesize
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Writeback_Inv_D)
9: lw $a1, mips_scache_size
lw $a2, mips_scache_linesize
blez $a1, 9f
sync
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Writeback_Inv_S)
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_flush_icache (void)
*
* Writeback and invalidate instruction cache only
*
****************************************************************************/
FUNCTION(m32_flush_icache)
SIZE_CACHE($a1, mips_icache_size)
/* writeback and invalidate primary instruction cache */
lw $a2, mips_icache_linesize
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Invalidate_I)
9: lw $a1, mips_scache_size
blez $a1, 9f
lw $a2, mips_scache_linesize
li $a0, KSEG0_BASE
cacheop($a0, $a1, $a2, Index_Writeback_Inv_S)
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_clean_cache (unsigned kva, size_t n)
*
* Writeback and invalidate address range in all caches
*
****************************************************************************/
FUNCTION(m32_clean_cache)
SIZE_CACHE($a2, mips_dcache_linesize)
vcacheop($a0, $a1, $a2, Hit_Writeback_Inv_D)
9: lw $a2, mips_icache_linesize
blez $a2, 9f
vcacheop($a0, $a1, $a2, Hit_Invalidate_I)
9: lw $a2, mips_scache_linesize
blez $a2, 9f
sync
vcacheop($a0, $a1, $a2, Hit_Writeback_Inv_S)
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_sync_icache (unsigned kva, size_t n)
*
* Synchronise icache and dcache for virtual address range
*
****************************************************************************/
FUNCTION(m32_sync_icache)
/* check for bad size */
PTR_ADDU maxaddr, $a0, $a1
blez $a1, 9f
/* get synci step and skip if not required */
rdhwr $a2, $1
PTR_ADDU maxaddr, -1
beqz $a2, 9f
/* ensure stores complete */
sync
/* align to line boundaries */
PTR_SUBU mask, $a2, 1
not mask
and addr, $a0, mask
PTR_SUBU addr, $a2
and maxaddr, mask
/* the cacheop loop */
10: PTR_ADDU addr, $a2
synci 0(addr)
bne addr, maxaddr, 10b
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_dcache_clean_invalidate (unsigned kva, size_t n)
*
* Writeback and invalidate address range in data caches
*
****************************************************************************/
FUNCTION(m32_dcache_clean_invalidate)
SIZE_CACHE($a2, mips_dcache_linesize)
vcacheop($a0, $a1, $a2, Hit_Writeback_Inv_D)
9: lw $a2, mips_scache_linesize
blez $a2, 9f
sync
vcacheop($a0, $a1, $a2, Hit_Writeback_Inv_S)
9: sync
jr.hb $ra
/****************************************************************************
*
* void m32_dcache_invalidate (unsigned kva, size_t n)
*
* Invalidate (but don't writeback) address range in data caches
* XXX Only safe if region is totally cache-line aligned.
*
****************************************************************************/
FUNCTION(m32_dcache_invalidate)
SIZE_CACHE($a2, mips_dcache_linesize)
vcacheop($a0, $a1, $a2, Hit_Invalidate_D)
9: lw $a2, mips_scache_linesize
blez $a2, 9f
vcacheop($a0, $a1, $a2, Hit_Invalidate_S)
9: sync
jr.hb $ra
/*
* Cache locking
*
* The MIPS32 cache architecture does support per-line cache locking.
*
* WARNING: if you lock any cache lines, then don't call the
* mips_flush_xcache routines, because these will flush the
* locked data out of the cache too; use only mips_clean_xcache.
*/
/****************************************************************************
*
* void m32_lock_dcache (void *data, size_t n)
*
* Load and lock a block of data into the d-cache
*
****************************************************************************/
FUNCTION(m32_lock_dcache)
SIZE_CACHE($a2, mips_dcache_linesize)
vcacheop($a0, $a1, $a2, Fetch_Lock_D)
sync
9: jr.hb $ra
/****************************************************************************
*
* void m32_lock_icache (void *code, size_t n)
*
* Load and lock a block of instructions into the i-cache
*
****************************************************************************/
FUNCTION(m32_lock_icache)
SIZE_CACHE($a2, mips_icache_linesize)
vcacheop($a0, $a1, $a2, Fetch_Lock_I)
sync
9: jr.hb $ra
/****************************************************************************
*
* void m32_lock_scache (void * data, size_t n)
*
* Load and lock a block of data into the s-cache
*
****************************************************************************/
FUNCTION(m32_lock_scache)
SIZE_CACHE($a2, mips_scache_linesize)
vcacheop($a0, $a1, $a2, Fetch_Lock_S)
sync
9: jr.hb $ra
/****************************************************************************
*
* void m32_dcache_clean (unsigned kva, size_t n)
*
* Writeback address range in data caches
*
****************************************************************************/
FUNCTION(m32_dcache_clean)
SIZE_CACHE($a2, mips_dcache_linesize)
vcacheop($a0, $a1, $a2, Hit_Writeback_D)
9: lw $a2, mips_scache_linesize
blez $a2, 9f
vcacheop($a0, $a1, $a2, Hit_Writeback_S)
9: sync
jr.hb $ra
#endif /* CONFIG_ALLOW_BSD_COMPONENTS */

View file

@ -15,6 +15,7 @@ CONFIG_16550_UART0_CLOCK=14745600
CONFIG_16550_UART0_IRQ=51
CONFIG_16550_UART0_SERIAL_CONSOLE=y
CONFIG_16550_UART=y
CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_ARCH="mips"
CONFIG_ARCH_BOARD="ci20"
CONFIG_ARCH_BOARD_CI20=y
@ -40,13 +41,6 @@ CONFIG_FS_PROCFS=y
CONFIG_GRAN=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_MIPS32_DCACHE=y
CONFIG_MIPS32_DCACHE_SIZE=32768
CONFIG_MIPS32_DLINE_SIZE=32
CONFIG_MIPS32_ICACHE=y
CONFIG_MIPS32_ICACHE_SIZE=32768
CONFIG_MIPS32_ILINE_SIZE=32
CONFIG_MIPS32_KSEG0_IBASE=0x80000000
CONFIG_MQ_MAXMSGSIZE=64
CONFIG_NET=y
CONFIG_NETDEV_IFINDEX=y

View file

@ -15,6 +15,7 @@ CONFIG_16550_UART0_CLOCK=14745600
CONFIG_16550_UART0_IRQ=51
CONFIG_16550_UART0_SERIAL_CONSOLE=y
CONFIG_16550_UART=y
CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_ARCH="mips"
CONFIG_ARCH_BOARD="ci20"
CONFIG_ARCH_BOARD_CI20=y
@ -37,13 +38,6 @@ CONFIG_FS_PROCFS=y
CONFIG_GRAN=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_MIPS32_DCACHE=y
CONFIG_MIPS32_DCACHE_SIZE=32768
CONFIG_MIPS32_DLINE_SIZE=32
CONFIG_MIPS32_ICACHE=y
CONFIG_MIPS32_ICACHE_SIZE=32768
CONFIG_MIPS32_ILINE_SIZE=32
CONFIG_MIPS32_KSEG0_IBASE=0x80000000
CONFIG_MQ_MAXMSGSIZE=64
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512