322 lines
8.8 KiB
C
322 lines
8.8 KiB
C
/* ------------------------------------------
|
|
* Copyright (c) 2016, Synopsys, Inc. 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 Synopsys, Inc., 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.
|
|
*
|
|
* \version 2016.05
|
|
* \date 2014-07-15
|
|
* \author Wayne Ren(Wei.Ren@synopsys.com)
|
|
--------------------------------------------- */
|
|
|
|
/**
|
|
* \file
|
|
* \ingroup ARC_HAL_MISC_CACHE
|
|
* \brief header file of cache module
|
|
*/
|
|
|
|
#ifndef _ARC_HAL_CACHE_H_
|
|
#define _ARC_HAL_CACHE_H_
|
|
|
|
#include "inc/embARC_toolchain.h"
|
|
#include "inc/arc/arc.h"
|
|
#include "inc/arc/arc_builtin.h"
|
|
#include "inc/arc/arc_exception.h"
|
|
|
|
/**
|
|
* \name instruction cache control register related definition
|
|
* \todo this definitions will be reviewed.
|
|
* @{
|
|
*/
|
|
#define IC_CTRL_IC_ENABLE 0x0 /*!< enable instruction cache */
|
|
#define IC_CTRL_IC_DISABLE 0x1 /*!< disable instruction cache */
|
|
#define IC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */
|
|
#define IC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */
|
|
#define IC_CTRL_OP_SUCCEEDED 0x8 /*!< instruction cache operation succeeded */
|
|
/** @} */
|
|
|
|
/**
|
|
* \name data cache control register related definition
|
|
* \todo this definition will be reviewed.
|
|
* @{
|
|
*/
|
|
#define IC_CTRL_I
|
|
#define DC_CTRL_DC_ENABLE 0x0 /*!< enable data cache */
|
|
#define DC_CTRL_DC_DISABLE 0x1 /*!< disable data cache */
|
|
#define DC_CTRL_INVALID_ONLY 0x0 /*!< invalid data cache only */
|
|
#define DC_CTRL_INVALID_FLUSH 0x40 /*!< invalid and flush data cache */
|
|
#define DC_CTRL_ENABLE_FLUSH_LOCKED 0x80 /*!< the locked data cache can be flushed */
|
|
#define DC_CTRL_DISABLE_FLUSH_LOCKED 0x0 /*!< the locked data cache cannot be flushed */
|
|
#define DC_CTRL_FLUSH_STATUS 0x100 /*!< flush status */
|
|
#define DC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */
|
|
#define DC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */
|
|
#define DC_CTRL_OP_SUCCEEDED 0x4 /*!< data cache operation succeeded */
|
|
/** @} */
|
|
|
|
/**
|
|
* \name instruction cache related inline function
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \brief check whether instruction cache is available,
|
|
* 0 for not available, >0 for available
|
|
*/
|
|
Inline uint8_t icache_available(void)
|
|
{
|
|
return (_arc_aux_read(AUX_BCR_I_CACHE) & 0xF);
|
|
}
|
|
|
|
/**
|
|
* \brief enable instruction cache
|
|
* \param[in] icache_en_mask operation mask
|
|
*/
|
|
Inline void icache_enable(uint32_t icache_en_mask)
|
|
{
|
|
if (!icache_available()) return;
|
|
_arc_aux_write(AUX_IC_CTRL, icache_en_mask);
|
|
}
|
|
|
|
/**
|
|
* \brief disable instruction cache
|
|
*/
|
|
Inline void icache_disable(void)
|
|
{
|
|
if (!icache_available()) return;
|
|
_arc_aux_write(AUX_IC_CTRL, IC_CTRL_IC_DISABLE);
|
|
}
|
|
|
|
/**
|
|
* \brief invalidate the entire instruction cache
|
|
*/
|
|
Inline void icache_invalidate(void)
|
|
{
|
|
if (!icache_available()) return;
|
|
/* invalidate the entire icache */
|
|
_arc_aux_write(AUX_IC_IVIC, 0);
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
}
|
|
|
|
/**
|
|
* \brief invalidate specific cache line
|
|
* \param[in] address memory address
|
|
*/
|
|
Inline void icache_invalidate_line(uint32_t address)
|
|
{
|
|
if (!icache_available()) return;
|
|
_arc_aux_write(AUX_IC_IVIL, address);
|
|
/* the 3 nops are required by ARCv2 ISA */
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
}
|
|
|
|
/**
|
|
* \brief lock specific cache line
|
|
* \param[in] address memory address
|
|
* \return 0, succeeded, -1, failed
|
|
*/
|
|
Inline int32_t icache_lock_line(uint32_t address)
|
|
{
|
|
if (!icache_available()) return -1;
|
|
_arc_aux_write(AUX_IC_LIL, address);
|
|
if(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) {
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief set icache access mode
|
|
* \param[in] mode, access mode, 1: indirect access 0:direct access
|
|
*/
|
|
Inline void icache_access_mode(uint32_t mode)
|
|
{
|
|
if (!icache_available()) return;
|
|
if (mode) {
|
|
_arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) | IC_CTRL_INDIRECT_ACCESS);
|
|
} else {
|
|
_arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) & (~IC_CTRL_INDIRECT_ACCESS));
|
|
}
|
|
}
|
|
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* \name data cache related inline functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \brief check whether data cache is available,
|
|
* 0 for not available, >0 for available
|
|
*/
|
|
Inline uint8_t dcache_available(void)
|
|
{
|
|
return (_arc_aux_read(AUX_BCR_D_CACHE) & 0xF);
|
|
}
|
|
|
|
/**
|
|
* \brief invalidate the entire data cache
|
|
*/
|
|
Inline void dcache_invalidate(void)
|
|
{
|
|
if (!dcache_available()) return;
|
|
uint32_t status;
|
|
|
|
status = cpu_lock_save();
|
|
_arc_aux_write(AUX_DC_IVDC, 1);
|
|
/* wait for flush completion */
|
|
while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
|
|
cpu_unlock_restore(status);
|
|
}
|
|
|
|
/**
|
|
* \brief invalidate the specific cache line
|
|
* \param[in] address memory address
|
|
*/
|
|
Inline void dcache_invalidate_line(uint32_t address)
|
|
{
|
|
if (!dcache_available()) return;
|
|
_arc_aux_write(AUX_DC_IVDL, address);
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
Asm("nop_s");
|
|
}
|
|
|
|
/**
|
|
* \brief enable data cache
|
|
* \param[in] dcache_en_mask operation mask
|
|
*/
|
|
Inline void dcache_enable(uint32_t dcache_en_mask)
|
|
{
|
|
if (!dcache_available()) return;
|
|
_arc_aux_write(AUX_DC_CTRL, dcache_en_mask);
|
|
}
|
|
|
|
/**
|
|
* \brief disable data cache
|
|
*/
|
|
Inline void dcache_disable(void)
|
|
{
|
|
if (!dcache_available()) return;
|
|
_arc_aux_write(AUX_DC_CTRL, DC_CTRL_DC_DISABLE);
|
|
}
|
|
|
|
/**
|
|
* \brief flush data cache
|
|
*/
|
|
Inline void dcache_flush(void)
|
|
{
|
|
if (!dcache_available()) return;
|
|
uint32_t status;
|
|
|
|
status = cpu_lock_save();
|
|
_arc_aux_write(AUX_DC_FLSH, 1);
|
|
/* wait for flush completion */
|
|
while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
|
|
cpu_unlock_restore(status);
|
|
}
|
|
|
|
/**
|
|
* \brief flush the specific data cache line
|
|
* \param[in] address memory address
|
|
*/
|
|
Inline void dcache_flush_line(uint32_t address)
|
|
{
|
|
if (!dcache_available()) return;
|
|
|
|
uint32_t status;
|
|
|
|
status = cpu_lock_save();
|
|
_arc_aux_write(AUX_DC_FLDL, address);
|
|
while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
|
|
cpu_unlock_restore(status);
|
|
}
|
|
|
|
/**
|
|
* \brief lock the specific data cache line
|
|
* \param[in] address memory address
|
|
* \return 0, succeeded, -1, failed
|
|
*/
|
|
Inline int dcache_lock_line(uint32_t address)
|
|
{
|
|
if (!dcache_available()) return -1;
|
|
_arc_aux_write(AUX_DC_LDL, address);
|
|
if(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) {
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief set dcache access mode
|
|
* \param[in] mode, access mode, 1: indirect access 0:direct access
|
|
*/
|
|
Inline void dcache_access_mode(uint32_t mode)
|
|
{
|
|
if (!dcache_available()) return;
|
|
if (mode) {
|
|
_arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) | DC_CTRL_INDIRECT_ACCESS);
|
|
} else {
|
|
_arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) & (~DC_CTRL_INDIRECT_ACCESS));
|
|
}
|
|
}
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* \name declarations of cache related functions
|
|
* @{
|
|
*/
|
|
extern int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size);
|
|
extern int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size);
|
|
extern int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data);
|
|
extern int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data);
|
|
extern int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data);
|
|
extern int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size);
|
|
extern int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size);
|
|
extern int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size);
|
|
extern int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data);
|
|
extern int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data);
|
|
extern int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data);
|
|
extern void arc_cache_init(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/** @} */
|
|
#endif /* _ARC_HAL_CACHE_H_ */
|